春节前处理完年前用户反馈的需求与改进,来年只需专注面向未来。 jfinal 3.6 有近 40 项增强与改进,部分功能与改进十分有价值,值得你拥有。
由于 setAttr 方法使用频率极高,为了进一步减少代码量、提升开发效率,新增了 set 方法,其使用方式与 setAttr 完全一样:
// 常见用法 set("user", user); // 链式用法 set("user", user).set("article", article).render("index.html");
set 方法相对于 setAttr 可以减少五次按键,用户体验更好。原方法 setAttr 会永久保留。
与 setAttr 方法同样高频使用的 getPara、getParaToXxx 方法也进行了同样改进,添加 get 系方法,进一步减少代码量,提升开发体验:
// get 系替代 getPara 系 get("title"); // getXxx 系替代 getParaToXxx 系 getInt("value"); getLong("counter");
当然,使用 action 注入比这更省代码:
// title、content 参数值会被自动注入 public void index(String title, String content) { service.save(title, content); }
set 与 get 系方法的添加,持续表达着 jfinal 在提升开发效率、开发体验方面永不止步的追求,未来也将永远进行下去。
#switch 指令特色之一是 #case 分支支持多参数:
#switch (month) #case (1, 3, 5, 7, 8, 10, 12) #(month) 月有 31 天 #case (2) #(month) 月平年有28天,闰年有29天 #default 月份错误: #(month ?? "null") #end
如上代码所示,#case 分支指令支持以逗号分隔的多个参数,这个功能就消解掉了 #break 指令的必要性,所以 enjoy 模板引擎是不需要 #break 指令的。
特色之二是 #case 参数支持任意表达式:
#case (a, b, x + y, "abc", "123")
上述代码中用逗号分隔的表达式先会被求值,然后再逐一与 #switch(value) 指令中的 value 进行比较,只要有一个值与其相等则该 case 分支会被执行。
#case 支持逗号分隔的多参数,从而无需引入 #break 指令,不仅减少了代码量,而且避免了忘写 #break 指令时带来的错误隐患。
使用 #call 指令,模板函数的名称与参数都可以动态指定,提升模板函数调用的灵活性,用法如下:
#call(funcName, p1, p2, ..., pn)
上述代码中的 funcName 为函数名,p1、p2、pn 为被调用函数所使用的参数。如果希望模板函数不存在时忽略其调用,添加常量值 true 在第一个参数位置即可:
#call(true, funcName, p1, p2, ..., pn)
数据库表字段中如果有备注可以生成在 getter、setter 方法之上,只需要一行配置即可:
generator.setGenerateRemarks(true);
生成备注以后,在开发时将鼠标指针放在方法名之上会自动弹出备注内容,消灭掉对数据表字段含义的记忆负担。
老版本 jfinal 应用在 Controller 上的 Tx 拦截器,如果使用 try catch 捕获异常,不太方便指定异常时响应的页面或者数据,通常需要使用一个全局拦截器统一管理。 jfinal 3.6 新版本改进后可以支持下面的用法:
@Before(Tx.class) public void trans { try { service.justDoIt(...); render("ok.html"); } catch (Exception e) { render("error.html"); throw e; } }
如上代码所示,在 catch 块中可以使用 render,也可以使用 renderJson 来灵活响应数据,注意最后别忘了 throw e 抛出异常,好让 Tx 拦截器感知异常并回滚事务。
jfinal 俱乐部 QQ 群中经常发现小伙伴们的代码是下面这样的:
if (value != null) { kv.set("value", value); } if (StrKit.notBlank(value)) { kv.set("value", value); }
用上 jfinal 3.6 以后,代码可以简化成下面这样的:
kv.setIfNotNull("value", value); kv.setIfNotBlank("value", value);
这仍然是 jfinal 追求更高开发效率,更爽开发体验的继续表达。
jfinal 3.0 针对于外部 sql 文件管理,添加了 #sql、#para、#namespace 三指令极简支持,小伙伴们已然爽翻了,没想到还有人提出了支持 String 变量管理 sql 的支持,用法是下面这样的:
String str = "select * from girls where age < #para(0) and weight < #para(1)"; SqlPara sp = Db.getSqlParaByString(str, 19, 50); Db.find(sp);
确实有些小伙伴喜欢将简单 sql 写在 java 代码中,但同时又希望用上 enjoy 引擎来管理 sql。如果没有这个功能的支持,往往要使用 StringBuilder 进行 sql 拼接,代码将会十分丑陋,而且与 SQL 配套的 Object... paras 处理起来也麻烦很多。
为了避免 select * 被大量使用,以及该功能可通过 find("select * from t") 比较方便地被消解掉,jfinal 一直未提供 findAll() 方法。但对于有些项目中存在一些类似于 dic 字典表这种小规模数据的 table 就能省些代码,对于这类需求,可以这么用了:
List<dictionary> = dictionaryList = dictionary.findAll();
仍然是追求开发效率、开发体验的继续表达。
新增 onStart()、onStop() 回调方法,分别替代 JFinalFilter 中的 afterJFinalStart()、beforeJFinalStop(),在减少代码量输出的同时,降低手动入错误的概率,而且还降低了记忆成本。
jfinal 3.5 版本以 JDK 8 起步以后,Model、Db 中的 findById、deleteById 在某些情况下会出现类型转换异常, jfinal 3.6 版本将针对多主键/联合主键的 findById、deleteById 添加了后缀字符 's' 解决了该问题
所以,如果你的老项目中有涉及多主键联合主键的 findById、deleteById 方法的使用,需要改成下面的用法:
document.findByIds(1, 1); Db.deleteByIds("user_role", "userId, roleId", 123, 456);
升级以后,如果有地主需要改的话,eclipse/IDEA 会提示要改的地方,所以升级很安全。
新增 Routes.setMappingSuperClass(boolean) 方法,可以配置是否要对 Controller 的超类中的 public 方法进行路由映射,默认值为 false。该优化的效果是会随着 controller 数量的增加而增加的。
这里要注意一个或级问题,如果用到了 jfinal weixin 项目,并且用到了其中的 MsgController,需要配置一下:
public void configRoute(Routes me) { me.setMappingSuperClass(true); }
因为 MsgController 中作为超类而存在的,其中的 index() 方法必须要被映射才能分发微信服务器发来的消息。
更多改进与增强可以在官网下载 changelog: http://www.jfinal.com
传送门: JFinal Undertow 1.5 发布,稳定、可靠服役于生产环境
传送门: JFinal Weixin 2.3 发布,早已支持微信小程序开发
传送门: Enjoy 3.6 发布,Java 开发者专用超轻量级模板引擎
传送门:Jetty Server 2019.1
ONE MORE THING :jfinal 新版本资源已更新并发布在了 jfinal 官网,maven 中心库也已经上传,可以极速升级。俱乐部福利也更新了一波: https://www.jfinal.com/club 。 新福利计划也已出台: https://www.jfinal.com/club/1-2