基于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就要最大化的发挥框架的作用,采用模板技术来定制组件的展示逻辑既可以达到组件化编程的效果,又可以使代码有更好的可读性和可维护性