springmvc+mybatis 實現分頁查詢


為簡化分頁功能,設計了一個分頁的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行

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM