SpringBoot结合MyBatisPlus轻松实现分页功能超详细教程(附完整实现代码以及保姆级解释)

前言

本文旨在使用SpringBoot + MyBatisPlus + thymeleaf 模版引擎实现分页效果。目标功能实现如下:
在这里插入图片描述
在此案例中,表单数据从数据库拿到,可动态显示当前页,总页数以及记录数。并且实现分页按钮组,包括动态生成页码,前一页和后一页。


首先,需要引入MyBatisPlus以及thymleaf模版引擎相关starter

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

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

相关环境引入之后,本文以User表为案例进行测试

测试实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
//指定该entity映射到数据库中user_table这张表
@TableName("user_table")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

数据库表及字段(案例参照mybatisPlus官方文档)

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

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

增加SpringBoot配置类引入分页插件组件

@Configuration
public class MyBatisConfig {

    @Bean
    public MybatisPlusInterceptor paginationInterceptor(){
        //新建MybatisPlus拦截器
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //新建分页拦截器paginationInnerInterceptor
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        //设置分页拦截器的一些属性
        paginationInnerInterceptor.setOverflow(true);
        paginationInnerInterceptor.setMaxLimit(100L);
        //把分页拦截器添加到MybatisPlus拦截器中
        mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
        //添加组件,大功告成!
        return mybatisPlusInterceptor;
    }
}
  • 这一步的主要目标是往Spring容器中mybatisPlus的分页插件拦截器

UserMapper接口

@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {

}
  • 实体类Mapper需要继承MybatisPlus的BaseMapper<T>类,其中的范性为该目标实体User。该写法为MyBatisPlus的标准写法,继承BaseMapper<T>后,可以给予<T>CRUD功能

Service层

  • UserService接口:

    public interface UserService extends IService<User> {
    }
    
    • 直接实现MyBatisPlus中的顶级接口IService<T>,其中的范型为目标实体
  • UserServiceImplUserService的真正实现类

    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    }
    
    • 首先,肯定要实现其对应的接口:implements Userservice

    • 其次需要继承ServiceImpl,该类为mybatisPlus中的IService<T>实现类,需要指定两个范性 <UserMapper, User>。显而易见,第一个范性为User对应的Mybatis需要指定的的Mapper类,第二个范性为目标实体类User

Controller层

@Controller
public class TableController {		
    //自动注入userService
    @Autowired
    UserService userService;
  
    @GetMapping("/table")
    public String tableController(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model){			
        //新建分页构造函数Page<T> T为目标实体类
        Page<User> userPage = new Page<User>(pn, 2);
        //result为分页查询结果
        Page<User> result = userService.page(userPage);
        model.addAttribute("result",result);
        return "table";
    }
}

Controller层相对复杂,主要是以下几个方面:

  • 控制器参数部分 @RequestParam(value = "pn",defaultValue = "1") Integer pn :前端传入一个需要跳转到的页面值pn,默认为第一页

  • Page<User> userPage = new Page<User>(pn, 2):new一个分页构造函数类Page的实体userPage

    这个Page对象是所有分页功能最重要的一个类,强烈建议看看源码!!分页查询的结果与分页信息会全部包装在这个类中返回!!!

    其构造函数源代码如下:

    /**
     * 分页构造函数
     *
     * @param current 当前页
     * @param size    每页显示条数
     */
    public Page(long current, long size) {
        this(current, size, 0);
    }
    

    即:传入你想指定的当前页值,和每页显示条数(好像是废话。。。)

  • Page<User> result = userService.page(userPage);:调用userService里面的page()方法,传入我们实例化好的userPage

    问题在这里userService没有定义任何方法,为什么会出现page()这个方法呢?

    这其实是userServiceImpl所继承的ServiceImpl<UserMapper, User>提供的方法

    而这里的Page类型的result返回值,里面会包括所有我们查询到的结果以及分页信息!!

  • model.addAttribute("result",result);没什么好说的,把这个result直接丢进Model,返回到前端处理

前端页面

前端使用了thymeleaf模版引擎,具体引入请参照官方文档

https://www.thymeleaf.org/

样式截取关键代码

首先是表单区域:

<tbody>
  <tr class="gradeX" th:each="user,stat:${result.records}">
    <td th:text="${stat.count}"></td>
    <td th:text="${user.id}"></td>
    <td th:text="${user.name}"></td>
    <td th:text="${user.age}"></td>
    <td th:text="${user.email}"></td>
  </tr>
</tbody>
  • th:each="user,stat:${result.records}":这里的result为之前controller放进model的Page<User> result对象,我们可以通过result.records获得我们查询返回的结果,并且命名每一个结果为user进行循环输出,其中stat为每个user的状态(提供自thymeleaf模版),可以得到许多额外信息

显示分页信息区域

<div class="row-fluid">
  <div class="span6">
    <div class="dataTables_info" id="dynamic-table_info">
      当前第 [[${result.current}]]
      总计 [[${result.pages}]] 页
      共[[${result.total}]] 条记录</div>
  </div>
</div>
  • 该区域动态显示其数据页面信息,如前文所解释,resultPage<User>对象,里面包含了所有分页相关的信息,我们可以调用其属性动态显示当前页码,页码总数,记录总数等信息!!
  • [[${}]]该写法为thyemleaf取值的行内写法,具体请见相关文档

页码按钮栏区域

<ul>
  <li th:class="${result.current == 1}? 'prev disabled':'prve'" class="prev disabled">
    <a th:href="@{/table(pn=${result.current}-1)}">← Previous</a></li>
  <li th:class="${num == result.current} ?'active':''"
      th:each="num:${#numbers.sequence(1,result.pages)}">
    <a th:href="@{/table(pn=${num})}">[[${num}]]</a>
  </li>
  <li class="next" th:class="${result.current == result.pages?'disabled next':'next'}">
    <a th:href="@{/table(pn=${result.current}+1)}">Next → </a></li>
</ul>

该区域看似比较复杂,实则结构十分简单,简化如下:

<ul>
  <li><a href="#">← Previous</a></li>
  <li><a href="#">动态生成的页面数</a></li>
  <li><a href="#">Next →</a></li>
</ul>

其中,Previous按钮与Next按钮的实现大同小异,以Previous按钮举例:

<li th:class="${result.current == 1}? 'prev disabled':'prve'" class="prev disabled">
  <a th:href="@{/table(pn=${result.current}-1)}">← Previous</a></li>
  • 首先是<li>标签内:th:class是thymeleaf模版引擎语法,可以修改class属性。
    ${result.current == 1}? 'prev disabled':'prve'是一个三元运算符,由显示分页信息区域 模块的解释可知,result是一个Page<User>对象,可以得到分页信息,如果当当前页面为1时,给<li>标签添加disabled样式禁用其选择。否则允许选择

  • <a>标签内:th:href语法同理可以修改a href里面的属性,@{/table(pn=${result.current}-1)}表示该<a>标签链接指向/table请求而(pn=${result.current}-1) 为thymeleaf语句,即传入一个参数pn,其值为result.current -1,即当前页数-1,传回给Controller。(见Controller章节写法)

动态生成页数区域:

<li th:class="${num == result.current} ?'active':''"
    th:each="num:${#numbers.sequence(1,result.pages)}">
  <a th:href="@{/table(pn=${num})}">[[${num}]]</a>
</li>
  • <li>标签中${num == result.current} ?'active':''"三元运算符给予当前页被选中的样式,如上同理,不多解释。th:each="num:${#numbers.sequence(1,result.pages)}"表示遍历生成${#numbers.sequence(1,result.pages)}这些数字,每个数字叫做num。而#numbers.sequence(from,to)为themeleaf内置函数,可以生成从fromto的序列。在此例中表示生成1到result.pages的序列
  • <a>标签中的原理与上类似,不同点在于赋值给pn对应的页面值

至此大功告成!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值