Struts2中實現(xiàn)自定義標簽很簡單,主要分為3步:
1.創(chuàng)建taglib文件(.tld),編寫標簽聲明。
2.編寫自定義標簽類。
3.在頁面中使用標簽。
下面以一個自定義的分頁標簽為例,進行說明。
其實,開發(fā)自定義標簽并不需要Struts2的支持,一般情況下,只需要繼承javax.servlet.jsp.tagext.BodyTagSupport類,重寫doStartTag,doEndTag等方法即可。這里在實現(xiàn)自定義標簽時,繼承的2個類分別是org.apache.struts2.views.jsp.ComponentTagSupport和org.apache.struts2.components.Component,ComponentTagSupport實際上是對BodyTagSupport的一次封裝,看一下ComponentTagSupport類的繼承關系就明了了:
java.lang.Objectextended by javax.servlet.jsp.tagext.TagSupportextended by javax.servlet.jsp.tagext.BodyTagSupportextended by org.apache.struts2.views.jsp.StrutsBodyTagSupportextended by org.apache.struts2.views.jsp.ComponentTagSupport
繼承ComponentTagSupport類是為了獲得標簽中的屬性值,并包裝成Component對象。繼承Component類是為了從Struts2中的ValueStack中獲得相對應的值。
1.聲明自定義標簽。
首先,需要創(chuàng)建一個tld文件,這是一個標準的XML文件,這個文件中就包含有對自定義標簽的聲明,聲明指出了標簽的名字,實現(xiàn)標簽的類,標簽的屬性等信息。當在頁面中使用該標簽時,web服務器就會從這個文件中找出相對應的標簽類,并實例化后執(zhí)行。這個文件其實與struts.xml文件的作用相類似。
tangs.tld
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"><taglib><tlib-version>2.2.3</tlib-version><jsp-version>1.2</jsp-version><short-name>tangs</short-name><uri>/tangs</uri><display-name>"Tangs Tags"</display-name><tag><name>pages</name><tag-class>com.tangs.tag.PageTag</tag-class> //標簽類<body-content>empty</body-content><attribute> //標簽中的屬性<name>cpage</name> //屬性名<required>true</required> //是否必須<rtexprvalue>true</rtexprvalue> //表示該自定義標簽的某屬性的值可以直接指定或者通過動態(tài)計算指定</attribute><attribute><name>total</name><required>true</required><rtexprvalue>true</rtexprvalue></attribute><attribute><name>url</name><required>true</required><rtexprvalue>true</rtexprvalue></attribute></tag></taglib>
2.編寫標簽類
PageTag.java
package com.tangs.tag;import com.opensymphony.xwork2.util.ValueStack;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts2.components.Component;import org.apache.struts2.views.jsp.ComponentTagSupport;/*** 分頁標簽* @author tangs*/public class PageTag extends ComponentTagSupport {private String cpage; //當前頁private String total; //總頁數(shù)private String url; //請求地址public void setCpage(String cpage) {this.cpage = cpage;}public void setTotal(String total) {this.total = total;}public void setUrl(String url) {this.url = url;}@Overridepublic Component getBean(ValueStack arg0, HttpServletRequest arg1, HttpServletResponse arg2) {return new Pages(arg0); //返回Pages Component,分頁的邏輯處理都在這個Component中}//獲得參數(shù)protected void populateParams() {super.populateParams();Pages pages = (Pages)component;pages.setCpage(cpage);pages.setTotal(total);pages.setUrl(url);}}
Pages.java
package com.tangs.tag;import com.opensymphony.xwork2.util.ValueStack;import java.io.IOException;import java.io.Writer;import java.util.logging.Level;import java.util.logging.Logger;import org.apache.struts2.components.Component;/*** 分頁邏輯Bean* @author tangs*/public class Pages extends Component {private String cpage;private String total;private String url;public String getCpage() {return cpage;}public void setCpage(String cpage) {this.cpage = cpage;}public String getTotal() {return total;}public void setTotal(String total) {this.total = total;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public Pages(ValueStack arg0) {super(arg0);}@Overridepublic boolean start(Writer writer) {boolean result = super.start(writer);try {StringBuilder str = new StringBuilder();boolean isValid = true;//從ValueStack中取出數(shù)值if (isValid) {if (total.startsWith("%{") && total.endsWith("}")) {total = total.substring(2, total.length() -1);total = (String)this.getStack().findValue(total);isValid = total == null ? false : true;} else {isValid = false;}}if (isValid) {if (cpage.startsWith("%{") && cpage.endsWith("}")) {cpage = cpage.substring(2, cpage.length() - 1);cpage = (String)this.getStack().findValue(cpage);isValid = cpage == null ? false : true;} else {isValid = false;}}if (isValid) {if (url.startsWith("%{") && url.endsWith("}")) {url = url.substring(2, url.length() - 1);url = (String)this.getStack().findValue(url);isValid = url == null ? false : true;} else {isValid = false;}}if (isValid) {Integer cpageInt = Integer.valueOf(cpage);//當前頁與總頁數(shù)相等if (cpage.equals(total)) {//如果total = 1,則無需分頁,顯示“[第1頁] [共1頁]”if ("1".equals(total)) {str.append("[第 " + cpage + " 頁]");str.append(" [共 " + total + " 頁]");} else {//到達最后一頁,顯示“[首頁] [上一頁] [末頁]”str.append("<a href='");str.append(url);str.append("?cpage=1&total="+total+"&url="+url);str.append("'>[首頁]</a> <a href='");str.append(url);str.append("?cpage=" + (cpageInt - 1) + "&total=" + total+"&url="+url);str.append("'>[上一頁]</a> <a href='");str.append(url);str.append("?cpage=" + total + "&total=" + total+"&url="+url);str.append("'>[末頁]</a>");}} else {//當前頁與總頁數(shù)不相同if ("1".equals(cpage)) {//第一頁,顯示“[首頁] [下一頁] [末頁]”str.append("<a href='");str.append(url);str.append("?cpage=1&total="+total+"&url="+url);str.append("'>[首頁]</a> <a href='");str.append(url);str.append("?cpage=" + (cpageInt + 1) + "&total=" + total+"&url="+url);str.append("'>[下一頁]</a> <a href='");str.append(url);str.append("?cpage=" + total + "&total=" + total+"&url="+url);str.append("'>[末頁]</a>");} else {//不是第一頁,顯示“[首頁] [上一頁] [下一頁] [末頁]”str.append("<a href='");str.append(url);str.append("?cpage=1&total="+total+"&url="+url);str.append("'>[首頁]</a> <a href='");str.append(url);str.append("?cpage=" + (cpageInt - 1) + "&total=" + total+"&url="+url);str.append("'>[上一頁]</a> <a href='");str.append(url);str.append("?cpage=" + (cpageInt + 1) + "&total=" + total+"&url="+url);str.append("'>[下一頁]</a> <a href='");str.append(url);str.append("?cpage=" + total + "&total=" + total+"&url="+url);str.append("'>[末頁]</a>");}}}writer.write(str.toString());} catch (IOException ex) {Logger.getLogger(Pages.class.getName()).log(Level.SEVERE, null, ex);}return result;}}
3.服務端
服務端主要是獲得請求然后轉(zhuǎn)向顯示的頁面
DisplayAction.java
/** To change this template, choose Tools | Templates* and open the template in the editor.*/package com.tangs.action;import com.opensymphony.xwork2.ActionSupport;/**** @author tangs*/public class DisplayAction extends ActionSupport {private String cpage;private String total;private String url;public String list() {//Get data from server//...//這里沒有做任何邏輯,直接跳轉(zhuǎn)到了頁面return SUCCESS;}public String getCpage() {return cpage;}public void setCpage(String cpage) {this.cpage = cpage;}public String getTotal() {return total;}public void setTotal(String total) {this.total = total;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}}
struts.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" ><struts><package name="tagTest" extends="struts-default"><action name="list" class="com.tangs.action.DisplayAction"><result name="success">/list.jsp</result></action></package></struts>
4.在頁面中使用標簽
list.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%><%@ taglib prefix="tangs" uri="/WEB-INF/tangs.tld"%><%@ taglib prefix="s" uri="/WEB-INF/struts-tags.tld"%><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>List</title></head><body>共 <s:property value="total"/> 頁 第 <s:property value="cpage"/> 頁<br><tangs:pages cpage="%{cpage}" total="%{total}" url="%{url}"/></body></html>
好了,啟動服務器,從瀏覽器中輸入http://localhost:7001/TagTest/list.page?cpage=1&total=5&url=list.page
就會得到下面的結果: