JFinal 是基于Java 语言的极速 web 开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python等动态语言的开发效率。
使用JFinal提供的逆向工程可以直接生成实体类以及JFinal需要的依赖类文件(_JFinalDemoGenerator类)。
JFinal提供了JfinalConfig类来管理项目的全局配置。自创一个类继承自JfinalConfig类并实现方法。
例如:
configConstant(ConsTants c)
配置项目全局常量
configRoute(Routes r)
配置路由。可以配置指定包下,也可以手动添加路由,映射到对应的Controller控制层。
configEngine(Engine e)
配置模板引擎(不常用)
configPlugin(Plugins p)
配置插件依赖
例如:
配置druid数据库连接池插件
DruidPlugin druidPlugin = new DruidPlugin(URL,username,password);
p.add(druidPlugin);
配置ActiveRecord操作数据库插件,需要依赖于JFinal逆向工程生成的类做表字段映射。
ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
//使用逆向工程类自动做映射关系
_MappingKit.mapping(arp);
p.add(arp);
configHandler(Handlers h) handler需要考虑线程安全问题
用来配置handler,handler接管所有的web请求,方便进一步做扩展。
configInterceptor(Interceptors i)
使用JFinal拦截器需要实现Interceptor接口去实现intercept方法。
配置拦截器,可以分为三种:全局拦截器、控制层拦截器、业务层拦截器
全局拦截器此方法和addGlobalActionInterceptor()是等价的,拦截所有controller中action的方法
i.add(new Inter());
控制层拦截器
i.addGlobalActionInterceptor(new Inter());
业务层拦截器
i.addGlobalServiceInterceptor(new Inter());
onStart()、onStop()
项目启动后需要执行的业务代码使用onStart()实现。
项目关闭前需要执行的业务代码使用onStop()实现。
控制层通过实现JFinal提供的类(Controller)实现控制层,并且是线程安全的。
通过在Controller类上加JFinal提供的@path注解来实现路由的定位。
在Controller中定义的方法,被public修饰的方法就可以称为一个action,action是每一个请求的最小单位。
如果不希望controller中的方法被修饰成action,可以使用@NotAction注解。
获取前端参数
get / getPara方法
getModel()
采用数据库表字段名来进行数据注入(不推荐使用)
getModel()一共有四个具体实现:
getModel(Class<T> modelClass)
getModel(Class<T> modelClass, boolean skipConvertError)
getModel(Class<T> modelClass, String modelName)
getModel(Class<T> modelClass, String modelName, boolean skipConvertError)
getBean()
采用实体类set()方法进行数据注入(推荐使用)
getBean()有四个方法实现:
getBean(Class<T> beanClass)
getBean(Class<T> beanClass, boolean skipConvertError)
getBean(Class<T> beanClass, String beanName)
getBean(Class<T> beanClass, String beanName, boolean skipConvertError)
获取后端参数(render)
// 渲染名为test.html的视图,且视图类型为 JFinal Template renderTemplate(”test.html”); // 生成二维码 renderQrCode("content"); // 渲染名为test.html的视图,且视图类型为FreeMarker renderFreeMarker(”test.html”); // 渲染名为test.html的视图,且视图类型为Velocity renderVelocity(“test.html”); // 将所有setAttr(..)设置的变量转换成 json 并渲染 renderJson(); // 以 "users" 为根,仅将 userList 中的数据转换成 json 并渲染 renderJson(“users”, userList); // 将user对象转换成 json 并渲染 renderJson(user); // 直接渲染 json 字符串 renderJson("{\"age\":18}" ); // 仅将setAttr(“user”, user)与setAttr(“blog”, blog)设置的属性转换成json并渲染 renderJson(new String[]{"user", "blog"}); // 渲染名为test.zip的文件,一般用于文件下载 renderFile("test.zip"); // 渲染纯文本内容 "Hello JFinal" renderText("Hello JFinal"); // 渲染 Html 内容 "Hello Html" renderHtml("Hello Html"); // 渲染名为 test.html 的文件,且状态为 404 renderError(404 , "test.html"); // 渲染名为 test.html 的文件,且状态为 500 renderError(500 , "test.html"); // 不渲染,即不向客户端返回数据 renderNull(); // 使用自定义的MyRender来渲染 render(new MyRender());
在JFinal中简化了传统AOP的复杂实现方式,使用拦截器对方法实现的操作。
intercepter、Before、Clear
intercepter可以对方法进行拦截,并在方法执行前后,执行切面代码。使用拦截器需要在配置类中指定拦截器,并实现JFinal提供的拦截器接口(Intercepter)重写其中intercept(Invocation invocation)方法,在其中写入被切入Action前后需要执行的逻辑代码。
Before是一个注解,主要作用于控制层和Action上,该注解有一个value,可以选择配置使用哪一种拦截器。
使用在类上,表示对该类所有方法进行拦截,并且执行切面操作
使用在Action上,表示对该方法进行拦截,执行切面操作
Clear是一个注解:拦截器从上到下依次分为 Global、Inject、Class、Method 四个层次,Clear 用于清除自身 所处层次以上层的拦截器。Clear 声明在 Method 层时将针对 Global、Inject、Class 进行清除。Clear 声明在 Class 层时 将针对 Global、Inject 进行清除。Clear 注解携带参数时清除目标层中指定的拦截器。clear可以配置清除指定的拦截器。
Inject注解依赖注入
使用Inject注解可以在controller、Intercepter中注入依赖对象。
JFinal提供了逆向工程工具类(Generator)
生成后的Model直接与javaBean无缝衔接,无需重写setter、getter方法。
具体使用:
// model 所使用的包名 (MappingKit 默认使用的包名) String modelPackageName = "com.demo.common.model"; // base model 所使用的包名 String baseModelPackageName = modelPackageName + ".base"; // base model 文件保存路径 String baseModelOutputDir = System.getProperty("user.dir") + "/src/main/java/" + baseModelPackageName.replace('.', '/'); System.out.println("输出路径:"+ baseModelOutputDir); // model 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径) String modelOutputDir = baseModelOutputDir + "/.."; // 创建生成器 Generator generator = new Generator(getDataSource(), baseModelPackageName, baseModelOutputDir, modelPackageName, modelOutputDir); // 配置是否生成备注 generator.setGenerateRemarks(true); // 设置数据库方言 generator.setDialect(new MysqlDialect()); // 设置是否生成链式 setter 方法,强烈建议配置成 false,否则 fastjson 反序列化会跳过有返回值的 setter 方法 generator.setGenerateChainSetter(false); // 添加不需要生成的表名到黑名单 generator.addBlacklist("adv"); // 设置是否在 Model 中生成 dao 对象 generator.setGenerateDaoInModel(false); // 设置是否生成字典文件 generator.setGenerateDataDictionary(false); // 设置需要被移除的表名前缀用于生成modelName。例如表名 "osc_user",移除前缀 "osc_"后生成的model名为 "User"而 // 非 OscUser generator.setRemovedTableNamePrefixes("t_"); // 将 mysql 8 以及其它原因之下生成 jdk 8 日期类型映射为 java.util.Date,便于兼容老项目,也便于习惯使用 java.util.Date 的同学 TypeMapping tm = new TypeMapping(); tm.addMapping(LocalDateTime.class, Date.class); tm.addMapping(LocalDate.class, Date.class); // tm.addMapping(LocalTime.class, LocalTime.class); // LocalTime 暂时不变 generator.setTypeMapping(tm); // 生成 generator.generate();
JFinal提供ActiveRecord来操作数据库。ActiveRecord在JFinal中做作为插件而存在。使用的话需要在JfinalConfig中进行配置。
例如:
public void configPlugin(Plugins me) { //数据库连接信息 DruidPlugin dp = new DruidPlugin("jdbc:mysql://localhost/db_name", "userName", "password"); me.add(dp); //数据库操作类,引入配置 ActiveRecordPlugin arp = new ActiveRecordPlugin(dp); me.add(arp); //下列方法表明数据库表与实体类的映射关系 arp.addMapping("user", User.class); //指定表article表的主键为article_id arp.addMapping("article", "article_id", Article.class); }
表的主键默认是"id",如果是其他名称,则需指定主键列名称
model
Model是ActiveRecord中最重要的组件之一,它充当MVC模式中的Model部分。
案例:
// 只需要继承Model类,来实现数据库增删改查的操作 public class UserService extends Model<User> { public static final User dao = new User().dao(); }; // 一些常用的方法 // 创建name属性为James,age属性为25的User对象并添加到数据库 new User().set("name", "James").set("age", 25).save(); // 删除id值为25的User User.dao.deleteById(25); // 查询id值为25的User将其name属性改为James并更新到数据库 User.dao.findById(25).set("name", "James").update(); // 查询id值为25的user, 且仅仅取name与age两个字段的值 User user = User.dao.findByIdLoadColumns(25, "name, age"); // 获取user的name属性 String userName = user.getStr("name"); // 获取user的age属性 Integer userAge = user.getInt("age"); // 查询所有年龄大于18岁的user List<User> users = User.dao.find("select * from user where age>18"); // 分页查询年龄大于18的user,当前页号为1,每页10个user Page<User> userPage = User.dao.paginate(1, 10, "select *", "from user where age > ?", 18);
Db + Record模式(数据库操作扩展,更为方便的书写复杂sql)
Db类加Record类在Model之上又提供了完整的数据库增删改查操作,更为方便的实现数据库复杂查询的操作。
案例:
// 创建name属性为James,age属性为25的record对象并添加到数据库 Record user = new Record().set("name", "James").set("age", 25); Db.save("user", user); // 删除id值为25的user表中的记录 Db.deleteById("user", 25); // 查询id值为25的Record将其name属性改为James并更新到数据库 user = Db.findById("user", 25).set("name", "James"); Db.update("user", user); // 获取user的name属性 String userName = user.getStr("name"); // 获取user的age属性 Integer userAge = user.getInt("age"); // 查询所有年龄大于18岁的user List<Record> users = Db.find("select * from user where age > 18"); // 分页查询年龄大于18的user,当前页号为1,每页10个user Page<Record> userPage = Db.paginate(1, 10, "select *", "from user where age > ?", 18);
paginate(分页)
案例:
// 普通分页 dao.paginate(1, 10, "select *", "from girl where age > ? and weight < ?", 18, 50); // 支持分页排序 例如: dao.paginate(1, 10, true, "select *", "from girl where age > ? group by age", 18);
EhCachePlugin是JFinal集成的缓存插件,通过使用EhCachePlugin可以提高系统的并发访问速度。
EhCachePlugin在JFinal中是作为插件而存在的,想要使用需要在JFinalConfig中进行配置。
案例:
public class DemoConfig extends JFinalConfig { public void configPlugin(Plugins me) { me.add(new EhCachePlugin()); } }
具体使用
// 在配置类中配置之后,只需要在Action中加上注解以及拦截器。当请求时如果缓存中有责直接反悔return,不回去出发Action,用法简单。 @Before(CacheInterceptor.class) public void list() { List<Blog> blogList = Blog.dao.find("select * from blog"); User user = User.dao.findById(getParaToInt()); setAttr("blogList", blogList); setAttr("user", user); render("blog.html"); }
EvictInterceptor 缓存清除
EvictInterceptor 根据CacheName注解来清除缓存中的数据
案例:
// EvictInterceptor拦截器根据CacheName来清除缓存中的数据。在JFinal 3.6版本之后CacheName可以定义多个来达到清除多个缓存的效果, 例如: @Before(EvictInterceptor.class) @CacheName("blogList") public void update() { getModel(Blog.class).update(); redirect("blog.html"); } @Before(EvictInterceptor.class) @CacheName("blogList, hotBlogList") // 逗号分隔多个 cacheName public void update() { ... }
CacheKit 缓存操作工具类
get(String cacheName, Object key) // 表示从缓存中拉取数据
put(String cacheName, Object key, Object value) // 表示将从缓存中拿取数据
Redis的极速化插件。使用RedisPlugin可以极度方便的使用redis,当然,在JFinal中想使用插件都需要在JFinal配置类中进行配置。RedisPlugin不仅提供丰富的RedisAPI,同时还支持多redis服务端。
Redis配置:
public class DemoConfig extends JFinalConfig { public void configPlugin(Plugins me) { // 用于缓存bbs模块的redis服务 RedisPlugin bbsRedis = new RedisPlugin("bbs", "localhost"); me.add(bbsRedis); // 用于缓存news模块的redis服务 RedisPlugin newsRedis = new RedisPlugin("news", "192.168.3.9"); me.add(newsRedis); } } // 依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.6.3</version> </dependency> <dependency> <groupId>de.ruedigermoeller</groupId> <artifactId>fst</artifactId> <version>2.57</version><!-- 注意:更高版本不支持 jdk 8 --> </dependency>
更多相关操作请访问
简介:Cron4jPlugin是JFinal集成的任务调度插件,通过使用Cron4jPlugin可以使用通用的cron表达式极为便利的实现任务调度功能。 官网: [JFinal 任务调度](https://jfinal.com/doc/9-2)
简介:Validator是JFinal校验组件,在Validator类中提供了非常方便的校验方法,学习简单,使用方便。 官网:[JFinal 校验组件](https://jfinal.com/doc/10-1)