SSM框架-实现Mybatis分页功能-foreknow_cms
##分页处理
分页
1、前台分页
2、数据库(后台)分页
3、存储过程
Orade (Rownum) Mysql(limit) sqlservier(Top N)
第一步 :
要在mybatis 核心xml中引入 拦截器插件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><plugins><plugin interceptor="com.foreknow.dao.interceptor.PageInterceptor"></plugin></plugins>
</configuration>
第二步:
创建com.foreknow.util 包 下
Page.java 总记录数 当前页数 总页数 每页要显示的额记录数
package com.foreknow.util;public class Page {// 总记录数private int totalNumber;// 当前页数private int currentPage;// 总页数private int totalPage;// 每页要显示的记录数private int pageNumber;public Page() {this.currentPage = 1;this.pageNumber = 5;}public int getTotalNumber() {return totalNumber;}/*** 计算总页数*/public void count() {this.totalPage = this.totalNumber / this.pageNumber;if (this.totalNumber % this.pageNumber > 0) {this.totalPage++;}if (this.totalPage <= 0) {this.totalPage = 1;}if (this.currentPage > this.totalPage) {this.currentPage = this.totalPage;}if (this.currentPage <= 0) {this.currentPage = 1;}}public void setTotalNumber(int totalNumber) {this.totalNumber = totalNumber;count();}public int getCurrentPage() {return currentPage;}public void setCurrentPage(int currentPage) {this.currentPage = currentPage;}public int getTotalPage() {return totalPage;}public void setTotalPage(int totalPage) {this.totalPage = totalPage;}public int getPageNumber() {return pageNumber;}public void setPageNumber(int pageNumber) {this.pageNumber = pageNumber;}}
MD5Util.java 加密
package com.foreknow.util;import java.io.File;
import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;/*** MD5加密工具类*/
public class MD5Util {private static final char DIGITS[] = { '0', '1', '2', '3', '4', '5', '6','7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };/*** 获取文件的MD5码* * @param absPath* 文件路径* @return 文件的MD5码*/public final static String getFileMD5(String absPath) {try {File file = new File(absPath);MessageDigest mdTemp = MessageDigest.getInstance("MD5");FileInputStream fis = new FileInputStream(file);FileChannel filechannel = fis.getChannel();MappedByteBuffer mbb = filechannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());mdTemp.update(mbb);byte[] md = mdTemp.digest();int j = md.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];str[k++] = DIGITS[byte0 >>> 4 & 0xf];str[k++] = DIGITS[byte0 & 0xf];}fis.close();return new String(str);} catch (Exception e) {return "";}}/*** 获取指定字符串的MD5码* * @param s* 字符串* @return 字符串的MD5码*/public final static String getMD5(String s) {char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f' };try {byte[] strTemp = s.getBytes();MessageDigest mdTemp = MessageDigest.getInstance("MD5");mdTemp.update(strTemp);byte[] md = mdTemp.digest();int j = md.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}return new String(str);} catch (Exception e) {return null;}}public static void main(String[] args) {System.out.println(getMD5("admin"));}
}
FileUtil.java 对文件的处理 获取 删除 文件的保存 上传
package com.foreknow.util;import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;public class FileUtil {/*** 将MultipartFile保存到指定的路径下* * @param file* Spring的MultipartFile对象* @param savePath* 保存路径* @return 保存的文件名,当返回NULL时为保存失败。* @throws IOException* @throws IllegalStateException*/public static String save(MultipartFile file, String savePath) throws IllegalStateException, IOException {if (file != null && file.getSize() > 0) {File fileFolder = new File(savePath);if (!fileFolder.exists()) {fileFolder.mkdirs();}File saveFile = getFile(savePath, file.getOriginalFilename());file.transferTo(saveFile);return saveFile.getName();}return null;}/*** 删除文件* * @param filePath* 文件路径* @return 是否删除成功:true-删除成功,false-删除失败*/public static boolean delete(String filePath) {File file = new File(filePath);if (file.isFile()) {file.delete();return true;}return false;}private static File getFile(String savePath, String originalFilename) {String fileName = System.currentTimeMillis() + "_" + originalFilename;File file = new File(savePath + fileName);if (file.exists()) {return getFile(savePath, originalFilename);}return file;}
}
CommonUtil.java
package com.foreknow.util;import java.util.UUID;/*** 共通工具类.*/
public class CommonUtil {/*** 方法描述:判断一个字符串是否为null或空字符串(被trim后为空字符串的也算)。* * @param str* 需要判断的字符串* @return false:不是空字符串,true:是空字符串*/public static boolean isEmpty(String str) {if (str == null || "".equals(str.trim())) {return true;}return false;}/*** 生成指定位数的随机整数* * @param number* 位数* @return 随机整数*/public static int random(int number) {return (int) ((Math.random() * 9 + 1) * Math.pow(10, number - 1));}/*** 获取UUID* * @return UUID*/public static String getUUID() {return UUID.randomUUID().toString().replace("-", "");}// /**
// * 判断session中存放的动作dto列表中是否包含指定的url
// * @param session
// * @param url
// * @param method http动作
// * @return true:包含,false:不包含
// */
// public static boolean contains(HttpSession session,String url,String method) {// Object obj = session.getAttribute(SessionKeyConst.ACTION_INFO);
// if(obj != null) {// @SuppressWarnings("unchecked")
// List<ActionDto> dtoList = (List<ActionDto>)obj;
// for(ActionDto actionDto : dtoList) {// if(!isEmpty(actionDto.getMethod()) && !actionDto.getMethod().equals(method)) {// continue;
// }
// if(!url.matches(actionDto.getUrl())) {// continue;
// }
// return true;
// }
// }
// return false;
// }
}
然后在bean包下 创建BaseBean.java 专门给分页使用 让Ad也继承这个类 因为只要是查询就涉及分页 就是查询需要分页 别的不需要分页 所以创建一个
##让其每一个bean 都继承BaseBean.java
package com.foreknow.bean;import com.foreknow.util.Page;/*** 分页的基础bean* @author ttc**/
public class BaseBean {//引入工具类 Page的接口private Page page;public BaseBean() {this.page = new Page();}public Page getPage() {return page;}public void setPage(Page page) {this.page = page;}
}
然后 实现 我们的自定义拦截器 mybatis
com.foreknow.dao.interceptor包下 PageInterceptor.java
package com.foreknow.dao.interceptor;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;import com.foreknow.bean.BaseBean;
import com.foreknow.util.Page;/*** 自定义拦截器* 获取的Mybatis的Statement是在StatementHandler这个对象中进行的 所以我们 * type=StatementHandler.class* method="prepare" 实现接口的 prepare 方法* @Intercepts:标识当前的类是一个拦截器* @Signature(type=StatementHandler.class,method="prepare",args={Connection.class})* 它标记了当前的拦截器只会拦截StatementHandler接口中的prepare方法,因为这个方法的的参数是Connection类型的,* 所以获取到这个方法 传参数需要使用args={Connection.class}指定参数的类型* @author ttc**/@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})
public class PageInterceptor implements Interceptor {public Object intercept(Invocation invocation) throws Throwable {// 获取目标对象StatementHandler statementHandler = (StatementHandler) invocation.getTarget();// 获取到元数据对象,从这个对象中可以通过其中的方法获取到我们要处理(拦截)的操作MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());// 根据KEY获取到映射对象MappedStatement---------------AdDao.xmlMappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");// 获取到要AdDao.xml里的ID拦截操作的IDString id = mappedStatement.getId();
//一般uerdao.xml中 分页都是后面带ByPage的 所以下面判断一下if (id.endsWith("ByPage")) {BoundSql boundSql = statementHandler.getBoundSql();// 获取到Mapper.xml中的SQLString sql = boundSql.getSql();// 计算总的记录数 t是别名String countSql = "select count(*) from(" + sql + ")t";// 获取到Statement prepare(Connection connection)Connection conn = (Connection) invocation.getArgs()[0];PreparedStatement statement = conn.prepareStatement(countSql);// 通过代理获取到ParameterHandler对象,目的是要将?替换为具体值ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");parameterHandler.setParameters(statement);// JDBC的执行查询ResultSet rs = statement.executeQuery();BaseBean bean = (BaseBean) boundSql.getParameterObject();Page page = bean.getPage();if (rs.next()) {page.setTotalNumber(rs.getInt(1));}// 通过上面的分析分页的格式:// select * from table limit (start-1)*limit,limit;// 其中start是页码,limit是每页显示的条数。String pageSql = sql + " limit "+(page.getCurrentPage()-1)*page.getPageNumber()+","+page.getPageNumber();//重写分页的SQL 因为以前的 adDAO.xml里的sql不带分页 所以要重写 delegate.boundSql.sql 就这么写 写死的metaObject.setValue("delegate.boundSql.sql", pageSql);}//将执行权交给下一个拦截器return invocation.proceed();}public Object plugin(Object target) {// TODO Auto-generated method stubreturn Plugin.wrap(target, this);}public void setProperties(Properties properties) {// TODO Auto-generated method stub}}
##分页的步骤:
首先自己定义的拦截器
- 列表第一项1.通过MappedStatement 里的方法 获取adDao.xml 依赖注入里的id
- 列表第一项2.因为id有多个 判断一下 page结尾的id
- 列表第一项3.获取到sql 后 记录总记录数
- 列表第一项4.对JDBC的操作 设置connection 参数后 执行查询
- 列表第一项5. 拼SQL
- 列表第一项6.重写SQL
- 列表第一项7.如果有下个拦截器 交给下一个 如果没有 就交给conntroller处理
然后在JSP中建一个自定义标签文件 tags
对应依赖的库 tag 复制到pom.xml中
#####定义一个自定义标签tag 在WEB-INF 下
<%@ tag language="java" pageEncoding="utf-8"%><!-- 获取页面的一些信息 引用一下
Page" name="page" 页数 和总记录数
获取属性 用attribute --><%@ attribute type="com.foreknow.util.Page" name="page" required="true"%>
<%@ attribute type="java.lang.String" name="jsMethodName" required="true"%>
<script type="text/javascript">/* 传一个当前的页码 参数 */function transCurrenPage(currentPage) {var rule = /^[0-9]*[1-9][0-9]*$/if(!rule.test(currentPage)) {currentPage = 1;}eval("${jsMethodName}(currentPage)");}
</script>
<div class="page fix"><a href="javascript:transCurrenPage('1')" class="first">首页</a><a href="javascript:transCurrenPage('${page.currentPage-1}')" class="pre">上一页</a>当前第<span>${page.currentPage}/${page.totalPage}</span>页<a href="javascript:transCurrenPage('${page.currentPage+1}')" class="next">下一页</a><a href="javascript:transCurrenPage('${page.totalPage}')" class="last">末页</a>跳转 <input type="text" id="currentPageText" value="1" class="allInput w28"> 页 <a href="javascript:transCurrenPage($('#currentPageText').val())" class="go">GO</a>
</div>
如果不想鼠标放上去 就显示url 为了网页的安全 可以写js
#####问题1:
引用的<%@ attribute type=“java.lang.String” name=“jsMethodName” required=“true”%> 什么意思?
解答:我们引用的是这个自定义的标签 那么 我们就应该把自定义标签定义一个名字
ame=“jsMethodName
#####问题2:
function transCurrenPage(currentPage) {
var rule = /1[1-9][0-9]/if(!rule.test(currentPage))currentPage=1;eval("/ if(!rule.test(currentPage)) { currentPage = 1; } eval("/if(!rule.test(currentPage))currentPage=1;eval("{jsMethodName}(currentPage)”);
}
解答: 这里我们运用的是一个正则表达式 判断一下 如果不符合这个规则 那么当前
当前页显示的是第一页
eval("${jsMethodName}(currentPage)");
意思说通过方法eval 把实际点击的这个当前页数传到自定义标签上 来解析这个jsMethodName 对应的JS 方法 search
adList.js
//显示信息
$(function(){common.showMessage($("#message").val())
})
//这个方法什么时候调用?
function search(currentPage){$("#currentPage").val(currentPage);$("#mainForm").submit();
}
这个#currentPage 定义的在JSP页面中的ID 对应的隐藏域 value 对应的是1页 也就说 默认是从第一页开始的 , 让后id=mainForm 是action里的 表单提交
adList.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="pager" tagdir="/WEB-INF/tags/" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"/><title></title><link rel="stylesheet" type="text/css" href="${basePath}/css/all.css"/><link rel="stylesheet" type="text/css" href="${basePath}/css/pop.css"/><link rel="stylesheet" type="text/css" href="${basePath}/css/main.css"/><script type="text/javascript" src="${basePath}/js/common/jquery-1.8.3.js"></script><script type="text/javascript" src="${basePath}/js/common/common.js"></script><script type="text/javascript" src="${basePath}/js/content/adList.js"></script>
</head><body style="background: #e1e9eb;">
<form action="${basePath}/ad/search" id="mainForm" method="post"><input type="hidden" id="id" name="id"/><input type="hidden" id="message" value="${pageCode.msg}"/><input type="hidden" id="basePath" value="${basePath}"/><input type="hidden" name="page.currentPage" id="currentPage" value="1"/><div class="right"><div class="current">当前位置:<a href="#">内容管理</a> > 广告管理</div><div class="rightCont"><p class="g_title fix">广告列表</p><table class="tab1"><tbody><tr><td align="right" width="80">标题:</td><td><input name="title" id="title" value="" class="allInput" type="text"/></td><td style="text-align: right;" width="150"><input class="tabSub" value="查询" onclick="search('1');" type="button"/> <%--<t:auth url="/ad/addInit">--%><input class="tabSub" value="添加" onclick="location.href='${basePath}/ad/addInit'" type="button"/><%--</t:auth>--%></td></tr></tbody></table><div class="zixun fix"><table class="tab2" width="100%"><tbody><tr><th>序号</th><th>标题</th><th>链接地址</th><th>操作</th></tr><c:forEach items="${list}" var="item" varStatus="s"><tr><td>${s.index+1}</td><td>${item.title}</td><td>${item.link}</td><td><%--<t:auth url="/ad/modifyInit">--%><a href="javascript:void(0);" onclick="">修改</a> <%--</t:auth>--%><%--<t:auth url="/ad/remove">--%><a href="javascript:void(0);" onclick="">删除</a><%--</t:auth>--%></td></tr></c:forEach></tbody></table><pager:page jsMethodName="search" page="${searchParam.page}"></pager:page></div></div></div>
</form>
</body>
</html>
其中
引用一下这个page
<%@ taglib prefix=“pager” tagdir="/WEB-INF/tags/" %>
就是引用的分页
<pager:page jsMethodName=“search” page="${searchParam.page}"></pager:page>
问题3
jsMethodName=“search” page="${searchParam.page} 是什么意思?
解答:因为在自定义标签中 有两个参数
所以 在jsMethodName=“search” 让他调用JS 函数提交
第二: searchParam是控制器的addAttribute Map集合里的Key
adAdd.js
adList.js
所以 这就实现了分页的功能
0-9 ↩︎
SSM框架-实现Mybatis分页功能-foreknow_cms相关推荐
- Mybatis分页功能 pagehelper插件
Mybatis分页功能 pagehelper插件 创建数据数据 use ssm; create table student (id int auto_incrementprimary key,name ...
- JavaWeb学习之路——SSM框架之Mybatis(三)
数据库配置和相关类创建看上篇:JavaWeb学习之路--SSM框架之Mybatis(二) https://blog.csdn.net/kuishao1314aa/article/details/832 ...
- SSM框架——使用MyBatis Generator自动创建代码
SSM框架--使用MyBatis Generator自动创建代码 这是通过命令行, 不用ide插件. 若在IDEA中通过插件generator, 还可以参考另一篇: IDEA搭建Spring+Spri ...
- php tp框架分页源代码,ThinkPHP3.2框架自带分页功能实现方法示例
本文实例讲述了ThinkPHP3.2框架自带分页功能实现方法.分享给大家供大家参考,具体如下: 1.前端-分页代码: {$page} 2.创建分页样式:如page.css 并将以下代码复制到该文件中 ...
- SpringBoot 集成FluentMyBatis 框架之集成分页功能
本文基于上一篇:SpringBoot 集成FluentMyBatis 框架之完善 SpringBoot 集成FluentMyBatis 框架之集成分页功能 FluentMyBatis 官方分页 官方提 ...
- 转:mybatis - 分页功能
本文转自http://www.cnblogs.com/jcli/archive/2011/08/09/2132222.html mybatis高级应用系列一:分页功能 Mybatis3.0出来已有段时 ...
- SSM框架实现登录注册功能
刚刚写出来的SSM登录注册案例,网上随便翻一下都有 ,本篇直接上手,使用Maven工程搭建一个简单的SSM框架实现简单的登录注册,验证重名功能. 目录 项目结构图 持久层相关配置文件 applicat ...
- ssm框架解读oracle,分页查询显示action的笔记SSM框架分页oracle数据库
SSM框架简单分页 分页类代码分页的例1 package http://www.doczj.com/doc/db3d98ab69eae009591bec1b.htmlmon.dto; public c ...
- SSM框架-使用MyBatis Generator自动创建代码
参考:http://blog.csdn.net/zhshulin/article/details/23912615 SSM搭建的时候用到MyBatis的代码自动生成的功能,由于MyBatis属于一种半 ...
最新文章
- vivado----fpga硬件调试 (五) ----找不到ila核问题及解决
- win7配置Eclipse+Cocos2dx+android开发环境
- 数据结构-栈详解(类C语言版)
- 只需5分钟即可启动并运行分层架构:: Spring Boot第1部分
- 前端网页广告无线翻滚_从小白到web前端工程师进阶之路 从0到1到更深
- mysql mac版本_mysql的安装、启动和基础配置 —— mac版本
- 【特别版】考证与学习,结构与功能,之间的因果关系
- 计算机专业学生,大三了找技术岗,怎么写一份好简历?内附269份简历模板
- 高通平台fastboot下载
- 维生素D与肠道菌群的互作
- java实现dde服务端,快速开启dde服务端
- win10安装PHP环境
- 吕 思 伟 ---- 潘 爱 民 :: ATL 介 绍( 二 )
- Sieve of Eratosthenes(埃拉托色尼筛选法)——C++实现
- 如何降低计算机版本,如何在win7系统电脑中将IE浏览器的版本降低
- 段永平抄底腾讯:高手不是最完美的,而是最淡定的
- python 作业3
- phpnow切换php,PHPNOW如何升级PHP
- 从浏览器跳转到前端框架的路由实现
- opencv在vs2015中 找不到opencv_world400d.dll的问题
热门文章
- Star-shaped polygon
- 大数据分析平台搭建方式有哪些
- 解析mysqlbinlog日志_关于mysql-binlog日志解析框架
- hikari如何切换数据源_spring boot+mybatis 多数据源切换(实例讲解)
- win7录屏_学用系列|清晰、体积小,这些录屏工具适合正在为录屏苦恼的你
- 三门问题的MonteCarlo仿真方法
- c语言代码re通常什么错误,求帮助 C语言realloc和free触发断点的问题
- html圆如何找到垂直中心线,一种用于找中心线及圆心的装置的制作方法
- c语言取字节高四位低四位,C语言取一个数的最高位
- 大数据面试官别再问闭包了