• 自定义通用分页标签01


    目录

    💛首先,我们需要准备一个pageBean对象:

    💚然后,就是后台数据查询了

    💙重构-提取公用方法


    我们为什么要制作通用分页?🤔

    简单而言就是方便我们查询数据。

    在制作自定义标签之前,我们先想一下分页是神马样子?

    是不是酱紫?

     好了,了解完分页标签是啥样之后就容易制作了。

    💛首先,我们需要准备一个pageBean对象:

    1. package com.ljq.mymvc.util;
    2. import java.util.Map;
    3. import javax.servlet.http.HttpServletRequest;
    4. import com.mysql.jdbc.StringUtils;
    5. /**
    6. * 分页实体类
    7. *
    8. * @author 一麟
    9. *
    10. */
    11. public class PageBean {
    12. private int page = 1;// 定义初始页码
    13. private int rows = 6;// 定义每页数据
    14. private int total = 0;// 初始化总共页数
    15. private boolean pagination = true;// 判断是否分页
    16. private String url;// 记录查询的url
    17. private Map parameterMap;// 用于存放请求参数,用于生成隐藏域中的元素
    18. /**
    19. * 初始化分页对象
    20. *
    21. * @param req
    22. */
    23. public void setRequest(HttpServletRequest req) {
    24. // 如果传送的数值没有发生变化就不让页面属性改变
    25. if (!StringUtils.isNullOrEmpty(req.getParameter("page")))
    26. this.page = Integer.valueOf(req.getParameter("page"));
    27. if (!StringUtils.isNullOrEmpty(req.getParameter("rows")))
    28. this.rows = Integer.valueOf(req.getParameter("rows"));
    29. if (!StringUtils.isNullOrEmpty(req.getParameter("pagination")))
    30. this.pagination = Boolean.valueOf(req.getParameter("pagination"));
    31. this.url = req.getRequestURI();// 將请求的路径赋值给页面对象的url
    32. this.parameterMap = req.getParameterMap();// 获得参数集合
    33. // 将分页对象存入req中
    34. req.setAttribute("pageBean", this);
    35. }
    36. public int getPage() {
    37. return page;
    38. }
    39. public void setPage(int page) {
    40. this.page = page;
    41. }
    42. public int getRows() {
    43. return rows;
    44. }
    45. public void setRows(int rows) {
    46. this.rows = rows;
    47. }
    48. public int getTotal() {
    49. return total;
    50. }
    51. public void setTotal(int total) {
    52. this.total = total;
    53. }
    54. public boolean isPagination() {
    55. return pagination;
    56. }
    57. public void setPagination(boolean pagination) {
    58. this.pagination = pagination;
    59. }
    60. public String getUrl() {
    61. return url;
    62. }
    63. public void setUrl(String url) {
    64. this.url = url;
    65. }
    66. public Map getParameterMap() {
    67. return parameterMap;
    68. }
    69. public void setParameterMap(Map parameterMap) {
    70. this.parameterMap = parameterMap;
    71. }
    72. /**
    73. * 获取初始位置
    74. * @return
    75. */
    76. public int getStartIndex() {
    77. return (this.page - 1) * this.rows;
    78. }
    79. /**
    80. * 获取总页数
    81. * @return
    82. */
    83. public int getTotalPage() {
    84. if (this.getTotal() % this.rows == 0) {// 刚好取整为0,那么总页数就是取整值
    85. return this.getTotal() / this.rows;
    86. } else {
    87. return this.getTotal() / this.rows + 1;// 取整值不为0,就说明有溢出则+1
    88. }
    89. }
    90. /**
    91. * 获取上一页
    92. * @return
    93. */
    94. public int getPreviousPage() {
    95. return this.page - 1 > 0 ? this.page - 1 : 1;
    96. }
    97. /**
    98. * 获取下一页
    99. * @return
    100. */
    101. public int getNextPage() {
    102. return this.page + 1 > getTotalPage() ? getTotalPage() : this.page + 1;
    103. }
    104. }

    💚然后,就是后台数据查询了

    下面呢,就是分页查询的流程:

                    

     当然,在编写查询语句之前少不了一件东西:

    就是数据库工具类了DBHepler:

    1. package com.ljq.mymvc.util;
    2. import java.io.InputStream;
    3. import java.sql.Connection;
    4. import java.sql.DriverManager;
    5. import java.sql.ResultSet;
    6. import java.sql.SQLException;
    7. import java.sql.Statement;
    8. import java.util.Properties;
    9. /**
    10. * 数据操作工具类
    11. *
    12. * @author 一麟
    13. *
    14. */
    15. public class DBHelper {
    16. // 驱动路径
    17. private static String DRIVER_NAME;
    18. //连接语句
    19. private static String DB_URL;
    20. // 用户名
    21. private static String DB_USER;
    22. // 密码
    23. private static String DB_PASSWORD;
    24. static {
    25. try {
    26. InputStream in = DBHelper.class.getResourceAsStream("/jdbc.properties");
    27. Properties pro = new Properties();
    28. pro.load(in);
    29. DRIVER_NAME = pro.getProperty("driver.name");
    30. DB_URL = pro.getProperty("db.url");
    31. DB_USER = pro.getProperty("db.user");
    32. DB_PASSWORD = pro.getProperty("db.password");
    33. } catch (Exception e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. // 私有化构造
    38. private DBHelper() {
    39. }
    40. /**
    41. * 加载驱动
    42. */
    43. static {
    44. try {
    45. Class.forName(DRIVER_NAME);
    46. } catch (ClassNotFoundException e) {
    47. e.printStackTrace();
    48. }
    49. }
    50. /**
    51. * 获得连接
    52. *
    53. * @return
    54. * @throws SQLException
    55. */
    56. public static Connection getConection() throws SQLException {
    57. Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    58. return connection;
    59. }
    60. /**
    61. * 关闭资源
    62. *
    63. * @param rs
    64. * @param ps
    65. * @param con
    66. */
    67. public static void closeDB(ResultSet rs, Statement ps, Connection con) {
    68. try {
    69. if (rs != null && !rs.isClosed()) {
    70. rs.close();
    71. }
    72. if (ps != null && !ps.isClosed()) {
    73. ps.close();
    74. }
    75. if (con != null && !con.isClosed()) {
    76. con.close();
    77. }
    78. } catch (SQLException e) {
    79. e.printStackTrace();
    80. }
    81. }
    82. /**
    83. * 关闭资源
    84. *
    85. * @param rs
    86. * @param ps
    87. */
    88. public static void closeDB(ResultSet rs, Statement ps) {
    89. try {
    90. if (rs != null && !rs.isClosed()) {
    91. rs.close();
    92. }
    93. if (ps != null && !ps.isClosed()) {
    94. ps.close();
    95. }
    96. } catch (SQLException e) {
    97. e.printStackTrace();
    98. }
    99. }
    100. public static void main(String[] args) throws SQLException {
    101. System.out.println(DBHelper.getConection());
    102. }
    103. }

    我们发现啊:以往我们编写的这个工具类里面的属性值都是定死的,但是我这边却不是定死的,而是通过读取一个文件中的属性值获得具体对应的属性值。为什么呢?

    是这样的,因为刚好我在准备自己编写MVC框架了,所以才通过从外部文件中读取的方式获得具体的属性值。

     就像这里我的项目:

    是有准备一个叫做jdbc.properties的文件用于读取具体的属性值。提高了我们开发的便捷性。

    文件内容如下:

    1. driver.name = com.mysql.jdbc.Driver
    2. db.url=jdbc:mysql://localhost:3306/good??useUnicode=true&characterEncoding=utf-8&useSSL=false
    3. db.user=root
    4. db.password=jiang

     最后我们再通过main方法测试得到控制台输出的结果为:

    就已经表示我们的连接已经建立完毕了。

    好了,前面的这些都是准备工作。

    💙重构-提取公用方法

    1)为了进行公共方法的抽取,需要找出上面实习中的可通用部分,和差异化部分。

    • 只要是分页,就会统计总记录数,而总记录数的统计是在业务sql外封装了一个select count(*)是有规律可循的,可以通用
    • 只要是分页,则封装分页sql也是有规律可循的(在业务sql后加limit子句即可),可以通用
    • 因为每个查询对应的业务实体(即模型)不同,所以ORM映射部分不能通用

    2)公用方法封装思路

    • 将可通用的部分封装到模板中
    • 差异化部分(即不可通用部分),可以定义一个处理接口,以便于通过参数传入个性化的实现部分
       

    具体实现如下所示:

    1. package com.ljq.mymvc.util;
    2. import java.sql.Connection;
    3. import java.sql.PreparedStatement;
    4. import java.sql.ResultSet;
    5. import java.sql.SQLException;
    6. import java.util.ArrayList;
    7. import java.util.List;
    8. /**
    9. *
    10. * @author 一麟
    11. *
    12. */
    13. /**
    14. * 分页查询工具类
    15. *
    16. * @author 一麟
    17. *
    18. */
    19. public class BaseDao {
    20. /**
    21. * 私有化构造
    22. */
    23. private BaseDao() {
    24. }
    25. /**
    26. * 回调函数接口
    27. *
    28. * @author 一麟
    29. *
    30. * @param
    31. */
    32. public static interface ICovent {
    33. List convent(ResultSet rs) throws SQLException;
    34. }
    35. /**
    36. * 查询封装方法
    37. *
    38. * @param 任意类型
    39. * @param sql传入的SQL查询语句
    40. * @param params参数数组
    41. * @param pageBean分页对象
    42. * @param covent转换器
    43. * @return 返回查询的结果集合
    44. */
    45. public static List query(String sql, Object[] params, PageBean pageBean, ICovent covent) {
    46. // 定义装载容器
    47. List students = new ArrayList();
    48. // 初始化查询工具
    49. Connection con = null;
    50. PreparedStatement ps = null;
    51. ResultSet rs = null;
    52. // 分页判断(如果传入的分页对象为空值或者是不需要查询)
    53. if (pageBean == null || !pageBean.isPagination()) {// 不需要分页的情况下
    54. try {
    55. con = DBHelper.getConection();// 连接
    56. ps = con.prepareStatement(sql);// 资源对象
    57. // 记录查询参数个数
    58. if(params!=null) {
    59. int i = 1;
    60. for (Object param : params) {
    61. ps.setObject(i, param);
    62. i++;
    63. }
    64. }
    65. // 结果集
    66. rs = ps.executeQuery();
    67. // 通过传入的回调函数进行转换
    68. students = covent.convent(rs);// 将结果集转换为我们需要的类型
    69. } catch (SQLException e) {
    70. e.printStackTrace();
    71. } finally {
    72. DBHelper.closeDB(rs, ps, con);
    73. }
    74. } else {// 需要分页的情况
    75. String countSql = "select COUNT(*) from (" + sql + ") tmp";// 注意:这个地方一定要给传入的SQL查询结果指定别名
    76. try {
    77. // 获得连接、对象资源
    78. con = DBHelper.getConection();
    79. ps = con.prepareStatement(countSql);
    80. // 记录参数个数
    81. int i = 1;
    82. for (Object param : params) {
    83. ps.setObject(i, param);
    84. i++;
    85. }
    86. // 结果集
    87. rs = ps.executeQuery();
    88. if (rs.next()) {// 遍历并查询总共的数据条数
    89. Integer total = rs.getInt(1);
    90. pageBean.setTotal(total);// 赋值给分页对象(刷新总数据条)
    91. }
    92. // 判断(如果分页对象中的总数据条刷新至0或者0以下就表示已经没有数据可查询了,就返回学生集合)
    93. if (pageBean.getTotal() <= 0) {
    94. return students;
    95. }
    96. // 查询当前页的数据
    97. String pagingSql = sql + " limit " + pageBean.getStartIndex() + ", " + pageBean.getRows();
    98. ps = con.prepareStatement(pagingSql);
    99. // 记录查询参数个数
    100. int j = 1;
    101. for (Object param : params) {
    102. ps.setObject(j, param);
    103. j++;
    104. }
    105. rs = ps.executeQuery();
    106. // 转换
    107. students = covent.convent(rs);
    108. } catch (SQLException e) {
    109. e.printStackTrace();
    110. } finally {
    111. DBHelper.closeDB(rs, ps, con);
    112. }
    113. }
    114. return students;
    115. }
    116. }

    当然这个实现其实还不够完善,为什么呢?我们发现里面的student类都是定死的,后期我们会通过spring注入的方式更加晚上这个地方。

    接下来就是我们分页查询学生的dao方了:

    1. package com.ljq.mymvc.util;
    2. import java.sql.ResultSet;
    3. import java.sql.SQLException;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. import java.util.Objects;
    7. import com.ljq.mymvc.model.Student;
    8. import com.ljq.mymvc.util.BaseDao.ICovent;
    9. /**
    10. * 学生分页查询dao方
    11. *
    12. * @author 一麟
    13. *
    14. */
    15. public class StudentDao {
    16. public List getStudents(String sname, PageBean pageBean) {
    17. // 构造sql语句 变化部分
    18. String sql = "select * from t_student t ";
    19. List param = new ArrayList<>();
    20. if (!Objects.isNull(sname) && sname.length() > 0) {
    21. sql += " where s_sname like ?";
    22. param.add(sname);
    23. }
    24. // 调用封装的代码进行查询
    25. List list = BaseDao.query(sql, param.toArray(), pageBean, new ICovent() {
    26. public List convent(ResultSet rs) throws SQLException {
    27. List students = new ArrayList<>();
    28. while (rs.next()) {
    29. Student stu = new Student();
    30. stu.setSid(rs.getInt(1));
    31. stu.setSname(rs.getString(2));
    32. stu.setScore(rs.getInt(3));
    33. stu.setClazz(rs.getString(4));
    34. students.add(stu);
    35. }
    36. return students;
    37. }
    38. });
    39. return list;
    40. }
    41. }
    42. 好啦分页查询就先到这了。下期将带来分页查询02,将会带来通用分页的余下知识点!😂😂😂

    43. 相关阅读:
      [附源码]java毕业设计实践教学管理系统
      WinUI 3 踩坑记:第一个窗口
      三大零知识(ZK)证明系统全面深度分析:STARKs SNARKs Bulletproof
      做直播或短视频 其实有几个精准粉丝就可以很快变现
      SpringBoot整合Redis,缓存批量删除 | redisTemplate.keys(pattern)模糊查询找不到keys,“ * “ 通配符无效
      Milvus Cloud——Agent 框架工作方式
      Step 3.1:垃圾收集器与内存分配策略
      解决Selenium中无法点击元素,Selemium使用JS代码 driver.execute_script点击元素
      linux硬件信息及性能基础运维命令
      php服装商城网站毕业设计源码241505
    44. 原文地址:https://blog.csdn.net/m0_67376124/article/details/125811865