最近在學layui這個前端框架的分頁功能,官方的文檔中,給出的分頁樣式如下圖所示:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>layPage快速使用</title> 6 <!--注意:這里引入的樣式路徑是你本地對應的路徑--> 7 <link rel="stylesheet" href="layui/css/layui.css" media="all"> 8 </head> 9 <body> 10 11 <div id="test1"></div> 12 <!--注意:這里引入的樣式路徑是你本地對應的路徑--> 13 <script src="layui/layui.js"></script> 14 <script> 15 layui.use('laypage', function(){ 16 var laypage = layui.laypage; 17 18 //執行一個laypage實例 19 laypage.render({ 20 elem: 'test1' //注意,這里的 test1 是 ID,不用加 # 號 21 ,count: 50 //數據總數,從服務端得到 22 }); 23 }); 24 </script> 25 </body> 26 </html>
執行后得到的效果如下圖所示:
作為后端的java開發,有時候需要用到這個分頁的功能,所以想着來結合layui分頁做一個前后端數據交互分頁。
關於分頁里面的參數這里就不一一說明了,官方的文檔講解的也很清楚:https://www.layui.com/doc/modules/laypage.html,如果實在不明白的話,可以參考這個教程視頻:https://www.bilibili.com/video/BV19V411b7sx?p=1
1、准備一下數據庫所需要的數據,一共兩百條,是從layui上面拿到的json文件,然后在數據庫中建立對應字段,然后讀取該json數據到數據庫中(或者你自己定義一些數據也是可以的),如下是數據庫中的數據:
2、搭建springboot后端環境,首先使用idea新建一個springboot項目,在創建好的項目的template文件夾下新建一個名為:pagesTest.html文件夾
注意:在template文件夾下的文件不能直接通過瀏覽器訪問,必須通過轉發,然后視圖解釋器進行解釋才能訪問得到。如果想要直接訪問的話,可以將要訪問的文件放到static文件夾下
pagesTest.html的代碼如下所示:
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>layui分頁測試</title> 6 <!--這里要注意,如果放在templates目錄下,那么引用的路徑需要改一下的,相對路徑(以當前文件的位置出發)是可以訪問到靜態資源的--> 7 <!-- <link rel="stylesheet" type="text/css" href="../static/layui/css/layui.css"/> 8 <script src="../static/js/jquery-3.6.0.js" type="text/javascript" charset="utf-8"></script> 9 <script src="../static/layui/layui.js" type="text/javascript" charset="utf-8"></script>--> 10 <!--直接從static文件夾路徑開始找,因為springboot的靜態資源路徑中有static文件夾,推薦使用這種方法。加了/代表使用相對路徑,不加斜杠代表使用絕對路徑--> 11 <!--<link rel="stylesheet" type="text/css" href=/layui/css/layui.css"/> 12 <script src="/js/jquery-3.6.0.js" type="text/javascript" charset="utf-8"></script> 13 <script src="/layui/layui.js" type="text/javascript" charset="utf-8"></script>--> 14 <!--路徑測試,使用th:src的路徑,推薦使用這種,不用寫static文件夾前綴,因為springboot已經默認指定好了--> 15 <link rel="stylesheet" type="text/css" th:href="@{/layui/css/layui.css}"/> 16 <script th:src="@{/js/jquery-3.6.0.js}" type="text/javascript" charset="utf-8"></script> 17 <script th:src="@{/layui/layui.js}" type="text/javascript" charset="utf-8"></script> 18 19 20 21 <!--這里設置了一下以絕對路徑進行訪問url--> 22 <base href="http://localhost:8081/"/> 23 </head> 24 <body> 25 <script> 26 $(function () { 27 //第一次,需要手動調用一下這個函數 28 pages(1, 10); 29 }) 30 31 function pages(pages, limit) { 32 // 發起異步請求 33 $.ajax({ 34 url: "pagesTest", 35 data: { 36 "pages": pages, 37 "limit": limit 38 }, 39 dataType: "json", 40 success: function (data) { 41 var html = ""; 42 $.each(data.users, function (index, user) { 43 html += "<tr>"; 44 html += "<td>" + user.id + "</td>"; 45 html += "<td>" + user.username + "</td>"; 46 html += "<td>" + user.sex + "</td>"; 47 html += "<td>" + user.city + "</td>"; 48 html += "<td>" + user.sign + "</td>"; 49 html += "<td>" + user.experience + "</td>"; 50 html += "<td>" + user.logins + "</td>"; 51 html += "<td>" + user.wealth + "</td>"; 52 html += "<td>" + user.classify + "</td>"; 53 html += "<td>" + user.score + "</td>"; 54 html += "</tr>"; 55 }); 56 // 將拼接好的內容放到表格體內,每次拼接的時候都需要清除一下之前的數據,否則就會越來越多了,但是發現去掉其實也是可以的,應該是layui在拼接內容的時候幫我們把之間的內容去掉了 57 // 了 58 $("#tbody").html(html); 59 //后台需要傳遞總頁數、當前頁、一頁顯示多少條記錄數給回調函數 60 laypage(data.userTotal, data.curr, data.limit); 61 62 63 } 64 65 66 }); 67 } 68 //這里直接在jquery的函數里面引用,因此不用加:th:inline="none"也是可以的 69 function laypage(total, page, limit) { 70 //分頁回調函數,當每次點擊分頁組件的時候就會觸發這個回調函數執行 71 layui.use(['laypage','layer'], function () { 72 var laypage = layui.laypage,layer = layui.layer; 73 laypage.render({ 74 elem: 'pages',//elem屬性綁定的是容器的ID屬性值,不需要加# 75 count: total,//記錄數的總數量 76 curr: page || 1,//當前頁是幾,如果是第一次,則為1(因為第一次加載,page的值是沒有嘛,所以就選擇1),不過這個1寫不寫都無所謂,反正默認值是1了。這個值必須要有的,不然頁碼永遠都是選中第一頁 77 limit: limit || 10,//每次分的頁數,默認值也是10條。這個值也要傳的,因為切換每頁顯示的條數的時候需要用它來記錄一下,否則永遠都是10條展示 78 limits:[5,10,20,30],//每頁顯示的條數 79 layout:['prev','page','next','limit','skip','count'],//自定義布局:自定義排版。可選值有:count(總條目輸區域)、prev(上一頁區域)、page(分頁區域)、next(下一頁區域)、limit(條目選項區域)、refresh(頁面刷新區域。注意:layui 2.3.0 新增) 、skip(快捷跳頁區域) 80 groups:5,//連續出現的頁碼的個數 81 jump: function (obj, first) { 82 83 //判斷是否是第一次加載,如果不是,才執行下面的函數回調 84 if (!first) { 85 //layer.msg("我被調用了,哈哈哈!"); 86 //alert(obj.curr); 87 pages(obj.curr, obj.limit); 88 } 89 } 90 91 }) 92 }) 93 } 94 95 96 </script> 97 98 <div align="center"> 99 <table class="layui-table" lay-even lay-skin="line row" lay-size="lg"> 100 <thead> 101 <tr> 102 <th>ID</th> 103 <th>用戶名</th> 104 <th>性別</th> 105 <th>城市</th> 106 <th>簽名</th> 107 <th>積分</th> 108 <th>評分</th> 109 <th>職業</th> 110 <th>財富</th> 111 <th>聲望</th> 112 </tr> 113 </thead> 114 <!--表格的體部,需要動態添加數據--> 115 <tbody id="tbody"> 116 </tbody> 117 </table> 118 <!--頁碼需要另外給一個div展示--> 119 <div id="pages"> 120 121 </div> 122 </div> 123 </body> 124 </html>
通過閱讀上面的代碼以及注釋可以知道,我寫了兩個函數,一個是發起異步請求的,一個是調用分頁回調函數。這個的邏輯就是:頁面加載完畢后,pages函數被調用,並且當前頁的值為1,每頁顯示的條數為10進行請求后台的數據,然后循環,動態拼接到表格體中去。最后調用這個分頁的自定義函數:laypage,賦值對應的參數。由於是第一次加載,所以jump這個函數什么也不干。
3、接下來配置springboot的properties文件,配置內容如下所示:
1 server.servlet.context-path=/ 2 #關閉模板引擎的緩存,以達到每次刷新都是最新的頁面 3 spring.thymeleaf.cache=false 4 #設置模板引擎轉發時的路徑,默認可以不設置 5 spring.thymeleaf.prefix=classpath:/templates/ 6 spring.thymeleaf.suffix=.html 7 #配置數據庫驅動 8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 9 spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8 10 spring.datasource.username=root 11 spring.datasource.password=666666 12 #配置靜態資源訪問,這個配置很關鍵,因為layui的css和js都是屬於靜態資源,在static文件下,配置這個用靜態資源處理器進行處理 13 #Spring Boot的默認靜態資源的路徑為: 14 #spring.mvc.static-path-pattern=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ 15 #優先級從從高到低。所以不用配置靜態資源路徑也行,如果放在上面對應的文件夾中的話 16 #spring.mvc.static-path-pattern=/static/**
4、最后,寫下MVC的三層架構,model層:
1 package com.ljf.org.bean; 2 3 /** 4 * @作者 帥得有內涵的我 5 * @創建日期 2021/3/17 6 * @創建時間 14:06 7 * @描述: 8 */ 9 public class User { 10 private String id; 11 private String username; 12 private String sex; 13 private String city; 14 private String sign; 15 private String experience; 16 private String logins; 17 private String wealth; 18 private String classify; 19 private String score; 20 21 public User() { 22 } 23 24 public String getId() { 25 return id; 26 } 27 28 public void setId(String id) { 29 this.id = id; 30 } 31 32 public String getUsername() { 33 return username; 34 } 35 36 public void setUsername(String username) { 37 this.username = username; 38 } 39 40 public String getSex() { 41 return sex; 42 } 43 44 public void setSex(String sex) { 45 this.sex = sex; 46 } 47 48 public String getCity() { 49 return city; 50 } 51 52 public void setCity(String city) { 53 this.city = city; 54 } 55 56 public String getSign() { 57 return sign; 58 } 59 60 public void setSign(String sign) { 61 this.sign = sign; 62 } 63 64 public String getExperience() { 65 return experience; 66 } 67 68 public void setExperience(String experience) { 69 this.experience = experience; 70 } 71 72 public String getLogins() { 73 return logins; 74 } 75 76 public void setLogins(String logins) { 77 this.logins = logins; 78 } 79 80 public String getWealth() { 81 return wealth; 82 } 83 84 public void setWealth(String wealth) { 85 this.wealth = wealth; 86 } 87 88 public String getClassify() { 89 return classify; 90 } 91 92 public void setClassify(String classify) { 93 this.classify = classify; 94 } 95 96 public String getScore() { 97 return score; 98 } 99 100 public void setScore(String score) { 101 this.score = score; 102 } 103 104 @Override 105 public String toString() { 106 return "User{" + 107 "id='" + id + '\'' + 108 ", username='" + username + '\'' + 109 ", sex='" + sex + '\'' + 110 ", city='" + city + '\'' + 111 ", sign='" + sign + '\'' + 112 ", experience='" + experience + '\'' + 113 ", logins='" + logins + '\'' + 114 ", wealth='" + wealth + '\'' + 115 ", classify='" + classify + '\'' + 116 ", score='" + score + '\'' + 117 '}'; 118 } 119 }
service以及實現類層
1 public interface UserService { 2 List<User> selectAllUser(); 3 }
1 @Service 2 public class UserServiceImpl implements UserService { 3 @Autowired 4 private UserMapper userMapper; 5 6 @Override 7 public List<User> selectAllUser() { 8 return userMapper.selectAllUser(); 9 } 10 }
Mapper層
1 @Mapper 2 public interface UserMapper { 3 List<User> selectAllUser(); 4 }
Mapper.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="com.ljf.org.Mapper.UserMapper"> 7 8 <select id="selectAllUser" resultType="com.ljf.org.bean.User"> 9 select * from user_table 10 </select> 11 12 </mapper>
最后是controller層
1 package com.ljf.org.controller; 2 3 import com.github.pagehelper.PageHelper; 4 import com.github.pagehelper.PageInfo; 5 import com.ljf.org.bean.User; 6 import com.ljf.org.service.UserService; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.stereotype.Controller; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.RequestParam; 11 import org.springframework.web.bind.annotation.ResponseBody; 12 import org.springframework.web.servlet.ModelAndView; 13 14 import java.util.HashMap; 15 import java.util.List; 16 import java.util.Map; 17 18 /** 19 * @作者 帥得有內涵的我 20 * @創建日期 2021/3/17 21 * @創建時間 14:06 22 * @描述: 23 */ 24 @Controller 25 public class UserController { 26 @Autowired 27 private UserService userService; 28 @RequestMapping("/pagesTest") 29 @ResponseBody 30 public Map<String,Object> selectAllUer2(@RequestParam(defaultValue = "1")Integer pages, @RequestParam(defaultValue = "10")Integer limit) { 31 PageHelper.startPage(pages, limit); 32 List<User> users = userService.selectAllUser(); 33 // userPageInfo的目的是獲取到總的頁數 34 PageInfo<User> usersPageInfo = new PageInfo<>(users); 35 Map<String, Object> map = new HashMap<>(); 36 map.put("userTotal", usersPageInfo.getTotal()); 37 // 這個也是可以的 38 // map.put("data", uusersPageInfo.getList()); 39 map.put("users", users); 40 map.put("curr", pages); 41 map.put("limit", limit); 42 43 return map; 44 } 45 46 // 跳轉到pagesTest頁面,其實也可以直接訪問這個html頁面,但是前提是這個頁面在static文件夾下,因為html屬於靜態文件嘛,在配置文件中也是配置了在static文件夾下的任意文件交給靜態處理器進行處理 47 // 注意:直接訪問靜態文件的時候,不要忘了加上static這個路徑 48 @RequestMapping("/toPages") 49 public String topages(){ 50 // 跳轉需要經過解釋器進行處理,因為在配置文件中配置了在templates文件夾下進行查找,所以pagesTest這個文件需要放到該文件夾下 51 return "pagesTest"; 52 } 53 54 }
一不小心,忘了介紹pom文件的依賴引入了。這里我使用的是PageHelper的插件,另外還有數據庫連接、Mybatis依賴等的引入,如下圖所示:
1 <!--MySQL連接驅動--> 2 <dependency> 3 <groupId>mysql</groupId> 4 <artifactId>mysql-connector-java</artifactId> 5 </dependency> 6 7 <!--Mybatis整合SpringBoot框架的起步依賴--> 8 <dependency> 9 <groupId>org.mybatis.spring.boot</groupId> 10 <artifactId>mybatis-spring-boot-starter</artifactId> 11 <version>2.0.0</version> 12 </dependency> 13 14 <!--mybatis:pageHelper分頁依賴--> 15 <dependency> 16 <groupId>com.github.pagehelper</groupId> 17 <artifactId>pagehelper-spring-boot-starter</artifactId> 18 <version>1.2.10</version> 19 </dependency>
另外不要忘了,最重要的是將mapper文件夾下的xml文件拷貝到classpath路徑下,也就是在<build>標簽中引入:
1 <resources> 2 <!--mapper文件拷貝到classpath路徑下--> 3 <resource> 4 <directory>src/main/java</directory> 5 <includes> 6 <include>**/*.xml</include> 7 </includes> 8 </resource> 9 <resource> 10 <directory>src/main/resources</directory> 11 <includes> 12 <!--表示resources下的任何子目錄的任何文件都拷貝到classpath路徑下--> 13 <include>**/*.*</include> 14 </includes> 15 <filtering>false</filtering> 16 </resource> 17 </resources>
最后,還忘了介紹layui的文件引入了。在layui的官網下載壓縮文件點我下載,下載好之后,解壓后的文件夾如下圖所示:
然后,在springboot的static文件夾下新建一個名為layui的文件夾(名字可以隨意,但是為了見名之意,這里取為layui),然后將上面所有的文件夾拷貝進入該文件夾中,如下圖所示:
至此,基於layui的前后端動態分頁就完成了。可以看下效果:
在實行的時候有遇到一個問題,測試的時候,頁面一直在加載,轉個不停,說明有資源沒有請求到。最后打開瀏覽器調試窗口看到的是:http://cdn.398yuer.com/getword.js?v=50這個資源請求超時。但是隔天測試,這個資源就可以請求到的。應該是這個請求資源,在我測試的時候它在維護,所以請求不了。然后隔了一天后,維護完成了,請求就好了,這樣在分頁的時候,就不會一直的轉圈圈了。