<2021SC@SDUSC>博客(3)山东大学软件工程应用与实践JPress代码分析(二)

2021SC@SDUSC

前文提要

JFinal 由 Handler、Interceptor、Controller、Render、Plugin 五大部分组成,上文对 JFinal 的 Controller、Render、Interceptor 部分进行了分析,本文将继续对 JFinal 框架的 Handler 部分进行分析。

2-JFinal-framework.png

Handler

JFinal 的核心组件即为 Handler,其中的核心内容有 ActiveRecord、Enjoy 模板引擎、Validator、JSON。本文将不对 Handler 中的非核心内容进行分析。

ActiveRecord
简介

ActiveRecord 是 JFinal 最核心的组成部分之一,通过 ActiveRecord 来操作数据库,将极大地减少代码量,极大地提升开发效率。

ActiveRecord 模式的核心是,一个 Model 对象唯一对应数据库表中的一条记录,而对应关系依靠的是数据库表的主键值。因此,ActiveRecord 模式要求数据库表必须要有主键,当数据库表没有主键时,只能使用 Db + Record 模式来操作数据库。

基本用法

Model 是 ActiveRecord 中最重要的组件之一,它充当 MVC 模式中的 Model 部分。抽象类 Model 实现了众多方便的操作数据库的方法,让业务中的真实 Model 类继承该抽象类即可拥有相关方法,以下以 User 类作为示例:

public abstract class Model<M extends Model> implements Serializable {}
public class User 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);
 
// 获取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);

ActiveRecord 模块下还提供了一个 Generator 工具类,可以自动生成 Model。生成后的 Model 将立刻拥有 JavaBean 的 Getter、Setter 方法,并遵守传统的 JavaBean 规则。

Db + Record 模式

Db 类及其配套的 Record 类,提供了在 Model 类之外更为丰富的数据库操作功能。使用 Db 与 Record 类时,无需对数据库表进行映射,Record 相当于一个通用的 Model。以下为 Db + Record 模式的一些常见用法:

// 创建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);

Db 类除上述使用方法外,还可以单独执行 SQL 语句:

//返回的字段只有一个时
List<String> titleList = Db.query("select title from blog");
List<Integer> idList = Db.query("select id from blog");

//返回的字段不为一时
List<Object[]> list = Db.query("select id, title, content from blog");
List<Object[]> list = Db.query("select * from blog");
Db.tx 事务处理

在 Db 工具类里面,提供了一个系列的 tx(…) 方法支持数据库事务,以下是 Java 8 的 lambda 语法使用示例:

Db.tx(() -> {
  Db.update("update t1 set f1 = ?", 123);
  Db.update("update t2 set f2 = ?", 456);
  return true;
});

以上代码中的两个 Db.update 数据库操作将开启事务,return true 提交事务,return false 则回滚事务。

Enjoy 模板引擎
Java 模板引擎介绍

模板引擎是为了解决用户界面(显示)与业务数据(内容)分离而产生的,其可生成特定格式的文档,常用的如格式如 HTML、XML 以及其他格式的文本文件。

模板引擎不只可以让你实现业务逻辑代码和用户界面代码分离,也可以实现动态数据与静态数据分离,还可以实现代码单元共享,甚至是多语言、动态页面与静态页面自动均衡等等与用户界面可能没有关系的功能。

除了我们即将介绍的 Enjoy 模板引擎,常见的模板引擎还有 Thymeleaf、FreeMaker、Velocity、JSP。

模板引擎的工作模式如下:

image.png

简介

官方文档对 Enjoy 模板引擎给出了如下概述:

Enjoy Template Engine 采用独创的 DKFF (Dynamic Key Feature Forward) 词法分析算法以及独创的 DLRD (Double Layer Recursive Descent) 语法分析算法,极大减少了代码量,降低了学习成本,并提升了用户体验。

Enjoy 模板引擎专为 Java 开发者打造,所以坚持两个核心设计理念:一是在模板中可以直接与 Java 代码通畅地交互,二是尽可能沿用 Java 语法规则,将学习成本降到极致。

Enjoy 模板引擎核心概念为指令、表达式,其中表达式是与 Java 直接打通,剩下有 #if、#for、#define、#set、#include、#switch、#(…) 七个指令需要了解。简而言之,整个 Enjoy 模板引擎学习成本很低。

示例表达式如下:

// 算术运算
1 + 2 / 3 * 4
// 比较运算
1 > 2
// 逻辑运算
!a && b != c || d == e
// 三元表达式
a > 0 ? a : b
// 方法调用
"abcdef".substring(0, 3)
target.method(p1, p2, pn)

分析 Enjoy 模板引擎后可知,由于代码及项目文档都较为零碎,加之作者本人并没有使用模板引擎相关的开发经验,因此必须要上手 Enjoy 模板引擎才能充分理解其中的奥义。由此,对该模板引擎的具体分析将留作分析 JPress 时的任务。

Validator

Validator 是 JFinal 校验组件,在 Validator 类中提供了非常方便的校验方法,其自身实现了 Interceptor 接口,所以它也是一个拦截器,配置方式与拦截器完全一样。

一些基本用法如下:

//通过实现 Validator 抽象类来进行校验操作
public class LoginValidator extends Validator {
    protected void validate(Controller c) {
       validateRequiredString("name", "nameMsg", "请输入用户名");
       validateRequiredString("pass", "passMsg", "请输入密码");
    }
    protected void handleError(Controller c) {
       c.keepPara("name");
       c.render("login.html");
    }
}

//利用普通的 Java 代码配合一个 addError() 方法可无限制、灵活定制验证功能
protected void validate(Controller c) {
    String nickName = c.getPara("nickName");
    if (userService.isExists(nickName)) {
        addError("msg", "昵称已被注册,请使用别的昵称!")}
}
JSON
概述

JFinal 的 JSON 模块以抽象类 Json 为核心,方便扩展第三方实现,JFinal 官方给出了三个 Json 实现,分别是 JFinalJson、FastJson、Jackson,这三个实现继承自抽象类 Json。

抽象类 Json 的核心抽象如下:

public abstract class Json {
    public abstract String toJson(Object object);
    public abstract <T> T parse(String jsonString, Class <T> type);
}

如上代码可以看出 Json 抽象就是 Object 与 JSON String 互转的两个方法,toJson() 将任意 Java 类型转成 JSON String,而 parse() 将 JSON String 再反向转成范型指定的对象。

基本用法

JSON 转换在 JFinal 中的使用分为两类用法,第一类是使用配置的 JSON 转换,第二类是指定某个实现进行 JSON 转换。

  1. 使用配置的 JSON 实现转换

    // 在 Controller 中使用 renderJson 进行 json 转换,并渲染给客户端
    renderJson();
    renderJson(key, object);
    renderJson(new String[]{...});
     
    // 使用 JsonKit 工具类进行 json 转换
    JsonKit.toJson(...);
    JsonKit.parse(...);
    
  2. 使用指定的 JSON 实现转换

    // 临时指定使用 FastJson 实现
    FastJson.getJson().toJson(...);
    FastJson.getJson().parse(...);
     
    // 为 Controller.renderJson(..) 方法直接传入转换好的 json string
    renderJson(FastJson.getJson().toJson(...));
    

总结

本文与 前文 对 JFinal 核心内容进行了分析与解释,为后续对 JBoot 和 JPress 的代码拆解打下了坚实的基础。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值