基于Freemarker模板技术的分页组件设计

基于struts2的程序设计中,一定会用到struts自带的标签库,提供了一些常用的表单元素和逻辑控制标签的封装,而我们在项目中常用的分页标签却没有直接提供,通过学习struts2的源码分析我们可以看到,struts2的标签库默认是使用freemarker模板技术实现的,如图

基于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.运行效果

基于Freemarker模板技术的分页组件设计

总结:

   网上看到很多到处抄来抄去的例子,很大一部分都是直接把这些分页的代码写在java代码里,if else一堆,本质上还是没有理解struts2标签的内部实现逻辑,既然用了struts2就要最大化的发挥框架的作用,采用模板技术来定制组件的展示逻辑既可以达到组件化编程的效果,又可以使代码有更好的可读性和可维护性



你可能感兴趣的:(freemarker)