基於Freemarker模板技術的分頁組件設計


基於struts2的程序設計中,一定會用到struts自帶的標簽庫,提供了一些常用的表單元素和邏輯控制標簽的封裝,而我們在項目中常用的分頁標簽卻沒有直接提供,通過學習struts2的源碼分析我們可以看到,struts2的標簽庫默認是使用freemarker模板技術實現的,如圖


在各個單獨的模板里定義了具體的頁面展現元素,因此我們可以參考官方標簽的做法來定制我們的分頁標簽

1.編寫分頁組件類Pagination

這個類用於向模板中傳遞參數使用的

package com.crazycoder2010.demo.pagination;

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

import org.apache.struts2.components.UIBean;
import org.apache.struts2.views.annotations.StrutsTag;

import com.opensymphony.xwork2.util.ValueStack;
@StrutsTag(
	    name="pagination",
	    tldTagClass="com.crazycoder2010.demo.pagination.PaginationTag",
	    description="Render a pagination component",
	    allowDynamicAttributes=true)
public class Pagination extends UIBean {//繼承自Struts2的標簽Bean
	private String pager;//分頁對象
	private String formId;//查詢時需要提交的表單ID
	public Pagination(ValueStack stack, HttpServletRequest request,
			HttpServletResponse response) {
		super(stack, request, response);
	}
	private static final String TEMPLATE = "pagination";
	@Override
	protected String getDefaultTemplate() {
		return TEMPLATE;
	}
	@Override
	protected void evaluateExtraParams() {//這個函數作用在與把值添加到valueStack中,這樣在頁面上就可以直接通過${parameters.pager.pageCount}調用
        if (pager != null) {
            addParameter("pager", findValue(pager));
        }
        if(formId != null){
        	addParameter("formId", findString(formId));
        }
    }
	public String getPager() {
		return pager;
	}
	public void setPager(String pager) {
		this.pager = pager;
	}
	public String getFormId() {
		return formId;
	}
	public void setFormId(String formId) {
		this.formId = formId;
	}
}
2.編寫分頁標簽PaginationTag

這個就是自定義標簽,用來從頁面上傳遞參數,在基於struts的標簽實現中,這個類的內部不再去負責渲染頁面邏輯,而是直接通過委托將渲染交給對應的組件(Pagination)和模板(pagination.ftl)去實現

package com.crazycoder2010.demo.pagination;

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

import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ui.AbstractUITag;

import com.opensymphony.xwork2.util.ValueStack;

/**
 * @author Kevin
 *
 */
public class PaginationTag extends AbstractUITag {//這個AbstractUITag也是繼承在jsp的JspTagSupport,本質上還是j2ee的東東
	private static final long serialVersionUID = -8042181780566234704L;
	private String pager;
	private String formId;
	
	public String getPager() {
		return pager;
	}

	public void setPager(String pager) {
		this.pager = pager;
	}

	public String getFormId() {
		return formId;
	}

	public void setFormId(String formId) {
		this.formId = formId;
	}

	@Override
	public Component getBean(ValueStack stack, HttpServletRequest req,
			HttpServletResponse res) {
		return new Pagination(stack, req, res);
	}
	protected void populateParams() {
        super.populateParams();

        Pagination pagination = ((Pagination) component);
        pagination.setFormId(formId);
        pagination.setPager(pager);
    }
}
4.編寫分頁標簽的tld文件

放在WEB-INF\tld\pagination.tld里

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
  <display-name>"Struts2 Pagination Tags"</display-name>
  <tlib-version>1.0</tlib-version>
  <short-name>p</short-name>
  <uri>/pagination-tags</uri>
  <tag>
    <name>pagination</name>
    <tag-class>com.crazycoder2010.demo.pagination.PaginationTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
      <name>formId</name>
      <required>true</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <name>pager</name>
      <required>true</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <dynamic-attributes>false</dynamic-attributes>
  </tag>
</taglib>

5.編寫模板pagination.ftl

這里為了演示,只是搞了一個簡單的demo,簡陋的很,將寫好的ftl模板放在webapp\template\simple目錄下,注意一下在我的程序里是設置了 struts的struts.ui.theme=simple所以才放在這個目錄下的,如果未這個配置,則需要放在webapp\template\xhml文件夾下

<#list 1..parameters.pager.pageCount as p>
	<#if p==parameters.pager.currentPage>
		${p}
	<#else><a href="#" onClick="goto(${p})"/>${p}</a>
	</#if>
</#list>
<script>
	function goto(p){
		document.getElementsByName('pager.currentPage')[0].value=p;
		document.getElementById('${parameters.formId}').submit();//點擊某一頁就是提交一下表單,這樣分頁時查詢條件就會自動帶到下一頁
	}
</script>
6.些個demo action,默認讀取數據
package com.crazycoder2010.demo.action;

import java.util.ArrayList;
import java.util.List;

import com.crazycoder2010.demo.domain.User;
import com.crazycoder2010.demo.pagination.Pager;
import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld extends ActionSupport {
	private static final long serialVersionUID = -2074005942987876477L;
	private List<User> users = new ArrayList<User>();
	private Pager pager = new Pager();
	@Override
	public String execute() throws Exception {
		this.getPager().setTotalItems(init().size());
		this.setUsers(pagedUsers());
		return SUCCESS;
	}
	
	private List<User> init(){
		List<User> users = new ArrayList<User>(102);
		for(int i = 0; i < 102; i++){
			User user = new User();
			user.setId(i+1);
			user.setName("USER_"+(i+1));
			users.add(user);
		}
		return users;
	}
	
	private List<User> pagedUsers(){
		int current = this.pager.getCurrentPage();
		List<User> users = this.init();
		int from = (current-1)*pager.getPageSize();
		int to = from + pager.getPageSize();
		return users.subList(from, to);
	}

	public List<User> getUsers() {
		return users;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}

	public Pager getPager() {
		return pager;
	}

	public void setPager(Pager pager) {
		this.pager = pager;
	}
}
7.頁面引用標簽

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%> 
<%@ taglib prefix="p" uri="/pagination-tags"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="helloWorld.action" id="helloForm">
	<input name="userName"><input type="submit" value="查詢"/>
	<s:hidden name="pager.currentPage"/>
</form>
<table>
	<thead>
		<tr>
			<td>id</td>
			<td>name</td>
		</tr>
	</thead>
	<tbody>
		<s:iterator value="users">
		<tr>
			<td><s:property value="id"/></td>
			<td><s:property value="name"/></td>
			</tr>
		</s:iterator>
	</tbody>
</table>
<p:pagination pager="pager" formId="helloForm"></p:pagination>
</body>
</html>
8.運行效果

總結:

   網上看到很多到處抄來抄去的例子,很大一部分都是直接把這些分頁的代碼寫在java代碼里,if else一堆,本質上還是沒有理解struts2標簽的內部實現邏輯,既然用了struts2就要最大化的發揮框架的作用,采用模板技術來定制組件的展示邏輯既可以達到組件化編程的效果,又可以使代碼有更好的可讀性和可維護性




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM