自己写struts2分页标签

来源:互联网 发布:上海驿友微盒软件 编辑:程序博客网 时间:2024/05/01 05:28

想自己做标签的朋友可以来看一下.

这几天一直在研究Web分页,可能有的朋友会觉得这很简单,我想说的是,把任何简单的事做好就是不简单.我也正在努力着.

因为在用struts2写一个东西,分页用得比较频繁,所以决定自己写一个分页标签,编入自己的类库,准备一用它很多年,拷贝好带身边:)

这里把源码跟大家分享,希望对某些朋友有用.其实我一直觉得标签和.net里服务器控件是一回事.struts2的高扩展性为我们自己实现标签提供了很大的便捷.OK,进入主题

实现自定义struts2标签分三个部分:

1.定义标签 在这步要创建标签说明文件 *.tld

2.实现标签组件 这里只需继承struts2中的组件类和标签类就行了

3.用freemarker渲染标签 这步要创建一个*.ftl文件.同时我把相关分页逻辑也写在了这里

这个标签是用在struts2环境里的,所以需要你的项目需要引入struts2的常用包.这里就不多说了.

下面是效果图

下面是源代码:

在/web-inf下建立tlds文件夹,在其中新建iThink.tld文件(名字随个人喜好),内容如下:

Code:
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>      
  2. <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">      
  3. <taglib>      
  4.   <tlib-version>2.2.3</tlib-version>      
  5.   <jsp-version>1.2</jsp-version>      
  6.   <short-name>ithink</short-name>      
  7.   <uri>/ithink-tags</uri>      
  8.   <display-name>"iThink Tags"</display-name>      
  9.   <description><![CDATA["iThink is a student team. iThink Tags supports custom components that usually used in web develop"]]></description>      
  10.   <tag>      
  11.     <name>pager</name>      
  12.     <tag-class>org.icim.pager.struts2.PagerTag</tag-class>      
  13.     <body-content>JSP</body-content>      
  14.            
  15.     <attribute>      
  16.       <name>totalRecord</name>      
  17.       <required>false</required>      
  18.       <rtexprvalue>true</rtexprvalue>      
  19.       <description><![CDATA[总记录数]]></description>      
  20.     </attribute>      
  21.                
  22.     <attribute>      
  23.       <name>totalPage</name>      
  24.       <required>true</required>      
  25.       <rtexprvalue>true</rtexprvalue>      
  26.       <description><![CDATA[总页数]]></description>      
  27.     </attribute>      
  28.       
  29.     <attribute>      
  30.       <name>curPage</name>      
  31.       <required>true</required>      
  32.       <rtexprvalue>true</rtexprvalue>      
  33.       <description><![CDATA[当前页号]]></description>      
  34.     </attribute>      
  35.       
  36.     <attribute>      
  37.       <name>pageLimit</name>      
  38.       <required>false</required>      
  39.       <rtexprvalue>true</rtexprvalue>      
  40.       <description><![CDATA[每版最多显示的页数,最好为奇数]]></description>      
  41.     </attribute>      
  42.                
  43.     <attribute>      
  44.       <name>url</name>      
  45.       <required>true</required>      
  46.       <rtexprvalue>true</rtexprvalue>      
  47.       <description><![CDATA[翻页时的请求地址,如:list?page={page},其中的{page}会被动态地替换]]></description>      
  48.     </attribute>      
  49.                
  50.     <attribute>      
  51.       <name>curCssClass</name>      
  52.       <required>false</required>      
  53.       <rtexprvalue>true</rtexprvalue>      
  54.       <description><![CDATA[当前页的span标签的cssClass]]></description>      
  55.     </attribute>      
  56.       
  57.     <attribute>      
  58.       <name>showTotalPage</name>      
  59.       <required>false</required>      
  60.       <rtexprvalue>true</rtexprvalue>      
  61.       <description><![CDATA[是否显示总页数,默认为"true"]]></description>      
  62.     </attribute>      
  63.                
  64.     <attribute>      
  65.       <name>showTotalRecord</name>      
  66.       <required>false</required>      
  67.       <rtexprvalue>true</rtexprvalue>      
  68.       <description><![CDATA[是否显示总记录数,只有设置了总记录数属性的时候才有效,默认为"false"]]></description>      
  69.     </attribute>      
  70.       
  71.     <attribute>      
  72.       <name>directJumpType</name>      
  73.       <required>false</required>      
  74.       <rtexprvalue>true</rtexprvalue>      
  75.       <description><![CDATA[直接跳转的方式,"goto"或"select",默认为none]]></description>      
  76.     </attribute>      
  77.            
  78.     <!--以下是原UIBean通用的属性-->      
  79.     <attribute>      
  80.       <name>accesskey</name>      
  81.       <required>false</required>      
  82.       <rtexprvalue>false</rtexprvalue>      
  83.       <description><![CDATA[Set the html accesskey attribute on rendered html element]]></description>      
  84.     </attribute>      
  85.            
  86.     <attribute>      
  87.       <name>cssClass</name>      
  88.       <required>false</required>      
  89.       <rtexprvalue>false</rtexprvalue>      
  90.       <description><![CDATA[The css class to use for element]]></description>      
  91.     </attribute>      
  92.     <attribute>      
  93.       <name>cssStyle</name>      
  94.       <required>false</required>      
  95.       <rtexprvalue>false</rtexprvalue>      
  96.       <description><![CDATA[The css style definitions for element to use]]></description>      
  97.     </attribute>      
  98.     <attribute>      
  99.       <name>disabled</name>      
  100.       <required>false</required>      
  101.       <rtexprvalue>false</rtexprvalue>      
  102.       <description><![CDATA[Set the html disabled attribute on rendered html element]]></description>      
  103.     </attribute>      
  104.     <attribute>      
  105.       <name>id</name>      
  106.       <required>false</required>      
  107.       <rtexprvalue>false</rtexprvalue>      
  108.       <description><![CDATA[id for referencing element. For UI and form tags it will be used as HTML id attribute]]></description>      
  109.     </attribute>      
  110.     <attribute>      
  111.       <name>key</name>      
  112.       <required>false</required>      
  113.       <rtexprvalue>false</rtexprvalue>      
  114.       <description><![CDATA[Set the key (name, value, label) for this particular component]]></description>      
  115.     </attribute>      
  116.     <attribute>      
  117.       <name>label</name>      
  118.       <required>false</required>      
  119.       <rtexprvalue>false</rtexprvalue>      
  120.       <description><![CDATA[Label expression used for rendering a element specific label]]></description>      
  121.     </attribute>      
  122.     <attribute>      
  123.       <name>labelposition</name>      
  124.       <required>false</required>      
  125.       <rtexprvalue>false</rtexprvalue>      
  126.       <description><![CDATA[Define label position of form element (top/left)]]></description>      
  127.     </attribute>      
  128.     <attribute>      
  129.       <name>name</name>      
  130.       <required>false</required>      
  131.       <rtexprvalue>false</rtexprvalue>      
  132.       <description><![CDATA[The name to set for element]]></description>      
  133.     </attribute>      
  134.     <attribute>      
  135.       <name>onblur</name>      
  136.       <required>false</required>      
  137.       <rtexprvalue>false</rtexprvalue>      
  138.       <description><![CDATA[ Set the html onblur attribute on rendered html element]]></description>      
  139.     </attribute>      
  140.     <attribute>      
  141.       <name>onchange</name>      
  142.       <required>false</required>      
  143.       <rtexprvalue>false</rtexprvalue>      
  144.       <description><![CDATA[Set the html onchange attribute on rendered html element]]></description>      
  145.     </attribute>      
  146.     <attribute>      
  147.       <name>onclick</name>      
  148.       <required>false</required>      
  149.       <rtexprvalue>false</rtexprvalue>      
  150.       <description><![CDATA[Set the html onclick attribute on rendered html element]]></description>      
  151.     </attribute>      
  152.     <attribute>      
  153.       <name>ondblclick</name>      
  154.       <required>false</required>      
  155.       <rtexprvalue>false</rtexprvalue>      
  156.       <description><![CDATA[Set the html ondblclick attribute on rendered html element]]></description>      
  157.     </attribute>      
  158.     <attribute>      
  159.       <name>onfocus</name>      
  160.       <required>false</required>      
  161.       <rtexprvalue>false</rtexprvalue>      
  162.       <description><![CDATA[Set the html onfocus attribute on rendered html element]]></description>      
  163.     </attribute>      
  164.     <attribute>      
  165.       <name>onkeydown</name>      
  166.       <required>false</required>      
  167.       <rtexprvalue>false</rtexprvalue>      
  168.       <description><![CDATA[Set the html onkeydown attribute on rendered html element]]></description>      
  169.     </attribute>      
  170.     <attribute>      
  171.       <name>onkeypress</name>      
  172.       <required>false</required>      
  173.       <rtexprvalue>false</rtexprvalue>      
  174.       <description><![CDATA[Set the html onkeypress attribute on rendered html element]]></description>      
  175.     </attribute>      
  176.     <attribute>      
  177.       <name>onkeyup</name>      
  178.       <required>false</required>      
  179.       <rtexprvalue>false</rtexprvalue>      
  180.       <description><![CDATA[Set the html onkeyup attribute on rendered html element]]></description>      
  181.     </attribute>      
  182.     <attribute>      
  183.       <name>onmousedown</name>      
  184.       <required>false</required>      
  185.       <rtexprvalue>false</rtexprvalue>      
  186.       <description><![CDATA[Set the html onmousedown attribute on rendered html element]]></description>      
  187.     </attribute>      
  188.     <attribute>      
  189.       <name>onmousemove</name>      
  190.       <required>false</required>      
  191.       <rtexprvalue>false</rtexprvalue>      
  192.       <description><![CDATA[Set the html onmousemove attribute on rendered html element]]></description>      
  193.     </attribute>      
  194.     <attribute>      
  195.       <name>onmouseout</name>      
  196.       <required>false</required>      
  197.       <rtexprvalue>false</rtexprvalue>      
  198.       <description><![CDATA[Set the html onmouseout attribute on rendered html element]]></description>      
  199.     </attribute>      
  200.     <attribute>      
  201.       <name>onmouseover</name>      
  202.       <required>false</required>      
  203.       <rtexprvalue>false</rtexprvalue>      
  204.       <description><![CDATA[Set the html onmouseover attribute on rendered html element]]></description>      
  205.     </attribute>      
  206.     <attribute>      
  207.       <name>onmouseup</name>      
  208.       <required>false</required>      
  209.       <rtexprvalue>false</rtexprvalue>      
  210.       <description><![CDATA[Set the html onmouseup attribute on rendered html element]]></description>      
  211.     </attribute>      
  212.     <attribute>      
  213.       <name>onselect</name>      
  214.       <required>false</required>      
  215.       <rtexprvalue>false</rtexprvalue>      
  216.       <description><![CDATA[Set the html onselect attribute on rendered html element]]></description>      
  217.     </attribute>      
  218.     <attribute>      
  219.       <name>required</name>      
  220.       <required>false</required>      
  221.       <rtexprvalue>false</rtexprvalue>      
  222.       <description><![CDATA[If set to true, the rendered element will indicate that input is required]]></description>      
  223.     </attribute>      
  224.     <attribute>      
  225.       <name>requiredposition</name>      
  226.       <required>false</required>      
  227.       <rtexprvalue>false</rtexprvalue>      
  228.       <description><![CDATA[Define required position of required form element (left|right)]]></description>      
  229.     </attribute>      
  230.     <attribute>      
  231.       <name>tabindex</name>      
  232.       <required>false</required>      
  233.       <rtexprvalue>false</rtexprvalue>      
  234.       <description><![CDATA[Set the html tabindex attribute on rendered html element]]></description>      
  235.     </attribute>      
  236.     <attribute>      
  237.       <name>template</name>      
  238.       <required>false</required>      
  239.       <rtexprvalue>false</rtexprvalue>      
  240.       <description><![CDATA[The template (other than default) to use for rendering the element]]></description>      
  241.     </attribute>      
  242.     <attribute>      
  243.       <name>templateDir</name>      
  244.       <required>false</required>      
  245.       <rtexprvalue>false</rtexprvalue>      
  246.       <description><![CDATA[The template directory.]]></description>      
  247.     </attribute>      
  248.     <attribute>      
  249.       <name>theme</name>      
  250.       <required>false</required>      
  251.       <rtexprvalue>false</rtexprvalue>      
  252.       <description><![CDATA[The theme (other than default) to use for rendering the element]]></description>      
  253.     </attribute>      
  254.     <attribute>      
  255.       <name>title</name>      
  256.       <required>false</required>      
  257.       <rtexprvalue>false</rtexprvalue>      
  258.       <description><![CDATA[Set the html title attribute on rendered html element]]></description>      
  259.     </attribute>      
  260.     <attribute>      
  261.       <name>tooltip</name>      
  262.       <required>false</required>      
  263.       <rtexprvalue>false</rtexprvalue>      
  264.       <description><![CDATA[Set the tooltip of this particular component]]></description>      
  265.     </attribute>      
  266.     <attribute>      
  267.       <name>tooltipConfig</name>      
  268.       <required>false</required>      
  269.       <rtexprvalue>false</rtexprvalue>      
  270.       <description><![CDATA[Set the tooltip configuration]]></description>      
  271.     </attribute>      
  272.     <attribute>      
  273.       <name>value</name>      
  274.       <required>false</required>      
  275.       <rtexprvalue>false</rtexprvalue>      
  276.       <description><![CDATA[Preset the value of input element.]]></description>      
  277.     </attribute>      
  278.     </tag>      
  279.            
  280.     <tag>      
  281.     <name>textfield</name>      
  282.     <tag-class>org.apache.struts2.views.jsp.ui.TextFieldTag</tag-class>      
  283.     <body-content>JSP</body-content>      
  284.     <description><![CDATA[Render an HTML input field of type text]]></description>      
  285.            
  286.   </tag>      
  287. </taglib>     

原UIBean通用的属性我是直接从struts2源代码包里面copy来的.支持属性非常丰富.呵呵

建立组件类和标签类:

Pager.java:

Code:
  1. /***********************************************************************     
  2.  *     
  3.  *   Pager.java     
  4.  *     
  5.  *   @creator       Bruce Tsai  
  6.  *   @create-time   Jun 12, 2009   10:53:38 PM     
  7.  ***********************************************************************/  
  8.   
  9. package org.icim.pager.struts2;   
  10.   
  11. import org.apache.struts2.components.UIBean;   
  12. import org.apache.struts2.views.annotations.StrutsTag;   
  13. import org.apache.struts2.views.annotations.StrutsTagAttribute;   
  14. import com.opensymphony.xwork2.util.ValueStack;   
  15.   
  16. import javax.servlet.http.HttpServletRequest;   
  17. import javax.servlet.http.HttpServletResponse;   
  18.   
  19. /**  
  20.  * struts2版的分页标签  
  21.  *   
  22.  */  
  23.   
  24. @StrutsTag(name = "pager", tldTagClass = "org.icim.pager.struts2.PagerTag", description = "struts2 pager by ithink")   
  25. public class Pager extends UIBean {   
  26.   
  27.     final public static String TEMPLATE = "pager";   
  28.   
  29.     protected String totalRecord;   
  30.     protected String totalPage;   
  31.     protected String curPage;   
  32.     protected String pageLimit;   
  33.     protected String url;   
  34.     protected String curCssClass;   
  35.     protected String showTotalPage;   
  36.     protected String showTotalRecord;   
  37.     protected String directJumpType;   
  38.   
  39.     public Pager(ValueStack stack, HttpServletRequest request,   
  40.             HttpServletResponse response) {   
  41.         super(stack, request, response);   
  42.     }   
  43.   
  44.     /**  
  45.      * 用于返回模板的名字,Struts2会自动在后面加入.ftl扩展名以找到特定的模板文件。  
  46.      */  
  47.     @Override  
  48.     protected String getDefaultTemplate() {   
  49.         return TEMPLATE;   
  50.     }   
  51.   
  52.     /**  
  53.      * 设置UIBean的属性,一般Tag中有几个这样的属性,这里就有几个 StrutsTagAttribute注解,说明该属性是int类型,这一步很重要  
  54.      *   
  55.      * @param totalPage  
  56.      */  
  57.   
  58.     @StrutsTagAttribute(description = "total records", type = "Long")   
  59.     public void setTotalRecord(String totalRecord) {   
  60.         this.totalRecord = totalRecord;   
  61.     }   
  62.   
  63.     @StrutsTagAttribute(description = "total pages", type = "Integer")   
  64.     public void setTotalPage(String totalPage) {   
  65.         this.totalPage = totalPage;   
  66.     }   
  67.   
  68.     @StrutsTagAttribute(description = "current page", type = "Integer")   
  69.     public void setCurPage(String curPage) {   
  70.         this.curPage = curPage;   
  71.     }   
  72.   
  73.     @StrutsTagAttribute(description = "how many pages in a panel once", type = "Integer")   
  74.     public void setPageLimit(String pageLimit) {   
  75.         this.pageLimit = pageLimit;   
  76.     }   
  77.   
  78.     @StrutsTagAttribute(description = "url to be linked", type = "String")   
  79.     public void setUrl(String url) {   
  80.         this.url = url;   
  81.     }   
  82.   
  83.     @StrutsTagAttribute(description = "css style of current page", type = "String")   
  84.     public void setCurCssClass(String curCssClass) {   
  85.         this.curCssClass = curCssClass;   
  86.     }   
  87.   
  88.     @StrutsTagAttribute(description = "whether to show totalPage", type = "Boolean", defaultValue = "true")   
  89.     public void setShowTotalPage(String showTotalPage) {   
  90.         this.showTotalPage = showTotalPage;   
  91.     }   
  92.   
  93.     @StrutsTagAttribute(description = "whether to show currentPage", type = "Boolean", defaultValue = "false")   
  94.     public void setShowTotalRecord(String showTotalRecord) {   
  95.         this.showTotalRecord = showTotalRecord;   
  96.     }   
  97.   
  98.     // TODO 直接页面跳转   
  99.     // 这里的directJumpType默认值为none, 可选值为 'select', 'goto'   
  100.     @StrutsTagAttribute(description = "show type of direct jump type. such as select,textbox which can lead going to a page directly", type = "String", defaultValue = "none")   
  101.     public void setDirectJumpType(String directJumpType) {   
  102.         this.directJumpType = directJumpType;   
  103.     }   
  104.   
  105.     /**  
  106.      * 重写evaluateExtraParams()方法,在UIBean初始化后会调用这个方法来初始化设定参数,如addParameter方法,会在freemarker里的parameters里加入一个key  
  107.      * value。这里要注意findString,还有相关的findxxxx方法,它们是已经封装好了的解释ognl语法的工具,具体是怎么样的,大家可以查看一下UIBean的api  
  108.      * doc  
  109.      */  
  110.     @Override  
  111.     protected void evaluateExtraParams() {   
  112.         super.evaluateExtraParams();   
  113.         // findValue()方法本身已对OGNL进行了处理   
  114.   
  115.         if (totalRecord != null) {   
  116.             addParameter("totalRecord", findValue(totalRecord));   
  117.         }   
  118.   
  119.         if (totalPage != null) {   
  120.             addParameter("totalPage", findValue(totalPage));   
  121.         }   
  122.   
  123.         if (curPage != null) {   
  124.             addParameter("curPage", findValue(curPage));   
  125.         }   
  126.   
  127.         if (pageLimit != null) {   
  128.             addParameter("pageLimit", findValue(pageLimit));   
  129.         }   
  130.   
  131.         if (url != null) {   
  132.             addParameter("url", findValue(url, String.class));   
  133.         }   
  134.   
  135.         if (curCssClass != null) {   
  136.             addParameter("curCssClass", findValue(curCssClass,String.class));   
  137.         }   
  138.   
  139.         if (showTotalPage != null) {   
  140.             addParameter("showTotalPage", findValue(showTotalPage,   
  141.                     Boolean.class));   
  142.         }   
  143.   
  144.         if (showTotalRecord != null) {   
  145.             addParameter("showTotalRecord", findValue(showTotalRecord,Boolean.class));   
  146.         }   
  147.   
  148.         if (directJumpType != null) {   
  149.             addParameter("directJumpType", findValue(directJumpType));   
  150.         }   
  151.   
  152.     }   
  153. }   

PagerTag.java:

Code:
  1. /***********************************************************************     
  2.  *     
  3.  *   PagerTag.java     
  4.  *     
  5.  *   @creator       Bruce Tsai  
  6.  *   @create-time   Jun 13, 2009   12:08:53 AM     
  7.  ***********************************************************************/  
  8.   
  9. package org.icim.pager.struts2;   
  10.   
  11. import org.apache.struts2.views.jsp.ui.AbstractUITag;   
  12. import org.apache.struts2.components.Component;   
  13. import com.opensymphony.xwork2.util.ValueStack;   
  14.   
  15. import javax.servlet.http.HttpServletRequest;   
  16. import javax.servlet.http.HttpServletResponse;   
  17.   
  18. /**  
  19.  * struts2 版分页标签  
  20.  */  
  21. public class PagerTag extends AbstractUITag {   
  22.        
  23.     private static final long serialVersionUID = 719669934024053141L;   
  24.        
  25.     protected String totalRecord;   
  26.     protected String totalPage;   
  27.     protected String curPage;   
  28.     protected String pageLimit;   
  29.     protected String url;   
  30.     protected String curCssClass;   
  31.     protected String showTotalPage;   
  32.     protected String showTotalRecord;   
  33.     protected String directJumpType;   
  34.   
  35.     protected void populateParams() {   
  36.   
  37.         super.populateParams();   
  38.   
  39.         Pager pager = (Pager) component;   
  40.            
  41.         pager.setTotalRecord(totalRecord);   
  42.         pager.setTotalPage(totalPage);   
  43.         pager.setCurPage(curPage);   
  44.         pager.setPageLimit(pageLimit);   
  45.         pager.setUrl(url);   
  46.         pager.setCurCssClass(curCssClass);   
  47.         pager.setShowTotalPage(showTotalPage);   
  48.         pager.setShowTotalRecord(showTotalRecord);   
  49.         pager.setDirectJumpType(directJumpType);   
  50.   
  51.     }   
  52.   
  53.     @Override  
  54.     public Component getBean(ValueStack stack, HttpServletRequest request,   
  55.             HttpServletResponse response) {   
  56.         return new Pager(stack, request, response);   
  57.     }   
  58.   
  59.     public void setTotalRecord(String totalRecord){   
  60.         this.totalRecord = totalRecord;   
  61.     }   
  62.        
  63.     public void setTotalPage(String totalPage) {   
  64.         this.totalPage = totalPage;   
  65.     }   
  66.   
  67.     public void setCurPage(String curPage) {   
  68.         this.curPage = curPage;   
  69.     }   
  70.   
  71.     public void setPageLimit(String pageLimit) {   
  72.         this.pageLimit = pageLimit;   
  73.     }   
  74.   
  75.     public void setUrl(String url) {   
  76.         this.url = url;   
  77.     }   
  78.   
  79.     public void setCurCssClass(String curCssClass) {   
  80.         this.curCssClass = curCssClass;   
  81.     }   
  82.   
  83.     public void setShowTotalPage(String showTotalPage) {   
  84.         this.showTotalPage = showTotalPage;   
  85.     }   
  86.   
  87.     public void setShowTotalRecord(String showTotalRecord) {   
  88.         this.showTotalRecord = showTotalRecord;   
  89.     }   
  90.   
  91.     public void setDirectJumpType(String directJumpType) {   
  92.         this.directJumpType = directJumpType;   
  93.     }   
  94.        
  95.        
  96. }   

在类文件根目录下(在myeclipse中是在src目录下,发布后会copy到web-inf/classes/ 里)建立template/simple/ 目录,里面创建pager.ftl文件,内容如下:

Code:
  1. <#--显示总记录数,只有同时设置了总记录数和显示总记录数时才有效-->  
  2. <#if (parameters.totalRecord?exists) && (parameters.showTotalRecord?exists) && (parameters.showTotalRecord == true)>  
  3.     <span>${parameters.totalRecord}</span><#rt/>  
  4. </#if>  
  5.   
  6. <#--打印选择页的面板 -->  
  7. <#--首先,当parameters.pageLimit为空时将其设定为total-->  
  8. <#if (parameters.pageLimit?exists)>  
  9.     <#assign limit = parameters.pageLimit />  
  10. <#else>  
  11.     <#assign limit = parameters.totalPage />  
  12. </#if>  
  13. <@pagePanel cur=parameters.curPage total=parameters.totalPage url=parameters.url limitlimit=limit />  
  14. <#--打印选择页的面板结束-->  
  15.   
  16. <#--显示总页数-->  
  17. <#if parameters.showTotalPage?exists && (parameters.showTotalPage == true)>  
  18.     <span>..${parameters.totalPage}</span><#rt/>  
  19. </#if>  
  20.   
  21. <#--打印翻页面板的宏,配合printPage,printButton-->  
  22. <#macro pagePanel cur total limit url curCssClass = "cur_page"><#--curCssClass默认值为cur_page-->  
  23.     <#--limit的中间数-->  
  24.     <#assign l_mid = (limit/2)?int + 1 />  
  25.        
  26.     <#--total的中间数-->  
  27.     <#assign t_mid = (total/2)?int />  
  28.        
  29.     <#--情况一:总页数小于等于限制显示页数,这时显示所有页-->  
  30.     <#if total <= limit>  
  31.         <@printButton direct="left" valuable = false />  
  32.         <@printPage left = 1 right = total curcur = cur urlurl = url curCssClasscurCssClass = curCssClass />  
  33.         <@printButton direct="right" valuable = false />                   
  34.     <#else>  
  35.     <#--情况二:总页数大于限制显示页数,这时又分三种情况-->  
  36.         <#--情况1:显示的limit个页号在total个页面中偏向左端,1作为最左边的页号,当前页没能显示在中间,偏左,例:   
  37.             total = 20,cur = 2,limit = 5.显示的页面为:1 [2] 3 4 5   
  38.             这种情况 cur <= l_mid    
  39.         -->  
  40.         <#if cur <= l_mid>  
  41.             <@printButton direct="left" valuable = false />  
  42.             <@printPage left = 1 right = limit curcur = cur urlurl = url curCssClasscurCssClass = curCssClass />  
  43.             <@printButton direct="right" valuable = true />  
  44.                
  45.         <#--情况2:显示的limit个页号在total个页面中偏向右端,total作为最右边的页号,当前页没能显示在中间,偏右,例:   
  46.             total = 20,cur = 19,limit = 5.显示的页面为:16 17 18 [19] 20   
  47.             这种情况 cur > total - l_mid   
  48.         -->  
  49.         <#elseif (cur > (total - l_mid))>  
  50.             <@printButton direct="left" valuable = true />  
  51.             <@printPage left = (total - limit + 1) right = total curcur = cur urlurl = url curCssClasscurCssClass = curCssClass />  
  52.             <@printButton direct="right" valuable = false />  
  53.                
  54.         <#--在中间的情况-->  
  55.         <#else>  
  56.             <@printButton direct="left" valuable = true />  
  57.             <@printPage left = (cur - l_mid + 1) right = (cur + l_mid -1) curcur = cur urlurl = url curCssClasscurCssClass = curCssClass />  
  58.             <@printButton direct="right" valuable = true />  
  59.         </#if>  
  60.     </#if>  
  61.        
  62. </#macro>  
  63.   
  64. <#--根据最左与最右的页号来打印所显示的页面,当前页为的cssStyle为curCssClass-->  
  65. <#macro printPage left right cur url curCssClass>  
  66.     <#list left..right as p>  
  67.         <#if p == cur>  
  68.             <span class = "${curCssClass}" >${p}</span><#rt/>  
  69.         <#else>  
  70.             <a href = "<@makeURL text=url page=p />">${p}</a><#rt/>  
  71.         </#if>         
  72.     </#list>       
  73. </#macro>  
  74.   
  75. <#--翻页控制按钮,direct选择"left"或"right",avaluable设置是否有链接-->  
  76. <#macro printButton direct valuable = true>  
  77.     <#if direct == "left">  
  78.         <#if valuable>  
  79.             <a href="<@makeURL text=parameters.url page=1 />"> << </a><#rt/>  
  80.             <a href="<@makeURL text=parameters.url page=parameters.curPage-1 />"> < </a><#rt/>  
  81.         <#else>  
  82.             <span><<</span><#rt/>  
  83.             <span><</span><#rt/>  
  84.         </#if>  
  85.     <#else>  
  86.         <#if valuable>  
  87.             <a href="<@makeURL text=parameters.url page=parameters.curPage+1 />"> > </a><#rt/>  
  88.             <a href="<@makeURL text=parameters.url page=parameters.totalPage />"> >> </a><#rt/>  
  89.         <#else>  
  90.             <span>></span><#rt/>  
  91.             <span>>></span><#rt/>  
  92.         </#if>  
  93.     </#if>  
  94. </#macro>  
  95.   
  96. <#--产生动态URL的宏-->  
  97. <#macro makeURL text page>  
  98.     <#if text?last_index_of("{page}") < 0>  
  99.         ${text}?page=${page}   
  100.     <#else>  
  101.         ${text?replace("{page}",page)}   
  102.     </#if>     
  103. </#macro>  

感觉freemarker用起来挺方便的,我花了一个上午粗略地学了一下.有兴趣可以看这篇笔记:FreeMarker详解:http://student.csdn.net/space.php?uid=46942&do=blog&id=4769

最后,需要在你的struts.xml配置文件里做如下设置

Code:
  1. <constant name="struts.ui.theme" value="simple" />  

也就是对应之前建立的theme/simple目录

好了,标签部分就做完了.下面就是使用标签.建立test.jsp

Code:
  1. <%@ page language="java" contentType="text/html; charset=utf-8"  
  2.     pageEncoding="utf-8"%>  
  3. <%@ taglib prefix="s" uri="/struts-tags"%>  
  4. <%@ taglib prefix="ithink" uri="/ithink-tags"%>  
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  6. <html>  
  7.     <head>  
  8.         <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
  9.         <title>pager tag test</title>  
  10.     </head>  
  11.     <body>  
  12.         <div class="pagination">  
  13.             <ithink:pager curPage="3" totalPage="88"  
  14.                 url="listPaper.action?pno={page}" pageLimit="9" showTotalPage="true"  
  15.                 totalRecord="1988" showTotalRecord="true" />  
  16.         </div>  
  17.     </body>  
  18. </html>  

还需要为它设置CSS样式:

Code:
  1. /*---------------------pagination-----------------------------*/  
  2.   
  3. div.pagination {   
  4.     padding:5px;   
  5.     margin:5px;   
  6.     text-align:center;   
  7.     float:left;   
  8.     font-size:12px;   
  9. }   
  10.   
  11. div.pagination a {   
  12.     padding2px 5px 2px 5px;   
  13.     margin-right2px;   
  14.     border1px solid #ddd;   
  15.     text-decorationnone;    
  16.     color#d8325d;   
  17. }   
  18. div.pagination a:hover, div.pagination a:active {   
  19.     border:1px solid #ddd;   
  20.     color#fff;   
  21.     background-color#d8325d;   
  22. }   
  23. div.pagination span.cur_page {   
  24.     padding2px 5px 2px 5px;   
  25.     margin-right2px;   
  26.     border1px solid #ddd;   
  27.     font-weightbold;   
  28.     background-color#d8325d;   
  29.     color#FFF;   
  30. }   
  31. div.pagination span {   
  32.     padding2px 5px 2px 5px;   
  33.     margin-right2px;   
  34.     border1px solid #ddd;   
  35.     text-decorationnone;    
  36.     color#d8325d;   
  37. }  

到此一切都OVER了.如果你觉得我的实现不能满足要求,完全可以自己再写一个pager.ftl.比如说显示:第一页 上一页 下一页 最后一页,只要在使用标签时指定theme属性,比如说"text",然后再在theme/text目录下重新写一个pager.ftl就行了

其中directJump属性所指的值还没有实现,希望有兴趣的朋友能一起完善它.