jfinalController
Action
在Controller中定义的public方法都成为Action,Acction是请求的最小单位。Action方法必须在Controller中定义,且必须是public可见性。
public class DemoController extends Controller{
public void index() {
renderText("Hello jfinal");
}
}
以上代码中定义了一个Action,Action可以有返回值,返回值可在拦截其中通过invocation.getReturnValue()获取到,以便进行render控制。
url访问Action的三种方式
1.Controller上方添加@Path(“/demo”)标签
通过"/demo/方法名"的方式访问
2.@ActionKey :可以通过Action 自己独立的路由路径访问
@Path("/demo")
public class DemoController extends Controller{
@ActionKey("/test")
public void test() {
renderText("这是一个测试");
}
}
3.Action一旦有了@ActionKey设置则会忽略@Path而直接使用@ActionKey的路径
@Path("/demo")
public class DemoController extends Controller{
@NotAction
public void mimi() {
System.out.println("这是一个秘密");
}
}
如果使用了该方法路径会自动跳转到默认index路径下页面
Action 中的 get / getPara 方法
Controller提供了getPara系列方法用来从请求中获取参数。
两种方式:
方式一: 第一个形参为String的getPara系列方法。 该系列方法是对HttpServletRequest.getParameter(String name)的封装,这类方法都是转调 了HttpServletRequest.getParameter(String name)。
方式二: 第一个形参为int或无形参的getPara系列方法。 该系列方法是去获取urlPara中所带的参数值。getParaMap与getParaNames分别对应 HttpServletRequest的getParameterMap与getParameterNames。
jfinal 3.6 重要更新:jfinal 3.6 针对 getPara 系以及 getParaToXxx 系统方法添加了 更简短的替代方法
Action中的set/setAttr方法
setAttr(String, Object) 转调了 HttpServletRequest.setAttribute(String, Object), 该方法可以将各种数据传递给View并在View中显示出来。
jfinal 3.6 新增:为了进一步减少代码量、提升开发效率,jfinal 3.6 新增了 set 方法替代setAttr。
// 替代 setAttr 的 set 用法
set(“article”, article);
// 链式用法
set(“project”, project).set(“replyList”,replyList).render(“index.html”);
Action 中的 render 方法
1.渲染纯文本内容"Hello JFinal" renderText(“Hello JFinal”);
2.渲染 Html 内容"Hello Html" renderHtml(“Hello Html");
3. 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);
- @param content 二维码中所包含的数据内容
- @param width 二维码宽度,单位为像素
- @param height 二维码高度,单位为像素
- 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
需要在配置类中的拦截方法中添加session在页面中使用:
@Override
public void configInterceptor(Interceptors me) {
me.add(new SessionInViewInterceptor());
}
Action 中的 getFile 方法
getFile系列方法支持文件上传
- 先要解决上传文件的依赖
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>cos</artifactId>
<version>2022.2</version>
</dependency>
- 使用getFile() 方法进行文件上传
注意:如果客户端请求为multipart request(form表单使用了enctype=“multipart/form-data”),那么必 须先调用getFile系列方法才能使getPara系列方法正常工作,因为multipart request需要通过getFile系列方法解 析请求体中的数据,包括参数。同样的道理在Interceptor、Validator中也需要先调用getFile。
文件默认上传至项目根路径下的upload子路径之下,该路径称为文件上传基础路径。可以在 JFinalConfig.configConstant(Constants me)方法中通过me.setBaseUploadPath(baseUploadPath) 设置文件 上传基础路径,该路径参数接受以”/”打头或者以windows磁盘盘符打头的绝对路径,即可将基础路径指向项目根径之外
Action 中的 keep 系方法
当页面提交表单请求到 action,如果提交过来的数据存在错误或者缺失,这时应该让用户 继续修改或填写表单数据,这时可以使用 keepPara 方法将用户之前填写过的内容保持住
// 保持住所有表单域
keepPara()
//指定保持住的表单域,如: nickName、email 等等
keepPara(“nickName”, “email”, …);
以上两种用法保持住的参数返回页面时,无论是什么类型都将转换成 String 类型,所以, 如果表单域的类型必须要保持住的话可以使用如下的方式
// 指定 keep 后的类型为 Date
keepPara(Date.class, “createAt”);
// 指定 keep 后的类型为 Integer
keepPara(Integer.class, “age”);
keepPara 一般用在 Validator 或者拦截器之中
AOP
JFinal采用极速化的AOP设计,专注AOP最核心的目标,将概念减少到极致,仅有三个概 念:Interceptor、Before、Clear,并且无需引入IOC也无需使用啰嗦的XML。
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式 和运行期间动态代理实现程序功能的统一维护的一种技术。
Interceptor
Interceptor 可以对方法进行拦截,并提供机会在方法的前后添加切面代码,实现 AOP 的 核心目标。Interceptor 接口仅仅定义了一个方法 public void intercept(Invocation inv)。
public class LoginInterceptor implements Interceptor{
@Override
public void intercept(Invocation inv) {
Controller controller = inv.getController();
HttpSession session = controller.getSession();
if(session.getAttribute("user")!=null) {
inv.invoke();
}else {
controller.redirect("/users");
}
}
}
注意:必须调用 inv.invoke() 方法,才能将当前调用传递到后续的 Interceptor 与 Action。 常见错误:目前为止仍有很多同学忘了调用 inv.invoke() 方法,造成 controller 中的 action 不会被执行。在此 再次强调一次,一定要调用一次 inv.invoke(),除非是刻意不去调用剩下的拦截器与 action,这种情况仍然需要 使用 inv.getController().render()/renderJson() 调用一下相关的 render() 方法为客户端响应数据。
Before
Before注解用来对拦截器进行配置,该注解可配置Class、Method级别的拦截器
// 配置一个Class级别的拦截器,她将拦截本类中的所有方法
@Before(AaaInter.class)
public class BlogController extends Controller { // 配置多个Method级别的拦截器,仅拦截本方法
@Before({BbbInter.class, CccInter.class})
public void index() {
}
// 未配置Method级别拦截器,但会被Class级别拦截器AaaInter所拦截
public void show() {
}
}
Clear
拦截器从上到下依次分为Global、Routes、Class、Method四个层次,Clear用于清除自 身所处层次以上层的拦截器。
Clear声明在Method层时将针对Global、Routes、Class进行清除。Clear声明在Class 层时将针对Global、Routes 进行清除。Clear注解携带参数时清除目标层中指定的拦截器。
Clear用法记忆技巧:
一共有Global、Routes、Class、Method 四层拦截器
清除只针对Clear本身所处层的向上所有层,本层与下层不清除
不带参数时清除所有拦截器,带参时清除参数指定的拦截器
Inject 依赖注入
使用 @Inject 注解可以向 Controller 以及 Interceptor 中注入依赖对象.
使用注入功能需要如下配置:
public void configConstant(Constants me) {
// 开启对 jfinal web 项目组件 Controller、Interceptor、Validator 的注入
me.setInjectDependency(true);
}
me.setInjectDependency(true) 仅是针于 jfinal 的 web 组件而言的配置。
配置完成以后就可以在控制器中使用了
public class AccountController {
@Inject
AccountService service; // 此处会注入依赖对象
public void index() {
service.justDoIt(); // 调用被注入对象的方法
}
}
Validator
Validator是JFinal校验组件,在Validator类中提供了非常方便的校验方法,学习简单,使 用方便。
1.基本用法
Validator自身实现了Interceptor接口,所以它也是一个拦截器,配置方式与拦截器完全 一样。下面代码定义了一个Validator的类
public class LoginValidator extends Validator{
@Override
protected void validate(Controller c) {
validateString("loginPhoneNumber", 11, 11, "phoneErr", "手机号长度为11位");
validateString("loginPassword", 8, 16, "pwdErr", "密码长度8-16位");
}
@Override
protected void handleError(Controller c) {
c.keepPara();
c.render("/login.html");
}
}
2.虽然 Validator 中提供了丰富的 validateXxx(…) 系列方法,但毕竟方法个数是有限的,当 validateXxx(…) 系列的方法不能满足需求时,除了可以用 validateRegex(…) 定制正则表达式来满足需求以外,还可以通过普通 java 代码来实现
protected void validate(Controller c) {
String nickName = c.getPara("nickName");
if (userService.isExists(nickName)) { addError("msg", "昵称已被注册,请使用别的昵称!");
}
}
只需要利用普通的 java 代码配合一个 addError(…) 方法就可以无限制、灵活定制验证功能。 此外, Validator 在碰到验证失败项时,默认会一直往下验证所有剩下的验证项,如果希望程序在碰 到验证失败项时略过后续验证项立即返回,可以通过如下代码来实现
protected void validate(Controller c) {
this.setShortCircuit(true);
....
}
setShortCircuit(boolean) 用于设置验证方式是否为 “短路型验证”。