對於搜索功能結果展示的分頁處理,首先應該明確的是目前頁,每頁顯示數據的條數,以及總的數據數目。
接下來,通過這些數據來計算出總的顯示頁數,以及數據庫語句limit查詢的范圍。
Object result:是分頁顯示的數據,這里設置為Object的目的是為了方便通過JSON傳輸。
1 public class PageBean { 2 private int pageNum; // 當前頁,從請求那邊傳過來 3 private int pageSize; // 每頁顯示的數據條數 4 private int totalRecord; //總的記錄條數 5 6 private int totalPage; // 總頁數:totalRecord/pageSize 7 private int startIndex; // 從第幾行開始查數據 8 9 private Object result; // JSON封裝好的數據 10 11 // 分頁顯示的頁數,比如在頁數上顯示1,2,3,4,5.start就是1,end就是5 12 private int start; 13 private int end; 14 15 public PageBean(int pageNum, int pageSize, int totalRecord) { 16 this.pageNum = pageNum; 17 this.pageSize = pageSize; 18 this.totalRecord = totalRecord; 19 20 // 計算總頁數 21 if (totalRecord % pageSize == 0) {// 總的數據正好整除每頁所顯示數據 22 this.totalPage = totalRecord / pageSize; 23 } else { 24 // 不整除,頁數+1 25 this.totalPage = totalRecord / pageSize + 1; 26 } 27 28 // 數據庫查詢索引 29 this.startIndex = (pageNum - 1) * pageSize; 30 // 顯示5頁 31 this.start = 1; 32 this.end = 5; 33 34 // 顯示頁數的算法 35 if (totalPage <= 5) {// 總頁數小於5頁 36 this.end = this.totalPage; 37 } else { 38 // 總頁數是大於5的,那么就要根據當前是第幾頁來判斷顯示的start和end 39 this.start = pageNum - 2; 40 this.end = pageNum + 2; 41 42 if (start <= 0) { 43 this.start = 1; 44 this.end = 5; 45 } 46 if (end > this.totalPage) { 47 this.end = totalPage; 48 this.start = end - 4; 49 } 50 } 51 52 } 53 54 public int getPageNum() { 55 return pageNum; 56 } 57 58 public void setPageNum(int pageNum) { 59 this.pageNum = pageNum; 60 } 61 62 public int getPageSize() { 63 return pageSize; 64 } 65 66 public void setPageSize(int pageSize) { 67 this.pageSize = pageSize; 68 } 69 70 public int getTotalRecord() { 71 return totalRecord; 72 } 73 74 public void setTotalRecord(int totalRecord) { 75 this.totalRecord = totalRecord; 76 } 77 78 public int getTotalPage() { 79 return totalPage; 80 } 81 82 public void setTotalPage(int totalPage) { 83 this.totalPage = totalPage; 84 } 85 86 public int getStartIndex() { 87 return startIndex; 88 } 89 90 public void setStartIndex(int startIndex) { 91 this.startIndex = startIndex; 92 } 93 94 public Object getResult() { 95 return result; 96 } 97 98 public void setResult(Object result) { 99 this.result = result; 100 } 101 102 public int getStart() { 103 return start; 104 } 105 106 public void setStart(int start) { 107 this.start = start; 108 } 109 110 public int getEnd() { 111 return end; 112 } 113 114 public void setEnd(int end) { 115 this.end = end; 116 } 117 118 119 }
持久層主要是得到PageBean對象里的startIndex和pageSize數據來進行limit查詢
代碼如下:

1 public class SearchUtils { 2 /** 3 * 通過模糊匹配帖子標題查詢所有帖子信息(themeId,themeTitle,createTime,userID,nickName,boardId, 4 * boardNamereadCount,postCount,) 5 * 6 * @param keyWord 7 * @return 8 */ 9 public static List<Object> searchByThemeTitle(String keyWord) { 10 List<Object> searchResult = null; 11 String sql = "select bt.themeId, bt.themeTitle,bt.createTime,bt.userID,u.nickName,bt.boardId,sb.smallBoardName,bt.readCount,bt.postCount,bt.content, bb.bigBoardName from bbs_theme bt, `user` u, smallboard sb, bigboard bb where bt.boardId = sb.smallBoardId and bt.userID = u.userID and sb.parentId=bb.bigBoardId and bt.themeTitle like '%"+keyWord+"%' order by bt.readCount DESC"; 12 Session session = HibernateSessionFactory.openSession(); 13 try { 14 SQLQuery sqlQuery = session.createSQLQuery(sql); 15 searchResult = sqlQuery.list(); 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 session.close(); 20 } 21 return searchResult; 22 } 23 24 /** 25 * 分頁查詢 26 * @param start 27 * @param end 28 * @param keyWord 29 * @return 30 */ 31 public static List<Object> searchByThemeTitle(int start, int end, String keyWord) { 32 List<Object> searchResult = null; 33 String sql = "select bt.themeId, bt.themeTitle,bt.createTime,bt.userID,u.nickName,bt.boardId,sb.smallBoardName,bt.readCount,bt.postCount,bt.content, bb.bigBoardName from bbs_theme bt, `user` u, smallboard sb, bigboard bb where bt.boardId = sb.smallBoardId and bt.userID = u.userID and sb.parentId=bb.bigBoardId and bt.themeTitle like '%"+keyWord+"%' order by bt.readCount DESC limit "+start+","+end; 34 Session session = HibernateSessionFactory.openSession(); 35 try { 36 SQLQuery sqlQuery = session.createSQLQuery(sql); 37 searchResult = sqlQuery.list(); 38 } catch (Exception e) { 39 e.printStackTrace(); 40 } finally { 41 session.close(); 42 } 43 return searchResult; 44 } 45 }
業務邏輯層主要負責創建PageBean對象並封裝數據
代碼如下:
1 public class SearchServiceImpl implements SearchService { 2 3 @Override 4 public String searchByTitle(int pageNum, int pageSize, String keyWord) { 5 List<Object> searchResult = SearchUtils.searchByThemeTitle(keyWord); 6 // 查詢的數據總數 7 int totalRecord = searchResult.size(); 8 // 創建pageBean對象 9 PageBean pb = new PageBean(pageNum, pageSize, totalRecord); 10 11 // 獲取查詢的索引 12 int startIndex = pb.getStartIndex(); 13 14 List<Object> searchForPageResult = SearchUtils.searchByThemeTitle(startIndex, pageSize, keyWord); 15 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 16 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 17 for (Object obj : searchForPageResult) { 18 Object[] objArray = (Object[]) obj; 19 Map<String, Object> map = new HashMap<String, Object>(); 20 map.put("themeId", objArray[0]); 21 map.put("themeTitle", objArray[1]); 22 // 解決從MySQL讀出的timestamp類型的數據中后面跟着.0的問題 23 try { 24 Date date = sdf.parse(String.valueOf(objArray[2])); 25 String createTime = sdf.format(date); 26 map.put("createTime", createTime); 27 } catch (ParseException e) { 28 e.printStackTrace(); 29 } 30 map.put("userID", objArray[3]); 31 map.put("nickName", objArray[4]); 32 map.put("boardId", objArray[5]); 33 map.put("smallBoardName", objArray[6]); 34 map.put("readCount", objArray[7]); 35 map.put("postCount", objArray[8]); 36 map.put("content", objArray[9]); 37 map.put("bigboardName", objArray[10]); 38 list.add(map); 39 } 40 pb.setResult(list); 41 String result = JSON.toJSONString(pb); 42 return result; 43 } 44 45 }
關於servlet層,應該為了考慮到微信小程序端的數據傳輸,所以關於數據的賦值是通過JSON傳輸,web端通過ajax來請求,接受數據。
代碼如下:
1 public class SearchServlet extends HttpServlet { 2 3 // 調用service 4 private SearchService searchService = new SearchServiceImpl(); 5 // 獲取輸出流 6 private PrintWriter out; 7 8 public void doGet(HttpServletRequest request, HttpServletResponse response) 9 throws ServletException, IOException { 10 // 設置編碼 11 request.setCharacterEncoding("UTF-8"); 12 response.setContentType("text/html;charset=utf-8"); 13 // 獲取前端數據 14 // 獲取搜索的類型 15 // String type = request.getParameter("searchType"); 16 // 目前就先實現關於帖子標題的模糊查詢 17 // 獲取關鍵詞 18 String kw = request.getParameter("kw"); 19 // 當前頁,默認為1 20 int pageNum = 1; 21 // 每頁顯示的記錄數 22 int pageSize = 5; 23 String result; 24 if ("".equals(kw) || kw == null) { 25 result = ""; 26 } else { 27 String keyWord = URLDecoder.decode(kw, "UTF-8"); 28 if (request.getParameter("pn") == null) {// 沒有pageNum,則默認為1 29 result = searchService.searchByTitle(pageNum, pageSize,keyWord); 30 } else { // 獲取當前頁 31 pageNum = Integer.valueOf(request.getParameter("pn")); 32 result = searchService.searchByTitle(pageNum, pageSize,keyWord); 33 } 34 } 35 response.setContentType("text/json;charset=utf-8"); 36 out = response.getWriter(); 37 out.write(result); 38 out.flush(); 39 } 40 41 42 public void doPost(HttpServletRequest request, HttpServletResponse response) 43 throws ServletException, IOException { 44 doGet(request, response); 45 } 46 47 }
接下來,就是web端獲取數據后如何處理?
這里通過Ajax請求數據填充網頁。
代碼如下:
1 $(document).ready(getSearch()); 2 3 // 獲取搜索結果 4 function getSearch() { 5 var url=location.search; 6 var k = url.split("=", 2)[1].split("&")[0]; 7 var kw = decodeURI(decodeURI(k)); 8 //console.log(url); 9 //console.log(decodeURI(decodeURI(kw))); 10 $.ajax({ 11 type: "GET", 12 url: "/DaTangBBs/SearchServlet"+url, 13 success: function(r) { 14 console.log(r); 15 // console.log(r.result); 16 var result = "結果: <em>找到 “<span>"+kw+"</span>” 相關內容"+r.totalRecord+"個</em>"; 17 $("#result").html(result); 18 var res = r.result; 19 var str = ""; 20 if (res.length == 0) { 21 str += "<p>對不起,沒有找到匹配結果</p>"; 22 } 23 else { 24 str += "<ul>"; 25 for (var key in res) { 26 // console.log(res[key].themeTitle); 27 var content = cutstring(htmlToText(res[key].content), 80); 28 // console.log(content); 29 str += "<li class='pbw'><h3 class='xs3'>"; 30 str += "<a href='/DaTangBBs/web/show.jsp?postID="+res[key].themeId+"&userID="+res[key].userID+"&method=read' target='_blank'>"+res[key].themeTitle+"</a>"; 31 str += "</h3>"; 32 str += "<p class='xg1'>"+res[key].postCount+"個回復 - "+res[key].readCount+"次查看</p>"; 33 str += "<p class='content'>"+content+"</p>"; 34 str += "<p><span>"+res[key].createTime+"</span> - <span>"; 35 str += "<a href='/DaTangBBs/web/userInfo/user.jsp?userID="+res[key].userID+"' target='_blank'>"+res[key].nickName+"</a></span> - <span>"; 36 str += "<a href='/DaTangBBs/web/plate.jsp?key="+encodeURI(encodeURI(res[key].bigboardName))+"&value="+encodeURI(encodeURI(res[key].smallBoardName))+"' target='_blank' class='xi1'>"+res[key].smallBoardName+"</a></span>"; 37 } 38 str += "</ul>"; 39 40 } 41 $("#threadlist").html(str); 42 var page = ""; 43 if (r.start == 1) {// 從第一頁開始,不顯示首頁 44 } else { 45 page += "<a href='/DaTangBBs/web/search.html?kw="+k+"&pn="+1+"'>首頁</a>"; 46 } 47 if (r.pageNum == 1) { 48 // 當前頁為首頁,不顯示上一頁 49 } else { 50 page += "<a href='/DaTangBBs/web/search.html?kw="+k+"&pn="+(r.pageNum-1)+"'>上一頁</a>"; 51 } 52 for (var i = r.start; i <= r.end; i++) { 53 if (i == r.pageNum) { 54 page += "<strong>"+i+"</strong>"; 55 } else { 56 page += "<a href='/DaTangBBs/web/search.html?kw="+k+"&pn="+i+"'>"+i+"</a>"; 57 } 58 59 } 60 61 if (r.pageNum == r.totalPage || r.totalPage == 0) { 62 // 當前頁為尾頁或者沒有搜索結果,不顯示下一頁 63 }else { 64 page += "<a href='/DaTangBBs/web/search.html?kw="+k+"&pn="+(r.pageNum+1)+"'>下一頁</a>"; 65 } 66 if (r.end == r.totalPage) { 67 // 不顯示尾頁 68 } else { 69 page += "<a href='/DaTangBBs/web/search.html?kw="+k+"&pn="+r.totalPage+"'>尾頁</a>"; 70 } 71 $("#pageList").html(page); 72 73 } 74 }); 75 } 76 77 // 將HTML轉為文本 78 function htmlToText(hcontent) { 79 var content = hcontent; 80 content = content.replace(/(\n)/g, ""); 81 content = content.replace(/(\t)/g, ""); 82 content = content.replace(/(\r)/g, ""); 83 content = content.replace(/<\/?[^>]*>/g, ""); // 匹配<..><../> 將其替換為"" 84 content = content.replace(/\s*/g, ""); 85 return content; 86 } 87 88 // 截取內容顯示 89 function cutstring(str, len) { 90 if (str.length <= len) { 91 return str; 92 } else { 93 str = str.substr(0,len) + "..."; 94 return str; 95 } 96 }
這里再來一小段關於分頁導航欄的css樣式
1 // 導航欄css 2 .pgs { 3 4 } 5 6 .mbm { 7 margin-bottom: 10px !important; 8 } 9 10 .c1 { 11 zoom:1; 12 } 13 14 .pg { 15 float: none; 16 line-height:33px; 17 } 18 19 .pg a, .pg strong { 20 float:left; 21 display:inline; 22 margin-left:4px; 23 padding:0 15px; 24 height:33px; 25 border:1px solid; 26 border-color: #e4e4e4; 27 background-color:#FFF; 28 background-repeat:no-repeat; 29 color:#555; 30 overflow:hidden; 31 text-decoration:none; 32 } 33 34 .pg strong { 35 background-color:#00aa98; 36 color:#FFF; 37 }
最后是效果圖:
在這里,要感謝@一杯涼茶的博文。
參考博文:https://www.cnblogs.com/whgk/p/6474396.html