您的位置:首页 > Web前端 > JavaScript

JSP标签实现分页功能(ORM-mybatis)

2015-09-22 16:17 766 查看

分页对象

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){
//将执行权交给下一个拦截器

14a40
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"%>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: