为了演示分页效果,首先需要导入大量数据才能体现分页功能的作用;所以,第一步需要导入数据,实验所需的SQL脚本内容较多,这里就不一一展示,其导入后效果如下图。
sql脚本下载地址为:sql下载地址
分页功能的交互流程是前端将所需页码page和每页展示条数limit两个参数传输给后端,而后端在接受到分页请求后会对分页参数进行处理并计算出需要查询的是从第几条数据到第几条数据,然后利用MySQL的limit关键字去查询对应的记录并返回给前端。
在entity包下创建AdminUser,java。在Dao包下创建AdminUserDao.java。
AdminUser.java
@Data
public class AdminUser implements Serializable {
private Long id;
private String userName;
private String password;
private String userToken;
private int isDeleted;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date createTime;
}
AdminUserDao.java
@Mapper
public interface AdminUserDao {
// 查询用户列表
List<AdminUser> findAdminUsers(Map param);
// 查询用户总数
int getTotalAdminUser(Map param);
}
在resources/mapper目录下新建Mapper接口的映射文件AdminUserDao.xml,之后进行映射文件的编写。
AdminUserDao.xml
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pikacho.springbootbbs.dao.AdminUserDao">
<resultMap type="com.pikacho.springbootbbs.entity.AdminUser" id="AdminUserResult">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="password" column="password_md5" jdbcType="VARCHAR"/>
<result property="userToken" column="user_token" jdbcType="VARCHAR"/>
<result property="isDeleted" column="is_deleted" jdbcType="TINYINT"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
resultMap>
<select id="findAdminUsers" parameterType="Map" resultMap="AdminUserResult">
select id, user_name, create_time from tb_admin_user
where is_deleted = 0
order by id desc
<if test="start != null and limit != null">
limit #{start}, #{limit}
if>
select>
<select id="getTotalAdminUser" parameterType="Map" resultType="int">
select count(*) from tb_admin_user
where is_delete = 0
select>
mapper>
分页结果需要使用一个对象返回给前端,所以这里需要一个包装类对结果进行包装。新建一个utils包,然后在该包下新建PageResult.java。
PageResult.java
@Data
public class PageResult implements Serializable {
// 总记录数
private int totalCount;
// 每页记录数
private int pageSize;
// 总页数
private int totalPage;
// 当前页数
private int currPage;
// 列表数据
private List<?> list;
// 分页结果
public PageResult(List<?> list, int totalCount, int pageSize, int currPage){
this.list = list;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currPage = currPage;
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
}
}
同样,前端传过来的数据与后端中书写sql语句需要的数据不一致,所以需要一个包装类进行包装,在utils包下新建PageUtil.java。
PageUtil.java
@Data
public class PageUtil extends LinkedHashMap<String, Object> {
// 当前页码
private int page;
// 每页条数
private int limit;
public PageUtil(Map<String, Object> params){
this.putAll(params);
// 分页参数
this.page = Integer.parseInt(params.get("page").toString());
this.limit = Integer.parseInt(params.get("limit").toString());
this.put("start", (page -1) * limit);
this.put("page", page);
this.put("limit", limit);
}
}
创建service包并在该包下创建AdminUserService.java以及实现类。
public interface AdminUserService {
// 分页功能
PageResult getAdminUserPage(PageUtil pageUtil);
}
@Service("adminUserService")
public class AdminUserServiceImpl implements AdminUserService {
@Autowired
private AdminUserDao adminUserDao;
@Override
public PageResult getAdminUserPage(PageUtil pageUtil){
List<AdminUser> users = adminUserDao.findAdminUsers(pageUtil);
int total = adminUserDao.getTotalAdminUser(pageUtil);
PageResult pageResult = new PageResult(users, total, pageUtil.getLimit(), pageUtil.getPage());
return pageResult;
}
}
AdminUserControler.java
@RestController
@RequestMapping("/fenye")
public class AdminUserController {
@Autowired
private AdminUserService adminUserService;
@RequestMapping(value = "/list", method = RequestMethod.GET)
public PageResult list(@RequestParam Map<String, Object> params) {
if (StringUtils.isEmpty(params.get("page")) || StringUtils.isEmpty(params.get("limit"))) {
return null;
}
//查询列表数据
PageUtil pageUtil = new PageUtil(params);
return adminUserService.getAdminUserPage(pageUtil);
}
}
http://localhost:8080/bbs/fenye/list?page=1&limit=10
http://localhost:8080/bbs/fenye/list?page=3&limit=10
可以看到,基本完成了分页功能;实际上,可以使用插件完成该功能,并不需要自己来实现这个功能。
这里有一点需要指出,使用该依赖需要注意依赖版本与Spring Boot版本的兼容性,不然会出现循环依赖的错误。这里使用的是Spring Boot2.7.2与pagehelper1.4.1。
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>1.4.1version>
dependency>
这里对该属性进行基础的配置,如果想要详细配置,可以查看其文档。
#pagehelper分页插件配置
pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
/**
* 使用插件分页
*/
@RequestMapping(value = "/list1", method = RequestMethod.GET)
public PageInfo<AdminUser> list1(@RequestParam Integer cur, @RequestParam Integer size){
PageHelper.startPage(cur, size);
List<AdminUser> list = adminUserDao.findAdminUsers1(cur, size);
PageInfo<AdminUser> pageInfo = new PageInfo<>(list);
return pageInfo;
}
只需要给定当前页和每页数量,该插件就会帮我们完成分页,并且包装好返回给前端。
<select id="findAdminUsers1" parameterType="Integer" resultMap="AdminUserResult">
select id, user_name, create_time from tb_admin_user
where is_deleted = 0
order by id desc
select>
可以看到使用分页插件完成分页功能要比自己实现简便不少,所以会造轮子和使用轮子都是很重要的。
demo源码下载地址:demo源码下载