iBatis分页(基于Struts2和Freemarker)

本文介绍基于iBatis的物理分页技术实现方法,通过整合Struts2、Spring3和iBatis2,实现高效的SQL分页查询,并提供Freemarker视图层的分页宏展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

添加必要的依赖,因为整合了Struts2和Spring,依赖就比较多了,如下:

首先来配置一下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. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEstrutsPUBLIC
  3. "-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.1.7//EN"
  4. "http://struts.apache.org/dtds/struts-2.1.7.dtd">
  5. <struts>
  6. <packagename="ibatis-paging"extends="struts-default"
  7. namespace="/">
  8. <result-types>
  9. <result-typename="freemarker"
  10. class="org.apache.struts2.views.freemarker.FreemarkerResult"
  11. default="true"/>
  12. </result-types>
  13. <actionname="user_*"class="userAction"method="{1}">
  14. <resultname="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-ddHH:mm:ss
  8. boolean_format=true,false
  9. whitespace_stripping=true
  10. tag_syntax=auto_detect
  11. auto_import=/Freemarker/page_macro.ftlasp

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

之后对Service和Action进行配置:
Xml代码 收藏代码
  1. <beanid="baseService"class="org.ourpioneer.service.BaseService">
  2. <propertyname="jdbcTemplate"ref="jdbcTemplate"></property>
  3. </bean>
  4. <beanid="userService"class="org.ourpioneer.service.UserService"
  5. parent="baseService">
  6. <propertyname="sqlMapClientTemplate"ref="sqlMapClientTemplate"/>
  7. </bean>
  8. <beanid="userAction"class="org.ourpioneer.action.UserAction">
  9. <propertyname="userService"ref="userService"/>
  10. </bean>

下面来看一下iBatis的配置,在配置SqlMapClient的时候,加入了iBatis的配置文件,我们来看看sqlMapConfig.xml如何来设置:
Xml代码 收藏代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEsqlMapConfig
  3. PUBLIC"-//iBATIS.com//DTDSQLMapConfig2.0//EN"
  4. "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
  5. <sqlMapConfig>
  6. <settingscacheModelsEnabled="true"enhancementEnabled="true"
  7. lazyLoadingEnabled="true"errorTracingEnabled="true"maxRequests="32"
  8. maxSessions="10"maxTransactions="5"/>
  9. <sqlMapresource="sqlMaps/user.xml"/>
  10. </sqlMapConfig>

其实内容也很简单,就是设置一下必要的信息,其中的含义可以参考之前写过的对iBatis的介绍的相关文章,最后不要忘了加入sqlMaps配置文件即可,这里我们就一个user.xml文件,为了测试,也就是一条查询,针对这个查询进行分页操作:
Xml代码 收藏代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEsqlMapPUBLIC"-//ibatis.apache.org//DTDSQLMap2.0//EN""http://ibatis.apache.org/dtd/sql-map-2.dtd">
  3. <sqlMap>
  4. <typeAliasalias="parameterMap"type="org.pioneer.bean.ParameterMap"/>
  5. <selectid="selectAllUsers"resultClass="java.util.HashMap">
  6. select*fromuser
  7. </select>
  8. </sqlMap>

ParameterMap在之前的介绍中也多次出现,这里我们也再来看下:
Java代码 收藏代码
  1. packageorg.ourpioneer.bean;
  2. importjava.util.HashMap;
  3. publicclassParameterMapextendsHashMap{
  4. publicParameterMap(Object...parameters){
  5. for(inti=0;i<parameters.length-1;i+=2){
  6. super.put(parameters[i],parameters[i+1]);
  7. }
  8. }
  9. }

其实就是扩展了一下HashMap类,来进行参数的放置,注意参数类型是可变参数的形式,也就是名-值对的形式出现的,不过本例中没有使用它。下面就是分页类的设计了:
Java代码 收藏代码
  1. packageorg.ourpioneer.bean;
  2. importjava.util.HashMap;
  3. importjava.util.List;
  4. importorg.springframework.jdbc.core.JdbcTemplate;
  5. importorg.springframework.orm.ibatis.SqlMapClientTemplate;
  6. importcom.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
  7. importcom.ibatis.sqlmap.engine.mapping.sql.Sql;
  8. importcom.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
  9. importcom.ibatis.sqlmap.engine.scope.SessionScope;
  10. importcom.ibatis.sqlmap.engine.scope.StatementScope;
  11. /**
  12. *iBatis分页类
  13. *
  14. *@authorNanlei
  15. *
  16. */
  17. publicclassPagingList{
  18. privateintrowCount=0;//记录总数
  19. privateintpageCount=1;//分页总数
  20. privateintpageSize=10;//每页记录数
  21. privateintpageNum=1;//当前页数
  22. privateintstartIndex=1;//起始记录数
  23. privateintendIndex=1;//结束记录数
  24. privateListlist;//记录列表
  25. /**
  26. *构造方法,进行分页
  27. *
  28. *@paramstatementName
  29. *iBatis中语句的ID
  30. *@paramparameterObject
  31. *SQL语句参数
  32. *@parampageNum
  33. *起始页数
  34. *@parampageSize
  35. *每页大小
  36. *@paramsqlMapClientTemplate
  37. *iBatis的sqlMapClientTemplate对象
  38. */
  39. publicPagingList(StringstatementName,ObjectparameterObject,
  40. intpageNum,intpageSize,
  41. SqlMapClientTemplatesqlMapClientTemplate,JdbcTemplatejdbcTemplate){
  42. preProcessParams(pageNum,pageSize);
  43. execute(statementName,parameterObject,pageNum,pageSize,
  44. sqlMapClientTemplate,jdbcTemplate);
  45. }
  46. /**
  47. *构造方法,进行分页
  48. *
  49. *@paramstatementName
  50. *iBatis中语句的ID
  51. *@parampageNum
  52. *起始页数
  53. *@parampageSize
  54. *每页大小
  55. *@paramsqlMapClientTemplate
  56. *iBatis的sqlMapClientTemplate对象
  57. */
  58. publicPagingList(StringstatementName,intpageNum,intpageSize,
  59. SqlMapClientTemplatesqlMapClientTemplate,JdbcTemplatejdbcTemplate){
  60. preProcessParams(pageNum,pageSize);
  61. execute(statementName,pageNum,pageSize,sqlMapClientTemplate,
  62. jdbcTemplate);
  63. }
  64. /**
  65. *执行方法
  66. *
  67. *@paramstatementName
  68. *@paramparameterObject
  69. *@parampageNum
  70. *@parampageSize
  71. *@paramsqlMapClientTemplate
  72. */
  73. publicvoidexecute(StringstatementName,ObjectparameterObject,
  74. intpageNum,intpageSize,
  75. SqlMapClientTemplatesqlMapClientTemplate,JdbcTemplatejdbcTemplate){
  76. //计算记录总数
  77. this.rowCount=jdbcTemplate.queryForInt(
  78. getCountSql(getSrcSql(statementName,parameterObject,
  79. sqlMapClientTemplate)),((HashMap)parameterObject)
  80. .values().toArray());
  81. System.out.println(rowCount);
  82. //计算分页数及起止记录
  83. countPage();
  84. //获取分页列表
  85. this.list=sqlMapClientTemplate.queryForList(statementName,
  86. parameterObject,(pageNum-1)*pageSize,pageSize);
  87. }
  88. /**
  89. *执行方法
  90. *
  91. *@paramstatementName
  92. *@parampageNum
  93. *@parampageSize
  94. *@paramsqlMapClientTemplate
  95. */
  96. publicvoidexecute(StringstatementName,intpageNum,intpageSize,
  97. SqlMapClientTemplatesqlMapClientTemplate,JdbcTemplatejdbcTemplate){
  98. //计算记录总数
  99. this.rowCount=jdbcTemplate.queryForInt(getCountSql(getSrcSql(
  100. statementName,null,sqlMapClientTemplate)));
  101. System.out.println(rowCount);
  102. //计算分页数及起止记录
  103. countPage();
  104. //获取分页列表
  105. this.list=sqlMapClientTemplate.queryForList(statementName,
  106. (pageNum-1)*pageSize,pageSize);
  107. }
  108. /**
  109. *预处理SQL语句和页面参数
  110. */
  111. privatevoidpreProcessParams(intpageNum,intpageSize){
  112. if(pageNum>0){
  113. this.pageNum=pageNum;
  114. }
  115. if(pageSize>0){
  116. this.pageSize=pageSize;
  117. }
  118. if(pageSize>1000){
  119. this.pageSize=1000;
  120. }
  121. }
  122. /**
  123. *计算分页数及起止记录
  124. */
  125. privatevoidcountPage(){
  126. //计算分页总数
  127. if((rowCount%pageSize)==0){
  128. pageCount=rowCount/pageSize;
  129. }else{
  130. pageCount=rowCount/pageSize+1;
  131. }
  132. if(pageCount==0){
  133. pageCount=1;
  134. }
  135. //判断pageNum是否过界
  136. if(pageNum>pageCount&&rowCount!=0){
  137. pageNum=pageCount;
  138. }
  139. //计算起止记录
  140. startIndex=(pageNum-1)*pageSize+1;
  141. endIndex=(pageNum)*pageSize;
  142. }
  143. /**
  144. *获得对象列表
  145. */
  146. publicListgetList(){
  147. returnlist;
  148. }
  149. /*获得起始记录数*/
  150. publicintgetStartIndex(){
  151. returnstartIndex;
  152. }
  153. publicIntegergetStartIndexInteger(){
  154. returnnewInteger(startIndex);
  155. }
  156. /*获得结束记录数*/
  157. publicintgetEndIndex(){
  158. returnendIndex;
  159. }
  160. publicIntegergetEndIndexInteger(){
  161. returnnewInteger(endIndex);
  162. }
  163. /*获得分页其它信息*/
  164. publicintgetPageCount(){
  165. returnpageCount;
  166. }
  167. publicintgetPageNum(){
  168. returnpageNum;
  169. }
  170. publicintgetPageSize(){
  171. returnpageSize;
  172. }
  173. publicintgetRowCount(){
  174. returnrowCount;
  175. }
  176. privateStringgetSrcSql(StringstatementName,ObjectparameterObject,
  177. SqlMapClientTemplatesqlMapClientTemplate){
  178. SqlMapClientImplsqlMapClientImpl=(SqlMapClientImpl)sqlMapClientTemplate
  179. .getSqlMapClient();
  180. MappedStatementmappedStatement=sqlMapClientImpl
  181. .getMappedStatement(statementName);
  182. Sqlsql=mappedStatement.getSql();
  183. StatementScopestatementScope=newStatementScope(newSessionScope());
  184. StringsrcSql=sql.getSql(statementScope,parameterObject);
  185. returnsrcSql;
  186. }
  187. privateStringgetCountSql(StringsrcSql){
  188. return"SELECTCOUNT(*)FROM("+srcSql+")CTBL_";
  189. }
  190. }

写好分页类,还要和框架进行集成,那么我们可以抽象出Service的基类,在业务逻辑层中调用它来获取分页信息:
Java代码 收藏代码
  1. packageorg.ourpioneer.service;
  2. importorg.ourpioneer.bean.PagingList;
  3. importorg.springframework.orm.ibatis.SqlMapClientTemplate;
  4. importcom.opensymphony.xwork2.ActionContext;
  5. importcom.opensymphony.xwork2.util.ValueStack;
  6. publicclassBaseService{
  7. privateJdbcTemplatejdbcTemplate;
  8. publicvoidsetJdbcTemplate(JdbcTemplatejdbcTemplate){
  9. this.jdbcTemplate=jdbcTemplate;
  10. }
  11. /**
  12. *获取ValueStack
  13. *
  14. *@returnValueStack对象
  15. */
  16. publicValueStackgetValueStack(){
  17. returnActionContext.getContext().getValueStack();
  18. }
  19. /**
  20. *获取分页的List
  21. *
  22. *@paramstatementName
  23. *@paramsqlMapClientTemplate
  24. *@return
  25. */
  26. publicPagingListgetPagingList(StringstatementName,
  27. SqlMapClientTemplatesqlMapClientTemplate){
  28. intpageNum=((Integer)getValueStack().findValue("pageNum"))
  29. .intValue();
  30. intpageSize=((Integer)getValueStack().findValue("pageSize"))
  31. .intValue();
  32. returnnewPagingList(statementName,pageNum,pageSize,
  33. sqlMapClientTemplate,jdbcTemplate);
  34. }
  35. /**
  36. *获取分页的List
  37. *
  38. *@paramstatementName
  39. *@paramparameterObject
  40. *@paramsqlMapClientTemplate
  41. *@return
  42. */
  43. publicPagingListgetPagingList(StringstatementName,
  44. ObjectparameterObject,SqlMapClientTemplatesqlMapClientTemplate){
  45. intpageNum=((Integer)getValueStack().findValue("pageNum"))
  46. .intValue();
  47. intpageSize=((Integer)getValueStack().findValue("pageSize"))
  48. .intValue();
  49. returnnewPagingList(statementName,parameterObject,pageNum,
  50. pageSize,sqlMapClientTemplate,jdbcTemplate);
  51. }
  52. }

两个构造方法我们都使用了,也就是一个带参数,一个不带参数。下面来看抽象出的Action基类,主要是处理页面传入的分页参数的处理:
Java代码 收藏代码
  1. packageorg.ourpioneer.action;
  2. importjava.util.Map;
  3. importjavax.servlet.http.HttpServletRequest;
  4. importorg.apache.struts2.ServletActionContext;
  5. importorg.ourpioneer.util.QueryUtil;
  6. importcom.opensymphony.xwork2.ActionContext;
  7. importcom.opensymphony.xwork2.ActionSupport;
  8. publicclassBaseActionextendsActionSupport{
  9. @Override
  10. publicStringexecute()throwsException{
  11. returnSUCCESS;
  12. }
  13. publicMap<String,Object>getParameters(){
  14. returnActionContext.getContext().getParameters();
  15. }
  16. publicHttpServletRequestgetRequest(){
  17. returnServletActionContext.getRequest();
  18. }
  19. /*分页信息*/
  20. protectedintpageNum=1;
  21. protectedintpageSize=10;
  22. publicintgetPageNum(){
  23. returnpageNum;
  24. }
  25. publicvoidsetPageNum(intpageNum){
  26. this.pageNum=pageNum;
  27. }
  28. publicintgetPageSize(){
  29. returnpageSize;
  30. }
  31. publicvoidsetPageSize(intpageSize){
  32. this.pageSize=pageSize;
  33. }
  34. publicintgetMaxPageSize(){
  35. return1000;
  36. }
  37. publicintgetDefaultPageSize(){
  38. return10;
  39. }
  40. //页面解析分页信息使用的方法
  41. publicStringgetQueryStringWithoutPageNum(){
  42. Map<String,Object>m=getParameters();
  43. m.remove("pageNum");
  44. returnQueryUtil.getQueryString(m);
  45. }
  46. publicStringgetFullUrlWithoutPageNum(){
  47. returngetRequest().getServletPath()+"?"
  48. +getQueryStringWithoutPageNum();
  49. }
  50. publicStringgetQueryStringWithoutPageInfo(){
  51. Map<String,Object>m=getParameters();
  52. m.remove("pageNum");
  53. m.remove("pageSize");
  54. returnQueryUtil.getQueryString(m);
  55. }
  56. publicStringgetFullUrlWithoutPageInfo(){
  57. returngetRequest().getServletPath()+"?"
  58. +getQueryStringWithoutPageInfo();
  59. }
  60. }

这里为了演示,我们将分页的信息都直接定义死了,大家可以根据需要来修改,其中处理信息的QueryUtil大家可以直接参考源代码,这里不做说明了,下面是UserAction处理代码的编写:
Java代码 收藏代码
  1. packageorg.ourpioneer.action;
  2. importorg.ourpioneer.bean.PagingList;
  3. importorg.ourpioneer.service.UserService;
  4. publicclassUserActionextendsBaseAction{
  5. privateUserServiceuserService;
  6. publicPagingListuserList;
  7. publicvoidsetUserService(UserServiceuserService){
  8. this.userService=userService;
  9. }
  10. publicPagingListgetUserList(){
  11. returnuserList;
  12. }
  13. publicStringlist(){
  14. userList=userService.getAllUsers();
  15. return"list";
  16. }
  17. }

根据前面的配置,我们也不难写出代码,下面就是视图处理了,我们使用了Freemarker进行解析,也编写了FreeMarker的分页宏:
Html代码 收藏代码
  1. <#--处理分页参数-->
  2. <#functiongetPageUrlpageNum>
  3. <#localpageUrl=base+fullUrlWithoutPageInfo>
  4. <#ifpageUrl?ends_with("?")>
  5. <#returnpageUrl+"pageSize="+pageSize+"&pageNum="+pageNum>
  6. <#else>
  7. <#returnpageUrl+"&pageSize="+pageSize+"&pageNum="+pageNum>
  8. </#if>
  9. </#function>
  10. <#--全部或分页显示-->
  11. <#functiongetPageUrlResizesize>
  12. <#localpageUrl=base+fullUrlWithoutPageInfo>
  13. <#ifpageUrl?ends_with("?")>
  14. <#returnpageUrl+"pageNum=1&pageSize="+size>
  15. <#else>
  16. <#returnpageUrl+"&pageNum=1&pageSize="+size>
  17. </#if>
  18. </#function>
  19. <#--分页信息-->
  20. <#macropagingpagingList>
  21. <#localpageCount=pagingList.pageCount>
  22. <#localrowCount=pagingList.rowCount>
  23. <#localpageNum=pagingList.pageNum>
  24. <#localpageSize=pagingList.pageSize>
  25. <#ifrowCount==0>
  26. <#ifuseFlag?exists>
  27. <divstyle="border:1pxsolid#666;padding:2525;background:#efefef;color:#333">没有相关记录</div>
  28. <#else>
  29. <#assignuseFlag=1>
  30. </#if>
  31. <#else>
  32. <table>
  33. <tr>
  34. <tdstyle="line-height:150%">共${rowCount}条记录${pageCount}页
  35. <#ifpageCountgt1&&pageSize!=maxPageSize>
  36. <spanclass="selectedPage"style="padding:2px3px03px"><aclass="page"href="${getPageUrlResize(maxPageSize)}">全部显示</a></span>
  37. <#elseifpageSize==maxPageSize>
  38. <spanclass="selectedPage"style="padding:2px3px03px"><aclass="page"href="${getPageUrlResize(defaultPageSize)}">分页显示</a></span>
  39. </#if>
  40. <#if(pageCount<=11)>
  41. <#localstartPage=1>
  42. <#localendPage=pageCount>
  43. <#elseif(pageNum+5>pageCount)>
  44. <#localstartPage=pageCount-10>
  45. <#localendPage=pageCount>
  46. <#elseif(pageNum-5<1)>
  47. <#localstartPage=1>
  48. <#localendPage=11>
  49. <#else>
  50. <#localstartPage=pageNum-5>
  51. <#localendPage=pageNum+5>
  52. </#if>
  53. <#if(pageCount>1)>
  54. <#if(pageNum!=1)>
  55. <#if(pageCount>11)>
  56. <aclass="page"href="${getPageUrl(1)}"style="font-family:Webdings"title="首页">9</a>
  57. </#if>
  58. <aclass="page"href="${getPageUrl(pageNum-1)}"style="font-family:Webdings"title="上页">3</a>
  59. <#else>
  60. <#if(pageCount>11)>
  61. <spanstyle="font-family:Webdings;color:#999">9</span>
  62. </#if>
  63. <spanstyle="font-family:Webdings;color:#999">3</span>
  64. </#if>
  65. <#liststartPage..endPageasx>
  66. <#ifx=pageNum>
  67. <spanclass="selectedPage">${x}</span>
  68. <#else>
  69. <spanclass="noSelectedPage"><aclass="page"href="${getPageUrl(x)}">${x}</a></span>
  70. </#if>
  71. </#list>
  72. <#if(pageCount!=pageNum)>
  73. <aclass="page"href="${getPageUrl(pageNum+1)}"style="font-family:Webdings"title="下页">4</a>
  74. <#if(pageCount>11)>
  75. <aclass="page"href="${getPageUrl(pageCount)}"style="font-family:Webdings"title="尾页">:</a>
  76. </#if>
  77. <#else>
  78. <spanstyle="font-family:Webdings;color:#999">4</span>
  79. <#if(pageCount>11)>
  80. <spanstyle="font-family:Webdings;color:#999">:</span>
  81. </#if>
  82. </#if>
  83. </#if>
  84. </td>
  85. </tr>
  86. </table>
  87. </#if>
  88. </#macro>

之后,我们来运行项目:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值