iBatis开发详解(5)-----------分页(Struts、freeMark)

之前介绍过基于Hibernate分页的原理和设计,这里我们所用的分页都是物理分页技术,不是JS实现的页面分页技术,是在SQL语句上执行的分页,可以获取结果集数量固定的列表,执行效率很高。下面来看看iBatis中如何设计分页,本文基于Struts2,Spring3来整合,因为暂时Spring不支持MyBatis3(可以选用MyBatis官方的MyBatis-Spring插件来实现,配有中文文档,很好理解),我们这里仍然以iBatis2作为载体来介绍。 
    首先就是搭建开发环境,这里可以说也是对Struts2,Spring3和iBatis2进行了简单的整合,大家也可以来参考。项目的结构如下,使用Maven创建的web项目: 
iBatis开发详解(5)-----------分页(Struts、freeMark)_第1张图片  
    添加必要的依赖,因为整合了Struts2和Spring,依赖就比较多了,如下: 
iBatis开发详解(5)-----------分页(Struts、freeMark)_第2张图片  
    首先来配置一下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开发详解(5)-----------分页(Struts、freeMark)_第3张图片  
    可以通过点击全部显示和页面来查看分页效果。 
     本文系作者本人的实践探索,方案可能不是最佳实践,希望和大家交流沟通,源码随附件可以下载。另外关于本文涉及到的技术可以参看本博客中以往对iBatis的介绍: 
框架系列: 框架技术 , 

你可能感兴趣的:(iBatis开发详解(5)-----------分页(Struts、freeMark))