JSP标签实现分页功能(ORM-mybatis)
来源:互联网 发布:金天鹅软件 编辑:程序博客网 时间:2024/05/29 03:51
分页对象
package com.pcitc.modules.pagination;import java.io.Serializable;import java.util.Arrays;import java.util.List;/** * 通用分页类 * @author mi * * @param <T> */public class Pagination<T> implements Serializable{ private static final long serialVersionUID = 1L; public static final int DEF_PAGE_SIZE = 3; //默认显示10条数据 public static final int DEF_DISLAY_PAGENUM = 10; //默认显示十个页码 protected int displayPageNum = DEF_DISLAY_PAGENUM; //默认显示10个页码 protected int totalCount = 0; //总记录条数 protected int pageSize = DEF_PAGE_SIZE; //页面中显示的数据多少 protected int pageNo = 1; //当前页码 protected List<T> pageData; //分页中显示的数据的集合 protected int startRow = 0;//起始行 protected int totalPageNo; //总的页码数 protected int[] pageNums; //页面显示的页码集 private String pageSizeName; private String pageNoName; private String totalCountName; public Pagination() { } /** * 构造器 * * @param pageNo * 页码 * @param pageSize * 每页几条数据 * @param totalCount * 总共几条数据 */ public Pagination(int pageNo, int pageSize, int totalCount) { setPageSize(pageSize); setTotalCount(totalCount); setPageNo(pageNo); calculateTotalPageNo(); //计算总的页码数 adjustPageNo(); //调整页码 caculateStartRow(); //进行startRow的计算 calculateDisNum(); //进行页码显示计算 } /** * 进行总的参数的调整,适合setter所有参数后,进行参数的调整 */ public void adjustAllProcess(){ calculateTotalPageNo(); //计算总的页码数 adjustPageNo(); //调整页码 caculateStartRow(); //进行startRow的计算 calculateDisNum(); //进行页码显示计算 } /** * 调整传入的请求页码 */ public void adjustPageNo() { if(this.totalPageNo < this.pageNo && this.totalPageNo > 0){ this.pageNo = this.totalPageNo; } } /** * 进行startRow的计算 */ public void caculateStartRow() { this.startRow = (this.pageNo -1) * this.pageSize; } /** * 计算总的页码数,注意这样一定要先注入pageSize和totalCount */ public void calculateTotalPageNo() { this.totalPageNo = this.totalCount%this.pageSize == 0?this.totalCount/this.pageSize:this.totalCount/this.pageSize+1; } /** * 获得页码 */ public int getPageNo() { return pageNo; } /** * 每页几条数据 */ public int getPageSize() { return pageSize; } /** * 总共几条数据 */ public int getTotalCount() { return totalCount; } /** * 是否第一页 */ public boolean isFirstPage() { return pageNo <= 1; } /** * 是否最后一页 */ public boolean isLastPage() { return pageNo >= this.totalPageNo; } /** * 下一页页码 */ public int getNextPage() { if (isLastPage()) { return pageNo; } else { return pageNo + 1; } } /** * 上一页页码 */ public int getPrePage() { if (isFirstPage()) { return pageNo; } else { return pageNo - 1; } } /** * if totalCount<0 then totalCount=0 * * @param totalCount */ public void setTotalCount(int totalCount) { if (totalCount < 0) { this.totalCount = 0; } else { this.totalCount = totalCount; } } /** * if pageSize< 1 then pageSize=DEF_COUNT * * @param pageSize */ public void setPageSize(int pageSize) { if (pageSize < 1) { this.pageSize = DEF_PAGE_SIZE; } else { this.pageSize = pageSize; } } /** * if pageNo < 1 then pageNo=1 * * @param pageNo */ public void setPageNo(int pageNo) { if (pageNo < 1) { this.pageNo = 1; } else { this.pageNo = pageNo; } } /** * 进行显示页码的计算 */ public void calculateDisNum(){ if(this.totalPageNo > this.displayPageNum){ this.pageNums = new int[this.displayPageNum]; int bet = (this.displayPageNum % 2 == 0 ? this.displayPageNum /2 : (this.displayPageNum /2+1)); if(this.pageNo <= bet){ for(int i=1;i<=this.displayPageNum;i++){ pageNums[i-1] = i; } }else{ //后面没有那么多 if((this.pageNo + bet) > this.totalPageNo){ for(int i=(this.totalPageNo-this.displayPageNum+1),j=0;i<=this.totalPageNo;i++,j++){ this.pageNums[j] = i; } }else{ //偶数 if(this.displayPageNum % 2 == 0){ for(int i=(this.pageNo-bet),j=0;i<=(this.pageNo+bet-1);i++){ this.pageNums[j] = i; j++; } }else{ for(int i=(this.pageNo-bet+1),j=0;i<=(this.pageNo+bet-1);i++){ System.out.println(i); this.pageNums[j] = i; j++; } } } } }else{ this.pageNums = new int[this.totalPageNo]; for(int i=1;i<=this.totalPageNo;i++){ this.pageNums[i-1] = i; } } } public List<T> getPageData() { return pageData; } public void setPageData(List<T> pageData) { this.pageData = pageData; } public int getStartRow() { return startRow; } public void setStartRow(int startRow) { this.startRow = startRow; } public int getTotalPageNo() { return totalPageNo; } public void setTotalPageNo(int totalPageNo) { this.totalPageNo = totalPageNo; } public int getDisplayPageNum() { return displayPageNum; } public void setDisplayPageNum(int displayPageNum) { if(displayPageNum <= 1){ this.displayPageNum = DEF_DISLAY_PAGENUM; }else{ this.displayPageNum = displayPageNum; } } @Override public String toString() { return "Pagination [displayPageNum=" + displayPageNum + ", totalCount=" + totalCount + ", pageSize=" + pageSize + ", pageNo=" + pageNo + ", pageData=" + pageData + ", startRow=" + startRow + ", totalPageNo=" + totalPageNo + ", pageNums=" + Arrays.toString(pageNums) + "]"; } public int[] getPageNums() { return pageNums; } public String getPageSizeName() { return pageSizeName; } public void setPageSizeName(String pageSizeName) { this.pageSizeName = pageSizeName; } public String getPageNoName() { return pageNoName; } public void setPageNoName(String pageNoName) { this.pageNoName = pageNoName; } public String getTotalCountName() { return totalCountName; } public void setTotalCountName(String totalCountName) { this.totalCountName = totalCountName; }}
Mybatis的plugin的实现
- 我这里选择拦截StatementHandler的prepare方法,也就是基本的JDBC中在发出SQL语句之的拦截,这里我们使用根据用户的SQL语句来查出相应的记录的总条数,因为在分页对象中这个参数是很必不可少的。
- 然后,进行分页(Pagination)参数的计算,当然这些计算已经封装在Pagination对象中。然后,根据计算的结果来进行重构Mybatis发出的SQL语句,也就是分页查询的最终SQL语句,对于Mysql和Orcale对于分页查询的语句是不同的,当然,这需要我们在配置插件的时候,进行指导数据库方言的属性。
- 对于用户来讲,这一切都是透明的。对于插件,我们都知道,这是在搭建框架的时候,我们总是用抽象的接口来组织逻辑,然后通过配置的方式来增加接口的实现,从而达到了插件的效果。这里进行配置是至关重要的,这里似乎用到AOP的思想,Advice为通知接口为我们自定义接口实现的逻辑方法,配置就相当于Advisor,Pointcut就是切入点。
package com.pcitc.modules.pagination;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Properties;import org.apache.ibatis.executor.parameter.ParameterHandler;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.logging.Log;import org.apache.ibatis.logging.LogFactory;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Plugin;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.reflection.DefaultReflectorFactory;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.ReflectorFactory;import org.apache.ibatis.reflection.factory.DefaultObjectFactory;import org.apache.ibatis.reflection.factory.ObjectFactory;import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.RowBounds;/** * 通过拦截<code>StatementHandler</code>的<code>prepare</code>方法,重写sql语句实现物理分页。 * 老规矩,签名里要拦截的类型只能是接口。 * * @author 湖畔微风 * */@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})public class PageInterceptor implements Interceptor { private static final Log logger = LogFactory.getLog(PageInterceptor.class); private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory(); private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory(); private static final ReflectorFactory DEFAULT_OBJECT_REFLECT_FACTORY = new DefaultReflectorFactory(); private static String defaultDialect = "mysql"; // 数据库类型(默认为mysql) private static String dialect = ""; // 数据库类型(默认为mysql) @Override public Object intercept(Invocation invocation) throws Throwable { //只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的MappedStatement的sql //进行Threadlocal进行分页参数的提取 Pagination<Object> page = PaginationManager.getPagination(); //若不存在分页参数 if(null == page){ //将执行权交给下一个拦截器 PaginationManager.remove(); return invocation.proceed(); } StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_OBJECT_REFLECT_FACTORY); // 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环可以分离出最原始的的目标类) while (metaStatementHandler.hasGetter("h")) { Object object = metaStatementHandler.getValue("h"); metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_OBJECT_REFLECT_FACTORY); } // 分离最后一个代理对象的目标类 while (metaStatementHandler.hasGetter("target")) { Object object = metaStatementHandler.getValue("target"); metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_OBJECT_REFLECT_FACTORY); } Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration"); if(null != configuration.getVariables()){ dialect = configuration.getVariables().getProperty("dialect"); //设置数据库方言,默认为mysql } if (null == dialect || "".equals(dialect)) { logger.warn("Property dialect is not setted,use default 'mysql' "); dialect = defaultDialect; } MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql"); String sql = boundSql.getSql(); // 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数 Connection connection = (Connection) invocation.getArgs()[0]; // 重设分页参数里的总页数等,若没有totalCount的数值 if(page.getTotalCount() <= 0){ setPagination(sql, connection, mappedStatement, boundSql, page); } page.adjustAllProcess(); //进行参数的调整 // 重写sql String pageSql = buildPageSql(sql, page); metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); // 将执行权交给下一个拦截器 return invocation.proceed(); } /** * 从数据库里查询总的记录数并计算总页数,回写进分页参数<code>Pagination</code>,这样调用者就可用通过 分页参数 * <code>Pagination</code>获得相关信息。 * * @param sql * @param connection * @param mappedStatement * @param boundSql * @param page */ private void setPagination(String sql, Connection connection, MappedStatement mappedStatement, BoundSql boundSql, Pagination<Object> 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); } 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); } } } /** * 对SQL参数(?)设值 * * @param ps * @param mappedStatement * @param boundSql * @param parameterObject * @throws SQLException */ private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException { ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql); parameterHandler.setParameters(ps); } /** * 根据数据库类型,生成特定的分页sql * * @param sql * @param page * @return */ private String buildPageSql(String sql, Pagination<Object> page) { if (page != null) { StringBuilder pageSql = new StringBuilder(); if ("mysql".equals(dialect)) { pageSql = buildPageSqlForMysql(sql, page); } else if ("oracle".equals(dialect)) { pageSql = buildPageSqlForOracle(sql, page); } else { return sql; } return pageSql.toString(); } else { return sql; } } /** * mysql的分页语句 * * @param sql * @param page * @return String */ public StringBuilder buildPageSqlForMysql(String sql, Pagination<Object> page) { StringBuilder pageSql = new StringBuilder(100); String beginrow = String.valueOf(page.getStartRow()); pageSql.append(sql); pageSql.append(" limit " + beginrow + "," + page.getPageSize()); return pageSql; } /** * 参考hibernate的实现完成oracle的分页 * * @param sql * @param page * @return String */ public StringBuilder buildPageSqlForOracle(String sql, Pagination<Object> page) { StringBuilder pageSql = new StringBuilder(100); pageSql.append("select * from ( select temp.*, rownum row_id from ( "); pageSql.append(sql); pageSql.append(" ) temp where rownum <= ").append(page.getPageNo() * page.getPageSize()); pageSql.append(") where row_id > ").append(page.getStartRow()); return pageSql; } @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) { }}
Filter的实现
- 这里通过Filter的配置来进行,需要分页的URL的定位,因为对于分页来讲我们需要进入同一个URL来进行取出数据库中不同位置的数据而已,只是需要传递不同的参数,如页码。
- 在Filter方法中,我们首先进行分页对象的初建立,并将其放入到ThreadLocal中,这样是为了mybatis中分页插件,能够拿到分页的部分参数,通过判断是否是用户第一次进入分页页码,来判断是否需要发出来统计分页总的记录数的语句。如需要发出总记录数相应的SQL语句,然后进行重构分页对象。
- 而且在doFilterChain方法后面需要释放,ThreadLocal中的线程变量,这里是至关重要的。
- 为什么要释放线程变量?(大坑)
因为我们知道Tomcat的架构,对于不同的请求是不同的线程来进行处理的,会给我们一个实现的接口servlet或者Filter来进行业务的处理。这里,tomcat的线程不是进行new出来的,因为对于new的操作需要耗费资源,这里采用的是线程池的方式,同样的思想体现于Datasource中。假如,一个线程池中有20个线程(这里可通过tomcat配置文件进行配置),时间上不同的请求可能用的是同一个线程池中某一个线程。那么,上一个线程存放的线程变量就可能被下一个线程取到相应的数据,所以我们需要在一个线程结束的时候,进行线程变量的清楚。
package com.pcitc.modules.pagination;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class PaginationFilter implements Filter { public static String PAGE_SIZE = "pageSize"; public static String PAGE_NO = "pageNo"; public static String TOTAL_COUNT = "totalCount"; private String pageSizeName = PAGE_SIZE; private String pageNoName = PAGE_NO; private String totalCountName = TOTAL_COUNT; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { System.out.println("分页插件,过滤器开始"); Integer pageSize = Integer.valueOf((request.getParameter(pageSizeName) == null)?"0":request.getParameter(pageSizeName)); Integer pageNo = Integer.valueOf(request.getParameter(pageNoName) == null?"0":request.getParameter(pageNoName)); Integer totalCount = Integer.valueOf(request.getParameter(totalCountName)== null?"0":request.getParameter(totalCountName)); Pagination<Object> pagination = new Pagination<Object>(); pagination.setPageNoName(pageNoName); pagination.setPageSizeName(pageSizeName); pagination.setTotalCountName(totalCountName); pagination.setPageSize(pageSize); pagination.setPageNo(pageNo); pagination.setTotalCount(totalCount); PaginationManager.setPagination(pagination); filterChain.doFilter(request, response); System.out.println("释放ThreadLoca中的值"); PaginationManager.remove(); }}
自定义JSP标签的实现
- 因为分页的HTML和CSS我们不能控制,为了减少代码侵入性,我们采用给标签中提供相应的分页信息,来让前端人员来自己对样式和dom结构的定义。
package com.pcitc.modules.pagination;import java.io.IOException;import javax.servlet.jsp.JspException;import javax.servlet.jsp.tagext.SimpleTagSupport;public class PaginationTag extends SimpleTagSupport{ public static String COMMON = "common"; //页码组信息 public static String PREPAGE = "prePage"; //前一页信息 public static String POSTPAGE = "postPage"; //后一页信息 private String searchUrl; private String pageType = COMMON; //判断是否是首页或者尾页 @Override public void doTag() throws JspException, IOException{ //循环遍历页面显示页码数 Pagination<Object> pagination = PaginationManager.getPagination(); if(pagination != null){ int[] pageNums = pagination.getPageNums(); if("common".equals(pageType)){ for(int i=0;i<pageNums.length;i++){ String url = this.searchUrl; if(!searchUrl.contains("?")){ url = url + "?"; } url = url + "&" + pagination.getPageSizeName() + "=" + pagination.getPageSize() + "&" + pagination.getPageNoName() + "=" + pageNums[i] + "&" + pagination.getTotalCountName() + "=" + pagination.getTotalCount(); //将分页的URL和pageNum设置到page 范围 getJspContext().setAttribute("pageUrl",url); getJspContext().setAttribute("pageNum", pageNums[i]); getJspContext().setAttribute("pageInfo", pagination); //输出标签体 getJspBody().invoke(null); } }else{ if(pageNums.length > 1){ if(PREPAGE.equals(pageType)){ String url = this.searchUrl; if(!searchUrl.contains("?")){ url = url + "?"; } url = url + "&" + pagination.getPageSizeName() + "=" + pagination.getPageSize() + "&" + pagination.getPageNoName() + "=" + pagination.getPrePage() + "&" + pagination.getTotalCountName() + "=" + pagination.getTotalCount(); //将分页的URL和pageNum设置到page 范围 getJspContext().setAttribute("pageUrl",url); getJspContext().setAttribute("pageNum", pagination.getPrePage()); getJspContext().setAttribute("pageInfo", pagination); //输出标签体 getJspBody().invoke(null); }else if(POSTPAGE.equals(pageType)){ String url = this.searchUrl; if(!searchUrl.contains("?")){ url = url + "?"; } url = url + "&" + pagination.getPageSizeName() + "=" + pagination.getPageSize() + "&" + pagination.getPageNoName() + "=" + pagination.getNextPage() + "&" + pagination.getTotalCountName() + "=" + pagination.getTotalCount(); //将分页的URL和pageNum设置到page 范围 getJspContext().setAttribute("pageUrl",url); getJspContext().setAttribute("pageNum", pagination.getNextPage()); getJspContext().setAttribute("pageInfo", pagination); //输出标签体 getJspBody().invoke(null); }else{ String url = this.searchUrl; if(!searchUrl.contains("?")){ url = url + "?"; } url = url + "&" + pagination.getPageSizeName() + "=" + pagination.getPageSize() + "&" + pagination.getTotalCountName() + "=" + pagination.getTotalCount() + "&" + pagination.getPageNoName() + "="; //将分页的URL的元素设置到page 范围 getJspContext().setAttribute("pageUrl",url); getJspContext().setAttribute("pageInfo", pagination); //输出标签体 getJspBody().invoke(null); } } } } } public String getSearchUrl() { return searchUrl; } public void setSearchUrl(String searchUrl) { this.searchUrl = searchUrl; } public String getPageType() { return pageType; } public void setPageType(String pageType) { this.pageType = pageType; }}
tld文件:
<?xml version="1.0" encoding="UTF-8" ?><taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <description>JSTL 1.1 core library</description> <display-name>JSTL core</display-name> <tlib-version>1.1</tlib-version> <short-name>util</short-name> <uri>http://ctbu.com/liumi</uri> <!-- 标签展示通用类 --> <tag> <name>page</name> <tag-class>com.pcitc.web.controller.common.PaginationTag</tag-class> <body-content>scriptless</body-content> <!-- 标签体中可以取出pageUrl,pageNum,pageInfo对象用来页面的展示和判断 --> <attribute> <name>searchUrl</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> </attribute> <attribute> <name>pageType</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> <description>common--代表显示的页码,prePage代表上一页信息,postPage代表下一页信息</description> </attribute> </tag></taglib>
JSP使用标签的简单实例:
<!--这里需要web.xml文件中引入相应utl文件位置--><%@ taglib uri="http://ctbu.com/liumi" prefix="util"%><util:page searchUrl="${ctx}/news/list" pageType="other">这里相当于通过pageType属性来获取相应的分页的信息:other:则是获取分页的信息common:会进行所有显示在页面页码的迭代出不同URL, 通过${pageUrl}来获取prePage和postPage:进行前页和后页信息的获取 显示第 ${pageInfo.startRow+1} 至 ${pageInfo.startRow+listSize} 项结果,共 ${pageInfo.totalCount} 项</util:page> <--上一页--> <util:page searchUrl="${ctx}/news/list" pageType="prePage"> <c:if test="${pageInfo.totalCount > pageInfo.pageSize}"> <li id="" class="paginate_button previous"> <a href="${pageUrl}">上页</a> </li> </c:if></util:page><!--所有页码--><util:page searchUrl="${ctx}/news/list" pageType="common"> <c:if test="${pageInfo.totalCount > pageInfo.pageSize}"> <li class="paginate_button <c:if test='${pageInfo.pageNo == pageNum}'>active</c:if>"> <a href="${pageUrl}">${pageNum}</a> </li> </c:if></util:page><!--后一页--><util:page searchUrl="${ctx}/news/list" pageType="postPage"><c:if test="${pageInfo.totalCount > pageInfo.pageSize}"> <li id="" class="paginate_button next"> <a tabindex="0" data-dt-idx="8" aria-controls="userTabel" href="${pageUrl}">下页</a> </li> </c:if></util:page>
ThreadLocal来进行Filter到JSP中分页对象传递
package com.pcitc.modules.pagination;/** * 将分页数据进行线程级别传递 * @author mi * */public class PaginationManager { //使用ThreadLocal保存Connection变量 private static final ThreadLocal<Pagination<Object>> pageHolder = new ThreadLocal<Pagination<Object>>(); public static Pagination<Object> getPagination(){ //ThreadLocal取得当前线程的分页数据 return pageHolder.get(); } public static void setPagination(Pagination<Object> pagination){ pageHolder.set(pagination); } public static void remove(){ pageHolder.remove(); }}
使用说明
- 在web.xml中进行对Filter的配置,主要是对那个URL进行分页的
拦截,和对tld文件的引入(jar包中meta文件中tld文件不用引入):
<filter> <filter-name>paginationFilter</filter-name> <filter-class> com.pcitc.modules.pagination.PaginationFilter </filter-class> </filter> <filter-mapping> <filter-name>paginationFilter</filter-name> <url-pattern>/news/list</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <jsp-config> <taglib> <taglib-uri>http://ctbu.com/liumi</taglib-uri> <taglib-location>/WEB-INF/util.tld</taglib-location> </taglib> </jsp-config>
- 配置mybatis拦截器
<plugins><plugin interceptor="com.pcitc.modules.pagination.PageInterceptor"> <!-- 或者mysql --> <property name="dialect" value="oracle"/></plugin></plugins>
- 在JSP表中引入:
<%@ taglib uri="http://ctbu.com/liumi" prefix="util"%>
0 0
- JSP标签实现分页功能(ORM-mybatis)
- JSP标签实现分页功能(ORM-mybatis)
- Google分页功能的jsp标签实现
- JSP标签分页实现
- MyBatis分页功能实现
- JSP实现分页功能
- JSP实现分页功能
- JSP实现分页功能
- JSP实现分页功能
- JSP实现分页功能
- Jsp实现分页功能
- jsp实现分页功能
- MyBatis 拦截器 (实现分页功能)
- jsp自定义标签实现分页
- Mybatis Generator实现分页功能
- Mybatis Generator实现分页功能
- Mybatis Generator实现分页功能
- mybatis实现分页功能要点
- Word公式和文字的显示位置调整
- 白盒测试中的逻辑覆盖
- Spark 源码阅读一-启动脚本
- jquery实现视频展示效果
- Test5.17
- JSP标签实现分页功能(ORM-mybatis)
- 测试uart_ldisc
- python socket 模块
- 使用 nginx + node.js 反向代理
- 可视化与办公自动化学习
- 可视化与办公自动化学习
- 第四周项目三(2)
- Android :利用Proguard去除日志信息
- Quartz2D-图形上下文栈