刚接触JFianl觉得开发很方便,JFinal的主要特点及优势如下:
1、MVC架构,设计精巧,使用简单;
2、遵循COC原则,零配置,无xml;
3、ActiveRecord支持,使数据库开发极致快速;
4、自动加载修改后的java文件,开发过程中无需重启Web server;
5、AOP支持,拦截器配置灵活,功能强大;
6、Plugin体系结构,扩展性强;
7、多视图支持,支持FreeMarker、JSP、Velocity;
8、强大的Validator后端校验功能;
9、功能齐全,拥有Struts2的绝大部分功能;
10、体积小仅180K,且无第三方依赖;
一、基于JFinal的web项目都需要创建一个继承自JFinalConfig类的子类,该类用于对整个web项目进行配置。并重写6个方法
public class BaseConfig extends JFinalConfig { public void configConstant(Constants me) {} public void configRoute(Routes me) {} public void configEngine(Engine me) {} public void configPlugin(Plugins me) {} public void configInterceptor(Interceptors me) {} public void configHandler(Handlers handlers) {} }
1.配置常量
/** * 配置JFinal常量值 * @param me */ public void configConstant(Constants me) { me.setReportAfterInvocation(false);//设置 devMode 之下的 action report 是否在 invocation 之后,默认值为 true PropKit.use("jdbc.properties");//读取配置文件 me.setDevMode(true);//设置开发模式 }
2.配置路由
/** * 配置访问路由 * @param me */ public void configRoute(Routes me) { me.setBaseViewPath("/view") //设置基础路径,渲染的页面都在/view目录下 me.add("/hello", HelloController.class); // "/hello"表示通过这个路径映射到HelloController上 me.add("/", BlogController.class, "/blog");// "/"表示通过这个路径映射到BlogController上,之后返回blog目录所在的渲染页面html、jsp上 }
3.配置Template Engine
/** * 配置引擎 * @param me */ public void configEngine(Engine me) { me.addSharedFunction("/view/common/_layout.html");//设置共享页面,在页面上通过#define layout()定义模板,#@layout()引用 me.addSharedFunction("/view/common/_layopen.html"); }
4.配置访问插件
public void configPlugin(Plugins me) { DruidPlugin dp = new DruidPlugin(PropKit.get("jdbcUrl"), PropKit.get("user"), PropKit.get("password")); me.add(dp); //配置数据库连接池 ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);//建立数据库表名到Model的映射关系 /*arp.addMapping("blog", "id", Blog.class);*/ _MappingKit.mapping(arp); //自动生成_MappingKit,相当于注释的arp.addMapping("blog", "id", Blog.class); me.add(arp); }
5.拦截器配置
public void configInterceptor(Interceptors me) {}
6.配置处理器
public void configHandler(Handlers me) {}
二、Controller
1.Action
在 Controller 之中定义的 public 方法称为Action。Action 是请求的最小单位。Action 方法必须在 Controller 中定义,且必须是 public 可见性。
下例通过访问路径:localhost/index就可以访问到
public void index(){ render("list.html"); }
2 参数获取
2.1 getPara系列方法分为两种类型。
第一种类型为第一个形参为String的getPara系列方法
第二种类型为第一个形参为int或无形参的getPara系列方法
如果请求访问方式为问号传参:localhost/list?page=1,getPara接收方式为String page = getParaToInt("page");
如果请求访问方式为Restful传参:localhost/list/1,getPara接收方式为String page = getParaToInt(0);
2.2 getModel / getBean
getModel 用来接收页面表单域传递过来的model对象,表单域名称以”modelName.attrName”方式命名,getModel使用的attrName必须与数据表字段名完全一样。
getBean 方法用于支持传统Java Bean,包括支持使用jfinal生成器生成了getter、setter方法的Model,页面表单传参时使用与setter方法相一致的attrName,而非数据表字段名。
public void submit(){ Blog blog = getModel(Blog.class,"blog"); blog.save(); redirect("/"); }
2.3 set / setAttr 方法 : 该方法可以将各种数据传递给View并在View中显示出来。
public void index(){ List<Blog> blogs = Blog.blogDao.find("select * from blog"); setAttr("blogs",blogs); render("list.html"); }
三、Aop
Intercepter 自定义Intercepter类实现Interceptor类,编写intercept方法,必须调用 inv.invoke() 方法,才能将当前调用传递到后续的 Interceptor 与 Action
public class BlogIntercepter implements Interceptor { public void intercept(Invocation invocation) { System.out.println("before"); invocation.invoke(); System.out.println("after"); } }
2.@Before 对拦截器进行配置
@Before(BlogIntercepter.class) public void index(){ List<Blog> blogs = Blog.blogDao.find("select * from blog"); setAttr("blogs",blogs); render("list.html"); }
3.@Clear 携带参数时清除目标层中指定的拦截器。Clear注解带有参数时,能清除指定的拦截器
@Clear(BlogIntercepter.class) public void submit(){ Blog blog = getModel(Blog.class,"blog"); blog.save(); redirect("/"); }
四、ActiveRecord
Model Blog通过继承Model,便立即拥有的众多方便的操作数据库的方法
public class Blog extends Model<Blog> { public static final Blog blogDao = new Blog(); }
2.Db+Record 使用Db与Record类时,无需对数据库表进行映射,Record相当于一个通用的Model
Db+Record和Model功能相似
相同点:
1、两者都提供了增删改查的数据库操作功能,两者查询相关功能最终都是通过 sql 查询操作。
2、两者都具有查询映射对象、查询属性、分页查询、缓存查询功能。
3、在 findXXX系列的方法中通过 ModelBuilder类和 RecordBuilder类 中的 build方法将查询结构构建成映射对象,DB构建成 Record通用的映射对象,Model构建成了具体集成此类的映射对象。在查询中最终基本是构建查询sql、执行sql获取结果集、构建映射对象结果集同一套流程。
不同点:
1、DB 在使用中面向数据库,通过 sql 进行简单灵活的数据操作。Model 在使用中面向映射对象,直接操作对象进行更丰富和复杂的操作。
2、DB 中查询方法返回单个类型值或者 Record 类型,Model 中查询方法返回单个类型值或者继承此类的对象类型。
3、DB 比 Model 中多了批量处理的一系列方法。
五、Validator
Validator自身实现了Interceptor接口,所以它也是一个拦截器,配置方式与拦截器完全一样
public class BlogValidator extends Validator { protected void validate(Controller controller) { validateRequiredString("blog.title","msg","请输入标题"); //前台页面通过msg弹出错误信息 } }
/** * 提交方法 */ @Before(BlogValidator.class) //验证信息拦截 public void submit(){ Blog blog = getModel(Blog.class,"blog"); blog.save(); renderJson(Ret.ok()); }
六、模板引擎
#if(c1)..#else if(c2)..#else..#end if判断用法
for基本用法
// 对 List、数组、Set 这类结构进行迭代 #for(x : list) #(x.field) #end // 对 Map 进行迭代 #for(x : map) #(x.key) #(x.value) #end
switch用法
#switch (month) #case (1, 3, 5, 7, 8, 10, 12) #(month) 月有 31 天 #case (2) #(month) 月平年有28天,闰年有29天 #default 月份错误: #(month ?? "null") #end
#include用于将外部模板内容包含进来
#define xx() ...#end可以定义模板函数
#define content() <div> 这里是模板内容部分,相当于传统模板引擎的 nested 的部分 </div> #end
#@xx() 引用某个名为xx()的模板
#@content()//引用