为简化分页功能,设计了一个分页的JSP标签,只需要在页面使用分页标签,就可以完成所有页面的分页功能。

1. 项目结构和数据库设计

(1) 项目结构:

(2) 数据库设计

2. PageModel.java和PagerTag.java
(1) PageModel.java

/**
* 分页实体
*/
public class PageModel { // 默认每页4条数据
public static int PAGE_DEFAULT_SIZE = 4; /** 分页总数据条数 */
private int recordCount;
/** 当前页面 */
private int pageIndex ;
/** 每页分多少条数据 */
private int pageSize = PAGE_DEFAULT_SIZE = 4; /** 总页数 */
private int totalSize; public int getRecordCount() {
this.recordCount = this.recordCount <= 0 ? 0:this.recordCount;
return recordCount;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public int getPageIndex() {
this.pageIndex = this.pageIndex <= 0?1:this.pageIndex;
/** 判断当前页面是否超过了总页数:如果超过了默认给最后一页作为当前页 */
this.pageIndex = this.pageIndex>=this.getTotalSize()?this.getTotalSize():this.pageIndex; return pageIndex;
}
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public int getPageSize() {
this.pageSize = this.pageSize <= PAGE_DEFAULT_SIZE?PAGE_DEFAULT_SIZE:this.pageSize;
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
} public int getTotalSize() {
if(this.getRecordCount() <=0){
totalSize = 0 ;
}else{
totalSize = (this.getRecordCount() -1)/this.getPageSize() + 1;
}
return totalSize;
} public int getFirstLimitParam(){
return (this.getPageIndex()-1)*this.getPageSize() ;
} }

(2) PagerTag.java

package com.game.util;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport; /**
* 分页标签
*/
public class PagerTag extends SimpleTagSupport {
/** 定义请求URL中的占位符常量 */
private static final String TAG = "{0}"; /** 当前页码 */
private int pageIndex;
/** 每页显示的数量 */
private int pageSize;
/** 总记录条数 */
private int recordCount;
/** 请求URL page.action?pageIndex={0}*/
private String submitUrl;
/** 样式 */
private String style = "sabrosus"; /** 定义总页数 */
private int totalPage = 0; /** 在页面上引用自定义标签就会触发一个标签处理类 */
@Override
public void doTag() throws JspException, IOException {
/** 定义它拼接是终的结果 */
StringBuilder res = new StringBuilder();
/** 定义它拼接中间的页码 */
StringBuilder str = new StringBuilder();
/** 判断总记录条数 */
if (recordCount > 0){ //1499 / 15 = 100
/** 需要显示分页标签,计算出总页数 需要分多少页 */
totalPage = (this.recordCount - 1) / this.pageSize + 1; /** 判断上一页或下一页需不需要加a标签 */
if (this.pageIndex == 1){ // 首页
str.append("<span class='disabled'>上一页</span>"); /** 计算中间的页码 */
this.calcPage(str); /** 下一页需不需要a标签 */
if (this.pageIndex == totalPage){
/** 只有一页 */
str.append("<span class='disabled'>下一页</span>");
}else{
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex + 1));
str.append("<a href='"+ tempUrl +"'>下一页</a>");
}
}else if (this.pageIndex == totalPage){ // 尾页
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex - 1));
str.append("<a href='"+ tempUrl +"'>上一页</a>"); /** 计算中间的页码 */
this.calcPage(str); str.append("<span class='disabled'>下一页</span>");
}else{ // 中间
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex - 1));
str.append("<a href='"+ tempUrl +"'>上一页</a>"); /** 计算中间的页码 */
this.calcPage(str); tempUrl = this.submitUrl.replace(TAG, String.valueOf(pageIndex + 1));
str.append("<a href='"+ tempUrl +"'>下一页</a>");
} /** 拼接其它的信息 */
res.append("<table width='100%' align='center' style='font-size:13px;' class='"+ style +"'>");
res.append("<tr><td style='COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; TEXT-DECORATION: none'>" + str.toString());
res.append("&nbsp;跳转到&nbsp;&nbsp;<input style='text-align: center;BORDER-RIGHT: #aaaadd 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #aaaadd 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 2px; BORDER-LEFT: #aaaadd 1px solid; COLOR: #000099; PADDING-TOP: 2px; BORDER-BOTTOM: #aaaadd 1px solid; TEXT-DECORATION: none' type='text' size='2' id='pager_jump_page_size'/>");
res.append("&nbsp;<input type='button' style='text-align: center;BORDER-RIGHT: #dedfde 1px solid; PADDING-RIGHT: 6px; BACKGROUND-POSITION: 50% bottom; BORDER-TOP: #dedfde 1px solid; PADDING-LEFT: 6px; PADDING-BOTTOM: 2px; BORDER-LEFT: #dedfde 1px solid; COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; BORDER-BOTTOM: #dedfde 1px solid; TEXT-DECORATION: none' value='确定' id='pager_jump_btn'/>");
res.append("</td></tr>");
res.append("<tr align='center'><td style='font-size:13px;'><tr><td style='COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; TEXT-DECORATION: none'>");
/** 开始条数 */
int startNum = (this.pageIndex - 1) * this.pageSize + 1;
/** 结束条数 */
int endNum = (this.pageIndex == this.totalPage) ? this.recordCount : this.pageIndex * this.pageSize; res.append("总共<font color='red'>"+ this.recordCount +"</font>条记录,当前显示"+ startNum +"-"+ endNum +"条记录。");
res.append("</td></tr>");
res.append("</table>");
res.append("<script type='text/javascript'>");
res.append(" document.getElementById('pager_jump_btn').onclick = function(){");
res.append(" var page_size = document.getElementById('pager_jump_page_size').value;");
res.append(" if (!/^[1-9]\\d*$/.test(page_size) || page_size < 1 || page_size > "+ this.totalPage +"){");
res.append(" alert('请输入[1-"+ this.totalPage +"]之间的页码!');");
res.append(" }else{");
res.append(" var submit_url = '" + this.submitUrl + "';");
res.append(" window.location = submit_url.replace('"+ TAG +"', page_size);");
res.append(" }");
res.append("}");
res.append("</script>"); }else{
res.append("<table align='center' style='font-size:13px;'><tr><td style='COLOR: #0061de; MARGIN-RIGHT: 3px; PADDING-TOP: 2px; TEXT-DECORATION: none'>总共<font color='red'>0</font>条记录,当前显示0-0条记录。</td></tr></table>");
}
this.getJspContext().getOut().print(res.toString());
} /** 计算中间页码的方法 */
private void calcPage(StringBuilder str) {
/** 判断总页数 */
if (this.totalPage <= 11){
/** 一次性显示全部的页码 */
for (int i = 1; i <= this.totalPage; i++){
if (this.pageIndex == i){
/** 当前页码 */
str.append("<span class='current'>"+ i +"</span>");
}else{
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='"+ tempUrl +"'>"+ i +"</a>");
}
}
}else{
/** 靠近首页 */
if (this.pageIndex <= 8){
for (int i = 1; i <= 10; i++){
if (this.pageIndex == i){
/** 当前页码 */
str.append("<span class='current'>"+ i +"</span>");
}else{
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='"+ tempUrl +"'>"+ i +"</a>");
}
}
str.append("...");
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(this.totalPage));
str.append("<a href='"+ tempUrl +"'>"+ this.totalPage +"</a>");
}
/** 靠近尾页 */
else if (this.pageIndex + 8 >= this.totalPage){
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(1));
str.append("<a href='"+ tempUrl +"'>1</a>");
str.append("..."); for (int i = this.totalPage - 10; i <= this.totalPage; i++){
if (this.pageIndex == i){
/** 当前页码 */
str.append("<span class='current'>"+ i +"</span>");
}else{
tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='"+ tempUrl +"'>"+ i +"</a>");
}
}
}
/** 在中间 */
else{
String tempUrl = this.submitUrl.replace(TAG, String.valueOf(1));
str.append("<a href='"+ tempUrl +"'>1</a>");
str.append("..."); for (int i = this.pageIndex - 4; i <= this.pageIndex + 4; i++){
if (this.pageIndex == i){
/** 当前页码 */
str.append("<span class='current'>"+ i +"</span>");
}else{
tempUrl = this.submitUrl.replace(TAG, String.valueOf(i));
str.append("<a href='"+ tempUrl +"'>"+ i +"</a>");
}
} str.append("...");
tempUrl = this.submitUrl.replace(TAG, String.valueOf(this.totalPage));
str.append("<a href='"+ tempUrl +"'>"+ this.totalPage +"</a>");
}
}
} /** setter 方法 */
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public void setSubmitUrl(String submitUrl) {
this.submitUrl = submitUrl;
}
public void setStyle(String style) {
this.style = style;
} }

3. 要使用JSP的标签,还需要在WEB-INF下增加一个tld标签文件:page.tld

<?xml version="1.0" encoding="utf-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1"> <!-- 描述 自定义标签版本的一种描述 -->
<description>Pager 1.0 core library</description>
<!-- 显示的名称 导包进行的一个展示 -->
<display-name>Pager core</display-name>
<!-- 版本号 -->
<tlib-version>1.0</tlib-version>
<!-- 短名 -->
<short-name>fkjava</short-name>
<!-- uri :导包 -->
<uri>/pager-tags</uri> <!-- 定义一个标签 -->
<tag>
<!-- 标签名 -->
<name>pager</name>
<!-- 标签处理类,根据自己的实际文件目录更改 -->
<tag-class>com.game.util.PagerTag</tag-class>
<!-- 设置标签为空 -->
<body-content>empty</body-content> <!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 表示分页的第几页 -->
<name>pageIndex</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute> <!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 表示分页标签 ,每页显示多少条数据 -->
<name>pageSize</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 记录分页的总数 -->
<name>recordCount</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 -->
<name>submitUrl</name>
<!-- 必须的 -->
<required>true</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<!-- 定义标签的属性 -->
<attribute>
<!-- 属性名 -->
<name>style</name>
<!-- 必须的 -->
<required>false</required>
<!-- run time expression value 为true支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>

4. notice.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="fkjava" uri="/pager-tags" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/> <!--其他代码省略-->
<table>
<tr>
<th>编号</th>
<th>标题</th>
</tr> <!--其他代码省略-->    <!-- 分页标签 -->
<tr valign="top">
<td align="center" class="font3">
<fkjava:pager
pageIndex="${requestScope.pageModel.pageIndex}"
pageSize="${requestScope.pageModel.pageSize}"
recordCount="${requestScope.pageModel.recordCount}"
style="digg"
submitUrl="${ctx}/notice?pageIndex={0}" />
</td>
     <!-- 点击一次分页标签就重新查询一次数据库 -->
</tr>
<!--其他代码省略-->

5. NoticeMapper和NoticesDynaSqlProvider.java
(1) NoticeMapper

// 动态查询
@SelectProvider(type=NoticesDynaSqlProvider.class,method="selectWithParam")
List<Notices> selectByPage(Map<String, Object> params); //查询公告数量
@SelectProvider(type=NoticesDynaSqlProvider.class,method="count")
Integer count(Map<String, Object> params);

(2) NoticesDynaSqlProvider.java

// 分页动态查询
public String selectWithParam(final Map<String, Object> params){
String sql = new SQL(){
{
SELECT("*");
FROM("notices");
if(params.get("notice") != null){
Notices notice = (Notices)params.get("notice");
if(notice.getNoticeName() != null && !notice.getNoticeName().equals("")){
WHERE(" noticeName LIKE CONCAT('%',#{notice.noticeName},'%') ");
}
if(notice.getNoticeContent() != null && !notice.getNoticeContent().equals("")){
WHERE(" noticeContent LIKE CONCAT('%',#{notice.noticeContent},'%') ");
}
}
}
}.toString(); if(params.get("pageModel") != null){
sql += " limit #{pageModel.firstLimitParam} , #{pageModel.pageSize} ";
}
return sql;
} // 动态查询总数量
public String count(final Map<String, Object> params){
return new SQL(){
{
SELECT("count(*)");//查询有多少行
FROM("notices");
if(params.get("notice") != null){
Notices notice = (Notices)params.get("notice");
if(notice.getNoticeName() != null && !notice.getNoticeName().equals("")){
WHERE(" noticeName LIKE CONCAT('%',#{notice.noticeName},'%') ");
}
if(notice.getNoticeContent() != null && !notice.getNoticeContent().equals("")){
WHERE(" noticeContent LIKE CONCAT('%',#{notice.noticeContent},'%') ");
}
}
}
}.toString();
}

6. TestService.java和TestServiceImpl.java
(1) TestService.java

    /**
* 查询所有公告
* @return Notices对象的List集合
*/
List<Notices> findNotices(Notices notices, PageModel pageModel);

(2) TestServiceImpl.java

@Transactional(readOnly=true)
@Override
public List<Notices> findNotices(Notices notices, PageModel pageModel) {
// TODO Auto-generated method stub
/** 当前需要分页的总数据条数 */
Map<String,Object> params = new HashMap<>();
params.put("notice", notices);
//调用count方法
int recordCount = noticesMapper.count(params);//一共多少条数据
pageModel.setRecordCount(recordCount); if(recordCount > 0){
/** 开始分页查询数据:查询第几页的数据 */
params.put("pageModel", pageModel);
} List<Notices> notices1 = noticesMapper.selectByPage(params); return notices1;
}

7. NoticeController.java

    @RequestMapping(value="/notice")
/**
* 处理查询请求
* @param model
* @param pageIndex
* @param notice
* @return
*/
public String notice(Model model,Integer pageIndex,
@ModelAttribute Notices notice){
PageModel pageModel = new PageModel();
if(pageIndex != null){
pageModel.setPageIndex(pageIndex);
}
/** 查询notices信息 */
List<Notices> notices = testService.findNotices(notice, pageModel);//根据输入的公告名称或公告内容,查询公告信息
model.addAttribute("notices", notices);
model.addAttribute("pageModel", pageModel);
return "notice";
}

8. Notices.java

public class Notices implements Serializable{
private Integer noticeID;
private String noticeName;//通知名称
private String noticeContent;//通知内容
private Date noticeTime;//通知时间 //空的构造方法
public Notices(){
super();
}
//getter and setter
}

9. 另外所需的文件:
(1)  pager.css
(2)  fkjava.ico
以上两个文件可在这里下载

效果如图:

改进:可在web.xml中配置来给所有的.jsp文件导入要依赖的库,这样就不用在每个.jsp页面都导入一遍要依赖的库了。
1. web.xml

    <!-- jsp的配置 -->
<jsp-config>
<jsp-property-group>
<!-- 配置拦截所有的jsp页面 -->
<url-pattern>*.jsp</url-pattern>
<!-- 可以使用el表达式 -->
<el-ignored>false</el-ignored>
<!-- 不能在页面使用java脚本 -->
<scripting-invalid>true</scripting-invalid>
<!-- 给所有的jsp页面导入要依赖的库,tablib.jsp就是一个全局的标签库文件 -->
<include-prelude>/WEB-INF/jsp/taglib.jsp</include-prelude>
</jsp-property-group>
</jsp-config>

2. taglib.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 设置一个项目路径的变量 -->
<c:set var="ctx" value="${pageContext.request.contextPath}"></c:set>
<!-- 配置分页标签 -->
<%@ taglib prefix="fkjava" uri="/pager-tags" %>

参考:《Spring+MyBatis企业应用实战》

------------------------------------------------------------------分割线-------------------------------------------------------------------

MySQL中limit的使用:

select * from notices limit 5 //获取notices表中的前5条数据
select * from notices limit 3, 4 //获取notices表从第3条记录(不包括第3条记录)开始,检索4条记录
select * from notices order by noticeID desc limit 1 //获取notices表中的最后一条数据
select * from notices limit 1 //获取notices表的第一条数据

MySQL中的分页:在SQL语句中得到是从哪条记录开始,取多少个记录。例:页长为3,每页有4条记录。那么第2页就是从第5条记录开始,一共取4条记录。

select * from notices limit 4, 4 //扫描满足条件的8行数据,扔掉前面的4行,返回最后的4行

springmvc+mybatis 实现分页查询的更多相关文章

  1. Mybatis包分页查询java公共类

    Mybatis包分页查询java公共类   分页----对于数据量非常大的查询中.是不可缺少的. mybatis底层的分页sql语句因为须要我们自己去手动写.而实现分页显示的时候我们须要依据分页查询条 ...

  2. Mybatis + SpringMVC + Maven实现分页查询

    使用Mybatis + Maven + SpringMVC 运行时,突然被需要分页查询的功能给难住了 这里推荐采用的插件是PageHelper这个插件,使用起来十分方便.该插件支持以下数据库: Ora ...

  3. springMVC + mybatis 搜索 分页等

    mybatis-3.0.5spring-core-3.2.0.RELEASE等MyBatis3+Spring3当前Spring版本(3.0.5)中未提供对MyBatis3的支持使用第三方jar包进行整 ...

  4. spring-boot 集合mybatis 的分页查询

    spring-boot 集合mybatis 的github分页查询 一.依赖包 <!-- mysql 数据库驱动. --> <dependency> <groupId&g ...

  5. 使用mybatis实现分页查询示例代码分析

    *******************************************分页查询开始*************************************************** ...

  6. mybatis之分页查询

    1)StudentDao.java /** * 持久层*/ public class StudentDao { /** * 增加学生 */ public void add(Student studen ...

  7. SpringBoot整合Mybatis关于分页查询的方法

    最近公司在用到SpringBoot整合Mybatis时当web端页面数据增多时需要使用分页查询以方便来展示数据.本人对分页查询进行了一些步骤的总结,希望能够帮助到有需要的博友.如有更好的方式,也希望评 ...

  8. Mybatis 使用分页查询亿级数据 性能问题 DB使用ORACLE

    一般用到了mybatis框架分页就不用自己写了 直接用RowBounds对象就可以实现,但这个性能确实很低 今天我用到10w级得数据分页查询,到后面几页就迭代了很慢 用于记录 1.10万级数据如下 [ ...

  9. mybatis中分页查询

    1 如果在查询方法中有多个参数,可以使用map对象将所有数据都存储进去.比如分页查询,需要用到两个参数,可以将这两个参数包装到map中. 例子:分页查询 dao层方法 public List<S ...

随机推荐

  1. Jenkins + Gitlab + Ansible--playbook 代码上线流程(文末有免费视频)

      jenkins 构建是支持 git 选择分支 安装 Git Parameter 插件在系统管理中的插件管理 然后点击选插件,在右上角输入 Git Parameter,找到 Git Paramete ...

  2. JetBrains全家桶使用攻略

    JetBrains全家桶使用攻略 今天狠狠心某宝买了一个key,可以使用15款开发软件,在此进行记录. 全家桶链接:https://www.jetbrains.com/products.html?fr ...

  3. C++模板的实现(模板函数和模板类,附带模板实现顺序表和链表代码)

    文章链接:https://blog.csdn.net/qq_38646470/article/details/80209469

  4. 传递JSON数据有没有必要用RequestBody?

    在使用SpringMVC的时候自己一直避免使用RequestBody,因为觉的它在参数处理的时候不够方便.理由如下:1.不使用RequestBody时是这样的:前端参数可以直接使用JSON对象: // ...

  5. Mysql行转列的简单应用

    最近在复习过程中愈发觉得,有些东西久了不用,真的会忘~——~. 将上面的表格转换为下面的表格 我拼sql拼了好久还是没弄出来,还是偶然看到我以前的笔记,才想起有行转列这样的操作(太久没有写过复杂点的s ...

  6. SICP读书笔记 3.5

    SICP CONCLUSION 让我们举起杯,祝福那些将他们的思想镶嵌在重重括号之间的Lisp程序员 ! 祝我能够突破层层代码,找到住在里计算机的神灵! 目录 1. 构造过程抽象 2. 构造数据抽象 ...

  7. GearCase UI v0.2 版本

    12 月闲暇的时间一直在更新 GearCase.通过不懈的努力,GearCase 今天迎来了一次中间版本的更新,这次的更新主要加入了 Springs 动画组件,部分组件也添加了此组件的动画效果. &g ...

  8. ActiveMQ笔记:管理和监控

    ActiveMQ提供了比较丰富的监控和管理工具.在ActiveMQ的网页里(http://activemq.apache.org/how-can-i-monitor-activemq.html)提到了 ...

  9. 遇到执行SQL 的参数最大个数

    报错: 传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确.此 RPC 请求中提供了过多的参数.最多应为 2100. 现象是: SQL 执行的参数过多,超过了 最大值 :2100 个. ...

  10. Python操作数据库之 MySQL

    Python操作数据库之MySQL 一.安装Python-MySQLdb模块 Python-MySQLdb是一个操作数据库的模块,Python 通过它对 mysql 数据实现各种操作. 如果要源码安装 ...