Struts 2 下在 View Layer 新增分頁 (Pager) tag 與相關設計分享

分頁是大家撰寫網頁時,常需實作的功能。最近因為有需要,所以在 Struts 2 下的實作出了個 Pager tag,用以方便分頁套版使用,我自己用起來是用得蠻開心的,就想說分享出來給大家看看。

因為加班好累,所以說明可能晚點待補,有需要的話,或許晚點會直接打包分享出來?另外再來有時間也會再補充說明 Struts 2 下的 tag 撰寫方式,做個小小的心得分享,

老王賣瓜一下,我自己覺得我寫的 Pager tag,有以下兩個優點︰

  1. 簡化套版-這是廢話 XD 主要應該算容易使用,下面我們會看到結果、
  2. 利用到 MVC 的特性,修改版面配置 (不只 CSS) 不需修改 Java 程式,只需修改 template 檔即可。

成果圖如下︰

Tag 設定︰Pager.tld

<?xml version="1.0" encoding="UTF-8"?>
<?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" /><?XML:NAMESPACE PREFIX = [default] http://java.sun.com/xml/ns/j2ee NS = "http://java.sun.com/xml/ns/j2ee" />
    分頁導覽器
    2.0
    pager
    /pager

    
        pager
        com.foo.tags.PagerTag
        JSP
        
        
            currentPage
            true
        
        
        
            totalRecordNumber
            true
        
        
        
        	actionUrl
            true
        
        
               
      		theme       
      		false       
      		false     
      		  
	    
	    
               
      		template       
      		false       
      		false
      		
	    
    

View Layer template 設定︰pager.ftl

	
	<@s.if test="${parameters.currentPage} != 1">
		
		<@s.if test="${parameters.actionUrl.lastIndexOf('?')} != -1">
			<@s.a href="${parameters.actionUrl}¤tPage=${parameters.currentPage-1}" title="上一頁">上一頁</@S.A> |
		</@S.IF>
		<@s.else>
			<@s.a href="${parameters.actionUrl}?currentPage=${parameters.currentPage-1}" title="上一頁">上一頁</@S.A> |
		</@S.ELSE>		
	</@S.IF>

	
	<@s.if test="${parameters.currentPage} != 1 && (${parameters.currentPage} - 5) >= 1">
		<@s.if test="${parameters.actionUrl.lastIndexOf('?')} != -1">
			<@s.a href="${parameters.actionUrl}¤tPage=${parameters.currentPage-5}" title="上五頁">...</@S.A>
		</@S.IF>
		<@s.else>
			<@s.a href="${parameters.actionUrl}?currentPage=${parameters.currentPage-5}" title="上五頁">...</@S.A>
		</@S.ELSE>
	</@S.IF>

	
	<@s.iterator value="totalRecordNumber.{#this}" id="pages" status="statPage">
		
		<@s.if test="${parameters.currentPage} == #statPage.count">
			<@s.property value="#statPage.count" />
		</@S.IF>
		
		<@s.else>
			
			<@s.if test="#statPage.count >= (${parameters.currentPage} - 4) && #statPage.count <= (${parameters.currentPage} + 4)">
				
				<@s.if test="#statPage.count <= ${parameters.totalRecordNumber}">
					<@s.if test="${parameters.actionUrl.lastIndexOf('?')} != -1">
						<@s.a href="${parameters.actionUrl}¤tPage=${statPage.count}" title="第${statPage.count}頁"><@s.property value="#statPage.count" /></@S.A>
					</@S.IF>
					<@s.else>
						<@s.a href="${parameters.actionUrl}?currentPage=${statPage.count}" title="第${statPage.count}頁"><@s.property value="#statPage.count" /></@S.A>
					</@S.ELSE>	
				</@S.IF>
			</@S.IF>
		</@S.ELSE>
	</@S.ITERATOR>
			
	
	<@s.if test="${parameters.currentPage} != ${parameters.totalRecordNumber} && (${parameters.totalRecordNumber} - ${parameters.currentPage}) >= 5">
		<@s.if test="${parameters.actionUrl.lastIndexOf('?')} != -1">
			<@s.a href="${parameters.actionUrl}¤tPage=${parameters.currentPage+5}" title="下五頁">...</@S.A>
		</@S.IF>
		<@s.else>
			<@s.a href="${parameters.actionUrl}?currentPage=${parameters.currentPage+5}" title="下五頁">...</@S.A>
		</@S.ELSE>
	</@S.IF>

	
	<@s.if test="${parameters.currentPage} != ${parameters.totalRecordNumber}">
		<@s.if test="${parameters.actionUrl.lastIndexOf('?')} != -1">
			| <@s.a href="${parameters.actionUrl}¤tPage=${parameters.currentPage+1}" title="下一頁">下一頁</@S.A>
		</@S.IF>
		<@s.else>
			| <@s.a href="${parameters.actionUrl}?currentPage=${parameters.currentPage+1}" title="下一頁">下一頁</@S.A>
		</@S.ELSE>
	</@S.IF>

Tag Java code︰Pager.java

import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.components.UIBean;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@StrutsTag(name = "pager", tldTagClass = "com.foo.tags.PagerTag", description = "Pager")
public class Pager extends UIBean {
	public final static String TEMPLATE = "pager";
	private static final Integer PAGESIZE = 10;  // 

	private String currentPage;			// 查詢頁數
	private String totalRecordNumber;	// 全部筆數
	private String actionUrl;			// 目標路徑
	private String template;			// 樣板名稱

	public Pager(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
		super(stack, request, response);
	}

	@Override
	protected String getDefaultTemplate() {
		if (getTemplate() != null && getTemplate().length() != 0) {
			return getTemplate();
		} else {
			return TEMPLATE;
		}
	}

	@StrutsTagAttribute(description = "set currentPage", type = "String")
	public void setCurrentPage(String currentPage) {
		this.currentPage = currentPage;
	}

	@StrutsTagAttribute(description = "set totalRecordNumber", type = "String")
	public void setTotalRecordNumber(String totalRecordNumber) {
		this.totalRecordNumber = totalRecordNumber;
	}

	@StrutsTagAttribute(description = "set template", type = "String")
	public void setTemplate(String template) {
		this.template = template;
	}

	public String getTemplate() {
		return template;
	}

	@StrutsTagAttribute(description = "set actionUrl", type = "String")
	public void setActionUrl(String actionUrl) {
		this.actionUrl = actionUrl;
	}

	@Override
	protected void evaluateExtraParams() {
		super.evaluateExtraParams();

		if (null != currentPage && null != totalRecordNumber && null != actionUrl) {
			// 查詢頁數
			Integer currentPageInt = (Integer) findValue(currentPage);
			// 全部頁數
			Integer totalRecordNumberPages = (Integer) findValue(totalRecordNumber);
			totalRecordNumberPages = (totalRecordNumberPages - 1) / PAGESIZE + 1;
			// 目標路徑
			String actionUrlStr = (String) findValue("actionUrl");

			addParameter("currentPage", currentPageInt);
			addParameter("totalRecordNumber", totalRecordNumberPages);
			addParameter("actionUrl", actionUrlStr);
		}
	}

Tag Java code︰PagerTag.java

import org.apache.struts2.views.jsp.ui.AbstractUITag;
import org.apache.struts2.components.Component;
import com.opensymphony.xwork2.util.ValueStack;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PagerTag extends AbstractUITag {
	private static final long serialVersionUID = 1L;

	private String currentPage;			// 查詢頁數
	private String totalRecordNumber;	// 全部筆數
	private String actionUrl;			// 目標路徑
	private String template;			// 樣板名稱


    @Override
    public Component getBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
        return new Pager(stack, request, response);
    }

    @Override
    protected void populateParams() {
        super.populateParams();

        Pager pager = (Pager)component;
        pager.setCurrentPage(currentPage);
        pager.setTotalRecordNumber(totalRecordNumber);
        pager.setActionUrl(actionUrl);
        pager.setTemplate(template);
    }

    public void setCurrentPage(String currentPage) {
        this.currentPage = currentPage;
    }
    
    public void setTotalRecordNumber(String totalRecordNumber){
    	this.totalRecordNumber = totalRecordNumber;
    }
    
    public void setActionUrl(String actionUrl){
    	this.actionUrl = actionUrl;
    }
    
    public void setTemplate(String template){
    	this.template = template;
    }
}

Tag Java code︰PagedBaseAction.java

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PagedBaseAction extends BaseAction {
	private static final Log logger = LogFactory.getLog(PagedBaseAction.class);

	protected int totalPageNumber = 0;		// 總頁數
	protected int totalRecordNumber = 0;	// 結果總筆數
	protected int currentPage = 1;			// 目前觀看頁數
	protected int firstRowIndex = 0;		// 本頁開始筆數
	protected int endRowIndex = 0;			// 本頁結束筆數

	// getters and setters - begin
	public int getTotalPageNumber() {
		return totalPageNumber;
	}

	public void setTotalPageNumber(int totalPageNumber) {
		this.totalPageNumber = totalPageNumber;
	}

	public int getTotalRecordNumber() {
		return totalRecordNumber;
	}

	public void setTotalRecordNumber(int totalRecordNumber) {
		this.totalRecordNumber = totalRecordNumber;
	}

	public int getCurrentPage() {
		return currentPage;
	}

	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}

	public int getFirstRowIndex() {
		return firstRowIndex;
	}

	public void setFirstRowIndex(int firstRowIndex) {
		this.firstRowIndex = firstRowIndex;
	}

	public int getEndRowIndex() {
		return endRowIndex;
	}

	public void setEndRowIndex(int endRowIndex) {
		this.endRowIndex = endRowIndex;
	}
	// getters and setters - end

	protected void pagedProcess(int pageSize) {
		logger.info("pagedProcess - start");

		if (totalRecordNumber == 0) {
			this.totalPageNumber = 0;
			this.firstRowIndex = -1;
			this.endRowIndex = -1;
		} else {
			this.totalPageNumber = (totalRecordNumber - 1) / pageSize + 1;	// 總頁數
			this.firstRowIndex = (pageSize * (currentPage - 1));			// 本頁開始筆數
			this.endRowIndex = ((firstRowIndex + pageSize + 1) > totalRecordNumber) ? totalRecordNumber - 1 : (firstRowIndex + pageSize - 1); // 本頁結束筆數
		}

		logger.debug(String.format("pagedProcess - totalRecordNumber=%d, totalPageNumber=%d, firstRowIndex=%d, endRowIndex=%d", totalRecordNumber, totalPageNumber, firstRowIndex, endRowIndex));
		
		logger.info("pagedProcess - end");
	}
}

使用方式 (對,以上面只是基礎建設 XD)︰

1. Controlerr 下,新增一個 Struts 2 的 Action,來繼承 PagedBaseAction 此分頁基底類別,舉例如下︰

public class PagedAction extends PagedBasedAction {

    public string execute() {
        totalRecordNumber = 100;    // Model 資料總筆數
        super.pagedProcess(10);	    // 每 10 頁一筆
        return SUCCESS;
    }
}

2. View Layer 下,使用如下方式套版,即可顯示分頁導航列了︰



    


是不是很簡單呢?XD

0 意見: