AI 摘要

文章系统演示 Spring Boot 无缝整合 MyBatis Plus 与 Thymeleaf 的完整流程:先引入 mybatis-plus-boot-starter 与 mysql 驱动,配置数据源,利用 BaseMapper、IService、ServiceImpl 零 SQL 完成 CRUD、逻辑删除、条件构造、分页插件;再引入 spring-boot-starter-thymeleaf,通过 Controller 将数据注入 Model,在 HTML 中以 th:text、th:each 等属性实现动静结合的模板渲染,并展示变量表达式与内置工具对象用法,实现前后端高效协同。

Spring Boot 整合 MyBatis Plus

MyBatis Plus 简介

MyBatis Plus 是一个 MyBatis 的增强工具,为简化开发、提高效率而生。

MyBatis Plus 文档:https://www.baomidou.com/

MyBatis Plus 的特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响。
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求。

Mybatis Plus 初体验

MyBatis Plus 内置通用 Mapper、通用 Service,无需编写 SQL 语句就能实现简单的 CRUD。


示例:Mybatis Plus 初体验

SQL 脚本:

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user`
(
    id BIGINT NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

Maven 项目配置文件(pom.xml):

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.2</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

Spring Boot 项目配置文件(classpath:/application.properties):

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo_project?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456..

User 实体类(package.entity.User):

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {

    private Integer id;

    private String name;

    private Integer age;

    private String email;

}

UserMapper 数据访问接口(package.dao.UserMapper):

@Mapper // Spring Boot中,数据访问接口需要加@mapper注解
public interface UserMapper extends BaseMapper<User> {

    // 在Mapper接口类上继承MyBatis Plus提供的BaseMapper
    // 继承的BaseMapper接口是泛型类,泛型对应实体类
    // 此时MyBatis Plus自动实现对这一实体的基本CRUD操作

}

UserService 业务逻辑接口(package.service.UserService):

public interface UserService extends IService<User> {

    // 在Service接口类上继承MyBatis Plus提供的IService
    // 继承的IService接口是泛型类,泛型对应实体类

}

UserServiceImpl 业务逻辑接口实现类(package.service.UserServiceImpl):

@Service    // 业务逻辑接口实现类加上@Service注解
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    // 在Service实现类上继承MyBatis Plus提供的ServiceImpl
    // 继承的ServiceImpl接口是泛型类,第一个参数表示对应的Mapper接口,第二个参数表示对应的实体类
    // 业务逻辑接口实现类实现业务逻辑接口

}

测试类(test.Tester):

// 注入Service层实现类
@Resource
UserService userService;

@Test
void contextLoads() {
    // 调用Service层查询用户列表
    List<User> userList = userService.list();

    // 遍历用户列表
    for (User user : userList) {
        System.out.println(user);
    }

}

示例效果:


借助 MyBatisCodeHelperPro 插件,可以快速生成 MyBatis Plus 代码。


示例:MyBatisCodeHelperPro

MyBatisCodeHelperPro 插件:


MyBatis Plus CRUD

数据访问层、业务逻辑层的内置了基础的增删改查方法,可以根据需求直接调用。


示例:MyBatis Plus CRUD

测试类(test.Tester):

@Test
void deleteUser() {
    userService.removeById(1);
}

如果需要手写 SQL 语句(如多表联查、复杂查询等),其实现方式和 MyBatis 一致。

MyBatis Plus 注解

MyBatis Plus 提供许多常用的注解。

  • 实体类通常不需要显式添加 @TableName、@TableField 注解。
  • MyBatis-Plus 提供了一种自动映射的机制,它会根据实体类的命名规则来推导对应的数据库表名和字段名。

示例:MyBatis Plus 注解

User 实体类(package.cn.duozai.demo.entity.User):

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("sys_user")
public class User {
    @TableId
    private Long id;

    @TableField("nickname")
    private String name;

    private Integer age;

    private String email;

}

MyBatis Plus 配置

MyBatis Plus 的部分配置继承自 MyBatis 原生所支持的配置。


示例:MyBatis Plus 配置

Spring Boot 项目配置文件(classpath:/application.properties):

mybatis-plus.mapper-locations=classpath:/mappers/*.xml

MyBatis Plus 日志

MyBatis Plus 配置日志输出可以帮助我们更好地了解应用程序在运行时的行为,包括数据库操作语句、查询结果、异常信息等。

通过查看日志输出,我们可以快速定位问题并进行调试,提高开发效率和程序稳定性。

MyBatis Plus 支持的日志系统:Log4j、LogBack、slf4j、stdout 等。


示例:MyBatis Plus 日志

Spring Boot 项目配置文件(classpath:/application.properties):

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

示例效果:


MyBatis Plus 逻辑删除

逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案。

  • 逻辑删除要求数据里面有一个字段 deleted 表示是否删除,其取值 0 表示未删除,1 表示已删除。
  • 删除数据时不再执行 DELETE,而是执行 UPDATE 将 deleted 字段的值修改为 1。
  • 查询数据时将 deleted 字段的值为 1 的数据排除在外,即拼接查询条件 deleted = 0。

示例:MyBatis Plus 逻辑删除

数据库表(user):

User 实体类(package.entity.User):

@TableLogic // 标记该属性表示逻辑删除
private Integer deleted;

Spring Boot 项目配置文件(classpath:/application.properties):

# 表示逻辑删除的字段
mybatis-plus.global-config.db-config.logic-delete-field=deleted
# 已删除时,逻辑删除字段的值,默认为1
mybatis-plus.global-config.db-config.logic-delete-value=1
# 未删除时,逻辑删除字段的值,默认为0
mybatis-plus.global-config.db-config.logic-not-delete-value=0

测试类(test.Tester):

@Test
void deleteUser() {
    // 仍然调用删除方法,MyBatis Plus自动识别逻辑删除
    userService.removeById(1);
}

示例效果:


MyBatis Plus 条件构造器

条件构造器(Wrapper)用于构造查询条件以实现复杂 SQL 语句。


示例:MyBatis Plus 条件构造器

测试类(test.Tester):

@Test
void contextLoads() {
    // 使用条件构造器构造查询条件
    QueryWrapper queryWrapper = new QueryWrapper();
    // 查询名字是Tom的用户列表
    queryWrapper.eq("name", "Tom");

    // 调用Service层查询用户列表
    List<User> userList = userService.list(queryWrapper);

    // 遍历用户列表
    for (User user : userList) {
        System.out.println(user);
    }
}

示例效果:


MyBatis Plus 的条件构造器还支持使用 lambda 表达式,可以通过方法引用的方式来使用实体字段名的操作,避免直接写数据库表字段名时的错写名字。


示例:lambda 条件构造器

测试类(test.Tester):

@Test
void contextLoads() {
    // 使用条件构造器构造查询条件
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>();
    // 查询名字是Tom的用户列表
    queryWrapper.eq(User::getName, "Tom");

    // 调用Service层查询用户列表
    List<User> userList = userService.list(queryWrapper);

    // 遍历用户列表
    userList.forEach(System.out::println);
}

MyBatis Plus 分页

MyBatis Plus 内置分页插件,只需要简单的配置就可以实现分页功能。


示例:MyBatis Plus 分页

MyBatis Plus 配置类(package.config.MyBatisPlusConfiguration):

@Configuration
public class MyBatisPlusConfiguration {

    /**
     * MybatisPlusInterceptor是MyBatis Plus的一个拦截器,用于配置插件
     *
     * @return com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
     * @author 多仔ヾ
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}

测试类(test.Tester):

@Test
void contextLoads() {
    // 实例化分页对象,设置分页参数:页码,页大小
    Page<User> page = new Page<User>(1, 2);

    // 调用Service层查询用户列表(分页)
    userService.page(page);

    // 遍历用户列表
    for (User record : page.getRecords()) {
        System.out.println(record);
    }
  
    System.out.println("页码:" + page.getCurrent());
    System.out.println("页大小:" + page.getSize());
    System.out.println("数据总数:" + page.getTotal());
    System.out.println("页码总数:" + page.getPages());
    System.out.println("是否有上一页:" + page.hasPrevious());
    System.out.println("是否有下一页:" + page.hasNext());
}

示例效果:


Spring Boot 整合 Thymeleaf

Thymeleaf 简介

Thymeleaf 是一个流行的模板引擎。

  • Thymeleaf 基于 HTML,以 HTML 标签为载体,Thymeleaf 要寄托在 HTML 标签下实现。
  • Spring Boot 官方推荐使用 Thymeleaf 来替代 JSP 技术。

Thymeleaf 的特点:

  • 动静结合:既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
  • 开箱即用:提供了 Spring 标准方言以及一个与 Spring MVC 完美集成的可选模块,可以快速地实现表单绑定、属性编辑器、国际化等功能。
  • 多方言支持:提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式,开发人员也可以扩展和创建自定义的方言。
  • 与 Spring Boot 完美整合:Spring Boot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器。

Thymeleaf 初体验

Thymeleaf 通过在 HTML 标签中,增加额外属性来达到模板 + 数据的展示方式。


示例:Thymeleaf 初体验

Maven 项目配置文件(pom.xml):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Hello 控制器(package.HelloController):

@Controller
public class HelloController {

    @Resource
    UserService userService;

    @GetMapping("/hello")
    public String hello(Model model) {
        // 存放一句话
        model.addAttribute("message", "Hello, Thymeleaf");

        // 存放用户列表
        List<User> userList = userService.list();
        model.addAttribute("userList", userList);

        // 返回classpath:/templates/下的视图名称
        return "hello";
    }

}

Hello 页面视图(classpath:/templates/hello.html):

<!DOCTYPE html>
<!--
    xmlns:th:声明名称空间,可以省略
-->
<html lang="cn" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!--
        使用th:text设置标签的文本内容,使用$符号取值
        也可以使用内联表达式取值
    -->
    <h1 th:text="${message}"></h1>
    <h1>[[${message}]]</h1>

    <!--
        使用th:each遍历列表
        item:列表中的每一个元素的别名
        state:列表状态
        state.index:数据下标,从0开始
        state.count:数据序号,从1开始
    -->
    <div th:each="item,state : ${userList}">
        <span th:text="${item.name}"></span>
    </div>
</body>
</html>

示例效果:


Thymeleaf 变量表达式

使用 ${xxx} 包裹的表达式被称为变量表达式。

变量表达式可以获取对象的属性和方法。

变量表达式获取对象的属性和方法的基本用法:

${user.userName}

变量表达式可以使用内置的基本对象。

  • #request:获取 HttpServletRequest 对象。
  • #response:获取 HttpServletResponse 对象。
  • #session:获取 HttpSession 对象。

变量表达式使用内置的基本对象的基本用法:

${#session.getAttribute('loginUser')}
${session.loginUser}

变量表达式可以使用内置的工具对象。

  • strings:字符串工具对象,常用方法有 equals、length、trim 等。
  • lists/sets:List/Set 集合工具对象,常用的方法有 size、isEmpty、contains 等。
  • arrays:数组工具对象,常用的方法 toArray、length、isEmpty、contains 等。

变量表达式使用内置的工具对象的基本用法:

${#strings.equals('多仔',name)}

Thymeleaf th 属性

Thymeleaf 提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用。

Thymeleaf 的基本 th 属性:

名称描述
th:id替换 HTML 标签 的 id 属性
th:text文本替换,会转义特殊字符,等同于 [[${xxx}]]
th:utext文本替换,不会转义特殊字符,等同于 [(${xxx})]
th:value替换 HTML 标签的 value 属性
th:style替换 HTML 标签的 style 属性
th:each遍历数组、列表、Map
th:if条件判断
th:unless和 th:if 判断相反,满足条件时不显示
th:switch
th:case
与 Java 的 switch case 语句类似,根据不同的条件展示不同的内容
th:replace加载文件,并替换该节点
th:include加载文件,将文件内容放到这个节点里面
th:selected替换 HTML 标签的 selected 属性