整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          springboot+freemarker+bootstrap快速實現分頁功能(含java源碼)

          節是建立在上節的基礎上,上一節給大家講了管理后臺表格如何展示數據,但是當我們的數據比較多的時候我們就需要做分頁處理了。這一節給大家講解如何實現表格數據的分頁顯示。

          準備工作

          • 1,項目要引入freemarker和bootstrap,如果不知道怎么引入的,請查看
          • 《springboot+freemarker+bootstrap快速實現管理后臺》

          還是老規矩,先看效果圖

          可以看出我們實現了如下功能

          • 1,表格數據的展示
          • 2,分頁效果的實現
          • 3,上一頁和下一頁的實現
          • 4,當前選中頁碼加重顏色

          下面來看實現步驟

          一,定義表格和分頁組件

          簡單說說代碼

          • head里面是引入bootstrap的樣式庫
          • table定義表格來展示數據
          • ul里定義分頁
          • 代碼如下:
          <html><head>
           <meta charset="utf-8">
           <title>freemarker+bootstrap學習</title>
           <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
           <!-- 新 Bootstrap4 核心 CSS 文件 -->
           <link rel="stylesheet"
           ></head><body><div class="container-fluid">
           <div class="row clearfix">
           <div class="col-md-12 column">
           <table class="table table-bordered table-condensed table-striped">
           <thead>
           <tr>
           <th>id</th>
           <th>姓名</th>
           <th>微信</th>
           <th colspan="2">操作</th>
           </tr>
           </thead>
           <tbody>
           <#list productInfoPage as productInfo>
           <tr>
           <td>${productInfo.id}</td>
           <td>${productInfo.name}</td>
           <td>${productInfo.wechat}</td>
           <td>
           <#if productInfo.id%2 == 0>
           <a href="#">下架</a>
           <#else>
           <a href="">上架</a>
           </#if>
           </td>
           </tr>
           </#list>
           </tbody>
           </table>
           </div>
           <#--分頁-->
           <div class="col-md-12 column">
           <ul class="pagination ">
           <#if currentPage lte 1>
           <li class="disabled "><a class="page-link" href="#">上一頁</a></li>
           <#else>
           <li>
           <a class="page-link" href="/pageList?page=${currentPage -
           1}&size=${size}">上一頁</a>
           </li>
           </#if>
           <#list 1..totalPage as index>
           <#if currentPage == index>
           <li class="page-item active "><a class="page-link" href="#">${index}</a>
           </li>
           <#else>
           <li>
           <a class="page-link" href="/pageList?page=${index}&size=${size}">
           ${index}</a>
           </li>
           </#if>
           </#list>
           <#if currentPage gte totalPage>
           <li class="disabled "><a class="page-link" href="#">下一頁</a></li>
           <#else>
           <li>
           <a class="page-link" href="/pageList?page=${currentPage + 1}&size=${size}">下一頁</a>
           </li>
           </#if>
           </ul>
           </div>
           </div></div></body></html>
          

          二,定義好頁面后,我們就來獲取數據

          同樣這里的數據我們先用模擬數據,后面會用數據庫里的數據。

          看下面代碼可以看出來,我們模擬了6條數據,然后每頁顯示2條數據。

          package com.qcl.demo.controller;import com.qcl.demo.bean.Demo;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.servlet.ModelAndView;import java.util.ArrayList;import java.util.List;import java.util.Map;/**
           * Created by qcl on 2019-04-29
           * desc:freemarker學習
           */@RestControllerpublic class DemoController { /*
           * 分頁效果的實現
           * */
           @GetMapping("/pageList") public ModelAndView list(@RequestParam(value = "page", defaultValue = "1") Integer page,
           @RequestParam(value = "size", defaultValue = "2") Integer size,
           Map<String, Object> map) {
           List<Demo> demoList = new ArrayList<>(4);
           demoList.add(new Demo(1, "標題1", "編程小石頭1", "2501902696"));
           demoList.add(new Demo(2, "標題2", "編程小石頭2", "2501902696"));
           demoList.add(new Demo(3, "標題3", "編程小石頭3", "2501902696"));
           demoList.add(new Demo(4, "標題4", "編程小石頭4", "2501902696"));
           demoList.add(new Demo(5, "標題5", "編程小石頭4", "2501902696"));
           demoList.add(new Demo(6, "標題6", "編程小石頭4", "2501902696"));
           demoList.add(new Demo(7, "標題7", "編程小石頭7", "2501902696")); int start = (page - 1) * 2; int end = start + size;
           List<Demo> subList = demoList.subList(start, end); int totalPage = (int) Math.ceil(demoList.size() / size);
           map.put("productInfoPage", subList);
           map.put("totalPage", totalPage);
           map.put("currentPage", page);
           map.put("size", size); return new ModelAndView("demo/list", map);
           }
          }
          

          三,啟動springboot查看效果。

          注意每一頁地址欄的url

          可以看出,我們第一次訪問時,默認顯示第一頁,url里沒有page和size字段。

          訪問第2頁和第3頁時,url里就有了page和size。page是顯示那一頁,size是每頁顯示多少條數據。

          到這里我們就實現的管理后臺的分頁效果。

          我會把10小時實戰入門java系列課程錄制成視頻,如果你看文章不能很好的理解,可以去看下視頻

          有任何關于編程的問題都可以私信我,我看到后會及時解答。

          編程小石頭,碼農一枚,非著名全棧開發人員。分享自己的一些經驗,學習心得,希望后來人少走彎路,少填坑。

          ue-pro-table

          一個基于 ElementUI 封裝的 table 列表頁組件,將包含搜索、列表、分頁等功能的頁面封裝成一個組件

          特性

          ?將搜索、列表、分頁三者的交互邏輯封裝到組件中,節省開發者代碼量

          ?配置化的請求函數,自動發送請求,自動獲取請求參數,自動顯示 loading 效果

          ?配置化的表格項,跟 el-table-column 的配置屬性類似

          ?配置化的搜索表單,支持大部分表單元素

          ?配置化的分頁,跟 el-pagination 的配置屬性類似

          ?自定義是否顯示搜索和分頁

          ?自定義標題欄和工具欄

          ?豐富的插槽提供功能擴展

          使用

          安裝和引入

          安裝

          // npm
          npm install vue-pro-table
          // yarn
          yarn add vue-pro-table
          

          引入

          該組件依賴 element-ui,需要自行引入

          import ElementUI from "element-ui";
          import "element-ui/lib/theme-chalk/index.css";
          Vue.use(ElementUI);

          // 引入vue-pro-table
          import VueProTable from "vue-pro-table";
          Vue.use(VueProTable);
          

          快速使用

          <template>
            <vue-pro-table title="列表" :request="getList" :columns="columns">
              <template #operate="scope">
                <el-button size="mini" type="primary">編輯</el-button>
                <el-button size="mini" type="danger">刪除</el-button>
              </template>
            </vue-pro-table>
          </template>
          
          <script>
          import {getUserList} from 'src/api/xxx';
          export default {
            data() {
              // 表格列配置,大部分屬性跟el-table-column配置一樣
              columns: [
                { label: '序號', type: 'index' },
                { label: '名稱', prop: 'nickName', width: 180 },
                { label: '郵箱', prop: 'userEmail' },
                {
                  label: '操作',
                  fixed: 'right',
                  width: 180,
                  align: 'center',
                  tdSlot: 'operate', // 自定義單元格內容的插槽名稱
                },
              ],
            },
            methods: {
              // 請求函數
              async getList(params) {
                // params是從組件接收的,包含分頁和搜索字段。
                const { data } = await getUserList(params)
          
                // 必須要返回一個對象,包含data數組和total總數
                return {
                  data: data.list,
                  total: +data.total,
                }
              },
            }
          }
          </script>
          

          預覽效果

          默認不包含搜索表單

          請求函數配置

          ?request,請求列表數據的函數

          組件加載的時候會自動執行 request 函數,并在加載過程中顯示 loading 效果

          • 函數接收參數:包含搜索表單的所有字段和分頁的 pageNum 和 pageSize
          • 函數必須返回一個對象,包含:

          ? data: 列表數據的數組

          ? total:總數,用于分頁

          表格配置

          ?columns 屬性的配置,是一個數組

          參數

          說明

          類型

          可選值

          默認值

          label

          對應 el-table-column 的 label

          string

          -

          -

          type

          對應 el-table-column 的 type

          string

          selection/index/expand

          -

          prop

          對應 el-table-column 的 prop

          string

          -

          -

          width

          對應 el-table-column 的 width

          string,number

          -

          -

          minWidth

          對應 el-table-column 的 min-width

          string,number

          -

          -

          align

          對應 el-table-column 的 align

          string

          left/center/right

          left

          fixed

          對應 el-table-column 的 fixed

          string, boolean

          true, left, right

          -

          sortable

          對應 el-table-column 的 sortable

          boolean

          false/true

          false

          filters

          對應 el-table-column 的 filters

          Array[{ text, value }]

          -

          -

          tdSlot

          單元格要自定義內容時,可以通過此屬性配置一個插槽名稱,并且是作用域插槽,可以接收 scope 數據

          string

          -

          -

          labelSlot

          表頭要自定義內容時,可以通過此屬性配置一個插槽名稱,并且是作用域插槽,可以接收 scope 數據

          string

          -

          -

          ?row-key 屬性配置

          對應 el-table 的 row-key,默認值是'id'

          搜索配置

          ?search 屬性的配置,是一個對象

          如果不想顯示搜索表單,可以不配置 search 或者 search 設置為 false

          參數

          說明

          類型

          可選值

          默認值

          labelWidth

          label 文字長度

          string

          -

          -

          inputWidth

          表單項長度

          string

          -

          -

          fields

          表單字段列表,包含 text,select,radio,checkbox,datetime 等類型,所有字段類型配置見下表

          Array[{字段類型}]

          -

          -

          ?fields 列表的字段類型配置

          參數

          說明

          類型

          可選值

          默認值

          type

          字段類型

          string

          text,textarea,select,radio,radio-button,checkbox,checkbox-button,number,date,daterange,datetime,datetimerange

          text

          label

          label 文本

          string

          -

          -

          name

          搜索時的提交的參數名稱

          string

          -

          -

          style

          額外的樣式

          object

          -

          -

          defaultValue

          默認值

          -

          -


          options

          當 type 是 select,radio,radio-button,checkbox,checkbox-button 時的枚舉選項

          Array[{name, value}]

          -

          -

          transform

          搜索前對表單數據進行轉換,比如表單數據是數組,但是搜索的時候需要傳遞字符串。它是一個函數,默認參數是字段的 value,需要返回轉換后的結果

          function(value)

          -

          -

          trueNames

          當 type 是 daterange,datetimerange 時,開始時間和結束時間是在一個數組里面,但是搜索時可能需要兩個字段,這時就需要把開始時間和結束時間分別賦值給兩個字段,這兩個字段的名稱就是通過 trueNames 配置,它是一個數組,例如:trueNames: ['startTime', 'endTime']

          Array[string]



          min

          當 type 是 number 時的最小值

          number

          -

          -

          max

          當 type 是 number 時的最大值

          number

          -

          -

          分頁配置

          ?

          pagination 屬性的配置,是一個對象

          如果不想顯示分頁,將 pagination 設置為 false

          參數

          說明

          類型

          可選值

          默認值

          layout

          組件布局

          string

          total, sizes, prev, pager, next, jumper

          total, sizes, prev, pager, next, jumper

          pageSize

          每頁顯示條目個數

          number

          -

          10

          pageSizes

          每頁顯示個數選擇器的選項設置

          Array[number]

          -

          [10, 20, 30, 40, 50, 100]

          標題欄配置

          表格上方有一個標題欄,標題欄左側顯示一個標題,右側是一個可自定義的工具欄

          ?hide-title-bar

          是否隱藏標題欄,布爾值

          ?title

          表格標題

          ?自定義表格標題

          提供一個具名插槽title,來自定義標題的內容

          ?工具欄

          工具欄默認是空的,提供一個具名插槽 toolbar,來自定義工具欄的內容

          事件

          ?selectionChange

          如果columns中配置了type為selection的列,可以通過該事件得到已選擇的行,參數是一個數組

          組件內部方法

          ?refresh

          配置 ref 屬性,可以通過 ref 獲取組件后調用組件內部的refresh方法刷新列表

          完整用法

          <template>
            <vue-pro-table
              ref="proTable"
              title="用戶列表"
              :request="getList"
              :columns="columns"
              :search="searchConfig"
              :pagination="paginationConfig"
              @selectionChange="handleSelectionChange"
            >
                <!-- 工具欄 -->
                <template #toolbar>
                  <el-button
                    type="primary"
                    icon="el-icon-plus"
                    @click="$router.push({name: 'userAdd'})"
                  >創建賬號</el-button>
                  <el-button
                    type="danger"
                    icon="el-icon-refresh"
                    @click="$refs.pageBox.refresh()"
                  >刷新</el-button>
                </template>
          
                <!-- 展開行 -->
                <template #expand="{row}">
                  {{row.userEmail}}
                </template>
          
                <!-- 狀態 -->
                <template #status="{row}">
                  <el-tag :type="+row.status === 1 ? 'success' : 'info'">{{+row.status === 1 ? '啟用' : '停用'}}</el-tag>
                </template>
          
                <!-- 表格操作欄 -->
                <template #page-operate="{row}">
          
                  <el-button
                    type="text"
                    @click="$router.push({name: 'userEdit', params: {
                          id: row.id
                        }})"
                  >編輯</el-button>
          
                  <el-button
                    v-if="+row.status === 1"
                    type="text"
                    @click="setUserStatus(row, 0)"
                  >停用</el-button>
          
                  <el-button
                    v-else
                    type="text"
                    @click="setUserStatus(row, 1)"
                  >啟用</el-button>
          
                </template>
          
                <!-- 操作欄頭部 -->
                <template #th-operate>
                  <el-input />
                </template>
          
            </vue-pro-table>
          </template>
          
          <script>
          import {getUserList} from 'src/api/xxx';
          export default {
            data() {
              // 表格列配置,大部分屬性跟el-table-column配置一樣
              columns: [
                  { label: '', type: 'expand', tdSlot: 'expand' },
                  { label: '全選', type: 'selection' },
                  { label: '序號', type: 'index' },
                  { label: '賬戶名稱', prop: 'nickName', sortable: true },
                  { label: '賬號', prop: 'userEmail', width: 80 },
                  {
                    label: '狀態',
                    prop: 'status',
                    tdSlot: 'status',
                    filters: [
                      { text: '啟用', value: 1 },
                      { text: '禁用', value: 0 },
                    ],
                  },
                  { label: '創建時間', prop: 'createTime', align: 'right' },
                  { label: '最后修改時間', prop: 'updateTime' },
                  {
                    label: '操作',
                    labelSlot: 'th-operate',
                    fixed: 'right',
                    width: 180,
                    align: 'center',
                    tdSlot: 'page-operate',
                  },
              ],
              // 搜索配置
              searchConfig: {
                  labelWidth: '90px',
                  inputWidth: '360px',
                  fields: [
                    {
                      type: 'text',
                      label: '賬戶名稱',
                      name: 'nickName',
                      defaultValue: 'abc',
                    },
                    {
                      type: 'textarea',
                      label: '描述',
                      name: 'description',
                    },
                    {
                      label: '狀態',
                      name: 'status',
                      type: 'select',
                      defaultValue: 1,
                      options: [
                        {
                          name: '已發布',
                          value: 1,
                        },
                        {
                          name: '未發布',
                          value: 0,
                        },
                      ],
                    },
                    {
                      label: '性別',
                      name: 'sex',
                      type: 'radio',
                      options: [
                        {
                          name: '男',
                          value: 1,
                        },
                        {
                          name: '女',
                          value: 0,
                        },
                      ],
                    },
                    {
                      label: '城市',
                      name: 'city',
                      type: 'radio-button',
                      options: [
                        {
                          name: '北京',
                          value: 'bj',
                        },
                        {
                          name: '上海',
                          value: 'sh',
                        },
                        {
                          name: '廣州',
                          value: 'gz',
                        },
                        {
                          name: '深圳',
                          value: 'sz',
                        },
                      ],
                    },
                    {
                      label: '愛好',
                      name: 'hobby',
                      type: 'checkbox',
                      defaultValue: ['吃飯'],
                      options: [
                        {
                          name: '吃飯',
                          value: '吃飯',
                        },
                        {
                          name: '睡覺',
                          value: '睡覺',
                        },
                        {
                          name: '打豆豆',
                          value: '打豆豆',
                        },
                      ],
                      transform: (val) => val.join(','),
                    },
                    {
                      label: '水果',
                      name: 'fruit',
                      type: 'checkbox-button',
                      options: [
                        {
                          name: '蘋果',
                          value: '蘋果',
                        },
                        {
                          name: '香蕉',
                          value: '香蕉',
                        },
                        {
                          name: '橘子',
                          value: '橘子',
                        },
                        {
                          name: '葡萄',
                          value: '葡萄',
                        },
                      ],
                      transform: (val) => val.join(','),
                    },
                    {
                      label: '日期',
                      name: 'date',
                      type: 'date',
                    },
                    {
                      label: '時間',
                      name: 'datetime',
                      type: 'datetime',
                      defaultValue: '2020-10-10 8:00:00',
                    },
                    {
                      label: '日期范圍',
                      name: 'daterange',
                      type: 'daterange',
                      trueNames: ['startDate', 'endDate'],
                      style: { width: '360px' },
                    },
                    {
                      label: '時間范圍',
                      name: 'datetimerange',
                      type: 'datetimerange',
                      trueNames: ['startTime', 'endTime'],
                      style: { width: '360px' },
                      defaultValue: ['2020-10-10 9:00:00', '2020-10-11 18:30:00'],
                    },
                    {
                      label: '數量',
                      name: 'num',
                      type: 'number',
                      min: 0,
                      max: 10,
                    },
                  ],
              },
              // 分頁配置
              paginationConfig: {
                layout: 'total, prev, pager, next, sizes', // 分頁組件顯示哪些功能
                pageSize: 5, // 每頁條數
                pageSizes: [5, 10, 20, 50],
              }
            },
            methods: {
              // 請求函數
              async getList(params) {
                // params是從組件接收的,包含分頁和搜索字段。
                const { data } = await getUserList(params)
          
                // 必須要返回一個對象,包含data數組和total總數
                return {
                  data: data.list,
                  total: +data.total,
                }
              },
              // 選擇
              handleSelectionChange(arr) {
                console.log(arr)
              },
            }
          }
          </script>
          

          效果:

          、分頁查詢概述

          分頁查詢則是在頁面上將本來很多的數據分段顯示,每頁顯示用戶自定義的行數。可提高用戶體驗度,同時減少一次性加載,內存溢出風險。

          1.1、分頁查詢分類

          1.1.1、真分頁

          每次翻頁從數據庫中查詢數據。

          1. 優點:不容易造成內存溢出。
          2. 缺點:實現復雜,性能相對低。

          1.1.2、假分頁

          一次性查詢所有數據存入內存,翻頁從內存中獲取數據。

          1. 優點:實現簡單,性能高。
          2. 缺點:容易造成內存溢出。

          1.2、分頁效果

          發送請求訪問一個帶有分頁頁面的數據,會發現其主要由兩部分組成:

          1. 當前頁的結果集數據,比如這一頁有哪些商品信息。
          2. 分頁條信息,比如包含【首頁】【上頁】【下頁】【末頁】等。

          二、分頁的設計

          2.1、分頁需要傳遞的參數

          2.1.1、用戶需要傳入的參數

          1. currentPage:當前頁,跳轉到第幾頁,int 類型,設置默認值,比如 1。
          2. pageSize:每頁最多多少條數據,int 類型,設置默認值,比如 10。

          2.1.2、分頁需要展示的數據

          1. start:首頁。
          2. prevPage:上一頁。
          3. nextPage:下一頁。
          4. totalPage:末頁頁碼。
          5. totalCounts:總記錄數。
          6. currentPage:當前頁。
          7. pageSize:每頁記錄數。

          2.1.3、分頁需展示的數據的來源

          • 來源于用戶傳入: currentPage: 當前頁,int 類型。 pageSize: 每頁顯示多少條數據,int 類型。
          • 來源于兩條 SQL 查詢: totalCount/rows: 數據總條數,int 類型。 data/list: 每一頁的結果集數據,List 類型。
          • 來源于程序計算: totalPage: 總頁數/末頁,int 類型。 prevPage: 上一頁,int 類型。 nextPage: 下一頁,int 類型。

          2.2、分頁原理

          結果總數(totalCount/rows)和結果集(data/list)是來源于兩條 SQL:

          1. 第一條SQL:查詢總數,返回一個數字(總記錄數)。
          select count(*) from province
          1. 查詢符合條件的結果集(返回一個結果集)。
          # 他有兩個參數,一個是起始頁的頁碼,另一個是每頁記錄數
          # start :(currentPage - 1) * pageSize
          # pageSize: 前臺給予
          select * from province limit #{start} ,#{pageSize}
          1. 計算出其余的參數(總頁數、上一頁、下一頁)
            // 分頁數據通過這個構造器封裝好
            public PageResult(int currentPage, int pageSize, int totalCount, List<T> data) {
              this.currentPage = currentPage;
              this.pageSize = pageSize;
              this.totalCount = totalCount;
              this.data = data;
              // 計算總頁數(要先算)
              this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
              // 利用三元運算符來計算上一頁,如果已經是第一頁的話,那么他就不會有上一頁,讓他的上一頁為第一頁,否則就當前頁減1為上一頁
              this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
              // 利用三元運算符計算下一頁,如果已經是最后一頁的話,那么就沒有下一頁了,就不讓他下一頁再增加,否則就當前頁自增
              this.nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;
          
            }

          三、分頁查詢實現

          3.1、訪問流程

          3.2、分頁參數的封裝

          為了能在頁面上顯示上述的分頁效果,那么我們就得在把頁面上的每一個數據封裝成到某個對象共享給

          JSP。

          如果我們不進行封裝的話,那么這個七個參數要全部在Session域中去取,比較復雜和惡心。

          我們一般會把多個需要共享的數據,封裝到一個對象,往后就只需要把數據封裝到該對象,再共享該對象即可。

          3.3、編寫PageResult

          package com.qo;
          
          import java.util.List;
          import lombok.AllArgsConstructor;
          import lombok.Data;
          import lombok.NoArgsConstructor;
          
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          
          /**
            封裝結果數據(某一頁的數據)
           * @author Xiao_Lin
           */
          public class PageResult<T> {
            // 用戶輸入的數據
            private int currentPage;  // 當前頁碼
            private int pageSize; // 每頁顯示的條數
          
            //SQL執行后的結果
            private int totalCount; // 總條數
            private List<T> data; // 當前頁數據結果集
          
            // 利用程序計算出來的
            private int prevPage; // 上一頁
            private int nextPage; // 下一頁
            private int totalPage; // 最后一頁
          
            // 分頁數據通過這個構造器封裝好
            public PageResult(int currentPage, int pageSize, int totalCount, List<T> data) {
              this.currentPage = currentPage;
              this.pageSize = pageSize;
              this.totalCount = totalCount;
              this.data = data;
              // 計算總頁數(要先算)
              this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
              // 利用三元運算符來計算上一頁,如果已經是第一頁的話,那么他就不會有上一頁,讓他的上一頁為第一頁,否則就當前頁減1為上一頁
              this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
              // 利用三元運算符計算下一頁,如果已經是最后一頁的話,那么就沒有下一頁了,就不讓他下一頁再增加,否則就當前頁自增
              this.nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;
            }
          }

          3.4、修改Mapper(Dao)

           // 查詢總記錄數,傳入一個封裝好的查詢對象,里面的參數有當前頁、每頁記錄數(可不傳,盡量傳,為模糊查詢做基礎)
            int queryCount(QueryObject qo);
          
          // 查詢結果集,傳入一個封裝好的查詢對象,里面封裝好的參數有當前頁、每頁記錄數、起始頁頁碼
            List<Province> query(QueryObject qo);

          3.5、修改Service以及ServiceImpl

            PageResult<Province> query(ProvinceQueryObject qo);
          package com.service.impl;
          
          /**
           * @author Xiao_Lin
           * @date 2021/1/22 22:25
           */
          public class ProvinceServiceImpl implements ProvinceService {
          
            ProvinceMapper mapper = ConnUtils.getConnection().getMapper(ProvinceMapper.class);
          
            @Override
            public PageResult<Province> query(ProvinceQueryObject qo) {
              // 獲取查詢的記錄數
              int totalCount = mapper.queryCount(qo);
              // 如果總記錄數為0,那么說明沒數據就不用下一步查詢了,提高效率。
              if (totalCount == 0){
                  // 返回一個查詢結果集,返回當前頁、每頁記錄數、以及一個空的結果集
                return new PageResult<Province>(qo.getCurrentPage(),qo.getPageSize(),totalCount,Collections.EMPTY_LIST);
              }
                // 記錄數不為0,查詢出一個結果集
              List<Province> provinces = mapper.query(qo);
                // 返回一個查詢結果集,返回當前頁、每頁記錄數、以及結果集
              return new PageResult<Province>(qo.getCurrentPage(),qo.getPageSize(),totalCount,provinces);
            }

          3.6、編寫QueryObject

          package com.domain;
          
          import lombok.AllArgsConstructor;
          import lombok.Data;
          import lombok.NoArgsConstructor;
          
          /**
           * 封裝分頁查詢需要的兩個請求傳入的分頁參數
           * @author Xiao_Lin
           * @date 2021/1/22 21:49
           */
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class QueryObject {
            private int currentPage = 1; // 當前頁碼,要跳轉到哪一頁的頁碼(需要給默認值)
            private int pageSize = 3 ; // 每頁顯示條數(需要給默認值)
           //用于 Limit 子句第一個 ? 取值,起始頁頁碼
            public int getStart(){
              return (currentPage-1)*pageSize;
            }
          }

          3.7、編寫測試類

          	ProvinceService provinceService = new ProvinceServiceImpl();
              QueryObject qo = new QueryObject();
          	PageResult<Province> pageResult = provinceService.query(qo);
              System.out.println("當前頁:"+pageResult.getCurrentPage());
              System.out.println("結果集數據:" + pageResult.getData());
              System.out.println("當前頁總記錄數:" + pageResult.getTotalCount());
              System.out.println("條數:" + pageResult.getData().size());
              System.out.println("總頁數:" + pageResult.getTotalPage());
              System.out.println("上一頁:" + pageResult.getPrePage());
              System.out.println("下一頁:" + pageResult.getNextPage());

          3.8、編寫Servlet

          package com.servlet;
          
          /**
           * @author Xiao_Lin
           * @date 2021/1/24 10:17
           */
          @WebServlet(urlPatterns = "/listall")
          public class ProvinceServlet extends HttpServlet {
          
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
              ProvinceService provinceService = new ProvinceServiceImpl();
              // 創建QueryObject對象
              QueryObject qo = new QueryObject();
              // 獲取參數
              String currentPage = req.getParameter("currentPage");
              // 利用工具類判斷是否傳了這個參數
              if (StringUtil.hasLength(currentPage)){
                // 如果傳了就賦值
                qo.setCurrentPage(Integer.parseInt(currentPage));
              }
              String pageSize = req.getParameter("pageSize");
              if (StringUtil.hasLength(pageSize)){
                qo.setPageSize(Integer.parseInt(pageSize));
              }
              // 調用業務層方法來處理請求查詢某一頁數據
              PageResult<Province> query = provinceService.query(qo);
              // 把數據共享給jsp
              req.setAttribute("pageResult", query);
              // 控制跳轉到 list.jsp 頁面
              req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(req, resp);
          
            }
          }

          3.9、前臺實現

          包含編寫 Servlet 及 JSP,Servlet 處理請求,調用業務方法,把查詢到數據共享到 JSP 中,展示給用戶。操作步驟:

          1. 瀏覽器發出分頁請求參數(去往第幾頁/每頁多少條數據),在 Servlet 中接收這些參數,并封裝 到 QueryObject 對象,調用 Service 中分頁查詢方法(query)。
          2. 把得到的分頁查詢結果對象(PageResult)共享在請求作用域中,跳轉到 JSP,顯示即可。
          3. 修改 JSP 頁面,編寫出分頁條信息(分頁條中的信息來源于 PageResult 對象)。
          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
          <html>
          <head>
              <title>產品列表</title>
              <script type="text/javascript">
                window.onload = function () {
                  var trClzs = document.getElementsByClassName("trClassName");
                  for(var i = 0; i < trClzs.length; i++){
                    trClzs[i].onmouseover = function () {
                      console.log(1);
                      this.style.backgroundColor = "gray";
                    }
                    trClzs[i].onmouseout = function () {
                      console.log(2);
                      this.style.backgroundColor = "";
                    }
                  }
                }
                // 分頁 JS
                function changePageSize() {
                  document.forms[0].submit();
                }
              </script>
          </head>
          <body>
          
          <form action="/product">
              <table border="1" cellspacing="0" cellpadding="0" width="80%">
                  <tr>
                      <th>編號</th>
                      <th>名稱</th>
                      <th>簡稱</th>
                  </tr>
                  <c:forEach var="province" items="${pageResult.data}"
                             varStatus="status">
                      <tr class="trClassName">
                          <td>${status.count}</td>
                          <td>${province.id}</td>
                          <td>${province.name}</td>
                          <td>${province.abbr}</td>
                          <td>
                              <a href="/listall?cmd=delete&id=${product.id}">刪除</a>
                              <a href="/listall?cmd=input&id=${product.id}">修改</a>
                          </td>
                      </tr>
                  </c:forEach>
                  <tr align="center">
                      <td colspan="9">
                          <a href="/listall?currentPage=1">首頁</a>
                          <a href="/listall?currentPage=${pageResult.prevPage}">上一頁
                          </a>
                          <a href="/listall?currentPage=${pageResult.nextPage}">下一頁
                          </a>
                          <a href="/listall?currentPage=${pageResult.totalPage}">尾頁
                          </a>
                          當前第 ${pageResult.currentPage} / ${pageResult.totalPage} 頁
                          一共 ${pageResult.totalCount} 條數據
                          跳轉到<input type="number" onchange="changePageSize()"
                                    name="currentPage" value="${pageResult.currentPage}" style="width: 60px;">頁
                          每頁顯示
                          <select name="pageSize" onchange="changePageSize()">
                              <option value="3" ${pageResult.pageSize == 3 ?
                                      'selected' : ''}> 3 </option>
                              <option value="5" ${pageResult.pageSize == 5 ?
                                      'selected' : ''}> 5 </option>
                              <option value="8" ${pageResult.pageSize == 8 ?
                                      'selected' : ''}> 8 </option>
                          </select>條數據
                      </td>
                  </tr>
              </table>
          </form>
          </body>
          </html>

          作者:XiaoLin_Java
          原文鏈接:https://juejin.cn/post/6987553953156169742


          主站蜘蛛池模板: 色国产在线视频一区| 亚洲福利视频一区| 波多野结衣免费一区视频| 国精产品一区一区三区免费视频| 青娱乐国产官网极品一区| 精品国产亚洲一区二区三区| 国产爆乳无码一区二区麻豆| 日韩免费一区二区三区| 国产福利视频一区二区| 国精产品一区一区三区有限公司| 国产成人一区在线不卡| 国产精品乱码一区二区三| 亚洲一区二区三区偷拍女厕| 国产精品熟女视频一区二区| 久久4k岛国高清一区二区| 爆乳熟妇一区二区三区霸乳| 日本国产一区二区三区在线观看 | 无码精品人妻一区二区三区免费| 日本中文字幕在线视频一区| 亚洲av乱码一区二区三区| 亚洲日韩国产精品第一页一区| 国产综合无码一区二区色蜜蜜| 亚洲中文字幕在线无码一区二区 | 亚洲视频在线一区二区三区| 久久精品一区二区三区中文字幕 | 男人的天堂av亚洲一区2区| 亚洲av无码一区二区三区观看| 91国在线啪精品一区| 日韩精品一区二三区中文 | 国产精品免费综合一区视频| 99久久无码一区人妻a黑| 91精品福利一区二区三区野战| 国产凹凸在线一区二区| 大伊香蕉精品一区视频在线| 无码日韩人妻AV一区二区三区| 一区二区三区AV高清免费波多| 色一情一乱一伦一区二区三区日本| 国产aⅴ一区二区| 国产一区二区精品尤物| 国产亚洲综合一区柠檬导航 | a级午夜毛片免费一区二区|