displaytag按需分页的包装及实例

3 篇文章 0 订阅
2 篇文章 0 订阅

displaytag1.1之后支持按需进行分页查询,在其官方网站有如下描述:

Displaytag 1.1 offers two alternative ways for working with partial lists:

  • the first one uses the valuelist pattern, and requires that the object that you give to displaytag implements theorg.displaytag.pagination.PaginatedList interface. You can pass this object to displaytag as an usual list, and it will extract paging and sorting information from it. This way is more recommended if you have to build your backend layer and you can easily follow this pattern.
  • a second way, recommended if you only have to use partial list for few tables that show a performance problem using full lists, is passing all the needed parameters as separate tag attributes (recors to be shown, page number, total number of records...)
参考:http://www.displaytag.org/1.2/tut_externalSortAndPage.html

当存在大数据量的时候,一般使用第一种方法。本文的示例来自实际项目,主要解决两个问题:

1) 按需取得数据,利用displaytag实现页面分页显示。

2) 对displaytag要求的分页参数进行设置及复杂性包装,便于快速开发。


主要的步骤如下:


1、创建一个简单类实现org.displaytag.pagination.PaginatedList接口,此类在项目中公用,对于所有的分页需求界面,不需要另造轮子。

package com.whyonly.core.displaytag;

import java.util.List;

import org.displaytag.pagination.PaginatedList;
import org.displaytag.properties.SortOrderEnum;

public class SimplePaginatedList<T> implements PaginatedList {

	private List<T> list;
	private int pageNumber = 1;
	private int objectsPerPage = 20;
	private int fullListSize = 0;
	private String sortCriterion;
	private SortOrderEnum sortDirection;
	private String searchId;

	public List<T> getList() {
		return list;
	}

	public void setList(List<T> list) {
		this.list = list;
	}

	public int getPageNumber() {
		return pageNumber;
	}

	public void setPageNumber(int pageNumber) {
		this.pageNumber = pageNumber;
	}

	public int getObjectsPerPage() {
		return objectsPerPage;
	}

	public void setObjectsPerPage(int objectsPerPage) {
		this.objectsPerPage = objectsPerPage;
	}

	public int getFullListSize() {
		return fullListSize;
	}

	public void setFullListSize(int fullListSize) {
		this.fullListSize = fullListSize;
	}

	public String getSortCriterion() {
		return sortCriterion;
	}

	public void setSortCriterion(String sortCriterion) {
		this.sortCriterion = sortCriterion;
	}

	public SortOrderEnum getSortDirection() {
		return sortDirection;
	}

	public void setSortDirection(SortOrderEnum sortDirection) {
		this.sortDirection = sortDirection;
	}

	public String getSearchId() {
		return searchId;
	}

	public void setSearchId(String searchId) {
		this.searchId = searchId;
	}

}

2,创建一个分页包装器,根据displaytag分页的要求包装共同性,同时把不同的部分通过接口的方式让子类去处理,此包装器也在项目中共用。

package com.whyonly.core.displaytag;

import java.util.List;

import javax.servlet.http.HttpServletRequest;


public abstract class PaginatedWrapper<T> {

	
	private int pageSize = 20;

	public void paginated(HttpServletRequest request) {
		int page = 1;

		if (request.getParameter("pageSize") != null
				&& !"".equals(request.getParameter("pageSize"))) {
			pageSize = Integer.parseInt(request.getParameter("pageSize"));
		} 
		if (request.getParameter("page") != null
				&& !"".equals(request.getParameter("page"))) {
			page = Integer.parseInt(request.getParameter("page"));
		} else {
			page = 1;
		}

		int fromIndex = (page - 1) * pageSize;
		int toIndex = fromIndex + pageSize;

		int fullListSize = getFullListSize();
		List<T> pageDatas = getPageDatas(fromIndex, toIndex);

		SimplePaginatedList<T> paginatedList = new SimplePaginatedList<T>();
		paginatedList.setPageNumber(page);

		if (pageDatas != null && pageDatas.size() > 0 && fullListSize > 0) {
			paginatedList.setFullListSize(fullListSize);
			paginatedList.setObjectsPerPage(pageSize);
			paginatedList.setList(pageDatas);
		} else {
			paginatedList.setFullListSize(0);
			paginatedList.setList(null);
		}
		request.setAttribute("pagedatas", paginatedList);
	}
	

	public PaginatedWrapper<T> setPageSize(int pageSize) {
		this.pageSize = pageSize;
		return this;
	}



	protected abstract List<T> getPageDatas(int fromIndex, int toIndex);

	protected abstract int getFullListSize();

}

PaginatedWrapper是一个抽象类,有以下几个特性:

1) 支持泛型<T>,可以根据模块的要求传入相应的bean对象。

2) paginated()方法内聚和包装了displaytag的参数需求,并进行了一些共有的初始化。同时也提供了pagesize大小的设置,默认是20,注意setPageSize放回的this,此处使用了反回自身的方式,便于连续的属性设置。

3) 抽象方法 protected abstract List<T> getPageDatas(int fromIndex, int toIndex) 和 protected abstract int getFullListSize() 对每个模块,具有不同性,因此通过接口方法的方式留给具体的模块去实现。实现一般放在Dao层,然后通过前台Controller(Spring),或者Action(Struts),或者Jsp去调用。


3,使用1,2步骤创建好的两个包装类,应用到具体的项目。下面以SSH2为例,也可以应用到其它的框架结构,因为SSH的框架比较通用,以下只给出关键代码,具体的实现应该是简单的。

3.1, Action类


	@Actions( {                                                                                       
		@Action(value = "/queryIncidental", results = {                                                         
				@Result(location = "center/pos/incidental_query_result.jsp", name = "success"), 
				})  
		})                                                                                              
	})                                                                                                
	public String queryIncidental(){                                                         
			new PaginatedWrapper<Posbatch>(){
				@Override
				protected List<Posbatch> getPageDatas(int fromIndex, int toIndex) {
					return service.initQueryIncidentalByPage(mv,getCompid(), fromIndex, toIndex);
				}

				@Override
				protected int getFullListSize() {
					return service.findFullSizeByCustAndDate(mv,getCompid());
				}
				
			}.paginated(request);
			return SUCCESS;                                                                                 
	}

以上Action的关键点在于实现getPageDatas()方法和getFullListSize()方法,service是业务逻辑成对象,如果用了Spring,可以通过@Autowired自动注入。


3.2) Service类

	public List<Posbatch> initQueryIncidentalByPage(IncidentalMV mv, int compid, int fromIndex, int toIndex) {	
		String custcode = mv.getCustcode();
		KTimestamp start = Kalendar.StringToKTimestamp("yyyy-MM-dd", mv.getStartdate());
		KTimestamp end = Kalendar.StringToKTimestamp("yyyy-MM-dd", mv.getEnddate());
		return posbatchDao.findByCustAndDateForPage(fromIndex,toIndex,compid,custcode,start,Kalendar.getKTimestampAfterDays(end, 1));
	}

	public int findFullSizeByCustAndDate(IncidentalMV mv, int compid) {
		String custcode = mv.getCustcode();
		KTimestamp start = Kalendar.StringToKTimestamp("yyyy-MM-dd", mv.getStartdate());
		KTimestamp end = Kalendar.StringToKTimestamp("yyyy-MM-dd", mv.getEnddate());
		return posbatchDao.findFullSizeByCustAndDate(compid, custcode, start, Kalendar.getKTimestampAfterDays(end, 1));
	}

3.3)Dao类


	public List<Posbatch> findByCustAndDateForPage(int fromIndex,int toIndex,int compid,String custcode, KTimestamp start,
			KTimestamp end) {
		StringBuffer buff = new StringBuffer();
		buff.append("select p from Posbatch p left join fetch p.customer c left join fetch p.wicustomer w left join fetch p.createPerson cp " +
				"where p.compid = ? and p.ctime >= ? and p.ctime<? ");
		buff.append("  order by p.batchnum desc");
		return super.find(buff.toString(), fromIndex, toIndex, compid,start,end);
	}
	
	public int findFullSizeByCustAndDate(int compid,String custcode, KTimestamp start,
			KTimestamp end) {
		StringBuffer buff = new StringBuffer();
		buff.append("select count(*) from Posbatch p " +
				"where p.compid = ? and p.ctime >= ? and p.ctime<? ");
		buff.append(custcode!=null && !custcode.equals("") ? " and p.custcode = ?" : "");
		buff.append("  order by p.batchnum desc");
		return super.findFullSize(buff.toString(),compid,start,end);
	}

此Dao用了Hibernate 的 left join fetch 的方式,因此直接注入Posbatch的关联对象,便于displaytag的显示。

另外,此Dao继承了自己的BaseHibernateDAO,findFullSize()以及find()方法的代码如下:

	public List<T> find(String hql ,int fromIndex,int toIndex, Object... params){
		Query query = getSession().createQuery(hql);
		for(int i = 0 , len = params.length ; i < len ; i++){
			query.setParameter(i , params[i]);
		}
		query.setFirstResult(fromIndex);
		query.setMaxResults(toIndex - fromIndex);
		return query.list();
	}
	
	public int findFullSize(String hql,Object... params){
		Query query = getSession().createQuery(hql);
		for(int i = 0 , len = params.length ; i < len ; i++){
			query.setParameter(i , params[i]);
		}
		return ((Long)query.list().get(0)).intValue();
	}

3.4) 页面显示(JSP)


<display:table id="pagedatas" name="pagedatas" export="false" sort="external" class="dispaytag" 
				 requestURI="queryIncidental"  decorator="com.whyonly.center.pos.mv.PosbatchWrapper"
				>
				<display:column property="batchnum" paramId="batchnum" paramProperty="batchnum"  href="incidental" titleKey="centerowl.posinvoicing.searchtran2" />
				<display:column property="custname" titleKey="centerowl.posinvoicing.searchtran3" />
				<display:column property="ctime"	titleKey="centerowl.posinvoicing.searchtran4" />
				<display:column property="createPerson.name" titleKey="centerowl.posinvoicing.searchtran5" />	
		</display:table>

此处用了一个包装器,用于显示日期。如果不需要对数据进行特殊的处理,直接忽略他。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值