J2EE通用分页02

目录

一.重构-提取公用方法        

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

    2.公用方法封装思路

      3. 具体实现

二.分页标签

2.1 准备一个Servlet

 3.2 结果展示页面

三. 过滤器解决中文乱码问题

四.加入分页功能

四.封装分页标签

 编写助手类

标签库描述文件中添加paging标签 

 使用分页标签首先在页面中引入标签

将原来的分页功能,替换为标签即可

MySQL分页

 最后结果展示页面


一.重构-提取公用方法        

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

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

    2.公用方法封装思路

  • 将可通用的部分封装到模板中

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

      3. 具体实现

通用分页查询模板类:

public final class DBTemplate {private DBTemplate() {}public static interface IORMConvert<T> {List<T> convert(ResultSet rs) throws SQLException;}public static <T> List<T> query(String sql, Object[] params, PageBean pageBean, IORMConvert<T> convert) {List<T> datas = new ArrayList<>();Connection con = null;PreparedStatement ps = null;ResultSet rs = null;//不需要分页if (pageBean == null || !pageBean.isPagination()) {try {con = DBUtil.getConection();ps = con.prepareStatement(sql);setParam(params, ps);rs = ps.executeQuery();datas = convert.convert(rs);return datas;} catch(Exception e) {e.printStackTrace();} finally {DBUtil.closeDB(rs, ps, con);}} else {//1. 查询总记录数//2. 查询当前页数据//1. 生成统计总记录数的SQL, 查询总记录数try {String countSql = "select count(*) from (" + sql + ") tmp";con = DBUtil.getConection();ps = con.prepareStatement(countSql);setParam(params, ps);rs = ps.executeQuery();while(rs.next()) {pageBean.setTotal(rs.getInt(1));}/** 如果统计的总记录数为0,则表示没有符合条件的记录,直接返回一个空结果集即可。*/if(pageBean.getTotal() == 0) {return datas;}} catch (Exception e) {e.printStackTrace();} finally {if(pageBean.getTotal() == 0) {DBUtil.closeDB(rs, ps, con);}DBUtil.closeDB(rs, ps);}//查询当前页数据try {String pagingSql = sql + " limit " + pageBean.getStartRow() + ", " + pageBean.getRows();ps = con.prepareStatement(pagingSql);setParam(params, ps);rs = ps.executeQuery();datas = convert.convert(rs);} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.closeDB(rs, ps, con);}}return datas;}private static void setParam(Object[] params, PreparedStatement ps) throws SQLException {if (params != null) {int i = 1;for (Object param : params) {ps.setObject(i, param);i++;}}}}

使用示例:

public class StudentDao2 {public List<Student> getStudents(String sname, PageBean pageBean) {String sql = "select * from t_student where sname like ?";return DaoTemplate.query(sql, new Object[] {sname}, pageBean, new IORMConvert<Student>() {@Overridepublic List<Student> convert(ResultSet rs) throws SQLException {List<Student> stus = new ArrayList<>();while(rs.next()) {Student stu = new Student();stu.setSid(rs.getInt("sid"));stu.setSname(rs.getString("sname"));stu.setAge(rs.getInt("age"));stu.setRemark(rs.getString("remark"));stus.add(stu);}return stus;}});}public static void main(String[] args) {StudentDao2 dao = new StudentDao2();PageBean pageBean = new PageBean();pageBean.setPage(3);List<Student> students = dao.getStudents("张%", pageBean);students.forEach(s -> System.out.println(s));}}

二.分页标签

2.1 准备一个Servlet

准备一个servlet用于处理请求,获取数据库中的数据,并转发到结果显示页面

@WebServlet(value = "/students")
public class StudentAction extends HttpServlet {private static final long serialVersionUID = 3152900867611381148L;private StudentDao2 studentDao = new StudentDao2();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {PageBean pageBean = new PageBean();pageBean.setRequest(request);request.setAttribute("pageBean", pageBean);String sname = request.getParameter("sname");List<Student> students = studentDao.getStudents(sname+"%", pageBean);request.setAttribute("students", students);System.out.println("dopost .......... ");request.getRequestDispatcher("/students/stuList.jsp").forward(request, response);}}

 3.2 结果展示页面

创建一个页面,该页面用于显示结果, 使用jstl的c标签来展示结果,为正常使用c标签,需要引入jstl-1.2.jar和standard-1.1.2.jar。

<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<%@taglib prefix="z" uri="/zking" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body><h1>学生信息</h1><form action="<%=request.getContextPath()%>/students" method="post"><input type="text" name="sname"><input type="submit" value="查询"></form><table border="1" style="width: 98%;"><tr><td>学号</td><td>姓名</td><td>年龄</td><td>备注</td></tr><c:forEach items="${students}" var="student"><tr><td>${student.sid}</td><td>${student.sname}</td><td>${student.age}</td><td>${student.remark}</td></tr></c:forEach><z:paging pageBean="${pageBean}"/></table>
</body>
</html>

三. 过滤器解决中文乱码问题

/*** 中文乱码处理*/@WebFilter("/*")
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();}}}

四.加入分页功能

  • 先不考虑功能性在页面上的table标签下,加入及分页工具条
<div style="text-align: right; width:98%;">第1页&nbsp;&nbsp;&nbsp;共100条记录&nbsp;&nbsp;&nbsp;<a>首页</a>&nbsp;&nbsp;&nbsp;<a>上页</a>&nbsp;&nbsp;&nbsp; <a>下页</a>&nbsp;&nbsp;&nbsp; <a>尾页</a>&nbsp;&nbsp;&nbsp;第<input type="text" size="2" /> <a href="#">GO</a></div>
  • 不考虑通过的分页如下实现,先在结果页面中实现分页功能。
<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<%@taglib prefix="z" uri="/zking" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body><h1>学生信息</h1><form action="<%=request.getContextPath()%>/students" method="post"><input type="text" name="sname"/><input type="submit" value="查询"></form><table border="1" style="width: 98%;"><tr><td>学号</td><td>姓名</td><td>年龄</td><td>备注</td></tr><c:forEach items="${students}" var="student"><tr><td>${student.sid}</td><td>${student.sname}</td><td>${student.age}</td><td>${student.remark}</td></tr></c:forEach></table><!-- 分页页面元素 --><div style="text-align: right; width:98%;">第${pageBean.page}页&nbsp;&nbsp;&nbsp;共${pageBean.total}条记录&nbsp;&nbsp;&nbsp;<a href="javascript: goPage(1);">首页</a>&nbsp;&nbsp;&nbsp;<a href="javascript: goPage('${pageBean.previousPage}');">上页</a>&nbsp;&nbsp;&nbsp; <a href="javascript: goPage('${pageBean.nextPage}');">下页</a>&nbsp;&nbsp;&nbsp; <a href="javascript: goPage('${pageBean.totalPage}')">尾页</a>&nbsp;&nbsp;&nbsp;第<input type="text" id="pagingPageNum" size="2" onkeypress="goSpecifiedPage(event,this.value);"/> <a href="javascript: goPage(document.getElementById('pagingPageNum').value)">GO</a></div><!-- 用于分页的隐藏表单 --><form action="${pageBean.url}" id="pagingForm" method="post"><input type="hidden" name="page" value="${pageBean.page}"/><!-- 先只考虑本功能的查询参数,没有考虑公用性(不同功能的参数不同) --><input type="hidden" name="sname" value="<%=request.getParameter("sname")%>"/></form><!-- 用于分页的js代码 --><script>function goPage(pageNum) {var form = document.getElementById("pagingForm");form.page.value = pageNum;form.submit();}function goSpecifiedPage(event) {if(event.keyCode == 13) {var pageNum = document.getElementById("pagingPageNum").value;var form = document.getElementById("pagingForm");form.page.value = pageNum;form.submit();}}</script></body>
</html>

目前为止,分页功能已经实现了。

遗留下来的问题:
1   如果其他功能需要分页,则需要复制大量代码才能重用该功能
2    如果系统需要修改分页工具栏的显示风格呢?

四.封装分页标签

为了方便代码的复用,及可维护性,我们将分页功能封装了一个自定义标签(其实就是将原来写在页面中的代码,通过移入到自定义标签中去实现),开发自定义标签分成三步:

  • 编写助手类
  • 编写标签描述文件
  • 在页面上引入标签库,并使用

 编写助手类

        

public class PagingTag extends BodyTagSupport {private PageBean pageBean;public PageBean getPageBean() {return pageBean;}public void setPageBean(PageBean pageBean) {this.pageBean = pageBean;}@Overridepublic int doStartTag() throws JspException {JspWriter out = this.pageContext.getOut();try {out.println(buildHtml());return SKIP_BODY;} catch (IOException e) {throw new JspException("分页标签异常", e);}}//生成Html内容private String buildHtml() {//构建分页页面元素String pagingElement = "<div style=\"text-align: right; width:98%;\">\r\n" + "		第"  + pageBean.getPage() + "页&nbsp;&nbsp;&nbsp;\r\n" + "		共" + pageBean.getTotal() + "条记录&nbsp;&nbsp;&nbsp;\r\n" + "		<a href=\"javascript: goPage(1);\">首页</a>&nbsp;&nbsp;&nbsp;\r\n" + "		<a href=\"javascript: goPage('" + pageBean.getPreviousPage() + "');\">上页</a>&nbsp;&nbsp;&nbsp; \r\n" + "		<a href=\"javascript: goPage('" + pageBean.getNextPage() + "');\">下页</a>&nbsp;&nbsp;&nbsp; \r\n" + "		<a href=\"javascript: goPage('" + pageBean.getTotalPage() + "')\">尾页</a>&nbsp;&nbsp;&nbsp;\r\n" + "		第<input type=\"text\" id=\"pagingPageNum\" size=\"2\" value='"+pageBean.getPage()+"' onkeypress=\"goSpecifiedPage(event,this.value);\"/> \r\n" + "		<a href=\"javascript: goPage(document.getElementById('pagingPageNum').value)\">GO</a>\r\n" + "	</div>";//构建隐藏表单,用于在分页时传递分页参数String hiddenForm = "<form action='" + pageBean.getUrl() + "' id=\"pagingForm\" method=\"post\">"+ "<input type=\"hidden\" name=\"page\" />";Map<String, String[]> parameterMap = pageBean.getParameterMap();for(Map.Entry<String, String[]> param: parameterMap.entrySet()) {String paramName = param.getKey();if("page".equals(paramName)) continue;String[] values = param.getValue();for(String val:  values) {hiddenForm += "<input type='hidden' name='" + paramName + "' value='" + val + "'>";}}hiddenForm += "</form>";//构建分页功能需要的js代码块String script = "<script>\r\n" + "	function goPage(pageNum) {\r\n" + "		var form = document.getElementById(\"pagingForm\");\r\n" + "		form.page.value = pageNum;\r\n" + "		form.submit();\r\n" + "	}\r\n" + "	\r\n" + "	function goSpecifiedPage(event) {\r\n" + "		if(event.keyCode == 13) {\r\n" + "			var pageNum = document.getElementById(\"pagingPageNum\").value;\r\n" + "			var form = document.getElementById(\"pagingForm\");\r\n" + "			form.page.value = pageNum;\r\n" + "			form.submit();\r\n" + "		}\r\n" + "	}\r\n" + "	</script>";return pagingElement + hiddenForm + script;}}

标签库描述文件中添加paging标签 

<tag><name>paging</name><tag-class>com.zking.mvc.tag.PagingTag</tag-class><body-content>empty</body-content><attribute><name>pageBean</name><required>true</required><rtexprvalue>true</rtexprvalue></attribute></tag>

 使用分页标签
首先在页面中引入标签

<%@taglib prefix="z" uri="/zking" %>

将原来的分页功能,替换为标签即可

<z:paging pageBean="${pageBean}"/>

MySQL分页

  • limit语法

select * from table_name limit [offset,] rows
  • 参数说明

参数说明
offset指定第一个返回记录行的偏移量(即从哪一行开始返回),注意:初始行的偏移量为0
offset

返回具体行数

 最后结果展示页面

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/10496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Clion开发STM32之W5500系列(NTP服务封装)

概述 在w5500基础库中进行封装&#xff0c;获取服务端的时间&#xff0c;来校准本地时间。本次使用的方案是通过ntp获取时间定时器更新保证时间准确。 NTP封装 头文件 /*******************************************************************************Copyright (c) [sc…

2:SpringIOC

文章目录 一&#xff1a;Spring_IOC概念引入_重要1&#xff1a;Spring解耦合的原理2&#xff1a;创建一个spring项目并实现IOC基本功能 二&#xff1a;Spring_IOC原理分析 ***1&#xff1a;XML解析技术读取配置文件**2**&#xff1a;反射技术实例化对象,放到容器中3&#xff1a…

【算法训练营】字符串转成整数

字符串转成整数 题目题解代码 题目 点击跳转: 把字符串转换为整数 题解 【题目解析】&#xff1a; 本题本质是模拟实现实现C库函数atoi&#xff0c;不过参数给的string对象 【解题思路】&#xff1a; 解题思路非常简单&#xff0c;就是上次计算的结果10&#xff0c;相当于10…

【大数据之Flume】三、Flume进阶之Flume Agent 内部原理和拓扑结构

1 Flume事务 2 Flume Agent 内部原理 重要组件&#xff1a; 1、ChannelSelector&#xff08;选择器&#xff09;   ChannelSelector 的作用就是选出 Event 将要被发往哪个 Channel。   &#xff08;1&#xff09;Replicating ChannelSelector&#xff08;复制或副本&#x…

格式工厂5.10.0版本安装

目前格式工厂有很多&#xff0c;大多都可以进行视频转换 之前遇到一个用ffmpeg拉流保存的MP4在vlc和迅雷都无法正常播放的问题&#xff0c;发现视频长度不对&#xff0c;声音也不对&#xff0c;最后换到了格式工厂的格式播放器是可以正常播放的 格式工厂下载之家的地址 http…

每天五分钟计算机视觉:单卷积层的前向传播过程

什么是单卷积层? 一张图片(输入)经过多个卷积核卷积就会得到一个输出,而这多个卷积核的组合就是一个单卷积层。 这些卷积核可能大小是不一样的,但是他们接收同样大小是输入,他们的输出必须是一般大小,所以不同的卷积核需要具备不同的步长和填充值。 单层卷积网络前向传…

你们公司的【前端项目】是如何做测试的?字节10年测试经验的我这样做的...

前端项目也叫web端项目&#xff08;通俗讲就是网页上的功能&#xff09;是我们能够在屏幕上看到并产生交互的体验。 前端项目如何做测试&#xff1f; 要讲清楚这个问题&#xff0c;先需要你对测试流程现有一个全局的了解&#xff0c;先上一张测试流程图&#xff1a; 测试流程…

旧版Xcode文件较大导致下载总是失败但又不能断点续传重新开始的解决方法

问题&#xff1a; 旧版mac下载旧版Xcode时需要进入https://developer.apple.com/download/all/?qxcode下载&#xff0c;但是下载这些文件需要登录。登录后下载中途很容易失败&#xff0c;失败后又必须重新下载。 解决方案&#xff1a; 下载这里面的内容都需要登录&#xff0…

开发一个RISC-V上的操作系统(二)—— 系统引导程序(Bootloader)

目录 文章传送门 一、什么是Bootloader 二、简单的启动程序 三、上板测试 文章传送门 开发一个RISC-V上的操作系统&#xff08;一&#xff09;—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统&#xff08;二&#xff09;—— 系统引导…

机器学习深度学习——多层感知机

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——感知机 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 上一节…

Git时间:版本控制工具进阶

Git时间&#xff1a;版本控制工具进阶 忽略文件 Git允许用户将指定的文件或目录排除在版本控制之外&#xff0c;它会检查代码仓库的目录下是否存在一个名为.gitignore的文件&#xff0c;如果存在&#xff0c;就去一行行读取这个文件中的内容&#xff0c;并把每一行指定的文件…

MySQL 读写分离

目录 一、什么是读写分离&#xff1f; 二、为什么要读写分离呢&#xff1f; 三、什么时候要读写分离&#xff1f; 四、主从复制与读写分离 五、MySQL 读写分离原理 六、企业 使用MySQL 读写分离场景 1&#xff09;基于程序代码内部实现 2&#xff09;基于中间代理层实现…

你说你会Java手动锁,但你会这道题吗???

按照这个格式输出你会吗&#xff1f;&#xff1f;&#xff1f; 你说你不会&#xff0c;接下来认真看认真学了。 1.首先引入原子类。AtomicInteger num new AtomicInteger(0); 什么是原子类&#xff1f; 就是可以保证线程安全的原子操作的数据类型。 有什么作用&#xff1f;…

在Debian 12 上安装 PHP 5.6, 7.4

环境&#xff1a;Debian 12 Debian 12 默认的PHP版本为 8.2 如果直接安装php7.4就出现下面的报错&#xff1a; sudo apt-get install libapache2-mod-php7.4 php7.4 php7.4-gd php7.4-opcache php7.4-mbstring php7.4-xml php7.4-json php7.4-zip php7.4-curl php7.4-imap p…

导出为PDF加封面且分页处理dom元素分割

文章目录 正常展示页面导出后效果代码 正常展示页面 导出后效果 代码 组件内 <template><div><div><div class"content" id"content" style"padding: 0px 20px"><div class"item"><divstyle"…

Ubuntu Server版 之 mysql 系列

Ubuntu 分 桌面版 和 服务版 桌面版 &#xff1a;有额外的简易界面 服务版&#xff1a;是纯黑框的。没有任何UI界面的可言 安装mysql 安装位置 一般按照的位置存放在 /usr/bin 中 sudo apt-get install mysql-server查看mysql的状态 service mysql status mysql 安全设置…

使用xtcp映射穿透指定服务

使用xtcp映射穿透指定服务 管理员Ubuntu配置公网服务端frps配置service自启(可选) 配置内网服务端frpc配置service自启(可选) 使用者配置service自启(可选) 通过frp实现内网client访问另外一个内网服务器 管理员 1&#xff09;配置公网服务端frps2&#xff09;配置内网服务端…

FS32K144官方提供串口Bootloader对接Matlab串口烧写程序

​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 前言 Bootloader升级工具&#xff1a;可用TTL、232、485&#xff08;硬件收发模式&#xff09;,其中的一种&#x…

CertGetCertificateChain trust error CERT_TRUST_REVOCATION_STATUS_UNKNOWN

执行命令&#xff1a; curl --cacert http_ca.crt -u elastic https://localhost:9200 结果报错了 直接访问https://localhost:9200/ &#xff0c;正常 解决办法&#xff1a; curl --cacert http_ca.crt -u elastic https://localhost:9200 --insecure

2_Apollo4BlueLite中断控制器NVIC

1.概述 Apollo4BlueLite 的中断控制器是采用 ARM Cortex-M4 内核&#xff0c;并集成了 NVIC&#xff08;Nested Vectored Interrupt Controller&#xff0c;嵌套向量中断控制器&#xff09;作为其中断控制器。 NVIC 是 ARM Cortex-M 系列处理器中常用的中断控制器&#xff0c…