摘要:前言給大家講解全棧通用分頁查詢碼字不易,點個關注轉載請說明開發工具思維導圖目錄一所需要的包二后端數據庫幫助類通用查詢分頁父類書籍層類分頁工具類三前端文件助手類前端界面四一所需要的包二后端數據庫
前言:給大家講解全棧通用分頁查詢
碼字不易,點個關注
轉載請說明!
開發工具:eclipse
思維導圖:
?
目錄
?DBAccess—數據庫助手類
package com.hpw.util;import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;/** * 提供了一組獲得或關閉數據庫對象的方法 * */public class DBAccess { private static String driver; private static String url; private static String user; private static String password; static {// 靜態塊執行一次,加載 驅動一次 try { InputStream is = DBAccess.class .getResourceAsStream("config.properties"); Properties properties = new Properties(); properties.load(is); driver = properties.getProperty("driver"); url = properties.getProperty("url"); user = properties.getProperty("user"); password = properties.getProperty("pwd"); Class.forName(driver); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 獲得數據連接對象 * * @return */ public static Connection getConnection() { try { Connection conn = DriverManager.getConnection(url, user, password); return conn; } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static void close(ResultSet rs) { if (null != rs) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Statement stmt) { if (null != stmt) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Connection conn) { if (null != conn) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Connection conn, Statement stmt, ResultSet rs) { close(rs); close(stmt); close(conn); } public static boolean isOracle() { return "oracle.jdbc.driver.OracleDriver".equals(driver); } public static boolean isSQLServer() { return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver); } public static boolean isMysql() { return "com.mysql.cj.jdbc.Driver".equals(driver); } public static void main(String[] args) { Connection conn = DBAccess.getConnection(); System.out.println(conn); DBAccess.close(conn); System.out.println("isOracle:" + isOracle()); System.out.println("isSQLServer:" + isSQLServer()); System.out.println("isMysql:" + isMysql()); System.out.println("數據庫連接(關閉)成功"); }}
?這里是對我們定義的XML文件進行解析來決定數據源,相比于之前定義的DBHelper類適用范圍更廣。
對應的dtl文件
#oracle9i#driver=oracle.jdbc.driver.OracleDriver#url=jdbc:oracle:thin:@localhost:1521:ora9#user=test#pwd=test#sql2005#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver#url=jdbc:sqlserver://localhost:1423;DatabaseName=test#user=sa#pwd=sa#sql2000#driver=com.microsoft.jdbc.sqlserver.SQLServerDriver#url=jdbc:microsoft:sqlserver://localhost:1433;databaseName=unit6DB#user=sa#pwd=888888#mysql8driver=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/mybatis_ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT&useSSL=trueuser=rootpwd=123456#mysql5#driver=com.mysql.jdbc.Driver#url=jdbc:mysql://127.0.0.1:3306/mybatis_ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT&useSSL=true#user=root#pwd=pppppp
EncodingFiter—編碼過濾類
package com.hpw.util;import java.io.IOException;import java.util.Iterator;import java.util.Map;import java.util.Set;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 中文亂碼處理 * */public class EncodingFiter implements Filter { private String encoding = "UTF-8";// 默認字符集 public EncodingFiter() { super(); } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // 中文處理必須放到 chain.doFilter(request, response)方法前面 res.setContentType("text/html;charset=" + this.encoding); if (req.getMethod().equalsIgnoreCase("post")) { req.setCharacterEncoding(this.encoding); } else { Map map = req.getParameterMap();// 保存所有參數名=參數值(數組)的Map集合 Set set = map.keySet();// 取出所有參數名 Iterator it = set.iterator(); while (it.hasNext()) { String name = (String) it.next(); String[] values = (String[]) map.get(name);// 取出參數值[注:參數值為一個數組] for (int i = 0; i < values.length; i++) { values[i] = new String(values[i].getBytes("ISO-8859-1"), this.encoding); } } } chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { String s = filterConfig.getInitParameter("encoding");// 讀取web.xml文件中配置的字符集 if (null != s && !s.trim().equals("")) { this.encoding = s.trim(); } }}
package dao;import java.lang.reflect.Field;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.ArrayList;import java.util.List;import com.hpw.util.DBAccess;import com.hpw.util.PageBean;import com.hpw.util.StringUtils;import entity.Book;public class BaseDao { /** * 所有Dao層的父類 提供解決方案 1.抽取變化部分作為參數 sql ,Class對象 結果集 2.抽取公共的父類,把重復性的代碼剝離出來 * * @param */ public List keylist(String sql, Class clz) throws Exception { // 不能確定集合裝什么東西 // 子類Dao繼承BaseDao子類傳遞什么類.class,那么集合中放到就是什么 List list = new ArrayList(); Connection con = DBAccess.getConnection(); PreparedStatement ps = con.prepareStatement(sql); ResultSet rs = ps.executeQuery(); while (rs.next()) { /** * 代碼不一樣 具體體現在 不同的表有不同字段 那么實體類對應的屬性就會不一樣 * * 1.實例化了一個對象 2.從ResultSet的對象的屬性獲取值(bid)獲取值賦值給了前面的實例化對象 3.把已經賦值了的對象 ,添加到集合中 */ T t = clz.newInstance(); Field[] fields = clz.getDeclaredFields(); for (Field f : fields) { f.setAccessible(true); f.set(t, rs.getObject(f.getName())); } list.add(t); } return list; } /** * 通用的分頁查詢 * * @param sql * @param clz * @return * @throws Exception */ public List executeQuery(String sql, Class clz ,PageBean pageBean) throws Exception { List list = new ArrayList(); Connection con = DBAccess.getConnection(); PreparedStatement ps = null; ResultSet rs = null; /* * 是否需要分頁? * 無需分頁 (項目中的下拉框,查詢條件教員下拉框 無需分頁) * 必須分頁(項目中列表類需求,訂單列表,商品列表,學生列表) */ if(pageBean != null && pageBean.isPagination()) { String countSQL = getcountSQL(sql); ps = con.prepareStatement(countSQL); rs = ps.executeQuery(); if(rs.next()) { pageBean.setTotal(String.valueOf(rs.getObject(1))); } //挪動到下面,是因為最后才處理返回的結果集 //必須分頁(列表需求) // *-- sql=SELECT * FROM t_mvc_book WHERE bname like "%圣墟%" // -- pagesql=sql limit (page-1)*rows,rows 對應某一頁的數據 // -- countsql=select COUNT(1) from (sql)t; 符合條件的總記錄數 String pageSQL = getpageSQL(sql,pageBean);//符合條件的某一頁數據 ps = con.prepareStatement(pageSQL); rs = ps.executeQuery(); }else { //不分頁(select需求) ps = con.prepareStatement(sql);//符合條件的所有數據 rs = ps.executeQuery(); } while (rs.next()) { T t = clz.newInstance(); Field[] fields = clz.getDeclaredFields(); for (Field f : fields) { f.setAccessible(true); f.set(t, rs.getObject(f.getName())); } list.add(t); } return list; } /** * 將原生sql轉換成countsql * @param sql * @return */ private String getcountSQL(String sql) { //countsql=select COUNT(1) from (sql)t;符合條件的總記錄數 return "select count(1) from ("+sql+") t"; } /** * 將原生SQL轉換成pageSQL * @param sql * @param pageBean * @return */ private String getpageSQL(String sql,PageBean pageBean) { //(this.page - 1) * this.rows; //sql:原生sql (page-1)*rows:起始下標 rows:多少頁 //pagesql=sql limit (page-1)*rows,rows return sql +" limit "+ pageBean.getStartIndex() +","+pageBean.getRows(); }}
package dao;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import com.hpw.util.DBAccess;import com.hpw.util.PageBean;import com.hpw.util.StringUtils;import entity.Book;public class BookDao extends BaseDao{ /** * * 簡單的查詢方法 (思路) * 1.建立數據庫連接 * 2.預定義對象PrepareStatement * 3.查詢結果集 * 4.處理結果集 * * 不足之處 * 換一張表查詢 t_jsoup_article * 1.以上三步 (建立數據庫連接 ,預定義對象PrepareStatement,查詢結果集 )都是重復的 * 2.都是返回數據庫表對應的集合 * 3.都是要處理結果集 ResultSet rs * 代碼不一樣 具體體現在 不同的表有不同字段 那么實體類對應的屬性就會不一樣 * * 總結:需要寫大量的重復代碼 , 系統中的查詢功能越多 重復代碼量越大 * * 提供解決方案 * 1.抽取變化部分作為參數 * sql ,Class對象 結果集 * 2.抽取公共的父類,把重復性的代碼剝離出來 */ public List keylist(Book book) throws Exception { List book1 = new ArrayList(); String sql = "select * from t_mvc_book where 1=1"; // 書籍名稱 String bname = book.getBname(); // 書籍名稱模糊查詢 是前臺jsp界面傳數據 if (StringUtils.isNotBlank(bname)) { sql += " and bname like "%" + bname + "%" "; } Connection con = DBAccess.getConnection(); PreparedStatement ps = con.prepareStatement(sql); ResultSet rs = ps.executeQuery(); while (rs.next()) { book1.add(new Book(rs.getInt("bid"), rs.getString("bname"), rs.getFloat("price"))); } return book1; } public List list2(Book book) throws Exception{ String sql = "select * from t_mvc_book where 1=1"; // 書籍名稱 String bname = book.getBname(); // 書籍名稱模糊查詢 是前臺jsp界面傳數據 if (StringUtils.isNotBlank(bname)) { sql += " and bname like "%" + bname + "%" "; } return super.keylist(sql, Book.class); } /** * 測試通用分頁查詢 * @param book * @param pageBean * @return * @throws Exception */ public List list3(Book book,PageBean pageBean) throws Exception{ String sql = "select * from t_mvc_book where 1=1"; // 書籍名稱 String bname = book.getBname(); // 書籍名稱模糊查詢 是前臺jsp界面傳數據 if (StringUtils.isNotBlank(bname)) { sql += " and bname like "%"+bname+"%""; } return super.executeQuery(sql, Book.class, pageBean); } /** * 思考: * 在項目中大量的出現分頁的需要(訂單列表,商品列表,學生列表...) * 目標: * 想要做一個通用的分頁查詢,子類去繼承父類,自帶了分頁功能,并且代碼量極少; * 最終當碰到分頁的需求的時候,只要寫少量的代碼 * 實現: * mysql分頁 * 分頁通常有關鍵的元素 第n頁 、顯式數目(rows)、符合條件的總記錄數(total) *-- sql=SELECT * FROM t_mvc_book WHERE bname like "%圣墟%" -- pagesql=sql limit (page-1)*rows,rows -- countsql=select COUNT(1) from (sql)t; * * 編碼: * 2.1原先List集合中返回的是符合條件的所有數據,現在我需要發揮第page頁的數據 * 那么意味著sql要加工成pageSql * 2.2需要分頁,那么要求出符合條件的總記錄數,保存到pagebean中,意味著sql要加工成countSql * 共85條數據 1頁10條 總共9頁 共70條數據 1頁10條 總共7頁 通過上面的數字,說明了要得出共n頁,那么必須求出總記錄數 共n頁的算法 : total % rows == 0 ? total / rows :total / rows +1; */ public static void main(String[] args) throws Exception { BookDao bd = new BookDao(); Book book = new Book(); book.setBname("圣墟"); //List list = bd.keylist(book); //List list = bd.list2(book); PageBean pageBean = new PageBean(); //查第二頁的數據 模擬從jsp傳遞頁碼2到后臺 //pageBean.setPage(2); //項目開發中 下拉框的需求 不分頁 模擬從jsp傳遞 不分頁的信息pagination=false pageBean.setPagination(false); List list = bd.list3(book, pageBean); for (Book book2 : list) { System.out.println(book2); } }}
?在父類中對key進行非空判斷是為了判斷用戶是否在輸入框中輸入值進行查詢,如果點擊下一頁之類的操作,key是上一次查詢請求的值,改變的只是頁碼參數,由PageBean這個類對上一次請求參數進行保存。
package com.hpw.util;import java.io.StringBufferInputStream;import java.util.HashMap;import java.util.Map;import javax.servlet.http.HttpServletRequest;import com.sun.net.httpserver.HttpServer;/** * 分頁工具類 * */public class PageBean { private int page = 1;// 頁碼 private int rows = 10;// 頁大小 private int total = 0;// 總記錄數 private boolean pagination = true;// 是否分頁 private String url;// 保存上一次請求的URL private Map paramMap = new HashMap();// 保存上一次請求的參數 /** * 初始化pagebean ,保存上一次請求的重要參數 */ public void setRequest(HttpServletRequest req) { // 1.1需要保存上一次請求的URL this.setUrl(req.getRequestURL().toString()); // 1.2需要保存上一次請求的參數 this.setParamMap(req.getParameterMap()); // 1.3需要保存上一次請求的分頁設置 this.setPagination(req.getParameter("pagination")); // 1.4需要保存上一次請求的展示條數 this.setRows(req.getParameter("rows")); // 1.5初始化的頁碼 this.setPage(req.getParameter("page")); } public void setPage(String page) { // TODO Auto-generated method stub if(StringUtils.isNotBlank(page)) { this.setPage(Integer.valueOf(page)); } } public void setRows(String rows) { // TODO Auto-generated method stub if(StringUtils.isNotBlank(rows)) { this.setRows(Integer.valueOf(rows)); } } public void setPagination(String pagination) { // TODO Auto-generated method stub// 只有在前臺jsp填寫了pagination=false,才代表不分頁 if(StringUtils.isNotBlank(pagination)) { this.setPagination(!"false".equals(pagination)); } } public void setPagination(boolean pagination) { this.pagination = pagination; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map getParamMap() { return paramMap; } public void setParamMap(Map paramMap) { this.paramMap = paramMap; } public PageBean() { super(); } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getRows() { return rows; } public void setRows(int rows) { this.rows = rows; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public void setTotal(String total) { this.total = Integer.parseInt(total); } public boolean isPagination() { return pagination; } /** * 獲得起始記錄的下標 * * @return */ public int getStartIndex() { return (this.page - 1) * this.rows; } /** * 最大頁 * * @return */ public int maxPage() { return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows + 1; } /** * 下一頁 */ public int nextPage() { // 如果當前頁小于最大頁,那就下一頁為當前頁加一,如果不小于,說明當前頁就是最大頁,那就無需加一 return this.page < this.maxPage() ? this.page + 1 : this.page; } /** * 上一頁 * * @return */ public int previousPage() { return this.page > 1 ? this.page - 1 : this.page; } @Override public String toString() { return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]"; }}
有了前端通用分頁,在每一個頁面中如果需要分頁,僅僅需要在jsp界面中編寫我們自己定義好的分頁標簽。將重復代碼都提取到了標簽助手類中。
hpw 1.1 core library hpw core 1.1 hpw http://hpw11.myjsp page com.hpw.tag.pageTag JSP pageBean true true
package com.hpw.tag;import java.io.IOException;import java.util.Map;import java.util.Map.Entry;import java.util.Set;import javax.servlet.jsp.JspException;import javax.servlet.jsp.JspWriter;import javax.servlet.jsp.tagext.BodyTagSupport;import com.hpw.util.PageBean;public class pageTag extends BodyTagSupport { private PageBean pageBean;// 包含了所有分頁相關的元素 public PageBean getPageBean() { return pageBean; } public void setPageBean(PageBean pageBean) { this.pageBean = pageBean; } @Override public int doStartTag() throws JspException { // TODO Auto-generated method stub // 沒有標簽體,要輸出內容 JspWriter out = pageContext.getOut(); try { out.print(toHTML()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return super.doStartTag(); } private String toHTML() { StringBuffer sb = new StringBuffer(); // 隱藏的form表單 這個就是上一次請求下次重新發的奧義所在 sb.append(" "); // 分頁條 sb.append(" "); // 分頁執行的jsp代碼 sb.append(""); return sb.toString(); }}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@taglib uri="http://hpw11.myjsp" prefix="p"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>書籍列表 書籍ID 書籍名 價格 ${b.bid } ${b.bname } ${b.price }
新增
效果展示:
?下面的分頁在jsp界面僅用一行就能完成,其他界面還需要也一樣,不用每個界面再寫HTML和JS來實現這個分頁條的效果!重復代碼。能有這些效果完全少不了PageBean對象!!! ?
package com.hpw.web;import java.io.IOException;import java.util.List;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.hpw.util.PageBean;import dao.BookDao;import entity.Book;@WebServlet("/book/search")public class BookServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /** * 目標: * 痛點:每次做分頁需求的時候,都會有大量的重復的后臺代碼,以及前臺代碼 * 后臺代碼重復問題已解決 * 前臺重復代碼問題 * 1.大量的前臺html重復 * 2.大量的javaScript代碼 * 目標: * 定義一個標簽 * * 無需寫任何的html以及js,就可以完成前端分頁 * 分析: * 1. 前臺分頁 后一次請求相較于上一次只不過是頁碼改變了 * 1.1需要保存上一次請的的URL * 1.2需要保留上一次請求的參數 * 1.3需要保存上一頁的分頁設置 pagination * 1.4需要保存上一次的展示條目數 * 1.5初始化請求的頁碼 page * 2.開發自定義jsp標簽(page標簽) * 定義pagebean 因為pagebean中包含了分頁中所有的元素 (page/rows/pagination/total/nexPage/previouPage/maxPage) * * 前臺jsp傳遞書名圣墟 , 后臺接收 req.getParameter("bname") * 愛好:傳遞一個數組 藍球,足球...hobby String[] hobbys = req.getParameterValues("") * * bname String 這個數組長度是為1的 * hobby String [] 可能會有很多個 * ... * 本方法的作用是接收jsp頁面傳遞到后臺的參數值鍵值對,也就是把parameteMap遍歷,可以拿到bname以及hobby Map parameteMap = req.getParameterMap(); */ BookDao bookDao=new BookDao(); Book book=new Book(); book.setBname(req.getParameter("bname")); PageBean pageBean=new PageBean(); pageBean.setRequest(req); try { List list3 = bookDao.list3(book, pageBean); req.setAttribute("books", list3); req.setAttribute("pageBean", pageBean); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } req.getRequestDispatcher("/index.jsp").forward(req, resp); //本方法的作用是接收jsp頁面傳遞到后臺的參數值鍵值對,也就是把parameteMap遍歷,可以拿到bname以及hobby// Map parameteMap = req.getParameterMap(); }}
前端用戶發送請求進過我們的一系列處理之后返回一個符合用戶請求的前端頁面呈現!!!帶著這個流程去查看學習對應地方的代碼。
這里的核心是PageBean,它幾乎每個流程都在,它由用戶需求決定,然后決定數據,再決定分頁條!!!
到這里就結束了,我依舊是那個學IT的小學生?
歡迎大佬指點?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119210.html
摘要:通用是為了解決使用中的基本操作,使用它可以很方便的進行開發,可以節省開發人員大量的時間。當該參數設置為時,時會查詢第一頁,超過總數時,會查詢最后一頁。 SpringBoot 是為了簡化 Spring 應用的創建、運行、調試、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規范,引入相關的依賴就可以輕易的搭建出一個 WEB 工...
摘要:但能拷貝圖粘貼后不失真通常是收費富文本編輯器才具備的能力。是否支持編程語言高亮,例如按,語言高亮是否支持數學公式等等因此選擇了兩款富文本編輯器,支持截屏粘貼,當做跟蹤系統時這個功能特別有用。 一、Web應用技術棧 在開發Web應用時,通常會使用到以下技術棧: showImg(https://segmentfault.com/img/bVbwceG);對應這些技術棧都已有相應的開源產品...
摘要:代碼自動生成底層服務有很多通用的,利用代碼生成最好不過了,這里作者將代碼生成放在中的,避免與正式代碼沖突。主要通過來實現,項目中的模板文件可以自行定義。相互學習,共同進步 從零開始學習Spring Boot也有幾天時間了,項目已經不允許我這么慢慢學習了,急需底層變現實現一套簡單的Restful API用于業務支撐。 于是在GitHub上找到了一個不錯的demo,直接看demo搭建自己的...
摘要:前端一種新一代高性能全棧開發實踐背景本項目將使用配合最簡單的邏輯來展示一個基于的全新一代高性能全棧開發實踐的為什么是對于為何不是等著名框架,或許可能很多人會產生疑惑,本身和非常的相似,而它的出現,不僅是大大改進過去時代性能低下通病,外加配 SanicCRUD-vue Sanic + 前端MVVM 一種新一代Python高性能全棧開發實踐showImg(https://segmentfa...
摘要:前端一種新一代高性能全棧開發實踐背景本項目將使用配合最簡單的邏輯來展示一個基于的全新一代高性能全棧開發實踐的為什么是對于為何不是等著名框架,或許可能很多人會產生疑惑,本身和非常的相似,而它的出現,不僅是大大改進過去時代性能低下通病,外加配 SanicCRUD-vue Sanic + 前端MVVM 一種新一代Python高性能全棧開發實踐showImg(https://segmentfa...
閱讀 3166·2021-11-23 09:51
閱讀 678·2021-10-14 09:43
閱讀 3200·2021-09-06 15:00
閱讀 2403·2019-08-30 15:54
閱讀 2557·2019-08-30 13:58
閱讀 1840·2019-08-29 13:18
閱讀 1372·2019-08-27 10:58
閱讀 506·2019-08-27 10:53