springMVC分页,interceptor实现
PageInterceptor.java
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PageInterceptor implements Interceptor {
private static final Logger logger = Logger
.getLogger(PageInterceptor.class);
private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
private static String defaultPageSqlId = ".*Page$"; // 需要拦截的ID(正则匹配)
private static String pageSqlId = ""; // 需要拦截的ID(正则匹配)
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation
.getTarget();
MetaObject metaStatementHandler = MetaObject.forObject(
statementHandler, DEFAULT_OBJECT_FACTORY,
DEFAULT_OBJECT_WRAPPER_FACTORY);
// 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环可以分离出最原始的的目标类)
while (metaStatementHandler.hasGetter("h")) {
Object object = metaStatementHandler.getValue("h");
metaStatementHandler = MetaObject.forObject(object,
DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
}
// 分离最后一个代理对象的目标类
while (metaStatementHandler.hasGetter("target")) {
Object object = metaStatementHandler.getValue("target");
metaStatementHandler = MetaObject.forObject(object,
DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
}
Configuration configuration = (Configuration) metaStatementHandler
.getValue("delegate.configuration");
Properties properties = configuration.getVariables();
if (null != properties
&& StringUtils.isNotBlank(properties.getProperty("pageSqlId"))) {
pageSqlId = properties.getProperty("pageSqlId");
} else {
pageSqlId = defaultPageSqlId;
}
MappedStatement mappedStatement = (MappedStatement) metaStatementHandler
.getValue("delegate.mappedStatement");
// 只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的MappedStatement的sql
if (mappedStatement.getId().matches(pageSqlId)) {
BoundSql boundSql = (BoundSql) metaStatementHandler
.getValue("delegate.boundSql");
Object parameterObject = boundSql.getParameterObject();
if (parameterObject == null) {
throw new NullPointerException("parameterObject is null!");
}
Map<String, Object> paramMap = (Map) parameterObject;
PageParameter page = (PageParameter) paramMap.get("0");
String sql = boundSql.getSql();
// 重写sql
String pageSql = buildPageSqlForMysql(sql, page);
metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
// 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数
metaStatementHandler.setValue("delegate.rowBounds.offset",
RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue("delegate.rowBounds.limit",
RowBounds.NO_ROW_LIMIT);
Connection connection = (Connection) invocation.getArgs()[0];
// 重设分页参数里的总页数等
setPageParameter(sql, connection, mappedStatement, boundSql, page);
}
// 将执行权交给下一个拦截器
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
// 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
}
/**
* mysql的分页语句
*
* @param sql
* @param page
* @return String
*/
public String buildPageSqlForMysql(String sql, PageParameter page) {
StringBuilder pageSql = new StringBuilder(100);
String beginrow = String.valueOf((page.getCurrentPage() - 1)
* page.getPageSize());
pageSql.append(sql);
pageSql.append(" limit " + beginrow + "," + page.getPageSize());
return pageSql.toString();
}
private void setPageParameter(String sql, Connection connection,
MappedStatement mappedStatement, BoundSql boundSql,
PageParameter page) {
// 记录总记录数
String countSql = "select count(0) from (" + sql + ") as total";
PreparedStatement countStmt = null;
ResultSet rs = null;
try {
countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(),
countSql, boundSql.getParameterMappings(),
boundSql.getParameterObject());
setParameters(countStmt, mappedStatement, countBS,
boundSql.getParameterObject());
rs = countStmt.executeQuery();
int totalCount = 0;
if (rs.next()) {
totalCount = rs.getInt(1);
}
page.setTotalCount(totalCount);
int totalPage = totalCount / page.getPageSize()
+ ((totalCount % page.getPageSize() == 0) ? 0 : 1);
page.setTotalPage(totalPage);
} catch (SQLException e) {
logger.error("Ignore this exception", e);
} finally {
try {
rs.close();
} catch (SQLException e) {
logger.error("Ignore this exception", e);
}
try {
countStmt.close();
} catch (SQLException e) {
logger.error("Ignore this exception", e);
}
}
}
private void setParameters(PreparedStatement ps,
MappedStatement mappedStatement, BoundSql boundSql,
Object parameterObject) throws SQLException {
ParameterHandler parameterHandler = new DefaultParameterHandler(
mappedStatement, parameterObject, boundSql);
parameterHandler.setParameters(ps);
}
}
PageParameter.java
public class PageParameter {
public static final int DEFAULT_PAGE_SIZE = 10;
private int pageSize;
private int currentPage;
private int prePage;
private int nextPage;
private int totalPage;
private int totalCount;
public PageParameter() {
this.currentPage = 1;
this.pageSize = DEFAULT_PAGE_SIZE;
}
/**
*
* @param currentPage
* @param pageSize
*/
public PageParameter(int currentPage, int pageSize) {
this.currentPage = currentPage;
this.pageSize = pageSize;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPrePage() {
return prePage;
}
public void setPrePage(int prePage) {
this.prePage = prePage;
}
public int getNextPage() {
return nextPage;
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
mybatis-config.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="*.*.PageInterceptor"></plugin>
</plugins>
</configuration>
使用:
Map<String, Object> paramMap = new HashMap<String, Object>();
PageParameter pageParameter = new PageParameter();
pageParameter.setCurrentPage(10000);
userService.findUserPage(pageParameter, null);
springMVC分页,interceptor实现的更多相关文章
- springmvc之interceptor(拦截器)
1.自定义MyInterceptor impletments HandlerInterceptor public class MyInterceptor implements HandlerInter ...
- SpringMvc中Interceptor拦截器用法
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆等. 一. 使用场景 1 ...
- springMVC之Interceptor拦截器
转自:https://blog.csdn.net/qq_25673113/article/details/79153547 Interceptor拦截器用于拦截Controller层接口,表现形式有点 ...
- SpringMVC分页查询无法直接将对象转换成json的解决办法(报org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type:错)
在用ajax获得分页数据时,无法将获取的值赋值给input标签,在修改用户信息时不显示用户已经注册的信息,百度可知 springmvc处理分页数据返回的对象时,无法直接将对象转换成json,会报org ...
- springmvc 异常Interceptor
无论做什么项目,进行异常处理都是非常有必要的,而且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,所以这时候进行统一的异常处理,展现一个比较友好的错误页面就显得很有必要了. springMVC提 ...
- SpringMVC中Interceptor和Filter区别
Interceptor 主要作用:拦截用户请求,进行处理,比如判断用户登录情况,权限验证,主要针对Action请求进行处理.是通过HandlerInterceptor 实现的. 配置如下: <m ...
- springmvc学习笔记--Interceptor机制和实践
前言: Spring的AOP理念, 以及j2ee中责任链(过滤器链)的设计模式, 确实深入人心, 处处可以看到它的身影. 这次借项目空闲, 来总结一下SpringMVC的Interceptor机制, ...
- SpringMVC学习记录5
Springmvc流程中的扩展点有很多,可以在很多地方插入自己的代码逻辑达到控制流程的目的. 如果要对Controller的handler方法做统一的处理.我想应该会有很多选择,比如:@ModelAt ...
- SpringMVC拦截器(实现登录验证拦截器)
本例实现登陆时的验证拦截,采用SpringMVC拦截器来实现 当用户点击到网站主页时要进行拦截,用户登录了才能进入网站主页,否则进入登陆页面 核心代码 首先是index.jsp,显示链接 <%@ ...
随机推荐
- PMO到底什么样?(2)
接上一篇,继续聊一聊PMO到底什么样. 交付功能,8大典型责任 1监控.评定和报告 项目办理单位从交付的视点必定要有监控评定.每个项目在要害的期间上它的进展是不是跟按期的相同:是不是有要害的专家在要害 ...
- 我所了解的chrome
Chrome的隐身模式 先来说说隐身模式的启用方法吧 1.键盘快捷:Ctrl + Shift + N. 2.在Windows7下的任务栏处,右击“Chrome”图标,会出一个下拉菜单,点击“新建隐身窗 ...
- [数据库连接池二]Java数据库连接池--C3P0和JDNI.
前言:上一篇文章中讲了DBCP的用法以及实现原理, 这一篇再来说下C3P0和JDNI的用法. 1.1.C3P0数据源 C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规 ...
- Java 线程 — AbstractQueuedSynchronizer
锁 锁就是一种状态,比如互斥锁:同一时间只能有一个线程拥有,可以使用一个整型值来标志当前的状态 0:表示没有现成占有锁 1:表示锁已经被占用 AbstractQueuedSynchronizer 实现 ...
- android NDK 生成so 文件流程-ecplice
1:生成jni目录 首先说一句网上,大部分博客这么写的:打开控制台,进入项目目录,运行javah -classpath bin/classes -d jni com.example.hellojni. ...
- 在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
这是我辅导的一个项目开发中的例子,他们是用WPF做界面开发,在学习了如何使用MVVM来实现界面与逻辑的分离,并且很好的数据更新之后,有一个疑问就是,这种双向的数据更新确实很不错,但如果我们希望用户可以 ...
- SQL Cookbook
1. 利用LAG OVER抑制结果集中的重复值 原始结果如下: SQL> select deptno,ename from emp order by deptno; DEPTNO ENAME ...
- zmNgFrameWork 架构升级ng1.5和md5静态资源缓存方案【angular1.x】
前言: 在我前面的博客,angular项目总结——angular + browserify + gulp + bower + less 架构分享 把我开发angular的架构进行了分享,并上传到了g ...
- 测试servlet学习笔记
操作方法: 1.新建工程: File——>new——>Java Project——>TestServlet(工程名称)——>Finish. 2.加载servlet-api.ja ...
- Windows Azure Service Bus (4) Service Bus Queue和Storage Queue的区别
<Windows Azure Platform 系列文章目录> 熟悉笔者文章的读者都了解,Azure提供两种不同方式的Queue消息队列: 1.Azure Storage Queue 具体 ...