7.Enjoy Template模板引擎
表达式特点
与Java规则基本相同的表达式、属性访问、方法调用、静态属性访问、静态方法调用
必须掌握的三个指令:取值#(),判断#if(),循环#for()
#()取值:
#(value)
#(object.field)
#(object.field ??)
#(a > b ? x : y)
#(seoTitle ?? "JFinal 俱乐部")
#(object.method(), null)
注意:第一行代码value参数可以为null,而第二行代码中的object为null时将会报异常,此时需要使用第三行代码中的空合安全取值调用运算符。最后一行代码中的输出指令参数为一个逗号表达式,逗号表达式的整体求值结果为最后一个表达式的值(结果为null)
#if()判断
#if(cond)
...
#end
………………………………………………………………
#if(c1)
#else if(c2)
#else.
#end
注意:cond支持模板中所有表达式,包括逗号表达式, else与if之间可以有空白字符
#for()循环
#for(x : list)
#(x.field)// #(for.index)获取当前循环的下下标,#(for.outer.index)获取上一层循环下标
#end
……………………………………………………….循环遍历
#for(x : map)
#(x.key)
#(x.value)
#end
注意:第一个for指令是对list进行迭代输出,用法与java语法完全一样,第二个for指令是对map进行迭代,取值方式为item.key与item.value。for指令嵌套时,各自拥有自己的变量名作用域,规则与java语言一致,例如上例中的两个#(x.field)处在不同的for指令作用域内,会正确获取到所属作用域的变量值。
#for(x : listAaa)
#(for.size) 被迭代对象的 size 值
#(for.index) 从 0 开始的下标值
#(for.count) 从 1 开始的记数值
#(for.first) 是否为第一次迭代
#(for.last) 是否为最后一次迭代
#(for.odd) 是否为奇数次迭代
#(for.even) 是否为偶数次迭代
#(for.outer) 引用上层 #for 指令状态
#end
…………………………………………………………for else用法
#for(blog : blogList)// 在for指令迭代次数为0时,将执行#else分支内部的语句
#(blog.title)
#else
您还没有写过博客,点击此处<a href="/blog/add">开博</a>
#end
……………………………………………………..下面是常规用法
#for(i = 0; i < 100; i++)
#(i)
#end
注意:#for 指令还支持 #continue、#break 指令,用法与java完全一致,在此不再赘述。
#set赋值指令
#include导入外部模板
#define自定义一个模板函数,使用前必须使用include指令将define所在页面导入,define可以传值
#define layout()
<div>
这里是模板内容部分,相当于传统模板引擎的 nested 的部分
</div>#end
………………………………………………使用
#include("layout.html")
#@layout()
……………………………………………………….如果一个模板行数或者一个页面需要被多个页面引用可以直接在configEngine中配置,如下:
me.setbaseSqlTemlatePath(PathKit.getWebRootPath);//定位到webapp目录
me.addSharedFunction(“/fromt/common.html”);//模板函数所在页面
me.addSharedStaticMethod(className.class);//在之前的表达式中(静态方法的调用比较麻烦:需要书写完整的类名),书写此方法后在页面中调用(直接方法名即可)
me.addSharedMethod(new className);
me.addSharedObject(key,new clasName);//这两个方法与前面的方法作用类似,需要使用key.方法名来调用,而不是原本的方法名了
注意:addSharedStaticMethod的(开放所有静态方法)。addSharedMethod/ addSharedObject(开放所有普通方法)。
注意:模板函数的调用比指令多一个@字符,是为了与指令掉哟个区分开来
8.EhCachePlugin缓存插件
是JFinal集成的缓存插件,通过使用EhCachePlugin可以提高系统的并发访问速度,即插即用
public void configPlugin(Plugins me) {//在启动类中配置
me.add(new EhCachePlugin());
}
………………………………………使用
@Before(CacheInterceptor.class)
@CacheName("blogList")//此处如果不写就是使用默认的缓存配置,如果写了缓存配置的name要与这里相同
public void list() {
List<Blog> blogList = Blog.dao.find("select * from blog");
…….
}
ehcache.xml的配置
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="20"
timeToLiveSeconds="60">
</defaultCache>
<!-- 存放用户登录信息,过期时间 3600秒,用ehache替换session功能 -->
<cache name="session"
maxElementsInMemory="10000"
maxElementsOnDisk="100000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="true"
diskPersistent="true"
/>
EvictInterceptor清除缓存
@Before(EvictInterceptor.class)
@CacheName("blogList")//必须要指定清除CacheName
public void update() {
getModel(Blog.class).update();
redirect("blog.html");
}
9.Cron4jPlugin定时任务调度(硬编码、外部配置文件:常用)
第一步:需要在configPlugin中加载Cron4的jar包与其配置文件
cp = new Cron4jPlugin("config.txt");
cp = new Cron4jPlugin("config.txt", "cron4j");
cp = new Cron4jPlugin(PropKit.use("config.txt"));
cp = new Cron4jPlugin(PropKit.use("config.txt"), "cron4j");
me.add(cp);
第二步:书写配置cron4.txt文件
cron4j=task1, task2
task1.cron=* * * * *
task1.class=com.xxx.TaskAaa
task1.daemon=true
task1.enable=true
task2.cron=* * * * *
….
第三步:在配置文件中设定时间(上面的五个*就是对应下面的规则)
分 :从 0 到 59
时 :从 0 到 23
天 :从 1 到 31,字母 L 可以表示月的最后一天
月 :从 1 到 12,可以别名:jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov" and "dec"
周 :从 0 到 6,0 表示周日,6 表示周六,可以使用别名: "sun", "mon", "tue", "wed", "thu", "fri" and "sat"
10.Validator校验
Validator自身实现了Interceptor接口,所以它也是一个拦截器,配置方式与拦截器完全一样
创建:自己创建一个校验类(继承Validator的抽象类,并实现其中的两个方法)
public class LoginValidator extends Validator {
protected void validate(Controller c) {
validateRequiredString("name", "nameMsg", "请输入用户名");//name就是前台表单提交时的name,nameMsg就是提示信息的key,请输入…就是提示信息
validateRequiredString("pass", "passMsg", "请输入密码");
}
protected void handleError(Controller c) {
c.keepPara("name");//此方法会将提交上来的数据保存到name的这个key中(前台方便我们回显,前台.html可以通过#{name}??’’回显)
c.render("login.html");//跳转到那个页面(这两个方法都是在没有通过判断时执行的,主要作用就是回显数据和提示信息)
}
}
使用:配置方式与拦截器完全一样@Before
public class UserController extends Controller {
@Before(LoginValidator.class) // 配置(使用)方式与拦截器完全一样
public void login() {
}
}
11.json转换
final 官方提供了 Json 抽象类的三个实现:JFinalJson、FastJson、Jackson,如果不进行配置,那么默认使用 JFinalJson 实现,指定为其它实现需要在 configConstant 进行配置
JFinalJson:只支持对象转 json string,不支持反向的 json string 转对象
FastJson:转换依赖于 Model、java bean 的 getter 方法
MixedJson:是对 JFinalJson、FastJson 的再一次封装,Object 转 json string 时使用 JFinalJson 的实现,而反向 json string 转 Object 使用 FastJson。(可以多用)
public void configConstant(Constants me) {
me.setJsonFactory(new FastJsonFactory());//使用FastJson来实现json转换(不指定就使用默认的)
}
注意:日期类转json的配置me.setJsonDatePattern("yyyy-MM-dd");
Json转换的使用:(toJson:转换为json,parse:json转换为指定类型或对象)
1.使用前面配置的json转换器转换
// 在 Controller 中使用 renderJson 进行 json 转换,并渲染给客户端
renderJson();
renderJson(key, object);
renderJson(new String[]{...});
// 使用 JsonKit 工具类进行 json 转换
JsonKit.toJson(...);
JsonKit.parse(...);
2.使用指定的json转换器转换(摆脱配置的json转换器)
// 临时指定使用 FastJson 实现
FastJson.getJson().toJson(...);
FastJson.getJson().parse(...);
// 为 Controller.renderJson(..) 方法直接传入转换好的 json string
renderJson(FastJson.getJson().toJson(...));
12.JFinal架构
JFinal由Handler、Interceptor、Controller、Render、Plugin五大部分组成(微内核全方位扩展架构)
undertow打包部署
1:命令行进入项目根目录,然后运行 mvn clean package 即可打包
2:打包完后,进入 jfinal_demo_for_maven/target/jfinal_demo_for_maven-release/jfinal_demo_for_maven
目录, linux 下启动、关闭、重启项目的命令分别为:
./jfinal.sh start (./jfinal.sh restart >>jboot-admin.log)
./jfinal.sh stop
./jfinal.sh restart (./jfinal.sh restart >>jboot-admin-service.log)
windows 下启动、关闭、重启项目的命令分别为:
jfinal.bat start
jfinal.bat stop
jfinal.bat restart
注意 jfinal_demo_for_maven/target 目录下面还会有一个 jfinal_demo_for_maven-release.zip 文件
该文件等价于对 target/jfinal_demo_for_maven-release/jfinal_demo_for_maven
目录进行的压缩,方便上传到服务器上解压即部署,可通过删除 package.xml 中的 <format>zip</format>
项避免打出该 zip 包,具体用法在 package.xml 中有说明
3:jfinal.sh 脚本中提供了详细的说明,根据说明可选择不同的运行模式