spring boot+mybatis+thymeleaf+pagehelper分页插件实现分页功能

前言

继上次写了springboot+mybatis+ajax实现注册功能后,这几天花了时间写了注册功能,这个功能不是用ajax异步实现的,而是控制层直接跳转页面,然后利用thymeleaf在前端展示, 这里我还是推荐用ajax,因为ajax实现的话,前端的一些效果不会被局限到。 因为我之前实现注册功能中很详细的写了用spring boot的整个流程,所以这一篇主要写pagehelper分页插件的使用还有前端thymeleaf要怎么处理等等一些细节,这里的一些配置都在注册功能那一篇的基础上加。

正文

业务场景

前端commons.html页面中标题栏有“专题”和“分类”(因为两者实现是一样的,所以我只写“专题”的实现),点击其下的标签,。
在这里插入图片描述
跳转到archive.html页面,该页面展示出分页的内容。
在这里插入图片描述
在这里插入图片描述

后端

pom.xml

这里说明一下,有的教程是用pagehelper的,两种其实本质都是一样的,写法配置可能不同,具体看mybatis使用pagehelper-spring-boot-starter与pagehelper的区别

<!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

application.yml

或者自己配置到application.properties中也一样。

#分页设置
pagehelper:
  reasonable: true    # reasonable:启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页。
  support-methods-arguments: true
  params: count=countSql
  helper-dialect: mysql   #数据库类型

额外话题,这里修改一下application.yml原来数据库的配置,因为我的数据库是放在centos虚拟机里面的,一开始查出来的时间相差8个小时,后面查了一下是我的虚拟机时区不是中国的(改虚拟机时区教程:mybatis查询mysql数据库出来的时间少8小时解决办法),后面改了时区后又相差14小时,后面查了说是mysql的时区不正确。所以下面的url加上了时区设定。

#因“CST”时区协商误解导致时间差了14或13小时 https://www.cnblogs.com/todayforever/p/11997424.html 与数据库连接时,定义时区,避免mybatis框架从mysql获取时区。在连接上加上 serverTimezone=GMT%2B8
    url: jdbc:mysql://192.168.0.113:3306/videoweb?serverTimezone=GMT%2B8   #路径,这里用虚拟机的mysql

实体类video.java和User.java----映射VideoMapper.xml----VideoMapper接口

因为我这是个视频网站,数据库设计如下,所以需要查出视频的相关信息以及视频发布者的名字,所以要多表查询,mapper看起来可能复杂点。这里涉及mybatis多表关系就不细说了,具体自己百度,速成的话我推荐how2j.cn中mybatis的教程,里面就有多表关系快速使用教程。另外要说明一下,mapper.xml查询到的属性必须和实体类中的属性相对应,到时候前端才能取到。 举个例子我一开始video表是没有countcomments、countlikes、countlooks这三项的,实体类Video中也没有对应的属性,而是用mysql中count()函数进行复杂查询查出相关数据,后面发现前端没办法取到值,因为尽管查询语句查到了,但是mybatis不知道你的数据要存到实体类中的哪个值。
数据库
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.Date;
import java.util.List;

public class Video {
    private Integer vid;        //视频id
    private String vname;       //视频名
    private String vtag;        //视频标签
//    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")  //https://www.cnblogs.com/huanggy/p/9471827.html
//    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date date;          //上传日期
    private String introduce;       //视频介绍
    private String url;             //视频路径
    private String imageurl;        //视频封面路径
    private Byte state;         //视频状态,通过/审核
    private String special;     //专题
    private Integer countcomments;      //评论数
    private Integer countlikes;         //喜欢数
    private Integer countlooks;         //观看数

    //    多对一,多个视频由一个用户上传
    private User user;

    //    一对多,一个视频有多个用户喜欢的记录
    List<LikesKey> likesKeys;

    //    一对多,一个视频多条评论
    List<Comments> comments;

    省略get和set方法....
}
import java.util.Date;

public class User {         //用户
    private Integer uid;                //用户id
    private String username;            //用户名
    private String password;        //用户密码
    private String email;           //用户邮箱
    private Date birthday;     //用户出生日期

    省略get和set方法....
}
<?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.liaojiexin.videoweb.mapper.VideoMapper" >
  <resultMap id="BaseResultMap" type="com.liaojiexin.videoweb.entity.Video" >
    <id column="vid" property="vid" jdbcType="INTEGER" />
    <result column="vname" property="vname" jdbcType="VARCHAR" />
    <result column="vtag" property="vtag" jdbcType="CHAR" />
    <result column="date" property="date" jdbcType="TIMESTAMP" />
<!--    <result column="uid" property="uid" jdbcType="INTEGER" />-->
    <result column="introduce" property="introduce" jdbcType="VARCHAR" />
    <result column="url" property="url" jdbcType="VARCHAR" />
    <result column="imageurl" property="imageurl" jdbcType="VARCHAR" />
    <result column="state" property="state" jdbcType="TINYINT" />
    <result column="special" property="special" jdbcType="VARCHAR" />
    <result column="countcomments" property="countcomments" jdbcType="INTEGER" />
    <result column="countlikes" property="countlikes" jdbcType="INTEGER" />
    <result column="countlooks" property="countlooks" jdbcType="INTEGER" />
    <!-- 多对一的关系 -->
    <!-- column:指的是数据库队列名,property: 指的是属性名称, javaType:指的是属性的类型 -->
    <association property="user" javaType="com.liaojiexin.videoweb.entity.User">
      <id column="uid" property="uid" jdbcType="INTEGER" />
      <result column="username" property="username" jdbcType="VARCHAR" />
      <result column="password" property="password" jdbcType="VARCHAR" />
      <result column="email" property="email" jdbcType="VARCHAR" />
      <result column="birthday" property="birthday" jdbcType="DATE" />
    </association>
    <!-- 一对多的关系 -->
    <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
    <collection property="likesKeys" ofType="com.liaojiexin.videoweb.entity.LikesKey">
      <id column="uid" property="uid" jdbcType="INTEGER" />
      <id column="vid" property="vid" jdbcType="INTEGER" />
    </collection>
    <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
    <collection property="comments" ofType="com.liaojiexin.videoweb.entity.Comments">
      <id column="commenttime" property="commenttime" jdbcType="TIMESTAMP" />
      <id column="uid" property="uid" jdbcType="INTEGER" />
      <id column="vid" property="vid" jdbcType="INTEGER" />
      <result column="comment" property="comment" jdbcType="VARCHAR" />
    </collection>
  </resultMap>
  <sql id="Base_Column_List" >
    vid, vname, vtag, date, uid, introduce, url, imageurl, state, special, countcomments, 
    countlikes, countlooks
  </sql>
  <!-- 首页查询专题,视频详细信息和用户名,评论数,喜欢数,观看数 -->
  <select id="specialSelect" resultMap="BaseResultMap">
    select video.*,username
    from video,user
    where special=#{special,jdbcType=VARCHAR} and video.uid=user.uid and video.state=1
    order by video.date DESC
  </select>
</mapper>
import java.util.List;

@Repository
@Mapper
public interface VideoMapper {
    //首页查询专题,视频详细信息和用户名,评论数,喜欢数,观看数
    List specialSelect(@Param("special") String special);
}

服务层ArchiveShowServiceImpl实现类和ArchiveShowService接口

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liaojiexin.videoweb.mapper.VideoMapper;
import com.liaojiexin.videoweb.service.ArchiveShowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ArchiveShowServiceImpl implements ArchiveShowService {     //处理视频浏览页的服务

    @Autowired      //注入DAO
    private VideoMapper videoMapper;
    
    @Override   //该标签会检查检查重写方法的正确性
    public PageInfo specialSelect(String special,int pageNum, int pageSize){      //首页专题页显示,开启分页插件,放在查询语句上面 帮助生成分页语句
        PageHelper.startPage(pageNum, pageSize);//底层实现原理采用改写语句  将下面的方法中的sql语句获取到然后做个拼接 limit
        try {
        List specialselect=videoMapper.specialSelect(special);      //全部的视频信息
        // 封装分页之后的数据  返回给客户端展示  PageInfo做了一些封装 作为一个类
        PageInfo pageInfoSpecialSelect = new PageInfo(specialselect);
        //所有分页属性都可以从pageInfoDemo拿到
        return pageInfoSpecialSelect;
        }finally {
            PageHelper.clearPage(); //清理 ThreadLocal 存储的分页参数,保证线程安全
        }
    }
}
import com.github.pagehelper.PageInfo;

public interface ArchiveShowService {     //视频浏览页的服务
    PageInfo specialSelect(String special,int pageNum, int pageSize);     //首页专题页显示
}

控制层SpecialController

在这里插入图片描述
在这里插入图片描述
这里把分页栏的数字变动处理也交由控制层处理。本来想写前端js来实现的,但是发现前端点击按钮后跳转请求页面刷新所以没法实现(所以说还是有ajax来实现比较好,这里如果用bootstrap自带的效果也能展现出来)

import com.github.pagehelper.PageInfo;
import com.liaojiexin.videoweb.service.ArchiveShowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;

@Controller
public class SpecialController {        //专题控制层
    @Autowired
    private ArchiveShowService archiveShowService;

    @GetMapping(value = "/specialSelect/{special}")
    private String specialShow(@PathVariable("special") String special,
                                   @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,   //在参数里接受当前是第几页 pageNum,以及每页显示多少条数据 pageSize.默认值分别是1和10
                                   @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
                                   Model model)
    {
        PageInfo specialSelect=archiveShowService.specialSelect(special,pageNum,pageSize);
        model.addAttribute("pages",specialSelect);

//        处理前端分页栏数字变动问题
        List pagenums = new ArrayList();
        if(pageNum>3&&specialSelect.getPages()>5)  //当前端页数超过第三页时,并且查询到的总页数大于5
        {
            if(pageNum>=specialSelect.getPages()-2){ //specialSelect.getPages()总页数,如果前端页数大于等于总页数-2时
                pagenums.add(specialSelect.getPages()-4);
                pagenums.add(specialSelect.getPages()-3);
                pagenums.add(specialSelect.getPages()-2);
                pagenums.add(specialSelect.getPages()-1);
                pagenums.add(specialSelect.getPages());
            }
            else{
                pagenums.add(pageNum-2);
                pagenums.add(pageNum-1);
                pagenums.add(pageNum);
                pagenums.add(pageNum+1);
                pagenums.add(pageNum+2);
            }
        }else{          //前端页数没超过第三页时
            if(specialSelect.getPages()<5) //如果总页数小于5
            {
                for(int i=0;i<specialSelect.getPages();i++)
                    pagenums.add(i+1);
            }else{
                pagenums.add("1");
                pagenums.add("2");
                pagenums.add("3");
                pagenums.add("4");
                pagenums.add("5");
            }
        }
        model.addAttribute("pagenums",pagenums);

		//跳到到personal.html页面,thymeleaf默认会拼串,classpath:/templates/xxx.html
        return "archive";       //这里不可以写redirect:/archive,前端页面获取不到model,https://www.wandouip.com/t5i350864/
    }
}

前端

这里前端模板用thymeleaf,还有bootstrap来实现样式。

commons.html

这里写专题的那部分,其他的省略,点击a标签连接后发出“/specialSelect/第四届NEW ERA青年电影季”的请求到控制层。

<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-play-circle-o"></i> 专题</a>
						<div class="dropdown-menu">
							<div class="dropdown-inner">
								<ul class="list-unstyled">
									<li><a th:href="@{/specialSelect/第四届NEW ERA青年电影季}">第四届NEW ERA青年电影季</a></li>
									<li><a th:href="@{/specialSelect/第91届奥斯卡入围动画短片大赏}">第91届奥斯卡入围动画短片大赏</a></li>
									<li><a th:href="@{/specialSelect/2019戛纳广告节必看广告合集}">2019戛纳广告节必看广告合集</a></li>
									<li><a th:href="@{/specialSelect/历届奥斯卡优秀短片合集}">历届奥斯卡优秀短片合集</a></li>
									<li><a th:href="@{/specialSelect/2019年V视频年度精选短片回顾}">2019年V视频年度精选短片回顾</a></li>
								</ul>
							</div> 
						</div>
					</li>

archive.html

控制层处理好数据后跳转到archive页面,然后用thymeleaf处理数据。
这里主要看两个模块,我在下面代码中也用分割线分割出来。
这里主要说thymeleaf中th:each的使用细节,我一开始看很多教程都没有细说,所以我尽管后端写好了,前端一直调用失败。
很多教程都是写th:each="page:${pages}",然后循环体内的标签属性写th:text="${page.xxx}"或者在标签内容写[[${page.xxx}]],这种写法都不太正确,具体应该看你们代码是怎么写的,比较正确的方法如下:
用IDEA编译器debug一下你的控制层,如下图所示,你会发现正确的写法应该是th:each="page:${pages.list}"
在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="">
    <meta name="author" content="">
	
    <title>浏览页</title>
	
    <!-- Bootstrap Core CSS -->
    <link rel="stylesheet" href="/css/bootstrap.min.css"  type="text/css">
	
	<!-- Custom CSS -->
    <link rel="stylesheet" href="/css/style.css">
	
	<!-- Owl Carousel Assets -->
    <link href="/owl-carousel/owl.carousel.css" rel="stylesheet">
    <link href="/owl-carousel/owl.theme.css" rel="stylesheet">
	
	<!-- Custom Fonts -->
    <link rel="stylesheet" href="/font-awesome-4.4.0/css/font-awesome.min.css"  type="text/css">
	
	<!-- jQuery and Modernizr-->
	<script src="/js/jquery-2.1.1.js"></script>
	
	<!-- Core JavaScript Files -->  	 
    <script src="/js/bootstrap.min.js"></script>

	<script src="/js/archive.js"></script>

	<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="/js/html5shiv.js"></script>
        <script src="/js/respond.min.js"></script>
    <![endif]-->
</head>

<body>

	<header th:replace="commons :: commonHeader"></header>

	<!-- /Content -->
	<div id="page-content" class="archive-page">
		<div class="container">
			<div class="row">

<!---------------------------------分页视频详细模块---------------------------------------->
				<div id="main-content" class="col-md-6" style="border-bottom:0px;border-top: 0px;padding-bottom: 0px" th:each="page:${pages.list}">
					<article style="height: 257px">
						<a href="#"><h4 class="vid-name" style="overflow: hidden;text-overflow:ellipsis;white-space: nowrap;">[[${page.vname}]]</h4></a>
						<div class="info">
							<h5>上传人:<a>[[${page.user.username}]]</a></h5>
							<!--    ↓↓↓  格式化时间日期    -->
							<span><i class="fa fa-calendar"></i>[[${#dates.format(page.date,"yyyy-MM-dd HH:mm:ss")}]]</span>
							<span><i class="fa fa-comment"></i> [[${page.countcomments}]] 评论</span>
							<span><i class="fa fa-heart"></i>[[${page.countlikes}]]</span>
							<span><i class="fa fa-eye"></i>[[${page.countlooks}]]</span>
							<ul class="list-inline"></ul>
						</div>
						<div class="wrap-vid">
							<div class="zoom-container">
								<div class="zoom-caption">
									<span>[[${page.vtag}]]</span>
									<a href="single.html">
										<i class="fa fa-play-circle-o fa-5x" style="color: #fff"></i>
									</a>
									<p style="font-size: 17px;overflow: hidden;text-overflow:ellipsis;white-space: nowrap;" >[[${page.vname}]]</p>
								</div>
								<img src="/images/9.jpg" />
							</div>
							<!-- p标签超出省略 http://www.bubuko.com/infodetail-2738912.html  -->
							<p style="font-size:18px;display: -webkit-box; word-break:break-all;-webkit-box-orient: vertical;-webkit-line-clamp: 6;text-overflow:ellipsis;overflow: hidden;text-indent:2em" th:text="${page.introduce}"></p>
						</div>
					</article>
					<br><div class="line" style="margin: 0"></div>
				</div>
<!------------------------------------------------------------------------------------->				
			</div>
			<div class="row">
				<div id="main-content2" class="col-md-12">

<!---------------------------------分页栏模块-------------------------------------->
					<span>相关记录视频[[${pages.total}]]条,共[[${pages.pages}]]页。</span>
					<center>
					<ul class="pagination">
						<li><a id="firstpage" th:href="${#httpServletRequest.getRequestURL()} +'?pageNum=1'">首页</a></li>
					</ul>
					<ul class="pagination">
						<li>
							<a th:if="${pages.pageNum} > '1'" id="previouspage" th:href="${#httpServletRequest.getRequestURL()}+'?pageNum='+${pages.prePage}" aria-label="Previous">
								<span aria-hidden="true">&laquo;</span>
							</a>
						</li>
					</ul>
                    <!--   当前页数 ,方便js调用 display:none;隐藏        -->
                    <span style="display:none;" id="pagenums">[[${pages.pageNum}]]</span>
					<ul class="pagination" th:each="pagenum:${pagenums}">
                    <!--	${#httpServletRequest.getRequestURL()}表示当前url,href中也可以不写,如下直接加参数		 -->
						<li><a th:class="'pagenum'+${pagenum}" th:href="'?pageNum='+${pagenum}">[[${pagenum}]]</a></li>
					</ul>
					<ul class="pagination">
						<li>
							<a th:if="${pages.pageNum} < ${pages.pages}" id="nextpage" th:href="${#httpServletRequest.getRequestURL()}+'?pageNum='+${pages.nextPage}" aria-label="Next">
								<span aria-hidden="true">&raquo;</span>
							</a>
						</li>
					</ul>
					<ul class="pagination">
						<li><a id="endpage" th:href="${#httpServletRequest.getRequestURL()}+'?pageNum='+${pages.pages}">末页</a></li>
					</ul>
					</center>

<!------------------------------------------------------------------------------------->
				</div>
			</div>
		</div>
	</div>

	<footer th:replace="commons :: commonFooter"></footer>
	
</body>
</html>

archive.js

这里主要是让分页栏显示对应页数按钮的样式

$(document).ready(function () {
    var pagenum='.pagenum'+$("#pagenums").text();
    $(pagenum).css({"background-color":"red","color":"white"});
});

展示js的效果差别
在这里插入图片描述
在这里插入图片描述

结语

以上就是实现分页功能的教程,里面还有很多细节性问题和知识可以值得你们去思考和学习(像虚拟机时区问题、查询时间格式化问题、p标签内容字数超出规定的长度变省略号…等一系列问题),具体可以看我代码的注释。如果有什么问题欢迎留言互相谈论。
参考:


业务问题扩展:我的项目里面有一个搜索功能,一开始我想要用同一个前端页面(即archive.html)来展示搜索结果,但是突然卡住了,因为我的搜索功能是一个form表单,发送请求到后端是不需要在路径中赋值的。如下代码

<form th:action="@{/checkSelect}" class="form-inline">
							<input class="form-control required" type="" name="vname" id="search-form" placeholder="请输入要搜索的视频名称" required/>
							<button class="btn" type="submit" style="color: black"><i class="fa fa-search"></i></button>
					</form>
@Controller
public class CheckController {        //搜索控制层
    @Autowired
    private ArchiveShowService archiveShowService;

    @GetMapping(value = "/checkSelect/{vname}")
    private String checkShow(@PathVariable("vname") String vname,
                               @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,   //在参数里接受当前是第几页 pageNum,以及每页显示多少条数据 pageSize.默认值分别是1和10
                               @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
                               Model model)
    {
    省略代码........
    }
 }

一开始我老是想在怎么把input的值赋值到url路径中,即:/checkSelect/xxx一样,但是form直接把input的值当成参数附在后面,即:/checkSelect?vame=xxx。这样的话,archive.html页面的分页栏就会报错,显示缺少vame参数。
想了各种方法,像js来赋值或者thymeleaf等等,弄了一晚上结果都不行,后面自己老老实实写了个新的前端页面来展示搜索效果,在修改这个这个新的页面分页栏路径时突然得到灵感。
我把控制层代码改成如下,把请求和参数vname改了,同时把vame赋值到model中,然后前端把分页栏的代码的路径改成如下来获取vame参数。

@Controller
public class CheckController {        //搜索控制层
    @Autowired
    private ArchiveShowService archiveShowService;

    @GetMapping(value = "/checkSelect")
    private String checkShow(@RequestParam("vname") String vname,
                               @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,   //在参数里接受当前是第几页 pageNum,以及每页显示多少条数据 pageSize.默认值分别是1和10
                               @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
                               Model model)
    {
        model.addAttribute("vname",vname);  //把vname传给分页栏
代码省略.........
	}
}
<div id="main-content2" class="col-md-12">
					<center>
					<ul class="pagination">
						<li><a id="firstpage" th:href="${#httpServletRequest.getRequestURL()} +'?pageNum=1&vname='+${vname} ">首页</a></li>
					</ul>
					<ul class="pagination">
						<li>
							<a th:if="${pages.pageNum} > '1'" id="previouspage" th:href="${#httpServletRequest.getRequestURL()}+'?pageNum='+${pages.prePage}+'&vname='+${vname} " aria-label="Previous">
								<span aria-hidden="true">&laquo;</span>
							</a>
						</li>
					</ul>
                    <!--   当前页数 ,方便js调用 display:none;隐藏        -->
                    <span style="display:none;" id="pagenums">[[${pages.pageNum}]]</span>
					<ul class="pagination" th:each="pagenum:${pagenums}">
                    <!--	${#httpServletRequest.getRequestURL()}表示当前url,href中也可以不写,如下直接加参数		 -->
						<li><a th:class="'pagenum'+${pagenum}" th:href="'?pageNum='+${pagenum}+'&vname='+${vname}">[[${pagenum}]]</a></li>
					</ul>
					<ul class="pagination">
						<li>
							<a th:if="${pages.pageNum} < ${pages.pages}" id="nextpage" th:href="${#httpServletRequest.getRequestURL()}+'?pageNum='+${pages.nextPage}+'&vname='+${vname}" aria-label="Next">
								<span aria-hidden="true">&raquo;</span>
							</a>
						</li>
					</ul>
					<ul class="pagination">
						<li><a id="endpage" th:href="${#httpServletRequest.getRequestURL()}+'?pageNum='+${pages.pages}+'&vname='+${vname}">末页</a></li>
					</ul>
					</center>
				</div>

这样的话,“专题”和“分类”没有vname参数的话,就会显示null,不会影响功能实现。
在这里插入图片描述
而搜索功能也能完美实现
在这里插入图片描述

Spring Boot + MyBatis + Thymeleaf项目中,实现分页功能通常需要以下几个步骤: 1. **添加依赖**: - 在`pom.xml`文件中添加ThymeleafSpring Web、MyBatis以及MyBatis Plus的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> ``` 2. **配置数据源**: 如果你的应用有多个数据源,配置对应的数据源。如果没有,只需配置默认数据源。 3. **创建Mapper接口**: 在Mapper接口中定义分页查询的方法,例如使用`Page<T>`接口,其中T是你需要返回的对象类型: ```java public interface UserMapper { Page<User> findAll(int pageNum, int pageSize); } ``` 4. **编写Service层**: 使用MyBatis Plus的动态SQL和PageHelper对Mapper方法进行封装,处理分页逻辑: ```java @Service public class UserService { private final UserMapper userMapper; public UserService(UserMapper userMapper) { this.userMapper = userMapper; } public PageResult<User> findAll(int pageNum, int pageSize) { PageOptions options = new PageOptions(); options.setPageSize(pageSize); options.setPageNum(pageNum); return userMapper.findAll(options); } } ``` 5. **创建Controller并注入Service**: 在Controller中接收前端传递的分页参数,并调用Service方法展示结果: ```java @RestController public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @GetMapping("/users") public String getUsers(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum, @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) { PageResult<User> pageResult = userService.findAll(pageNum, pageSize); // 将分页结果渲染到Thymeleaf模板 return "users", pageResult; } } ``` 6. **创建Thymeleaf视图**: 在resources/templates目录下创建一个名为`users.html`的Thymeleaf模板,用于显示分页数据: ```html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <body> <table> <!-- 显示数据 --> <tr th:each="user : ${users}"> <td th:text="${user.name}"></td> </tr> <!-- 分页导航 --> <div th:fragment="pagination"> <ul> <li th:classappend="${#lists.indexOf(pagination.current, pagination.page) == 0} ? 'active'" th:text="${pagination.first}"></li> <!-- 其他页码... --> </ul> </div> </table> <!-- 引入分页脚部 --> <script th:src="@{/static/js/pagination.js}" type="text/javascript"></script> </body> </html> ``` 7. **编写分页脚本(如JavaScript)**: 在静态资源目录`static/js`下的`pagination.js`中,根据从服务器获取的分页信息动态生成页码链接。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值