目录
- 分页主要逻辑,在3.7和3.8
- 1.准备工作
- 1.1 参考博客
- 1.2 项目结构
- 2. 数据库
- 3. 详细代码部分
- 3.1 pom依赖
- 3.2 application.yml
- 3.3 BookMapper.xml
- 3.4 BookMapper
- 3.5 BookService 和 BookServiceImpl
- 3.6 实体类entity book
- 3.7控制层 BookController
- 3.8 前端页面bookList.html
- 3.9 工具类
- 3.9.1 mybatis-plus 插入时间和更新时间字段自动填充工具
- 3.9.2 分页插件工具
- 4. 运行效果
分页主要逻辑,在3.7和3.8
1.准备工作
1.1 参考博客
Mybatis-Plus | Spring Boot+Mybatis-Plus+Thymeleaf+Bootstrap分页页查询(前后端都有)
主要参考了这篇博客。
1.2 项目结构
运行截图
2. 数据库
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '序号',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '书名',
`author` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '作者',
`publisher` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '出版社',
`amount` int(0) NULL DEFAULT NULL COMMENT '在库数量',
`version` int(0) NULL DEFAULT NULL COMMENT '版本',
`deleted` int(0) NULL DEFAULT NULL COMMENT '逻辑删',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`modify_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '图书' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of book
-- ----------------------------
INSERT INTO `book` VALUES (3, '《鲁迅文集》', '鲁迅', '广西出版社', 20, NULL, 0, '2022-12-24 14:30:23', '2022-12-24 14:30:23');
INSERT INTO `book` VALUES (4, '《边城》', '沈从文', '武汉出版社', 10, NULL, 0, '2022-12-24 14:50:43', '2022-12-24 14:50:43');
INSERT INTO `book` VALUES (5, '《人生》', '路遥', '北京十月文艺出版社', 11, NULL, 0, '2022-12-24 14:51:41', '2022-12-24 14:51:41');
INSERT INTO `book` VALUES (6, '《平凡的世界》', '路遥', '北京十月文艺出版社', 11, NULL, 0, '2022-12-24 14:52:14', '2022-12-24 14:52:14');
3. 详细代码部分
3.1 pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nndx</groupId>
<artifactId>its</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>its</name>
<description>Demo project for nndx ITS auto-opera</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 第三方分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.3</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!--mybatis-plus-generator 生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<!--velocity-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!--freemarker引擎模板-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.2 application.yml
server:
port: 8080
#设置开发环境
spring:
datasource:
username: root
password: xxxx
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/wm-demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
thymeleaf:
cache: false
encoding: UTF-8
mode: HTML5
prefix: classpath:/templates/
suffix: .html
#pagehelper分页配置
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
params: count=countsql
mybatis-plus:
#配置日志 log-impl:日志实现
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: isDelete # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
3.3 BookMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.book.mapper.BookMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.book.entity.Book">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="author" property="author" />
<result column="publisher" property="publisher" />
<result column="amount" property="amount" />
<result column="version" property="version" />
<result column="deleted" property="deleted" />
<result column="create_time" property="createTime" />
<result column="modify_time" property="modifyTime" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, name, author, publisher, amount, version, deleted, create_time, modify_time
</sql>
</mapper>
3.4 BookMapper
package com.book.mapper;
import com.book.entity.Book;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BookMapper extends BaseMapper<Book> {
}
3.5 BookService 和 BookServiceImpl
package com.book.service;
import com.book.entity.Book;
import com.baomidou.mybatisplus.extension.service.IService;
public interface BookService extends IService<Book> {
}
package com.book.service.impl;
import com.book.entity.Book;
import com.book.mapper.BookMapper;
import com.book.service.BookService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {
}
3.6 实体类entity book
package com.book.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(chain = true)
@TableName("book")
@ApiModel(value = "Book对象", description = "图书")
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("序号")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("书名")
@TableField("name")
private String name;
@ApiModelProperty("作者")
@TableField("author")
private String author;
@ApiModelProperty("出版社")
@TableField("publisher")
private String publisher;
@ApiModelProperty("在库数量")
@TableField("amount")
private Integer amount;
@ApiModelProperty("版本")
@TableField("version")
@Version
private Integer version;
@ApiModelProperty("逻辑删")
@TableField("deleted")
@TableLogic
private Integer deleted;
@ApiModelProperty("创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@ApiModelProperty("更新时间")
@TableField(value = "modify_time", fill = FieldFill.INSERT_UPDATE)
private Date modifyTime;
}
3.7控制层 BookController
package com.book.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.book.entity.Book;
import com.book.mapper.BookMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Controller
@RequestMapping("/book")
public class BookController {
//首页
@RequestMapping("/index")
public String toIndexPage(Model model){
return "index";
}
//回到登录页
@RequestMapping("/toLogion")
public String toLogion(Model model){
return "login";
}
@Autowired
private BookMapper bookMapper;
//分页查询用户数据
@RequestMapping("/selectPage")
public String userList(Model model,
@RequestParam(required = false,defaultValue="1",value="pageNum")Integer pageNum,
@RequestParam(defaultValue="3",value="pageSize")Integer pageSize){
//为了程序的严谨性,判断非空:
//设置默认当前页
if(pageNum==null || pageNum<=0){
pageNum = 1;
}
//设置默认每页显示的数据数
if(pageSize == null){
pageSize = 1;
}
System.out.println("当前页是:"+pageNum+"显示条数是:"+pageSize);
//1.引入分页插件,pageNum是第几页,pageSize是每页显示多少条,默认查询总数count
PageHelper.startPage(pageNum,pageSize);
//2.紧跟的查询就是一个分页查询-必须紧跟.后面的其他查询不会被分页,除非再次调用PageHelper.startPage
try {
QueryWrapper<Book> wrapper = new QueryWrapper();
List<Book> bookList = bookMapper.selectList(wrapper);
System.out.println("分页数据:"+bookList);
//3.使用PageInfo包装查询后的结果,5是连续显示的条数,结果list类型是Page<E>
PageInfo<Book> pageInfo = new PageInfo<Book>(bookList,pageSize);
//4.使用model传参数回前端
model.addAttribute("pageInfo",pageInfo);
model.addAttribute("bookList",bookList);
//model.addAttribute("username","测试");
}finally {
//清理 ThreadLocal 存储的分页参数,保证线程安全
PageHelper.clearPage();
}
return "bookList";
}
}
3.8 前端页面bookList.html
<!DOCTYPE html>
<!--xmlns:th="http://www.thymeleaf.org"用于引入Thymeleaf模板引擎-->
<!--th标签是Thymeleaf模板提供的,但使用这种Thymeleaf模板页面不是一个标准的Html5页面了-->
<!--如果想使用Thymeleaf进行纯html5开发,要使用data-th-*替代th:*,替代后不需要引入模板引擎,但是没有快捷提示,所以不推荐-->
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro=“http://www.thymeleaf.org/thymeleaf-extras-shiro”>
<head>
<meta charset="UTF-8">
<title>图书管理 分页插件demo测试</title>
<!-- bilibili 小电视图标 -->
<!-- <link rel="shortcut icon" href="https://www.bilibili.com/favicon.ico?v=1"> -->
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
<link rel="stylesheet" th:href="@{/bootstrap461/css/bootstrap.css}">
</head>
<body>
<div class="container" id="app">
<div class="row clearfix">
<nav class="nav nav-tabs my-5">
<li class="nav-item"><a class="nav-link" href="/book/index">主页</a></li>
<li class="nav-item"><a class="nav-link active" href="/book/selectPage">图书管理</a></li>
<li class="nav-item"><a class="nav-link" href="/book/selectPage">page2</a></li>
<li class="nav-item"><a class="nav-link" href="/book/selectPage">page3</a></li>
<li class="nav-item"><a class="nav-link" href="/book/toLogion">登录</a></li>
</nav>
<div class="col-md-12 column my-1">
<table class="table">
<thead>
<tr>
<th>序号</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th>在库数量</th>
<th>创建时间</th>
</tr>
</thead>
<tbody>
<tr th:each="aBook,infoStat : ${bookList}">
<th th:text="${infoStat.count}"></th>
<td th:text="${aBook.name}"></td>
<td th:text="${aBook.author}"></td>
<td th:text="${aBook.publisher}"></td>
<td th:text="${aBook.amount}"></td>
<!-- 格式化后台传来的时间 -->
<td th:text="${#dates.format(aBook.createTime,'yyyy-MM-dd HH:mm:ss')}"></td>
</tr>
</tbody>
</table>
<!--显示分页信息部分代码-->
<div class="">
<div class="col-md-6">
<strong>当前第 [[${pageInfo.pageNum}]]页,共 [[${pageInfo.pages}]] 页.一共 [[${pageInfo.total}]] 条记录
</strong>
</div>
<div class="btn-group mr-2">
<ul class="pagination pull-right no-margin">
<li th:if="${pageInfo.hasPreviousPage}" class="btn bg-light text-dark">
<a th:href="'/book/selectPage?pageNum=1'">首页</a>
</li>
<li class="prev btn bg-light text-dark" th:if="${pageInfo.hasPreviousPage}">
<a th:href="'/book/selectPage?pageNum='+${pageInfo.prePage}">
<< </a>
</li>
<li th:each="nav:${pageInfo.navigatepageNums}" class="btn bg-light text-dark">
<a th:href="'/book/selectPage?pageNum='+${nav}" th:text="${nav}"
th:if="${nav != pageInfo.pageNum}"></a>
<span style="font-weight: bold;" th:if="${nav == pageInfo.pageNum}"
th:text="${nav}"></span>
</li>
<li class="next btn bg-light text-dark" th:if="${pageInfo.hasNextPage}">
<a th:href="'/book/selectPage?pageNum='+${pageInfo.nextPage}">
>>
</a>
</li>
<li class="btn bg-light text-dark">
<a th:href="'/book/selectPage?pageNum='+${pageInfo.pages}">尾页</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
3.9 工具类
3.9.1 mybatis-plus 插入时间和更新时间字段自动填充工具
package com.book.util;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
//mp的自动填充时间处理
@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("modifyTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
3.9.2 分页插件工具
package com.book.util;
import java.util.List;
// 分页工具类
public class PageUtil<T> {
// 对象记录结果集
private List<T> list;
// 总记录数
private int total = 0;
// 每页显示记录数
private int limit = 20;
// 总页数
private int pages = 1;
// 当前页
private int pageNumber = 1;
// 是否为第一页
private boolean isFirstPage = false;
// 是否为最后一页
private boolean isLastPage = false;
// 是否有前一页
private boolean hasPreviousPage = false;
// 是否有下一页
private boolean hasNextPage = false;
// 导航页码数
private int navigatePages = 8;
// 所有导航页号
private int[] navigatePageNumbers;
// 尾页
private int lastPage = 0 ;
// 首页
private int firstPage = 1 ;
// 上一页
private int prePage = 0;
// 下一页
private int nextPage = 0;
public PageUtil(int pageNumber, int limit, List<T> list) {
init(list, pageNumber, limit);
}
private void init(List<T> list, int pageNumber, int limit){
//设置基本参数
this.list = list;
this.total = list.size();
this.limit = limit;
this.pages = (this.total-1)/this.limit+1;
this.lastPage = pages;
this.firstPage = 1;
this.prePage = pageNumber-1;
this.nextPage = pageNumber+1;
//根据输入可能错误的当前号码进行自动纠正
if(pageNumber<1){
this.pageNumber=1;
}else if(pageNumber>this.pages){
this.pageNumber=this.pages;
}else{
this.pageNumber=pageNumber;
}
//基本参数设定之后进行导航页面的计算
calcNavigatePageNumbers();
//以及页面边界的判定
judgePageBoudary();
}
/**
* 计算导航页
*/
private void calcNavigatePageNumbers(){
//当总页数小于或等于导航页码数时
if(pages<=navigatePages){
navigatePageNumbers=new int[pages];
for(int i=0;i<pages;i++){
navigatePageNumbers[i]=i+1;
}
}else{ //当总页数大于导航页码数时
navigatePageNumbers=new int[navigatePages];
int startNum=pageNumber-navigatePages/2;
int endNum=pageNumber+navigatePages/2;
if(startNum<1){
startNum=1;
//(最前navPageCount页
for(int i=0;i<navigatePages;i++){
navigatePageNumbers[i]=startNum++;
}
}else if(endNum>pages){
endNum=pages;
//最后navPageCount页
for(int i=navigatePages-1;i>=0;i--){
navigatePageNumbers[i]=endNum--;
}
}else{
//所有中间页
for(int i=0;i<navigatePages;i++){
navigatePageNumbers[i]=startNum++;
}
}
}
}
/**
* 判定页面边界
*/
private void judgePageBoudary(){
isFirstPage = pageNumber == 1;
isLastPage = pageNumber == pages && pageNumber!=1;
hasPreviousPage = pageNumber!=1;
hasNextPage = pageNumber!=pages;
}
/**
* 得到当前页的内容
* @return {List}
*/
public List<T> getList() {
int endIndex = total;
if(pageNumber*limit <= total){
endIndex = pageNumber*limit;
}
List<T> pagelist = list.subList((pageNumber-1)*limit, endIndex);
return pagelist;
}
public int getLastPage() {
return lastPage;
}
public void setLastPage(int lastPage) {
this.lastPage = lastPage;
}
public int getFirstPage() {
return firstPage;
}
public void setFirstPage(int firstPage) {
this.firstPage = firstPage;
}
public int getPrePage() {
return prePage;
}
public void setPrePage(int prePage) {
this.prePage = prePage;
}
public int getNextPage() {
return nextPage;
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
/**
* 得到记录总数
* @return {int}
*/
public int getTotal() {
return total;
}
/**
* 得到每页显示多少条记录
* @return {int}
*/
public int getLimit() {
return limit;
}
/**
* 得到页面总数
* @return {int}
*/
public int getPages() {
return pages;
}
/**
* 得到当前页号
* @return {int}
*/
public int getPageNumber() {
return pageNumber;
}
/**
* 得到所有导航页号
* @return {int[]}
*/
public int[] getNavigatePageNumbers() {
return navigatePageNumbers;
}
public boolean isFirstPage() {
return isFirstPage;
}
public boolean isLastPage() {
return isLastPage;
}
public boolean hasPreviousPage() {
return hasPreviousPage;
}
public boolean hasNextPage() {
return hasNextPage;
}
}
4. 运行效果