iBatis分页(基于Struts2和Freemarke)

  之前介绍过基于Hibernate分页的原理和设计,这里我们所用的分页都是物理分页技术,不是JS实现的页面分页技术,是在SQL语句上执行的分页,可 以获取结果集数量固定的列表,执行效率很高。下面来看看iBatis中如何设计分页,本文基于Struts2,Spring3来整合,因为暂时 Spring不支持MyBatis3(可以选用MyBatis官方的MyBatis-Spring插件来实现,配有中文文档,很好理解),我们这里仍然以 iBatis2作为载体来介绍。
    首先就是搭建开发环境,这里可以说也是对Struts2,Spring3和iBatis2进行了简单的整合,大家也可以来参考。项目的结构如下,使用Maven创建的web项目:
iBatis分页(基于Struts2和Freemarke)
    添加必要的依赖,因为整合了Struts2和Spring,依赖就比较多了,如下:
iBatis分页(基于Struts2和Freemarke)
    首先来配置一下Struts2,这个就比较简单了,相信大家都不陌生。在web.xml中:

Xml代码   收藏代码
  1. <!-- Struts2的过滤器 -->   
  2. < filter >   
  3.     < filter-name > struts2 </ filter-name >   
  4. < filter-class > org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </ filter-class >   
  5. </ filter >   
  6. < filter-mapping >   
  7.     < filter-name > struts2 </ filter-name >   
  8.     < url-pattern > *.action </ url-pattern >   
  9. </ filter-mapping >   


    然后是struts.xml,配置Struts相关的内容,这里我们配置freemarker为默认的结果类型,然后配置一个测试的Action,因为和Spring进行了集成,所以Action具体的配置放到Spring中来进行,如下即可:

Xml代码   收藏代码
  1. <? xml   version = "1.0"   encoding = "UTF-8"   ?>   
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.1.7.dtd">   
  5. < struts >   
  6.     < package   name = "ibatis-paging"   extends = "struts-default"   
  7.         namespace = "/" >   
  8.         < result-types >   
  9.             < result-type   name = "freemarker"   
  10.         class = "org.apache.struts2.views.freemarker.FreemarkerResult"   
  11.                 default = "true"   />   
  12.         </ result-types >   
  13.         < action   name = "user_*"   class = "userAction"   method = "{1}" >   
  14.             < result   name = "list" > user_list.ftl </ result >   
  15.         </ action >   
  16.     </ package >   
  17. </ struts >   


    对Freemarker做一个简单的设置,卸载freeemarer.properties文件中即可,这里我们主要是引用了一个宏文件,就是分页宏的配置,如下:

Properties代码   收藏代码
  1. template_update_delay= 5   
  2. default_encoding=UTF-8   
  3. url_escaping_charset=UTF-8   
  4. number_format=0 .#  
  5. date_format=yyyy-MM-dd  
  6. time_format=HH:mm:ss  
  7. datetime_format=yyyy-MM-dd HH:mm:ss  
  8. boolean_format=true,false  
  9. whitespace_stripping=true  
  10. tag_syntax=auto_detect  
  11. auto_import=/Freemarker/page_macro.ftl as p  


    Log4J的配置这里不再贴出代码,大家可以去下载源码,一看就明白了,之后我们配置Spring,在resources文件夹下创建spring子目录,里面放置Spring的配置文件,在web.xml中如下设置即可加载Spring的配置文件:

Xml代码   收藏代码
  1. < context-param >   
  2.     < param-name > contextConfigLocation </ param-name >   
  3.     < param-value > classpath:spring/*.xml </ param-value >   
  4. </ context-param >   
  5. <!-- Spring加载配置文件来初始化IoC容器 -->   
  6. < listener >          < listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >   
  7. </ listener >   


    Spring中主要配置数据源,iBatis的SqlMapClient和SqlMapClientTemplate,事务处理还有Action和Service的管理,其实内容大家也都很熟悉了,比较简单:

Xml代码   收藏代码
  1. < bean   id = "dataSource"   class = "org.apache.commons.dbcp.BasicDataSource"   
  2.         destroy-method = "close" >   
  3.         < property   name = "driverClassName"   value = "com.mysql.jdbc.Driver"   />   
  4.         < property   name = "url"   value = "jdbc:mysql://localhost:3306/test"   />   
  5.         < property   name = "username"   value = "root"   />   
  6.         < property   name = "password"   value = "123"   />   
  7.         < property   name = "maxActive"   value = "100"   />   
  8.         < property   name = "maxIdle"   value = "50"   />   
  9.         < property   name = "maxWait"   value = "100"   />   
  10.         < property   name = "defaultAutoCommit"   value = "true"   />   
  11.     </ bean >   
  12.     <!-- 创建JdbcTemplate -->   
  13.     < bean   id = "jdbcTemplate"   class = "org.springframework.jdbc.core.JdbcTemplate" >   
  14.         < property   name = "dataSource"   ref = "dataSource"   />   
  15.     </ bean >   
  16.     <!-- 创建sqlMapClient -->   
  17.     < bean   id = "sqlMapClient"   class = "org.springframework.orm.ibatis.SqlMapClientFactoryBean" >   
  18.         < property   name = "configLocation"   value = "classpath:sqlMapConfig.xml"   />   
  19.         < property   name = "dataSource"   ref = "dataSource"   />   
  20.     </ bean >   
  21.     <!-- 创建sqlMapClientTemplate -->   
  22.     < bean   id = "sqlMapClientTemplate"   class = "org.springframework.orm.ibatis.SqlMapClientTemplate" >   
  23.         < constructor-arg >   
  24.             < ref   bean = "sqlMapClient"   />   
  25.         </ constructor-arg >   
  26.     </ bean >   
  27.     <!-- 事务管理器 -->   
  28.     < bean   id = "transactionManager"   
  29.         class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >   
  30.         < property   name = "dataSource"   ref = "dataSource"   />   
  31.     </ bean >   
  32.     <!-- 配置事务处理通知 -->   
  33.     < tx:advice   id = "txAdvice"   transaction-manager = "transactionManager" >   
  34.         < tx:attributes >   
  35.             < tx:method   name = "get*"   read-only = "true"   />   
  36.             < tx:method   name = "add*"   rollback-for = "Exception"   />   
  37.             < tx:method   name = "addOrUpdate*"   rollback-for = "Exception"   />   
  38.             < tx:method   name = "del*"   rollback-for = "Exception"   />   
  39.             < tx:method   name = "update*"   rollback-for = "Exception"   />   
  40.         </ tx:attributes >   
  41.     </ tx:advice >   
  42.     < aop:config   proxy-target-class = "true" >   
  43.         < aop:pointcut   id = "serviceMethod"   
  44.             expression = "execution(* org.ourpioneer.service.*Service.*(..))"   />   
  45.         < aop:advisor   advice-ref = "txAdvice"   pointcut-ref = "serviceMethod"   />   
  46.     </ aop:config >   


    之后对Service和Action进行配置:

Xml代码   收藏代码
  1. < bean   id = "baseService"   class = "org.ourpioneer.service.BaseService" >   
  2.     < property   name = "jdbcTemplate"   ref = "jdbcTemplate" > </ property >   
  3. </ bean >   
  4.   
  5. < bean   id = "userService"   class = "org.ourpioneer.service.UserService"   
  6.     parent = "baseService" >   
  7.     < property   name = "sqlMapClientTemplate"   ref = "sqlMapClientTemplate"   />   
  8. </ bean >   
  9. < bean   id = "userAction"   class = "org.ourpioneer.action.UserAction" >   
  10.     < property   name = "userService"   ref = "userService"   />   
  11. </ bean >   


    下面来看一下iBatis的配置,在配置SqlMapClient的时候,加入了iBatis的配置文件,我们来看看sqlMapConfig.xml如何来设置:

Xml代码   收藏代码
  1. <? xml   version = "1.0"   encoding = "UTF-8"   ?>    
  2. <!DOCTYPE sqlMapConfig   
  3.     PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"   
  4.     "http://www.ibatis.com/dtd/sql-map-config-2.dtd">   
  5. < sqlMapConfig >   
  6.     < settings   cacheModelsEnabled = "true"   enhancementEnabled = "true"   
  7.         lazyLoadingEnabled = "true"   errorTracingEnabled = "true"   maxRequests = "32"   
  8.         maxSessions = "10"   maxTransactions = "5"   />   
  9.     < sqlMap   resource = "sqlMaps/user.xml"   />   
  10. </ sqlMapConfig >   


    其实内容也很简单,就是设置一下必要的信息,其中的含义可以参考之前写过的对iBatis的介绍的相关文章,最后不要忘了加入sqlMaps配置文件即可,这里我们就一个user.xml文件,为了测试,也就是一条查询,针对这个查询进行分页操作:

Xml代码   收藏代码
  1. <? xml   version = "1.0"   encoding = "UTF-8"   ?>   
  2. <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">   
  3. < sqlMap >   
  4.     < typeAlias   alias = "parameterMap"   type = "org.pioneer.bean.ParameterMap"   />   
  5.     < select   id = "selectAllUsers"   resultClass = "java.util.HashMap" >   
  6.         select * from user  
  7.     </ select >   
  8. </ sqlMap >   


    ParameterMap在之前的介绍中也多次出现,这里我们也再来看下:

Java代码   收藏代码
  1. package  org.ourpioneer.bean;  
  2. import  java.util.HashMap;  
  3. public   class  ParameterMap  extends  HashMap {  
  4.     public  ParameterMap(Object... parameters) {  
  5.         for  ( int  i =  0 ; i < parameters.length -  1 ; i +=  2 ) {  
  6.             super .put(parameters[i], parameters[i +  1 ]);  
  7.         }  
  8.     }  
  9. }  


    其实就是扩展了一下HashMap类,来进行参数的放置,注意参数类型是可变参数的形式,也就是名-值对的形式出现的,不过本例中没有使用它。下面就是分页类的设计了:

Java代码   收藏代码
  1. package  org.ourpioneer.bean;  
  2.   
  3. import  java.util.HashMap;  
  4. import  java.util.List;  
  5.   
  6. import  org.springframework.jdbc.core.JdbcTemplate;  
  7. import  org.springframework.orm.ibatis.SqlMapClientTemplate;  
  8.   
  9. import  com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;  
  10. import  com.ibatis.sqlmap.engine.mapping.sql.Sql;  
  11. import  com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;  
  12. import  com.ibatis.sqlmap.engine.scope.SessionScope;  
  13. import  com.ibatis.sqlmap.engine.scope.StatementScope;  
  14.   
  15. /**  
  16.  * iBatis分页类  
  17.  *   
  18.  * @author Nanlei  
  19.  *   
  20.  */   
  21. public   class  PagingList {  
  22.     private   int  rowCount =  0 // 记录总数   
  23.     private   int  pageCount =  1 // 分页总数   
  24.     private   int  pageSize =  10 // 每页记录数   
  25.     private   int  pageNum =  1 // 当前页数   
  26.     private   int  startIndex =  1 // 起始记录数   
  27.     private   int  endIndex =  1 // 结束记录数   
  28.     private  List list; // 记录列表   
  29.   
  30.     /**  
  31.      * 构造方法,进行分页  
  32.      *   
  33.      * @param statementName  
  34.      *            iBatis中语句的ID  
  35.      * @param parameterObject  
  36.      *            SQL语句参数  
  37.      * @param pageNum  
  38.      *            起始页数  
  39.      * @param pageSize  
  40.      *            每页大小  
  41.      * @param sqlMapClientTemplate  
  42.      *            iBatis的sqlMapClientTemplate对象  
  43.      */   
  44.     public  PagingList(String statementName, Object parameterObject,  
  45.             int  pageNum,  int  pageSize,  
  46.             SqlMapClientTemplate sqlMapClientTemplate, JdbcTemplate jdbcTemplate) {  
  47.         preProcessParams(pageNum, pageSize);  
  48.         execute(statementName, parameterObject, pageNum, pageSize,  
  49.                 sqlMapClientTemplate, jdbcTemplate);  
  50.     }  
  51.   
  52.     /**  
  53.      * 构造方法,进行分页  
  54.      *   
  55.      * @param statementName  
  56.      *            iBatis中语句的ID  
  57.      * @param pageNum  
  58.      *            起始页数  
  59.      * @param pageSize  
  60.      *            每页大小  
  61.      * @param sqlMapClientTemplate  
  62.      *            iBatis的sqlMapClientTemplate对象  
  63.      */   
  64.     public  PagingList(String statementName,  int  pageNum,  int  pageSize,  
  65.             SqlMapClientTemplate sqlMapClientTemplate, JdbcTemplate jdbcTemplate) {  
  66.         preProcessParams(pageNum, pageSize);  
  67.         execute(statementName, pageNum, pageSize, sqlMapClientTemplate,  
  68.                 jdbcTemplate);  
  69.     }  
  70.   
  71.     /**  
  72.      * 执行方法  
  73.      *   
  74.      * @param statementName  
  75.      * @param parameterObject  
  76.      * @param pageNum  
  77.      * @param pageSize  
  78.      * @param sqlMapClientTemplate  
  79.      */   
  80.     public   void  execute(String statementName, Object parameterObject,  
  81.             int  pageNum,  int  pageSize,  
  82.             SqlMapClientTemplate sqlMapClientTemplate, JdbcTemplate jdbcTemplate) {  
  83.         // 计算记录总数   
  84.         this .rowCount = jdbcTemplate.queryForInt(  
  85.                 getCountSql(getSrcSql(statementName, parameterObject,  
  86.                         sqlMapClientTemplate)), ((HashMap) parameterObject)  
  87.                         .values().toArray());  
  88.         System.out.println(rowCount);  
  89.         // 计算分页数及起止记录   
  90.         countPage();  
  91.         // 获取分页列表   
  92.         this .list = sqlMapClientTemplate.queryForList(statementName,  
  93.                 parameterObject, (pageNum - 1 ) * pageSize, pageSize);  
  94.     }  
  95.   
  96.     /**  
  97.      * 执行方法  
  98.      *   
  99.      * @param statementName  
  100.      * @param pageNum  
  101.      * @param pageSize  
  102.      * @param sqlMapClientTemplate  
  103.      */   
  104.     public   void  execute(String statementName,  int  pageNum,  int  pageSize,  
  105.             SqlMapClientTemplate sqlMapClientTemplate, JdbcTemplate jdbcTemplate) {  
  106.         // 计算记录总数   
  107.         this .rowCount = jdbcTemplate.queryForInt(getCountSql(getSrcSql(  
  108.                 statementName, null , sqlMapClientTemplate)));  
  109.         System.out.println(rowCount);  
  110.         // 计算分页数及起止记录   
  111.         countPage();  
  112.         // 获取分页列表   
  113.         this .list = sqlMapClientTemplate.queryForList(statementName,  
  114.                 (pageNum - 1 ) * pageSize, pageSize);  
  115.     }  
  116.   
  117.     /**  
  118.      * 预处理SQL语句和页面参数  
  119.      */   
  120.     private   void  preProcessParams( int  pageNum,  int  pageSize) {  
  121.         if  (pageNum >  0 ) {  
  122.             this .pageNum = pageNum;  
  123.         }  
  124.         if  (pageSize >  0 ) {  
  125.             this .pageSize = pageSize;  
  126.         }  
  127.         if  (pageSize >  1000 ) {  
  128.             this .pageSize =  1000 ;  
  129.         }  
  130.     }  
  131.   
  132.     /**  
  133.      * 计算分页数及起止记录  
  134.      */   
  135.     private   void  countPage() {  
  136.         // 计算分页总数   
  137.         if  ((rowCount % pageSize) ==  0 ) {  
  138.             pageCount = rowCount / pageSize;  
  139.         } else  {  
  140.             pageCount = rowCount / pageSize + 1 ;  
  141.         }  
  142.         if  (pageCount ==  0 ) {  
  143.             pageCount = 1 ;  
  144.         }  
  145.         // 判断pageNum是否过界   
  146.         if  (pageNum > pageCount && rowCount !=  0 ) {  
  147.             pageNum = pageCount;  
  148.         }  
  149.         // 计算起止记录   
  150.         startIndex = (pageNum - 1 ) * pageSize +  1 ;  
  151.         endIndex = (pageNum) * pageSize;  
  152.     }  
  153.   
  154.     /**  
  155.      * 获得对象列表  
  156.      */   
  157.     public  List getList() {  
  158.         return  list;  
  159.     }  
  160.   
  161.     /* 获得起始记录数 */   
  162.     public   int  getStartIndex() {  
  163.         return  startIndex;  
  164.     }  
  165.   
  166.     public  Integer getStartIndexInteger() {  
  167.         return   new  Integer(startIndex);  
  168.     }  
  169.   
  170.     /* 获得结束记录数 */   
  171.     public   int  getEndIndex() {  
  172.         return  endIndex;  
  173.     }  
  174.   
  175.     public  Integer getEndIndexInteger() {  
  176.         return   new  Integer(endIndex);  
  177.     }  
  178.   
  179.     /* 获得分页其它信息 */   
  180.     public   int  getPageCount() {  
  181.         return  pageCount;  
  182.     }  
  183.   
  184.     public   int  getPageNum() {  
  185.         return  pageNum;  
  186.     }  
  187.   
  188.     public   int  getPageSize() {  
  189.         return  pageSize;  
  190.     }  
  191.   
  192.     public   int  getRowCount() {  
  193.         return  rowCount;  
  194.     }  
  195.   
  196.     private  String getSrcSql(String statementName, Object parameterObject,  
  197.             SqlMapClientTemplate sqlMapClientTemplate) {  
  198.         SqlMapClientImpl sqlMapClientImpl = (SqlMapClientImpl) sqlMapClientTemplate  
  199.                 .getSqlMapClient();  
  200.         MappedStatement mappedStatement = sqlMapClientImpl  
  201.                 .getMappedStatement(statementName);  
  202.         Sql sql = mappedStatement.getSql();  
  203.         StatementScope statementScope = new  StatementScope( new  SessionScope());  
  204.         String srcSql = sql.getSql(statementScope, parameterObject);  
  205.         return  srcSql;  
  206.     }  
  207.   
  208.     private  String getCountSql(String srcSql) {  
  209.         return   "SELECT COUNT(*) FROM ( "  + srcSql +  " ) CTBL_" ;  
  210.     }  
  211.   
  212. }  


    写好分页类,还要和框架进行集成,那么我们可以抽象出Service的基类,在业务逻辑层中调用它来获取分页信息:

Java代码   收藏代码
  1. package  org.ourpioneer.service;  
  2. import  org.ourpioneer.bean.PagingList;  
  3. import  org.springframework.orm.ibatis.SqlMapClientTemplate;  
  4. import  com.opensymphony.xwork2.ActionContext;  
  5. import  com.opensymphony.xwork2.util.ValueStack;  
  6. public   class  BaseService {  
  7.     private  JdbcTemplate jdbcTemplate;  
  8.   
  9.     public   void  setJdbcTemplate(JdbcTemplate jdbcTemplate) {  
  10.         this .jdbcTemplate = jdbcTemplate;  
  11.     }  
  12.   
  13.     /**  
  14.      * 获取ValueStack  
  15.      *   
  16.      * @return ValueStack对象  
  17.      */   
  18.     public  ValueStack getValueStack() {  
  19.         return  ActionContext.getContext().getValueStack();  
  20.     }  
  21.   
  22.     /**  
  23.      * 获取分页的List  
  24.      *   
  25.      * @param statementName  
  26.      * @param sqlMapClientTemplate  
  27.      * @return  
  28.      */   
  29.     public  PagingList getPagingList(String statementName,  
  30.             SqlMapClientTemplate sqlMapClientTemplate) {  
  31.         int  pageNum = ((Integer) getValueStack().findValue( "pageNum" ))  
  32.                 .intValue();  
  33.         int  pageSize = ((Integer) getValueStack().findValue( "pageSize" ))  
  34.                 .intValue();  
  35.         return   new  PagingList(statementName, pageNum, pageSize,  
  36.                 sqlMapClientTemplate, jdbcTemplate);  
  37.     }  
  38.   
  39.     /**  
  40.      * 获取分页的List  
  41.      *   
  42.      * @param statementName  
  43.      * @param parameterObject  
  44.      * @param sqlMapClientTemplate  
  45.      * @return  
  46.      */   
  47.     public  PagingList getPagingList(String statementName,  
  48.             Object parameterObject, SqlMapClientTemplate sqlMapClientTemplate) {  
  49.         int  pageNum = ((Integer) getValueStack().findValue( "pageNum" ))  
  50.                 .intValue();  
  51.         int  pageSize = ((Integer) getValueStack().findValue( "pageSize" ))  
  52.                 .intValue();  
  53.         return   new  PagingList(statementName, parameterObject, pageNum,  
  54.                 pageSize, sqlMapClientTemplate, jdbcTemplate);  
  55.     }  
  56. }  


    两个构造方法我们都使用了,也就是一个带参数,一个不带参数。下面来看抽象出的Action基类,主要是处理页面传入的分页参数的处理:

Java代码   收藏代码
  1. package  org.ourpioneer.action;  
  2. import  java.util.Map;  
  3. import  javax.servlet.http.HttpServletRequest;  
  4. import  org.apache.struts2.ServletActionContext;  
  5. import  org.ourpioneer.util.QueryUtil;  
  6. import  com.opensymphony.xwork2.ActionContext;  
  7. import  com.opensymphony.xwork2.ActionSupport;  
  8. public   class  BaseAction  extends  ActionSupport {  
  9.     @Override   
  10.     public  String execute()  throws  Exception {  
  11.         return  SUCCESS;  
  12.     }  
  13.     public  Map<String, Object> getParameters() {  
  14.         return  ActionContext.getContext().getParameters();  
  15.     }  
  16.     public  HttpServletRequest getRequest() {  
  17.         return  ServletActionContext.getRequest();  
  18.     }  
  19.     /* 分页信息 */   
  20.     protected   int  pageNum =  1 ;  
  21.     protected   int  pageSize =  10 ;  
  22.     public   int  getPageNum() {  
  23.         return  pageNum;  
  24.     }  
  25.     public   void  setPageNum( int  pageNum) {  
  26.         this .pageNum = pageNum;  
  27.     }  
  28.     public   int  getPageSize() {  
  29.         return  pageSize;  
  30.     }  
  31.     public   void  setPageSize( int  pageSize) {  
  32.         this .pageSize = pageSize;  
  33.     }  
  34.     public   int  getMaxPageSize() {  
  35.         return   1000 ;  
  36.     }  
  37.     public   int  getDefaultPageSize() {  
  38.         return   10 ;  
  39.     }  
  40.     // 页面解析分页信息使用的方法   
  41.     public  String getQueryStringWithoutPageNum() {  
  42.         Map<String, Object> m = getParameters();  
  43.         m.remove("pageNum" );  
  44.         return  QueryUtil.getQueryString(m);  
  45.     }  
  46.     public  String getFullUrlWithoutPageNum() {  
  47.         return  getRequest().getServletPath() +  "?"   
  48.                 + getQueryStringWithoutPageNum();  
  49.     }  
  50.     public  String getQueryStringWithoutPageInfo() {  
  51.         Map<String, Object> m = getParameters();  
  52.         m.remove("pageNum" );  
  53.         m.remove("pageSize" );  
  54.         return  QueryUtil.getQueryString(m);  
  55.     }  
  56.     public  String getFullUrlWithoutPageInfo() {  
  57.         return  getRequest().getServletPath() +  "?"   
  58.                 + getQueryStringWithoutPageInfo();  
  59.     }  
  60. }  


    这里为了演示,我们将分页的信息都直接定义死了,大家可以根据需要来修改,其中处理信息的QueryUtil大家可以直接参考源代码,这里不做说明了,下面是UserAction处理代码的编写:

Java代码   收藏代码
  1. package  org.ourpioneer.action;  
  2. import  org.ourpioneer.bean.PagingList;  
  3. import  org.ourpioneer.service.UserService;  
  4. public   class  UserAction  extends  BaseAction {  
  5.     private  UserService userService;  
  6.     public  PagingList userList;  
  7.     public   void  setUserService(UserService userService) {  
  8.         this .userService = userService;  
  9.     }  
  10.     public  PagingList getUserList() {  
  11.         return  userList;  
  12.     }  
  13.     public  String list() {  
  14.         userList = userService.getAllUsers();  
  15.         return   "list" ;  
  16.     }  
  17. }  


    根据前面的配置,我们也不难写出代码,下面就是视图处理了,我们使用了Freemarker进行解析,也编写了FreeMarker的分页宏:

Html代码   收藏代码
  1. < #-- 处理分页参数 -- >   
  2. < #function getPageUrl pageNum >   
  3. < #local  pageUrl = base +fullUrlWithoutPageInfo >   
  4. < #if pageUrl?ends_with("?") >   
  5. < #return pageUrl + " pageSize = " + pageSize + " & pageNum =" + pageNum >   
  6. < #else >   
  7. < #return pageUrl + "& pageSize = " + pageSize + " & pageNum =" + pageNum >   
  8. </ #if >   
  9. </ #function >   
  10. < #-- 全部或分页显示 -- >   
  11. < #function getPageUrlResize size >   
  12. < #local  pageUrl = base +fullUrlWithoutPageInfo >   
  13. < #if pageUrl?ends_with("?") >   
  14. < #return pageUrl + " pageNum = 1 & pageSize =" + size >   
  15. < #else >   
  16. < #return pageUrl + "& pageNum = 1 & pageSize =" + size >   
  17. </ #if >   
  18. </ #function >   
  19.   
  20. < #-- 分页信息 -- >   
  21. < #macro paging pagingList >   
  22. < #local  pageCount = pagingList .pageCount >   
  23. < #local  rowCount = pagingList .rowCount >   
  24. < #local  pageNum = pagingList .pageNum >   
  25. < #local  pageSize = pagingList .pageSize >   
  26. < #if  rowCount  == 0 >   
  27.     < #if useFlag?exists >   
  28.         < div   style = "border:1px solid #666;padding:2 5 2 5;background:#efefef;color:#333" > 没有相关记录 </ div >   
  29.     < #else >   
  30.         < #assign  useFlag  =  1 >   
  31.     </ #if >   
  32. < #else >   
  33. < table >   
  34.     < tr >   
  35.         < td   style = "line-height:150%" > 共 ${rowCount} 条记录 ${pageCount} 页   
  36.         < #if pageCount gt 1 && pageSize!=maxPageSize >   
  37.             < span   class = "selectedPage"   style = "padding:2px 3px 0 3px" > < a   class = "page"   href = "${getPageUrlResize(maxPageSize)}" > 全部显示 </ a > </ span >   
  38.         < #elseif  pageSize ==maxPageSize >   
  39.             < span   class = "selectedPage"   style = "padding:2px 3px 0 3px" > < a   class = "page"   href = "${getPageUrlResize(defaultPageSize)}" > 分页显示 </ a > </ span >   
  40.         </ #if >   
  41.         < #if (pageCount  < = 11) >   
  42.             < #local  startPage  =  1 >   
  43.             < #local  endPage  =  pageCount >   
  44.         < #elseif (pageNum + 5  >  pageCount) >   
  45.             < #local  startPage  =  pageCount  - 10 >   
  46.             < #local  endPage  =  pageCount >   
  47.         < #elseif (pageNum - 5  <   1 ) >   
  48.             < #local  startPage  =  1 >   
  49.             < #local  endPage  =  11 >   
  50.         < #else >   
  51.             < #local  startPage  =  pageNum  - 5 >   
  52.             < #local  endPage  =  pageNum  + 5 >   
  53.         </ #if >   
  54.         < #if (pageCount  >  1) >   
  55.             < #if (pageNum != 1) >   
  56.                 < #if (pageCount  >  11) >   
  57.                     < a   class = "page"   href = "${getPageUrl(1)}"   style = "font-family:Webdings"   title = "首页" > 9 </ a >   
  58.                 </ #if >   
  59.                 < a   class = "page"   href = "${getPageUrl(pageNum-1)}"   style = "font-family:Webdings"   title = "上页" > 3 </ a >   
  60.             < #else >   
  61.                 < #if (pageCount  >  11) >   
  62.                     < span   style = "font-family:Webdings;color:#999" > 9 </ span >   
  63.                 </ #if >   
  64.                 < span   style = "font-family:Webdings;color:#999" > 3 </ span >   
  65.             </ #if >   
  66.             < #list startPage..endPage as x >   
  67.                 < #if  x = pageNum >   
  68.                     < span   class = "selectedPage" > ${x} </ span >   
  69.                 < #else >   
  70.                     < span   class = "noSelectedPage" > < a   class = "page"   href = "${getPageUrl(x)}" > ${x} </ a > </ span >   
  71.                 </ #if >   
  72.             </ #list >   
  73.             < #if (pageCount != pageNum) >   
  74.                 < a   class = "page"   href = "${getPageUrl(pageNum+1)}"   style = "font-family:Webdings"   title = "下页" > 4 </ a >   
  75.                 < #if (pageCount  >  11) >   
  76.                     < a   class = "page"   href = "${getPageUrl(pageCount)}"   style = "font-family:Webdings"   title = "尾页" > : </ a >   
  77.                 </ #if >   
  78.             < #else >   
  79.                 < span   style = "font-family:Webdings;color:#999" > 4 </ span >   
  80.                 < #if (pageCount  >  11) >   
  81.                     < span   style = "font-family:Webdings;color:#999" > : </ span >   
  82.                 </ #if >   
  83.             </ #if >   
  84.         </ #if >   
  85.         </ td >   
  86.     </ tr >   
  87. </ table >   
  88. </ #if >   
  89. </ #macro >   


    之后,我们来运行项目:
iBatis分页(基于Struts2和Freemarke)
    可以通过点击全部显示和页面来查看分页效果。
     本文系作者本人的实践探索,方案可能不是最佳实践,希望和大家交流沟通,源码随附件可以下载。另外关于本文涉及到的技术可以参看本博客中以往对iBatis的介绍:
框架系列:框架技术
    最后,希望它对使用者和学习有用。根据大家的反馈意见全新修改。

你可能感兴趣的:(freemark)