Jfinal-简
JFinalConfig配置类
基于JFinal的web项目需要创建一个继承自JFinalConfig类的子类,该类用于对整个web项目进行配置。
JFinalConfig子类需要实现六个抽象方法:
public class DemoConfig extends JFinalConfig{
public void configConstant(Constants me){}
public void configRoute(Routes me){}
public void configEngine(Engine me){}
public void configInterceptor(Interceptors me){}
public void configHandler(Handlers me){}
}
配置类中configConstant方法
me.setDevMode(true);//配置开发模式,true值为开发模// 式
// 配置aop代理使用cglib,否则将使用jfinal默认动态编译代理方案
me.setToCglibProxyFactory();
// 配置依赖注入时,是否对被注入类的超类进行注入
me.setInjectDependency(true);
//配置基础下载路径,默认为webapp下的download
me.setBaseDownloadPath(...);
//配置基础上传路径,默认为webapp下的upload
me.setBaseUploadPath(...);
// 配置 404,500页面
me.setError404View("/comon/404.html");
me.setError500View("/comon/500.html");
// 配置 encoding,默认为UTF8
me.setEncoding(UTF8);
// 默认上传最大数据量,默认10M
me.setMaxPostSize(10*1024*1024)
配置类中configRoute方法
路由扫描,jfinal 4.9.03 新增功能。
参数 "com.xxx." 表示扫描被限定的包名,
// 扫描仅会在该包以及该包的子包下进行
me.scan("com.xxx.");
// 手工添加路由。
注意:使用了路由扫描就不要再使用手工添加路由,
两者选其一
me.add("/hello", HelloController.class);
路由的使用-手动添加路由
public void configROute(Routes me){// 参数1demo:是访问控制器的url// 参数2 DemoController.class: 是控制器类// 参数3 html:是该控制器访问视图的路径
me.add("demo",DemoController.class,"html");
}
路由自动扫描
public void configRoute(Routes me){
// 参数 指定controller所在的包
me.scan("com.ape.web.");
}
注意:使用了路由自动扫描,就需要@Path注解来修饰controller类
注:参数是访问controller的url,需要注意的就是明确指向view的路径
配置类中其他方法
configPlugin(..) 该方法使用来配置插件
configInterceptor(..) 该方法使用来配置拦截器
configHandler(..) Handler可以接管所有web请求,并对应用拥有完全的控制权,可以很方便地实 现更高层的功能性扩展 onStart()、onStop() 方法 JFinal 会在系统启动完成之后以及系统关闭之前分别回调这两个方法.
Controller
Controller是JFinal核心类之一,该类作为MVC模式中的控制器,基于JFinal的Web应用的控制器需要继承该类。Controller是定义Action方法的地点,是组织Action的一种方式,一个Controller可以包含多个Action。Controller是线程安全的。
Action
在Controller之中定义的public方法称为Action,Action是请求的最小单位。
Action方法必须在Controller中定义,且必须是public可见性。
public class HelloController extends Controller{public void index(){renderText(“此方法是一个action”);
}public String test(){return "index.html";
}
}
以上代码中,定义了两个Action:HelloController.index(),HelloController.test().
Action可以有返回值,返回值可在拦截器中通过invocation.getReturnValue()获取到,以便进行render控制。
Action中的@ActionKey注解
如果希望controller中的ACtion自己独立的路由路径,可以使用@ActionKey,例如:
@Path("demo")
public class DemoController extends Controller {
@ActionKey("hello")
public void index() {
render("/html/show.html");
}
}
Action一旦有了@ActionKey设置则会忽略@Path而直接使用@ActionKey的路径。
@NotAction注解
如果希望 controller 中的 public 方法不成为一个 action,可以使用 @NotAction 注解。 @NotAction 注解通常用于引入了 BaseController 的中间 Controller,例如:
@Path("demo")
public class BaseController extends Controller {
// 不希望成为 action,仅供子类调用,或拦截器中调用
@NotAction
public void getLoginUser() {
}
}
@Action中的get/getPara方法
Controller提供了getPara系列方法用来从请求中获取参数
两种方式:
方式一:
第一个形参为String的getPara系列方法。
该系列方法是对HttpServletRequest.getParameter(String name)的封装,这类方法都是转调了HttpServletRequest的getParameterMap与getParameterNames.
方式二:
第二个形参为int或无形参的getPara系列方法
该系列方法是去获取urlPara中所带的参数值。getParaMap与getParaNames分别对应HttpServletRequest的getParameterMap与getParameterNames.
Action中的get/getPara方法
Action中的set/setAttr方法
setAttr(String,Object)转调了HttpServletRequest.setAttribute(String,Object),该方法可以将各种数据传递给View并在View中显示出来。
// 链式用法
set("project", project).set("replyList", replyList).render("index.html");
Action中的render方法
渲染纯文本内容 Hello JFinal
renderText("Hello JFinal“);
渲染Html内容”Hello Html“
renderHtml("<a>Hello Html</a>");
render(String view) 方法将对view所指向的模板进行渲染
注意:最终指向的模板 baseViewPath + viewPath + view 使用技巧:baseViewPath 配置为项目存放模板的总的根目录。viewPath 配置为当前被映射的 controller 的子 目录。最终的效果就是 render(view) 的参数 view 永远是一个最终的文件名 当需要打破 baseViewPath 与 viewPath 这两个参数的限制时,view 参数以 "/" 打头即可。
Action中的renderQrCode方法
生成二维码并响应用户:
需要的依赖
<dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.2.1</version></dependency>
renderQrCode(content,width,height);
param1:二维码中所包含的数据内容
param2:二维码宽度,单位为像素
param3:二维码高度,单位为像素
renderQrCode(data, 200, 200, 'M'); ‘M’为纠错参数可以在二维码图片被遮挡或者被损坏一部分时仍然可以正确读取其中的内容。 纠错级别从高到低可以指定为:'H'、'Q'、'M'、'L',其纠错率分别为:30%、25%、15%、7%。 值默认为 'L'。
Action 中的 setSessionAttr 方法
通过 setSessionAttr(key, value) 可以向 session 中存放数据
通过 getSessionAttr(key) 可以从 session 中读取数据
通过 getSession()得到 session 对象从而使用全面的session API
Action 中的 getFile 方法
需要的依赖
<dependency><groupId>com.jfinal</groupId><artifactId>cos</artifactId><version>2022.2</version></dependency>
AOP:
JFinal采用极速化的AOP设计,专注AOP最核心的目标,将概念减少到极致,仅有三个概 念:Interceptor、Before、Clear,并且无需引入IOC也无需使用啰嗦的XML。 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式 和运行期间动态代理实现程序功能的统一维护的一种技术
Interceptor
interceptor 可以对方法进行拦截,并提供机会在方法的前后添加切面代码,实现 AOP 的 核心目标。Interceptor 接口仅仅定义了一个方法 public void intercept(Invocation inv)。
public class DemoInterceptor implements Interceptor {
public void intercept(Invocation inv) {
System.out.println("Before method invoking");
inv.invoke();
System.out.println("After method invoking");
}
注意:必须调用 inv.invoke() 方法,才能将当前调用传递到后续的 Interceptor 与 Action。
常见错误:目前为止仍有很多同学忘了调用 inv.invoke() 方法,造成 controller 中的 action 不会被执行。在此 再次强调一次,一定要调用一次 inv.invoke(),除非是刻意不去调用剩下的拦截器与 action,这种情况仍然需要 使用 inv.getController().render()/renderJson() 调用一下相关的 render() 方法为客户端响应数据。
E n j o y模板引擎
模板引擎是为了解决用户界面(显示)与业务数据(内容)分离而产生的。 他可以生成特定格式的文档,常用的如格式如HTML、xml以及其他格式的文本格式。其工作模式如下:
主要了解这几个就够了:#if、#for、#define、#set、#include、#switch。
Enjoy指令 #if
if指令需要一个 cond 表达式作为参数,并且以 #end 为结尾符,当 cond 求值为 true 时,执行 if 分支之中的代码。
#if(cond) ... #end
#if #else if 与 #else 分支块结构:
#if(c1) ...
#else if(c2) ...
#else if (c3) ...
#else ... #end
Enjoy指令 #for
// 对 List、数组、Set 这类结构进行迭代
#for(x : list)
#(x.field)
#end
// 对 Map 进行迭代
#for(x : map)
#(x.key)
#(x.value)
#en
注意:当被迭代的目标为 null 时,不需要做 null 值判断,for 指令会自动跳过,不进行迭代。
for指令还支持对其状态进行获取
#for(x : listAaa)
#(for.size) 被迭代对象的 size 值
#(for.index) 从 0 开始的下标值
#(for.count) 从 1 开始的记数值
#(for.first) 是否为第一次迭代
#(for.last) 是否为最后一次迭代
#(for.odd) 是否为奇数次迭代
#(for.even) 是否为偶数次迭代
#(for.outer) 引用上层
#for 指令状态
#(for.outer.size) 引用上层
#for 指令被迭代对象的 size 值
Enjoy指令 #date #number
date指令用于格式化输出日期型数据,包括Date、Timestamp等一切继承自Date类的对 象的输出
#date(account.createAt)
#date(account.createAt, "yyyy-MM-dd HH:mm:ss")
number 指令用于格式化输出数字型数据,包括 Double、Float、Integer、Long、 BigDecimal 等一切继承自Number类的对象的输出
#number(3.1415926, "#.##") #number(0.9518, "#.##%")
#number(123456789, ",###") #number(300000, "光速为每秒,### 公里。"
Enjoy指令 #include
#include指令用于将外部模板内容包含进来,被包含的内容会被解析成为当前模板中的一 部分进行使用。
注意:#include 指令第一个参数必须为 String 常量,当以 ”/” 打头时将以 baseTemplatePath 为相对路径去找文件,否则将以使用 #include 指令的当前模板的路 径为相对路径去找文件。
Enjoy指令 #switch
#switch 指令对标 java 语言的 switch 语句。 #switch (month) #case (1, 3, 5, 7, 8, 10, 12) #(month) 月有 31 天 #case (2) #(month) 月平年有28天,闰年有29天 #default 月份错误: #(month ?? "null") #end #case 指令参数还可以是任意表达式 #case (a, b, x + y, "abc", "123")
#case 支持逗号分隔的多参数,从而无需引入 #break 指令,不仅减少了代码量,而且避免了忘写 #break 指令 时带来的错误隐患。还有一个与 java 语法有区别的地方是 #case、#default 指令都未使用冒号字符。