SpringMVC+MyBatis分页插件简单实现

1.封装分页Page类

  1 package com.framework.common.page.impl;
  2 
  3 import java.io.Serializable;
  4 
  5 import com.framework.common.page.IPage;
  6 /**
  7  * 
  8  * 
  9  *
 10  */
 11 public abstract class BasePage implements IPage, Serializable {
 12 
 13     /**
 14      * 
 15      */
 16     private static final long serialVersionUID = -3623448612757790359L;
 17     
 18     public static int DEFAULT_PAGE_SIZE = 20;
 19     private int pageSize = DEFAULT_PAGE_SIZE;
 20     private int currentResult;
 21     private int totalPage;
 22     private int currentPage = 1;
 23     private int totalCount = -1;
 24 
 25     public BasePage(int currentPage, int pageSize, int totalCount) {
 26         this.currentPage = currentPage;
 27         this.pageSize = pageSize;
 28         this.totalCount = totalCount;
 29     }
 30 
 31     public int getTotalCount() {
 32         return this.totalCount;
 33     }
 34 
 35     public void setTotalCount(int totalCount) {
 36         if (totalCount < 0) {
 37             this.totalCount = 0;
 38             return;
 39         }
 40         this.totalCount = totalCount;
 41     }
 42 
 43     public BasePage() {
 44     }
 45 
 46     public int getFirstResult() {
 47         return (this.currentPage - 1) * this.pageSize;
 48     }
 49 
 50     public void setPageSize(int pageSize) {
 51         if (pageSize < 0) {
 52             this.pageSize = DEFAULT_PAGE_SIZE;
 53             return;
 54         }
 55         this.pageSize = pageSize;
 56     }
 57 
 58     public int getTotalPage() {
 59         if (this.totalPage <= 0) {
 60             this.totalPage = (this.totalCount / this.pageSize);
 61             if ((this.totalPage == 0) || (this.totalCount % this.pageSize != 0)) {
 62                 this.totalPage += 1;
 63             }
 64         }
 65         return this.totalPage;
 66     }
 67 
 68     public int getPageSize() {
 69         return this.pageSize;
 70     }
 71 
 72     public void setPageNo(int currentPage) {
 73         this.currentPage = currentPage;
 74     }
 75 
 76     public int getPageNo() {
 77         return this.currentPage;
 78     }
 79 
 80     public boolean isFirstPage() {
 81         return this.currentPage <= 1;
 82     }
 83 
 84     public boolean isLastPage() {
 85         return this.currentPage >= getTotalPage();
 86     }
 87 
 88     public int getNextPage() {
 89         if (isLastPage()) {
 90             return this.currentPage;
 91         }
 92         return this.currentPage + 1;
 93     }
 94 
 95     public int getCurrentResult() {
 96         this.currentResult = ((getPageNo() - 1) * getPageSize());
 97         if (this.currentResult < 0) {
 98             this.currentResult = 0;
 99         }
100         return this.currentResult;
101     }
102 
103     public int getPrePage() {
104         if (isFirstPage()) {
105             return this.currentPage;
106         }
107         return this.currentPage - 1;
108     }
109 
110 
111 }

 

 1 package com.framework.common.page.impl;
 2 
 3 import java.util.List;
 4 /**
 5  * 
 6  * 
 7  *
 8  */
 9 public class Page extends BasePage {
10 
11     /**
12      * 
13      */
14     private static final long serialVersionUID = -970177928709377315L;
15 
16     public static ThreadLocal<Page> threadLocal = new ThreadLocal<Page>();
17 
18     private List<?> data; 
19     
20     public Page() {
21     }
22 
23     public Page(int currentPage, int pageSize, int totalCount) {
24         super(currentPage, pageSize, totalCount);
25     }
26 
27     public Page(int currentPage, int pageSize, int totalCount, List<?> data) {
28         super(currentPage, pageSize, totalCount);
29         this.data = data;
30     }
31 
32     public List<?> getData() {
33         return data;
34     }
35 
36     public void setData(List<?> data) {
37         this.data = data;
38     }
39     
40 
41 }

2.封装分页插件

  1 package com.framework.common.page.plugin;
  2 
  3 import java.sql.Connection;
  4 import java.sql.PreparedStatement;
  5 import java.sql.ResultSet;
  6 import java.sql.SQLException;
  7 import java.util.List;
  8 import java.util.Properties;
  9 
 10 import javax.xml.bind.PropertyException;
 11 
 12 import org.apache.commons.lang3.StringUtils;
 13 import org.apache.ibatis.executor.ErrorContext;
 14 import org.apache.ibatis.executor.ExecutorException;
 15 import org.apache.ibatis.executor.statement.BaseStatementHandler;
 16 import org.apache.ibatis.executor.statement.RoutingStatementHandler;
 17 import org.apache.ibatis.mapping.BoundSql;
 18 import org.apache.ibatis.mapping.MappedStatement;
 19 import org.apache.ibatis.mapping.ParameterMapping;
 20 import org.apache.ibatis.mapping.ParameterMode;
 21 import org.apache.ibatis.plugin.Interceptor;
 22 import org.apache.ibatis.plugin.Intercepts;
 23 import org.apache.ibatis.plugin.Invocation;
 24 import org.apache.ibatis.plugin.Plugin;
 25 import org.apache.ibatis.reflection.MetaObject;
 26 import org.apache.ibatis.reflection.property.PropertyTokenizer;
 27 import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
 28 import org.apache.ibatis.session.Configuration;
 29 import org.apache.ibatis.type.TypeHandler;
 30 import org.apache.ibatis.type.TypeHandlerRegistry;
 31 
 32 import com.framework.common.page.impl.Page;
 33 import com.framework.common.utils.ReflectUtil;
 34 /**
 35  * 
 36  * 
 37  *
 38  */
 39 @Intercepts({ @org.apache.ibatis.plugin.Signature(type = org.apache.ibatis.executor.statement.StatementHandler.class, method = "prepare", args = { Connection.class }) })
 40 public class PagePlugin implements Interceptor {
 41 
 42     private String dialect = "";
 43     private String pageSqlId = "";
 44 
 45     @Override
 46     public Object intercept(Invocation invocation) throws Throwable {
 47         if (invocation.getTarget() instanceof RoutingStatementHandler) {
 48             BaseStatementHandler delegate = (BaseStatementHandler) ReflectUtil
 49                     .getValueByFieldName(
 50                             (RoutingStatementHandler) invocation.getTarget(),
 51                             "delegate");
 52             MappedStatement mappedStatement = (MappedStatement) ReflectUtil
 53                     .getValueByFieldName(delegate,
 54                             "mappedStatement");
 55 
 56             Page page = Page.threadLocal.get();
 57             if (page == null) {
 58                 page = new Page();
 59                 Page.threadLocal.set(page);
 60             }
 61 
 62             if (mappedStatement.getId().matches(".*(" + this.pageSqlId + ")$") && page.getPageSize() > 0) {
 63                 BoundSql boundSql = delegate.getBoundSql();
 64                 Object parameterObject = boundSql.getParameterObject();
 65 
 66                 String sql = boundSql.getSql();
 67                 String countSqlId = mappedStatement.getId().replaceAll(pageSqlId, "Count");
 68                 MappedStatement countMappedStatement = null;
 69                 if (mappedStatement.getConfiguration().hasStatement(countSqlId)) {
 70                     countMappedStatement = mappedStatement.getConfiguration().getMappedStatement(countSqlId);
 71                 }
 72                 String countSql = null;
 73                 if (countMappedStatement != null) {
 74                     countSql = countMappedStatement.getBoundSql(parameterObject).getSql();
 75                 } else {
 76                     countSql = "SELECT COUNT(1) FROM (" + sql + ") T_COUNT";
 77                 }
 78                 
 79                 int totalCount = 0;
 80                 PreparedStatement countStmt = null;
 81                 ResultSet resultSet = null;
 82                 try {
 83                     Connection connection = (Connection) invocation.getArgs()[0];
 84                     countStmt = connection.prepareStatement(countSql);
 85                     BoundSql countBoundSql = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);
 86                     
 87                     setParameters(countStmt, mappedStatement, countBoundSql, parameterObject);
 88                     
 89                     resultSet = countStmt.executeQuery();
 90                     if(resultSet.next()) {
 91                         totalCount = resultSet.getInt(1);
 92                     }
 93                 } catch (Exception e) {
 94                     throw e;
 95                 } finally {
 96                     try {
 97                         if (resultSet != null) {
 98                             resultSet.close();
 99                         }
100                     } finally {
101                         if (countStmt != null) {
102                             countStmt.close();
103                         }
104                     }
105                 }
106                 
107                 page.setTotalCount(totalCount);
108                 
109                 ReflectUtil.setValueByFieldName(boundSql, "sql", generatePageSql(sql,page));
110             }
111         }
112 
113         return invocation.proceed();
114     }
115     
116 
117     /** 
118      * 对SQL参数(?)设值,参考org.apache.ibatis.executor.parameter.DefaultParameterHandler 
119      * @param ps 
120      * @param mappedStatement 
121      * @param boundSql 
122      * @param parameterObject 
123      * @throws SQLException 
124      */  
125     private void setParameters(PreparedStatement ps,MappedStatement mappedStatement,BoundSql boundSql,Object parameterObject) throws SQLException {  
126         ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());  
127         List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();  
128         if (parameterMappings != null) {  
129             Configuration configuration = mappedStatement.getConfiguration();  
130             TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();  
131             MetaObject metaObject = parameterObject == null ? null: configuration.newMetaObject(parameterObject);  
132             for (int i = 0; i < parameterMappings.size(); i++) {  
133                 ParameterMapping parameterMapping = parameterMappings.get(i);  
134                 if (parameterMapping.getMode() != ParameterMode.OUT) {  
135                     Object value;  
136                     String propertyName = parameterMapping.getProperty();  
137                     PropertyTokenizer prop = new PropertyTokenizer(propertyName);  
138                     if (parameterObject == null) {  
139                         value = null;  
140                     } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {  
141                         value = parameterObject;  
142                     } else if (boundSql.hasAdditionalParameter(propertyName)) {  
143                         value = boundSql.getAdditionalParameter(propertyName);  
144                     } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX)&& boundSql.hasAdditionalParameter(prop.getName())) {  
145                         value = boundSql.getAdditionalParameter(prop.getName());  
146                         if (value != null) {  
147                             value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));  
148                         }  
149                     } else {  
150                         value = metaObject == null ? null : metaObject.getValue(propertyName);  
151                     }  
152                     TypeHandler typeHandler = parameterMapping.getTypeHandler();  
153                     if (typeHandler == null) {  
154                         throw new ExecutorException("There was no TypeHandler found for parameter "+ propertyName + " of statement "+ mappedStatement.getId());  
155                     }  
156                     typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());  
157                 }  
158             }  
159         }  
160     }  
161     
162     /** 
163      * 根据数据库方言,生成特定的分页sql 
164      * @param sql 
165      * @param page 
166      * @return 
167      */  
168     private String generatePageSql(String sql,Page page){  
169         if(page!=null && StringUtils.isNotBlank(dialect)){  
170             StringBuffer pageSql = new StringBuffer();  
171             if("mysql".equals(dialect)){  
172                 pageSql.append(sql);  
173                 pageSql.append(" LIMIT "+page.getCurrentResult()+","+page.getPageSize());  
174             }else if("oracle".equals(dialect)){  
175                 pageSql.append("SELECT * FROM (SELECT TMP_TB.*,ROWNUM ROW_ID FROM (");  
176                 pageSql.append(sql);  
177                 pageSql.append(") AS TMP_TB WHERE ROWNUM <= ");  
178                 pageSql.append(page.getCurrentResult()+page.getPageSize());  
179                 pageSql.append(") WHERE ROW_ID > ");  
180                 pageSql.append(page.getCurrentResult());  
181             }  
182             return pageSql.toString();  
183         }else{  
184             return sql;  
185         }  
186     } 
187 
188     @Override
189     public Object plugin(Object target) {
190         return Plugin.wrap(target, this);
191     }
192 
193     @Override
194     public void setProperties(Properties properties) {
195         try {
196             if (StringUtils.isEmpty(this.dialect = properties
197                     .getProperty("dialect"))) {
198                 throw new PropertyException("dialect property is not found!");
199             }
200             if (StringUtils.isEmpty(this.pageSqlId = properties
201                     .getProperty("pageSqlId"))) {
202                 throw new PropertyException("pageSqlId property is not found!");
203             }
204         } catch (PropertyException e) {
205             e.printStackTrace();
206         }
207     }
208 
209 }

3.MyBatis配置文件:mybatis-config.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
 3 <configuration>
 4     <plugins>
 5         <plugin interceptor="com.framework.common.page.plugin.PagePlugin">
 6             <property name="dialect" value="mysql" />
 7             <property name="pageSqlId" value="ByPage" />
 8         </plugin>
 9     </plugins>
10 </configuration>

4.分页拦截器

 1 package com.framework.common.page.interceptor;
 2 
 3 import javax.servlet.http.HttpServletRequest;
 4 import javax.servlet.http.HttpServletResponse;
 5 
 6 import org.apache.commons.lang3.math.NumberUtils;
 7 import org.springframework.web.servlet.ModelAndView;
 8 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 9 
10 import com.framework.common.page.impl.Page;
11 /**
12  * 
13  * 14  *
15  */
16 public class PageInterceptor extends HandlerInterceptorAdapter {
17 
18     @Override
19     public void postHandle(HttpServletRequest request,
20             HttpServletResponse response, Object handler,
21             ModelAndView modelAndView) throws Exception {
22         super.postHandle(request, response, handler, modelAndView);
23         Page page = Page.threadLocal.get();
24         if (page != null) {
25             request.setAttribute("page", page);
26         }
27         Page.threadLocal.remove();
28     }
29 
30     @Override
31     public boolean preHandle(HttpServletRequest request,
32             HttpServletResponse response, Object handler) throws Exception {
33         String pageSize = request.getParameter("pageSize");
34         String pageNo = request.getParameter("pageNo");
35         Page page = new Page();
36         if (NumberUtils.isNumber(pageSize)) {
37             page.setPageSize(NumberUtils.toInt(pageSize));
38         }
39         if (NumberUtils.isNumber(pageNo)) {
40             page.setPageNo(NumberUtils.toInt(pageNo));
41         }
42         Page.threadLocal.set(page);
43         return true;
44     }
45 
46 }

5.Spring配置

 1     <!-- =================================================================== 
 2     - Load property file 
 3     - =================================================================== -->
 4     <context:property-placeholder location="classpath:application.properties" />
 5     
 6     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
 7         <property name="dataSource" ref="dataSource" />
 8         <property name="configLocation" value="classpath:mybatis-config.xml" />
 9         <property name="mapperLocations">
10             <list>
11                 <value>classpath:/com/framework/mapper/**/*Mapper.xml</value>
12             </list>
13         </property>
14     </bean>
15     
16     <!-- =================================================================== 
17     - 通过扫描的模式,扫描目录下所有的dao, 根据对应的mapper.xml为其生成代理类 
18     - =================================================================== -->
19     <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
20         <property name="basePackage" value="com.framework.dao" />
21         <property name="processPropertyPlaceHolders" value="true" />
22         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
23     </bean>

6.SpringMVC配置拦截器

 1 <!-- 分页拦截器 -->
 2     <bean id="pageInterceptor" class="com.framework.common.page.interceptor.PageInterceptor"></bean>
 3     
 4     <!-- 配置拦截器 -->
 5     <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
 6         <property name="interceptors">
 7             <list>
 8                 <ref bean="pageInterceptor" />
 9             </list>
10         </property>
11     </bean>

 

posted @ 2015-06-28 12:48  liuxiujun  阅读(7320)  评论(3编辑  收藏  举报