先看一下官網關於component標簽的注釋: Description Renders an custom UI widget using the specified templates. Additional objects can be passed in to the template using the param tags. Freemarker: Objects provided can be retrieve from within the template via $parameters.paramname. Jsp: Objects provided can be retrieve from within the template via <s:property value="%{parameters.paramname}" /> In the bottom JSP and Velocity samples, two parameters are being passed in to the component. From within the component, they can be accessed as:- Freemarker: $parameters.get('key1') and $parameters.get('key2') or $parameters.key1 and $parameters.key2 Jsp: <s:property value="%{parameters.key1}" /> and <s:property value="%{'parameters.key2'}" /> or <s:property value="%{parameters.get('key1')}" /> and <s:property value="%{parameters.get('key2')}" /> Currently, your custom UI components can be written in Velocity, JSP, or Freemarker, and the correct rendering engine will be found based on file extension. Remember: the value params will always be resolved against the ValueStack so if you mean to pass a string literal to your component, make sure to wrap it in quotes i.e. value="'value1'" otherwise, the the value stack will search for an Object on the stack with a method of getValue1(). (now that i've written this, i'm not entirely sure this is the case. i should verify this manana) If Jsp is used as the template, the jsp template itself must lie within the webapp itself and not the classpath. Unlike Freemarker or Velocity, JSP template could not be picked up from the classpath. templateDir and theme attribute The final path to the template will be built using the templateDir andtemplate attributes, like ${templateDir}/${theme}/${template}. If for example your component is under /components/html/option.jsp, you would have to set templateDir="components", theme="html" and template="options.jsp". For any Struts tag that you use in your component, make sure that you set its templateDir="template" ------------------------------------------------------------------------------------------------------------------------------------- self.tld: [html] <?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>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>map</short-name> <tag> <name>self</name> <tag-class>servlet.SelfDefinationTag</tag-class> <body-content>JSP</body-content> </tag> </taglib> 釋義:這是JSP模板文件,定義了self標簽,self標簽的處理類為SelfDefinationTag。 SelfDefinationTag.jsp: [html] <%@ page language="java" pageEncoding="gb2312"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%@taglib prefix="s" uri="/struts-tags"%> <html> <body> <s:component template="/components/image.jsp templateDir="MyTemplate" theme="xhtml" /> </body> </html> 釋義:Struts2中的component標簽是用來方便開發者定義自己開發的標簽。(component:組件;template:模板) 這裡定義了一個新的JSP文件,在該文件中使用component標簽來調用image.jsp這個模板文件。 templateDir:定義模板文件所在的根目錄名,若不顯示聲明則默認為"template"; theme:定義主題,若不顯示聲明則默認為"xhtml"。 因此,若templateDir和theme都不聲明,則系統調用的模板文件就是/template/xhtml下的模板文件。 image.jsp: [html] <%@ page language="java" pageEncoding="gb2312"%> <%@ taglib uri="Self" prefix="s" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <body> <s:self></s:self> </body> </html> 釋義:自定義標簽<s:self>,具體的標簽含義在下面的SelfDefinationTag標簽處理類。 SelfDefinationTag.java: [java] package servlet; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; public class SelfDefinationTag extends TagSupport { private static final long serialVersionUID = 1L; String contextPath; public int doStartTag() throws JspException { JspWriter out = pageContext.getOut(); try{ out.println("<img src=\"..\\validateImage\"/>"); }catch (IOException ioe1){ ioe1.printStackTrace(); } return EVAL_BODY_INCLUDE ; } public String getContextPath( HttpServletRequest req ) { String servletPath = req.getServletPath(); ServletContext servletContext = pageContext.getServletContext(); String realPath = servletContext.getRealPath( servletPath ); int lastSlash = realPath.lastIndexOf( System.getProperty( "file.separator" ) ); if ( lastSlash > -1 ) { String contextPath = realPath.substring( 0, lastSlash + 1 ); return contextPath; } return ""; } } 釋義:通過實現Struts2的TagSupport接口定義了一個標簽處理類,重寫了doStartTag()方法。這個自定義標簽只是插入了一段HTML圖像代碼。 注意<img src="../validateImage" />其中的“../”不能掉,它是上下文路徑的表示,默認路徑是WebRoot,這和Html中訪問不同目錄層次要加“../”是一樣的道理。 ValidateImage.java: [java] package servlet; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; public class ValidateImage extends HttpServlet { protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ response.setContentType("image/jpeg"); createImage(response.getOutputStream()); response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0); } private void createImage(OutputStream out)throws IOException { int width=60, height=20; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); Random random = new Random(); g.setColor(getRandColor(200,250)); g.fillRect(0, 0, width, height); g.setFont(new Font("Times New Roman",1,15)); //g.setColor(new Color()); //g.drawRect(0,0,width-1,height-1); g.setColor(getRandColor(160,200)); for (int i=0;i<155;i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x,y,x+xl,y+yl); } //String rand = request.getParameter("rand"); //rand = rand.substring(0,rand.indexOf(".")); String sRand=""; for (int i=0;i<4;i++){ String rand=String.valueOf(random.nextInt(10)); sRand+=rand; g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110))); g.drawString(rand,13*i+6,16); } // session.setAttribute("rand",sRand); g.dispose(); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image); param.setQuality(1.0f, false); encoder.setJPEGEncodeParam(param); try{ encoder.encode(image); }catch (IOException ioe){ ioe.printStackTrace(); } } Color getRandColor(int fc,int bc){ Random random = new Random(); if(fc>255) fc=255; if(bc>255) bc=255; int r=fc+random.nextInt(bc-fc); int g=fc+random.nextInt(bc-fc); int b=fc+random.nextInt(bc-fc); return new Color(r,g,b); } } 釋義:生成動態數字圖的servlet類,在web.xml中也有該servlet的映射定義。 web.xml: [html] <?xml version="1.0" encoding="GB2312"?> <web-app > <servlet> <servlet-name>ValidateImage</servlet-name> <servlet-class>servlet.ValidateImage</servlet-class> </servlet> <servlet-mapping> <servlet-name>ValidateImage</servlet-name> <url-pattern>/validateImage</url-pattern> </servlet-mapping> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <taglib> <taglib-uri>Self</taglib-uri> <taglib-location>/WEB-INF/tlds/self.tld</taglib-location> </taglib> </web-app> 釋義:注意過濾器<filter-mapping>中不能用<url-pattern>/*</url-pattern>(攔截所有HTTP請求),而是只過濾.jsp和.action請求(不過濾servlet請求),這點一定要注意,否則異常: 21:51:16,907 WARN [Dispatcher] Could not find action or result There is no Action mapped for namespace / and action name validateImage. - [unknown location] struts.xml: [html] <?xml version="1.0" encoding="gb2312"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="C05.7" extends="struts-default"> </package> </struts> 釋義:struts.xml中不用任何配置。 整體思路:self.tld文件用<taglib>自定義了標簽<s:self>;此模板的核心含義,即標簽處理類SelfDefinationTag.java。image.jsp文件調用了自定義的標簽<s:self></s:self>,此文件即是JSP模板文件(調用了自定義標簽的JSP文件)。這樣一來,自定義JSP標簽<s:self>就完成了,功能集中於image.jsp中了(即完成了self標簽的功能)。之後在view層SelfDefination.jsp文件中用<s:component>標簽調用image.jsp這個模板就行了。至於ValidateImage.java,這是一個獨立的產生動態數字圖片"流"的servlet類。在web.xml中定義了url映射及過濾攔截。