Action 跟 Actionsupport 的區別
Action 跟 Actionsupport 的區別 當我們在寫action的時候,可以實現Action接口,也可以繼承Actionsupport這個類.到底這兩個有什么區別呢?
Action接口有: public static final java.lang.String SUCCESS = "success"; public static final java.lang.String NONE = "none"; public static final java.lang.String ERROR = "error"; public static final java.lang.String INPUT = "input"; public static final java.lang.String LOGIN = "login";
public abstract java.lang.String execute() throws java.lang.Exception;
而Actionsupport這個工具類在實現了Action接口的基礎上還定義了一個validate()方法,重寫該方法,它會在execute()方法之前執行,如校驗失敗,會轉入input處,必須在配置該Action時配置input屬性。
另外,Actionsupport還提供了一個getText(String key)方法還實現國際化,該方法從資源文件上獲取國際化信息.
這樣在自定義標簽時可以定義一個變量為new actionsupport對象實現國際化。
ActionSupport類的作用 struts2不要求我們自己設計的action類繼承任何的struts基類或struts接口,但是我們為了方便實現我們自己的action,大多數情況下都會繼承com.opensymphony.xwork2.ActionSupport類,並重寫此類里的public String execute() throws Exception方法。因為此類中實現了很多的實用借口,提供了很多默認方法,這些默認方法包括國際化信息的方法、默認的處理用戶請求的方法等,這樣可以大大的簡化Acion的開發。 Struts2中通常直接使用Action來封裝HTTP請求參數,因此,Action類里還應該包含與請求參數對應的屬性,並且為屬性提供對應的getter和setter方法。
========================== <s:property> 關於struts2標簽取值的備忘錄
取值要通過<s:property value="" />或在任意的<s:/>標簽內使用%{};
當Action的valueStack中有該屬性的值時,只需直接使用該屬性的名字即可;
當Action的valueStack中沒有該屬性的值時,比如在session,application范圍中的屬性值時,需要加#或者#attr.;
例子: 假設某Action中有person成員變量,在application中存在company屬性 那么我們可以通過以下方法取值: <s:property value="person.name" /> <s:property value="#person.name" /> <s:property value="company.name" /> //無法取到,因為company不在action的valueStack中 <s:property value="#company.name" />
<s:textfield name="person.name" value="person.name" /> //錯誤,value會直接顯示person.name字樣 <s:textfield name="person.name" value="%{person.name}" /> <s:textfield name="person.company.name" value="%{#company.name}" /> <s:textfield name="person.company.name" value="%{#attr.company.name}" />
===================== 一次Action調用都會創建一個ActionContext 調用:ActionContext context = ActionContext.getContext() ValueStack由OGNL框架實現 可以把它簡單的看作一個集合
Stack Object:放入stack中的對象,一般是action Stack Context(map):stack上下文,它包含一些列對象,包括request/session/attr/application map等。
EL:存取對象的任意屬性,調用對象的方法,遍歷整個對象結…
=========== WebWork2.2筆記(二)ActionSupport及其他基礎知識 絕大多數情況下,WebWork不是直接實現com.opensymphony.xwork.Action接口,而是擴展 com.opensymphony.xwork.ActionSupport類。ActionSupport實現了除Action以外的其他幾個接口,主要的幾個接口是: com.opensymphony.xwork.Validateable com.opensymphony.xwork.Validateaware com.opensymphony.xwork.TextProvider com.opensymphony.xwork.LocaleProvider 這些接口主要是提供給WebWork的攔截器使用的,接口配合攔截器可以實現AOP功能。比如Validateable接口和Validateaware 接口配合DefailtWorkflowInterceptor就可以實現對用戶輸入進行檢驗的功能,當用戶調用Action時,首先執行 Validateable接口定義的validate()方法,如果在這個方法中用戶使用接口Validateaware中的方法設置了錯誤信息,則 DefaultWorkflowInterceptor會自動終止Action的執行,並產生一個INPUT的result,只有沒有任何錯誤信息才會執行Action的剩余部分。
前面我們定義的xwork.xml配置文件中包含了一句:<include file="webwork-default.xml">,這個webwork-default.xml包含在webwork的jar包中。 webwork-default.xml預建了很多常用的result-type、interceptor和interceptor-stack。其中 interceptor和interceptor-stack用於定義webwork將要使用那些攔截器。interceptor定義一個攔截器,而 interceptor定義一組攔截器。如果一個Action使用一組攔截器,則這些攔截器將以其定義的順序執行,可見,interceptor- stack中攔截器的順序時很重要的。
在webwork-default.xml中有如下定義: <interceptor class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor" name="workflow"> ...... 而名為validationWorkflowStack和completeStack這兩個預建的interceptor-stack則包含了workflow這個interceptor。
下面做一個檢查用戶輸入的練習,如果用戶沒有輸入內容,則讓用戶重新輸入,並且提示錯誤信息。
web.xml 與上次的相同。
xwork.xml </interceptor></include> xml 代碼
1. 2. "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
3. 4. <xwork> 5. <include file="webwork-default.xml" />
6. 7. <package name="default" extends="webwork-default"> 8.
9. <default-interceptor-ref name="validationWorkflowStack"/> 10. <action name="alidateInput" class="example.ValidateInputAction"> 11. <result name="success">success.jspresult> 12. <result name="input">input.jspresult> 13. action> 14. 15. package> 16. xwork>
input.jsp xml 代碼
1. <%@taglib prefix="ww" uri="/webwork"%> 2. <html> 3. <head><title>Input Somethingtitle>head> 4. <body>
5. 6. <ww:form action="alidateInput.action"> 7. <ww:textfield label="Input something:" name="something">ww:textfield>
8. <ww:submit>ww:submit> 9. ww:form> 10. 11. body> 12. html>
success.jsp xml 代碼
1. <%@taglib prefix="ww" uri="/webwork"%> 2. <html> 3. <head><title>Success!title>head> 4. <body> 5. <ww:property value="something"/> 6. body> 7. html>
============================== Action的實例,總是放到value stack中。因為Action放在stack中,而stack是root(根對象),所以對Action中的屬性的訪問就可以省略#標記。但是,要訪問 ActionContext中其它對象的屬性,就必須要帶上#標記,以便讓OGNL知道,不是從根對象,而是從其它對象中去尋找。
Struts2中OGNL,valueStack,stackContext的學習 學習Struts2,一直不明白表單中的值是怎么傳給Action的,上網查了些資料,基本了解了!下面基本是從幾個人的BOLG轉載過來,以后記不清了再來看~
[color=red]先看看我做的實驗jsp頁面 Java代碼
<s:form action="hello/converter.action" method="post"> <s:textfield name="point" label="點"></s:textfield> <s:textfield name="point2" label="2"></s:textfield> <s:textfield name="point3" label="3"></s:textfield> <s:textfield name="age" label="年齡"></s:textfield> <s:textfield name="date" label="日期"></s:textfield> <s:submit name="提交"></s:submit> </s:form>
結果圖(是通過<s:debug></s:debug>得到的) value stack:
[點擊查看原始大小圖片]
Stack context:
通過圖中我們可以看到 valuestack中包括我傳遞的值(point,point2,point3,age,date) stack context中包括了 request application OgnlValueStack(root) session parameters 等屬性
值棧(ValueStack) Struts2將OGNL上下文設置為Struts2中的ActionContext(內部使用的仍然是OgnlContext),並將值棧設為OGNL的根對象。 我們知道,OGNL上下文中的根對象可以直接訪問,不需要使用任何特殊的“標記”,而引用上下文中的其他對象則需要使用“#”來標記。由於值棧是上下文中的根對象,因此可以直接訪問。那么對於值棧中的對象該如何訪問呢?Struts2提供了一個特殊的OGNLPropertyAccessor,它可以自動查找棧內的所有對象(從棧頂到棧底),直接找到一個具有你所查找的屬性的對象。也就是說,對於值棧中的任何對象都可以直接訪問,而不需要使用 “#”。 假設值棧中有兩個對象:student和employee,兩個對象都有name屬性,student有學號屬性number,而 employee有薪水屬性salary。employee先入棧,student后入棧,位於棧頂,那么對於表達式name,訪問的就是student 的name屬性,因為student對象位於棧頂;表達式salary,訪問的就是employee的salary屬性。正如你所見,訪問值棧中的對象屬性或方法,無須指明對象,也不用“#”,就好像值棧中的對象都是OGNL上下文中的根對象一樣。這就是Struts2在OGNL基礎上做出的改進。
值棧中的Action實例 Struts2框架總是把Action實例放在棧頂。因為Action在值棧中,而值棧又是OGNL中的根,所以引用Action的屬性可以省略“#”標記,這也是為什么我們在結果頁面中可以直接訪問Action的屬性的原因。
Struts2中的命名對象 Struts2還提供了一些命名對象,這些對象沒有保存在值棧中,而是保存在ActionContext中,因此訪問這些對象需要使用“#”標記。這些命名對象都是Map類型。
parameters 用於訪問請求參數。如:#parameters['id']或#parameters.id,相當於調用了HttpServletRequest對象的getParameter()方法。 注意,parameters本質上是一個使用HttpServletRequest對象中的請求參數構造的Map對象,一量對象被創建(在調用Action實例之前就已經創建好了),它和HttpServletRequest對象就沒有了任何關系。
request 用於訪問請求屬性。如:#request['user']或#request.user,相當於調用了HttpServletRequest對象的getAttribute()方法。
session 用於訪問session屬性。如:#session['user']或#session.user,相當於調用了HttpSession對象的getAttribute()方法。
application 用於訪問application屬性。如:#application['user']或#application.user,相當於調用了ServletContext的getAttribute()方法。
attr 如果PageContext可用,則訪問PageContext,否則依次搜索request、session和application對象。
以下是轉過來的:先分清楚下ActionContext 、ValueStack 、Stack Context三者
ActionContext 一次Action調用都會創建一個ActionContext 調用:ActionContext context = ActionContext.getContext()
ValueStack 由OGNL框架實現 可以把它簡單的看作一個棧(List) 。
Stack Object:放入stack中的對象,一般是action。 Stack Context(map):stack上下文,它包含一系列對象,包括request/session/attr/application map等。 EL:存取對象的任意屬性,調用對象的方法,遍歷整個對象結…
ActionContext是Action上下文,可以得到request session application ValueStack是值棧 存放表單中的值 Stack Context 棧上下文 也是用來存值的
struts2對OGNL上下文的概念又做了進一步擴充,在struts2中,OGNL上下文通常如下所示:
|--request
|
|--application
|
context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|
|--session
|
|--attr
|
|--parameters
在Struts2中,采用標准命名的上下文(Context)來處理OGNL表達式。處理OGNL的頂級對象是一個Map(也叫context map),而OGNL在這個context中就是一個頂級對象(root)。在用法上,頂級對象的屬性訪問,是不需要任何標記前綴的。而其它非頂級的對象訪問,需要使用#標記。 Struts2框架把OGNL Context設置為我們的ActionContext。並且ValueStack作為OGNL的根對象。除value stack之外,Struts2框架還把代表application、session、request這些對象的Map對象也放到 ActionContext中去。(這也就是Struts2建議在Action類中不要直接訪問Servlet API的原因,他可以通過ActionContext對象來部分代替這些(Servlet API)功能,以方便對Action類進行測試!) Action的實例,總是放到value stack中。因為Action放在stack中,而stack是root(根對象),所以對Action中的屬性的訪問就可以省略#標記。但是,要訪問 ActionContext中其它對象的屬性,就必須要帶上#標記,以便讓OGNL知道,不是從根對象,而是從其它對象中去尋找。 那么訪問Action中的屬性的代碼就可以這樣寫
<s:property value="postalCode"/> 其它ActionContext中的非根對象屬性的訪問要像下面這樣寫: <s:property value="#session.mySessionPropKey"/> or <s:property value="#session['mySessionPropKey']"/> or <s:property value="#request['myRequestPropKey']"/> 對Collection的處理,內容就很簡單。 <s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" /> 這是處理List。這個代碼在頁面上建立一個下拉選項,內容是list中的內容,默認值是name2. 處理map
<s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />
需要注意的是,判斷一個值是否在collection中。我們要使用in或者not in來處理。 <s:if test="'foo' in {'foo','bar'}"> muhahaha </s:if> <s:else> boo </s:else> 另外,可以使用通配符來選擇collection對象的子集。 ?——所有匹配選擇邏輯的元素 ^——只提取符合選擇邏輯的第一個元素 $——只提取符合選擇邏輯的最后一個元素 person.relatives.{? #this.gender == 'male'}
`````````````````````````````````````````````````````````````````````````````````
以下為補充摘錄的一些問題:
提問:在Struts2中,如何使用自身的Tag讀取Action中的變量?
Struts2自身的Tag會根據value中的OGNL表達式,在ValueStack中尋找相應的對象。因為action在 ValueStack的頂部,所以默認情況下,Struts2的Tag中的OGNL表達式將查找action中的變量。請注意,value中的內容直接是 OGNL表達式,無需任何el的標簽包裝。
例如:<s:property value="user.name" />
提問:在Struts2中,如何使用自身的Tag讀取HttpServletRequest,HttpSession中的變量?
在上面的知識中,我們知道,Struts2中OGNL的上下文環境中,包含request,session,application等 servlet對象的Map封裝。既然這些對象都在OGNL的上下文中,那么根據OGNL的基本知識,我們可以通過在表達式前面加上#符號來對這些變量的值進行訪問。
例如:<s:property value="%{#application.myApplicationAttribute}" /> <s:property value="%{#session.mySessionAttribute}" /> <s:property value="%{#request.myRequestAttribute}" /> <s:property value="%{#parameters.myParameter}" />
提問:在Struts2中,如何使用JSTL來讀取Action中的變量?
這是一個歷史悠久的問題。因為事實上,很多朋友(包括我在內)是不使用Struts2自身的標簽庫,而是使用JSTL的,可能因為JSTL標簽庫比較少,簡單易用的原因吧。
我們知道,JSTL默認是從page,request,session,application這四個Scope逐次查找相應的EL表達式所對應的對象的值。那么如果要使用JSTL來讀取Action中的變量,就需要把Action中的變量,放到request域中才行。所以,早在 Webwork2.1.X的年代,我們會編寫一個攔截器來做這個事情的。大致的原理是:在Action執行完返回之前,依次讀取Action中的所有的變量,並依次調用request.setAttribute()來進行設置。具體的整合方式,請參考以下這篇文檔:http://wiki.opensymphony.com/display/WW /Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1
不過隨着時代的發展,上面的這種方式,已經不再被推薦使用了。(雖然如此,我們依然可以學習它的一個解決問題的思路)目前來說,自從 Webwork2.2以后,包括Struts2,都使用另外一種整合方式:對HttpServletRequest進行裝飾。讓我們來看一下源碼: Java代碼
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
/** * The constructor * @param req The request */ public StrutsRequestWrapper(HttpServletRequest req) { super(req); }
/**
* Gets the object, looking in the value stack if not found * * @param s The attribute key */ public Object getAttribute(String s) {
if (s != null && s.startsWith("javax.servlet")) { // don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(s); }
ActionContext ctx = ActionContext.getContext(); Object attribute = super.getAttribute(s);
boolean alreadyIn = false; Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute"); if (b != null) { alreadyIn = b.booleanValue(); }
// note: we don't let # come through or else a request for // #attr.foo or #request.foo could cause an endless loop if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {
try { // If not found, then try the ValueStack
ctx.put("__requestWrapper.getAttribute", Boolean.TRUE); ValueStack stack = ctx.getValueStack(); if (stack != null) { attribute = stack.findValue(s); } } finally {
ctx.put("__requestWrapper.getAttribute", Boolean.FALSE); } }
return attribute; } }
看到了嘛?這個類會在Struts2初始化的時候,替換HttpServletRequest,運行於整個Struts2的運行過程中,當我們試圖調用 request.getAttribute()的時候,就會執行上面的這個方法。(這是一個典型的裝飾器模式)在執行上面的方法時,會首先調用 HttpServletRequest中原本的request.getAttribute(),如果沒有找到,它會繼續到ValueStack中去查找,而action在ValueStack中,所以action中的變量通過OGNL表達式,就能找到對應的值了。
在這里,在el表達式廣泛使用的今天,JSTL1.1以后,也支持直接使用el表達式。注意與直接使用struts2的tag的區別,這里需要使用el的表示符號:${}
例如:${user.name}, <c:out value="${department.name}" />
提問:在Struts2中,如何使用Freemarker等模板來讀取Action中的變量以及HttpServletRequest和HttpSession中的變量?
Freemarker等模板在Struts2中有對應的Result,而在這些Result中,Freemarker等模板會根據 ValueStack和ActionContext中的內容,構造這些模板可識別的Model,從而使得模板可以以他們各自的語法對ValueStack 和ActionContext中的內容進行讀取。
有關Freemarker對於變量的讀取,可以參考Struts2的官方文檔,非常詳細:http://struts.apache.org/2.0.14/docs/freemarker.html
設值計算
Struts2中使用OGNL進行設值計算,就是指View層傳遞數據到Control層,並且能夠設置到相應的Java對象中。這個過程從邏輯上說需要分成兩步來完成:
1. 對於每個請求,都建立一個與相應Action對應的ActionContext作為OGNL的上下文環境和ValueStack,並且把Action壓入ValueStack
2. 在請求進入Action代碼前,通過某種通用的機制,搜集頁面上傳遞過來的參數,並調用OGNL相關的代碼,對Action進行設值。 上面的第一個步驟,在處理URL請求時完成,而第二個步驟由struts2內置的攔截器完成。
================================ Struts2教程:使用validate方法驗證數據 在Struts2中最簡單的驗證數據的方法是使用validate。我們從ActionSupport類的源代碼中可以看到,ActionSupport類實現了一個Validateable接口。這個接口只有一個validate方法。如果Action類實現了這個接口,Struts2在調用execute方法之前首先會調用這個方法,我們可以在validate方法中驗證,如果發生錯誤,可以根據錯誤的level選擇字段級錯誤,還是動作級錯誤。並且可使用addFieldError或addActionError加入相應的錯誤信息,如果存在Action或 Field錯誤,Struts2會返回“input”(這個並不用開發人員寫,由Struts2自動返回),如果返回了“input”,Struts2就不會再調用execute方法了。如果不存在錯誤信息,Struts2在最后會調用execute方法。
這兩個add方法和ActionErrors類中的add方法類似,只是add方法的錯誤信息需要一個ActionMessage對象,比較麻煩。除了加入錯誤信息外,還可以使用addActionMessage方法加入成功提交后的信息。當提交成功后,可以顯示這些信息。
以上三個add方法都在ValidationAware接口中定義,並且在ActionSupport類中有一個默認的實現。其實,在 ActionSupport類中的實現實際上是調用了ValidationAwareSupport中的相應的方法,也就是這三個add方法是在 ValidationAwareSupport類中實現的,代碼如下:
1. private final ValidationAwareSupport validationAware = new ValidationAwareSupport(); 2. 3. public void addActionError(String anErrorMessage) 4. { validationAware.addActionError(anErrorMessage); 5. } 6. public void addActionMessage(String aMessage) 7. { 8. validationAware.addActionMessage(aMessage); 9. } 10. public void addFieldError(String fieldName, String errorMessage) 11. { 12. validationAware.addFieldError(fieldName, errorMessage); 13. }
下面我們來實現一個簡單的驗證程序,來體驗一個validate方法的使用。
先來在Web根目錄建立一個主頁面(validate.jsp),代碼如下:
1. < %@ page language="java" import="java.util.*" pageEncoding="GBK"%> 2. < %@ taglib prefix="s" uri="/struts-tags" %> 3. < html> 4. < head> 5. < title>驗證數據< /title> 6. < /head>
7. 8. < body> 9. < s:actionerror/> 10. < s:actionmessage/> 11. < s:form action="validate.action" theme="simple"> 12. 輸入內容:< s:textfield name="msg"/> 13. < s:fielderror key="msg.hello" /> 14. < br/> 15. < s:submit/> 16. < /s:form> 17. < /body> 18. < /html>
在上面的代碼中,使用了Struts2的tag:< s:actionerror>、< s:fielderror>和< s:actionmessage>,分別用來顯示動作錯誤信息,字段錯誤信息,和動作信息。如果信息為空,則不顯示。
現在我們來實現一個動作類,代碼如下:
1. package action; 2. 3. import javax.servlet.http.*; 4. 5. import com.opensymphony.xwork2.ActionSupport; 6. import org.apache.struts2.interceptor.*; 7. 8. public class ValidateAction extends ActionSupport 9. { 10. private String msg; 11. public String execute() 12. { 13. System.out.println(SUCCESS); 14. return SUCCESS;
15. } 16. public void validate() 17. { 18. if(!msg.equalsIgnoreCase("hello")) 19. { 20. System.out.println(INPUT);
21. this.addFieldError("msg.hello", "必須輸入hello!"); 22. this.addActionError("處理動作失敗!"); 23. } 24. else 25. { 26. this.addActionMessage("提交成功"); 27. } 28. } 29. public String getMsg() 30. { 31. return msg; 32. } 33. public void setMsg(String msg) 34. { 35. this.msg = msg; 36. } 37. }
大家從上面的代碼可以看出,Field錯誤需要一個key(一般用來表示是哪一個屬性出的錯誤),而Action錯誤和Action消息只要提供一個信息字符串就可以了。
最后來配置一下這個Action,代碼如下:
1. < package name="demo" extends="struts-default"> 2. < action name="validate" class="action.ValidateAction"> 3. < result name="success">/error/validate.jsp< /result> 4. < result name="input">/error/validate.jsp< /result> 5. < /action>
6. < /package>
假設應用程序的上下文路徑為demo,則可通過如下的URL來測試程序:
http://localhost:8080/demo/validate.jsp
我們還可以使用ValidationAware接口的其他方法(由ValidationAwareSupport類實現)獲得或設置字段錯誤信息、動作錯誤信息以及動作消息。如hasActionErrors方法判斷是否存在動作層的錯誤,getFieldErrors獲得字段錯誤信息(一個Map 對象)。下面是ValidationAware接口提供的所有的方法:
1. package com.opensymphony.xwork2;
2. 3. import java.util.Collection; 4. import java.util.Map; 5.
6. public interface ValidationAware 7. { 8. void setActionErrors(Collection errorMessages); 9. Collection getActionErrors();
10. 11. void setActionMessages(Collection messages); 12. Collection getActionMessages(); 13. void setFieldErrors(Map errorMap); 14. Map getFieldErrors(); 15. void addActionError(String anErrorMessage); 16. void addActionMessage(String aMessage); 17. void addFieldError(String fieldName, String errorMessage); 18. boolean hasActionErrors(); 19. boolean hasActionMessages(); 20. boolean hasErrors(); 21. boolean hasFieldErrors(); 22. }
=========================== 實現com.opensymphony.xwork2.TextProvider接口 --需要導入xwork.jar 該接口主要提供讀取消息資源文件,獲取消息文本的功能。該接口的getText()用來獲取消息文本的內容。
一般繼承ActionSupport助手類,其實現了TextProvider接口並提供了默認實現 所以在,action/攔截器中(只要其繼承了actionSupport)要獲取資料文件(properties文件),可以直接放入以下代碼:
import com.opensymphony.xwork2.LocaleProvider; import com.opensymphony.xwork2.TextProvider; import com.opensymphony.xwork2.TextProviderFactory;
public class Log攔截器 extends AbstractInterceptor implements LocaleProvider { //初始化攔截器時,獲取資源文件 public void init() { protected TextProvider operateCodeProvider = new TextProviderFactory().createInstance( ResourceBundle.getBundle( "LogDefinitions資源文件名", getLocale()), this); }
/** * 獲取語言 */ public Locale getLocale() { ActionContext ctx = ActionContext.getContext(); if (ctx != null) { return ctx.getLocale(); } else { sysLogger.debug("Action context not initialized"); return null; } }
調用方法: this.operateCodeProvider.getText("hwj") -->便可獲取hwj的值. }
看看ActionSupport 是怎樣實現TextProvider的: public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class); private final transient TextProvider textProvider = new TextProviderFactory().createInstance (getClass(), this); //返回國際化信息的方法 public String getText(String aTextName) { return textProvider.getText(aTextName); } 文章出處:http://hi.baidu.com/%B1%F5%BA%A3%BB%C4%C1%D6/blog/item/35fa343ffe619bfe3c6d976e.html
Action接口有: public static final java.lang.String SUCCESS = "success"; public static final java.lang.String NONE = "none"; public static final java.lang.String ERROR = "error"; public static final java.lang.String INPUT = "input"; public static final java.lang.String LOGIN = "login";
public abstract java.lang.String execute() throws java.lang.Exception;
而Actionsupport這個工具類在實現了Action接口的基礎上還定義了一個validate()方法,重寫該方法,它會在execute()方法之前執行,如校驗失敗,會轉入input處,必須在配置該Action時配置input屬性。
另外,Actionsupport還提供了一個getText(String key)方法還實現國際化,該方法從資源文件上獲取國際化信息.
這樣在自定義標簽時可以定義一個變量為new actionsupport對象實現國際化。
ActionSupport類的作用 struts2不要求我們自己設計的action類繼承任何的struts基類或struts接口,但是我們為了方便實現我們自己的action,大多數情況下都會繼承com.opensymphony.xwork2.ActionSupport類,並重寫此類里的public String execute() throws Exception方法。因為此類中實現了很多的實用借口,提供了很多默認方法,這些默認方法包括國際化信息的方法、默認的處理用戶請求的方法等,這樣可以大大的簡化Acion的開發。 Struts2中通常直接使用Action來封裝HTTP請求參數,因此,Action類里還應該包含與請求參數對應的屬性,並且為屬性提供對應的getter和setter方法。
========================== <s:property> 關於struts2標簽取值的備忘錄
取值要通過<s:property value="" />或在任意的<s:/>標簽內使用%{};
當Action的valueStack中有該屬性的值時,只需直接使用該屬性的名字即可;
當Action的valueStack中沒有該屬性的值時,比如在session,application范圍中的屬性值時,需要加#或者#attr.;
例子: 假設某Action中有person成員變量,在application中存在company屬性 那么我們可以通過以下方法取值: <s:property value="person.name" /> <s:property value="#person.name" /> <s:property value="company.name" /> //無法取到,因為company不在action的valueStack中 <s:property value="#company.name" />
<s:textfield name="person.name" value="person.name" /> //錯誤,value會直接顯示person.name字樣 <s:textfield name="person.name" value="%{person.name}" /> <s:textfield name="person.company.name" value="%{#company.name}" /> <s:textfield name="person.company.name" value="%{#attr.company.name}" />
===================== 一次Action調用都會創建一個ActionContext 調用:ActionContext context = ActionContext.getContext() ValueStack由OGNL框架實現 可以把它簡單的看作一個集合
Stack Object:放入stack中的對象,一般是action Stack Context(map):stack上下文,它包含一些列對象,包括request/session/attr/application map等。
EL:存取對象的任意屬性,調用對象的方法,遍歷整個對象結…
=========== WebWork2.2筆記(二)ActionSupport及其他基礎知識 絕大多數情況下,WebWork不是直接實現com.opensymphony.xwork.Action接口,而是擴展 com.opensymphony.xwork.ActionSupport類。ActionSupport實現了除Action以外的其他幾個接口,主要的幾個接口是: com.opensymphony.xwork.Validateable com.opensymphony.xwork.Validateaware com.opensymphony.xwork.TextProvider com.opensymphony.xwork.LocaleProvider 這些接口主要是提供給WebWork的攔截器使用的,接口配合攔截器可以實現AOP功能。比如Validateable接口和Validateaware 接口配合DefailtWorkflowInterceptor就可以實現對用戶輸入進行檢驗的功能,當用戶調用Action時,首先執行 Validateable接口定義的validate()方法,如果在這個方法中用戶使用接口Validateaware中的方法設置了錯誤信息,則 DefaultWorkflowInterceptor會自動終止Action的執行,並產生一個INPUT的result,只有沒有任何錯誤信息才會執行Action的剩余部分。
前面我們定義的xwork.xml配置文件中包含了一句:<include file="webwork-default.xml">,這個webwork-default.xml包含在webwork的jar包中。 webwork-default.xml預建了很多常用的result-type、interceptor和interceptor-stack。其中 interceptor和interceptor-stack用於定義webwork將要使用那些攔截器。interceptor定義一個攔截器,而 interceptor定義一組攔截器。如果一個Action使用一組攔截器,則這些攔截器將以其定義的順序執行,可見,interceptor- stack中攔截器的順序時很重要的。
在webwork-default.xml中有如下定義: <interceptor class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor" name="workflow"> ...... 而名為validationWorkflowStack和completeStack這兩個預建的interceptor-stack則包含了workflow這個interceptor。
下面做一個檢查用戶輸入的練習,如果用戶沒有輸入內容,則讓用戶重新輸入,並且提示錯誤信息。
web.xml 與上次的相同。
xwork.xml </interceptor></include> xml 代碼
1. 2. "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
3. 4. <xwork> 5. <include file="webwork-default.xml" />
6. 7. <package name="default" extends="webwork-default"> 8.
9. <default-interceptor-ref name="validationWorkflowStack"/> 10. <action name="alidateInput" class="example.ValidateInputAction"> 11. <result name="success">success.jspresult> 12. <result name="input">input.jspresult> 13. action> 14. 15. package> 16. xwork>
input.jsp xml 代碼
1. <%@taglib prefix="ww" uri="/webwork"%> 2. <html> 3. <head><title>Input Somethingtitle>head> 4. <body>
5. 6. <ww:form action="alidateInput.action"> 7. <ww:textfield label="Input something:" name="something">ww:textfield>
8. <ww:submit>ww:submit> 9. ww:form> 10. 11. body> 12. html>
success.jsp xml 代碼
1. <%@taglib prefix="ww" uri="/webwork"%> 2. <html> 3. <head><title>Success!title>head> 4. <body> 5. <ww:property value="something"/> 6. body> 7. html>
============================== Action的實例,總是放到value stack中。因為Action放在stack中,而stack是root(根對象),所以對Action中的屬性的訪問就可以省略#標記。但是,要訪問 ActionContext中其它對象的屬性,就必須要帶上#標記,以便讓OGNL知道,不是從根對象,而是從其它對象中去尋找。
Struts2中OGNL,valueStack,stackContext的學習 學習Struts2,一直不明白表單中的值是怎么傳給Action的,上網查了些資料,基本了解了!下面基本是從幾個人的BOLG轉載過來,以后記不清了再來看~
[color=red]先看看我做的實驗jsp頁面 Java代碼
<s:form action="hello/converter.action" method="post"> <s:textfield name="point" label="點"></s:textfield> <s:textfield name="point2" label="2"></s:textfield> <s:textfield name="point3" label="3"></s:textfield> <s:textfield name="age" label="年齡"></s:textfield> <s:textfield name="date" label="日期"></s:textfield> <s:submit name="提交"></s:submit> </s:form>
結果圖(是通過<s:debug></s:debug>得到的) value stack:
[點擊查看原始大小圖片]
Stack context:
通過圖中我們可以看到 valuestack中包括我傳遞的值(point,point2,point3,age,date) stack context中包括了 request application OgnlValueStack(root) session parameters 等屬性
值棧(ValueStack) Struts2將OGNL上下文設置為Struts2中的ActionContext(內部使用的仍然是OgnlContext),並將值棧設為OGNL的根對象。 我們知道,OGNL上下文中的根對象可以直接訪問,不需要使用任何特殊的“標記”,而引用上下文中的其他對象則需要使用“#”來標記。由於值棧是上下文中的根對象,因此可以直接訪問。那么對於值棧中的對象該如何訪問呢?Struts2提供了一個特殊的OGNLPropertyAccessor,它可以自動查找棧內的所有對象(從棧頂到棧底),直接找到一個具有你所查找的屬性的對象。也就是說,對於值棧中的任何對象都可以直接訪問,而不需要使用 “#”。 假設值棧中有兩個對象:student和employee,兩個對象都有name屬性,student有學號屬性number,而 employee有薪水屬性salary。employee先入棧,student后入棧,位於棧頂,那么對於表達式name,訪問的就是student 的name屬性,因為student對象位於棧頂;表達式salary,訪問的就是employee的salary屬性。正如你所見,訪問值棧中的對象屬性或方法,無須指明對象,也不用“#”,就好像值棧中的對象都是OGNL上下文中的根對象一樣。這就是Struts2在OGNL基礎上做出的改進。
值棧中的Action實例 Struts2框架總是把Action實例放在棧頂。因為Action在值棧中,而值棧又是OGNL中的根,所以引用Action的屬性可以省略“#”標記,這也是為什么我們在結果頁面中可以直接訪問Action的屬性的原因。
Struts2中的命名對象 Struts2還提供了一些命名對象,這些對象沒有保存在值棧中,而是保存在ActionContext中,因此訪問這些對象需要使用“#”標記。這些命名對象都是Map類型。
parameters 用於訪問請求參數。如:#parameters['id']或#parameters.id,相當於調用了HttpServletRequest對象的getParameter()方法。 注意,parameters本質上是一個使用HttpServletRequest對象中的請求參數構造的Map對象,一量對象被創建(在調用Action實例之前就已經創建好了),它和HttpServletRequest對象就沒有了任何關系。
request 用於訪問請求屬性。如:#request['user']或#request.user,相當於調用了HttpServletRequest對象的getAttribute()方法。
session 用於訪問session屬性。如:#session['user']或#session.user,相當於調用了HttpSession對象的getAttribute()方法。
application 用於訪問application屬性。如:#application['user']或#application.user,相當於調用了ServletContext的getAttribute()方法。
attr 如果PageContext可用,則訪問PageContext,否則依次搜索request、session和application對象。
以下是轉過來的:先分清楚下ActionContext 、ValueStack 、Stack Context三者
ActionContext 一次Action調用都會創建一個ActionContext 調用:ActionContext context = ActionContext.getContext()
ValueStack 由OGNL框架實現 可以把它簡單的看作一個棧(List) 。
Stack Object:放入stack中的對象,一般是action。 Stack Context(map):stack上下文,它包含一系列對象,包括request/session/attr/application map等。 EL:存取對象的任意屬性,調用對象的方法,遍歷整個對象結…
ActionContext是Action上下文,可以得到request session application ValueStack是值棧 存放表單中的值 Stack Context 棧上下文 也是用來存值的
struts2對OGNL上下文的概念又做了進一步擴充,在struts2中,OGNL上下文通常如下所示:
|--request
|
|--application
|
context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|
|--session
|
|--attr
|
|--parameters
在Struts2中,采用標准命名的上下文(Context)來處理OGNL表達式。處理OGNL的頂級對象是一個Map(也叫context map),而OGNL在這個context中就是一個頂級對象(root)。在用法上,頂級對象的屬性訪問,是不需要任何標記前綴的。而其它非頂級的對象訪問,需要使用#標記。 Struts2框架把OGNL Context設置為我們的ActionContext。並且ValueStack作為OGNL的根對象。除value stack之外,Struts2框架還把代表application、session、request這些對象的Map對象也放到 ActionContext中去。(這也就是Struts2建議在Action類中不要直接訪問Servlet API的原因,他可以通過ActionContext對象來部分代替這些(Servlet API)功能,以方便對Action類進行測試!) Action的實例,總是放到value stack中。因為Action放在stack中,而stack是root(根對象),所以對Action中的屬性的訪問就可以省略#標記。但是,要訪問 ActionContext中其它對象的屬性,就必須要帶上#標記,以便讓OGNL知道,不是從根對象,而是從其它對象中去尋找。 那么訪問Action中的屬性的代碼就可以這樣寫
<s:property value="postalCode"/> 其它ActionContext中的非根對象屬性的訪問要像下面這樣寫: <s:property value="#session.mySessionPropKey"/> or <s:property value="#session['mySessionPropKey']"/> or <s:property value="#request['myRequestPropKey']"/> 對Collection的處理,內容就很簡單。 <s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" /> 這是處理List。這個代碼在頁面上建立一個下拉選項,內容是list中的內容,默認值是name2. 處理map
<s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />
需要注意的是,判斷一個值是否在collection中。我們要使用in或者not in來處理。 <s:if test="'foo' in {'foo','bar'}"> muhahaha </s:if> <s:else> boo </s:else> 另外,可以使用通配符來選擇collection對象的子集。 ?——所有匹配選擇邏輯的元素 ^——只提取符合選擇邏輯的第一個元素 $——只提取符合選擇邏輯的最后一個元素 person.relatives.{? #this.gender == 'male'}
`````````````````````````````````````````````````````````````````````````````````
以下為補充摘錄的一些問題:
提問:在Struts2中,如何使用自身的Tag讀取Action中的變量?
Struts2自身的Tag會根據value中的OGNL表達式,在ValueStack中尋找相應的對象。因為action在 ValueStack的頂部,所以默認情況下,Struts2的Tag中的OGNL表達式將查找action中的變量。請注意,value中的內容直接是 OGNL表達式,無需任何el的標簽包裝。
例如:<s:property value="user.name" />
提問:在Struts2中,如何使用自身的Tag讀取HttpServletRequest,HttpSession中的變量?
在上面的知識中,我們知道,Struts2中OGNL的上下文環境中,包含request,session,application等 servlet對象的Map封裝。既然這些對象都在OGNL的上下文中,那么根據OGNL的基本知識,我們可以通過在表達式前面加上#符號來對這些變量的值進行訪問。
例如:<s:property value="%{#application.myApplicationAttribute}" /> <s:property value="%{#session.mySessionAttribute}" /> <s:property value="%{#request.myRequestAttribute}" /> <s:property value="%{#parameters.myParameter}" />
提問:在Struts2中,如何使用JSTL來讀取Action中的變量?
這是一個歷史悠久的問題。因為事實上,很多朋友(包括我在內)是不使用Struts2自身的標簽庫,而是使用JSTL的,可能因為JSTL標簽庫比較少,簡單易用的原因吧。
我們知道,JSTL默認是從page,request,session,application這四個Scope逐次查找相應的EL表達式所對應的對象的值。那么如果要使用JSTL來讀取Action中的變量,就需要把Action中的變量,放到request域中才行。所以,早在 Webwork2.1.X的年代,我們會編寫一個攔截器來做這個事情的。大致的原理是:在Action執行完返回之前,依次讀取Action中的所有的變量,並依次調用request.setAttribute()來進行設置。具體的整合方式,請參考以下這篇文檔:http://wiki.opensymphony.com/display/WW /Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1
不過隨着時代的發展,上面的這種方式,已經不再被推薦使用了。(雖然如此,我們依然可以學習它的一個解決問題的思路)目前來說,自從 Webwork2.2以后,包括Struts2,都使用另外一種整合方式:對HttpServletRequest進行裝飾。讓我們來看一下源碼: Java代碼
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
/** * The constructor * @param req The request */ public StrutsRequestWrapper(HttpServletRequest req) { super(req); }
/**
* Gets the object, looking in the value stack if not found * * @param s The attribute key */ public Object getAttribute(String s) {
if (s != null && s.startsWith("javax.servlet")) { // don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(s); }
ActionContext ctx = ActionContext.getContext(); Object attribute = super.getAttribute(s);
boolean alreadyIn = false; Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute"); if (b != null) { alreadyIn = b.booleanValue(); }
// note: we don't let # come through or else a request for // #attr.foo or #request.foo could cause an endless loop if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {
try { // If not found, then try the ValueStack
ctx.put("__requestWrapper.getAttribute", Boolean.TRUE); ValueStack stack = ctx.getValueStack(); if (stack != null) { attribute = stack.findValue(s); } } finally {
ctx.put("__requestWrapper.getAttribute", Boolean.FALSE); } }
return attribute; } }
看到了嘛?這個類會在Struts2初始化的時候,替換HttpServletRequest,運行於整個Struts2的運行過程中,當我們試圖調用 request.getAttribute()的時候,就會執行上面的這個方法。(這是一個典型的裝飾器模式)在執行上面的方法時,會首先調用 HttpServletRequest中原本的request.getAttribute(),如果沒有找到,它會繼續到ValueStack中去查找,而action在ValueStack中,所以action中的變量通過OGNL表達式,就能找到對應的值了。
在這里,在el表達式廣泛使用的今天,JSTL1.1以后,也支持直接使用el表達式。注意與直接使用struts2的tag的區別,這里需要使用el的表示符號:${}
例如:${user.name}, <c:out value="${department.name}" />
提問:在Struts2中,如何使用Freemarker等模板來讀取Action中的變量以及HttpServletRequest和HttpSession中的變量?
Freemarker等模板在Struts2中有對應的Result,而在這些Result中,Freemarker等模板會根據 ValueStack和ActionContext中的內容,構造這些模板可識別的Model,從而使得模板可以以他們各自的語法對ValueStack 和ActionContext中的內容進行讀取。
有關Freemarker對於變量的讀取,可以參考Struts2的官方文檔,非常詳細:http://struts.apache.org/2.0.14/docs/freemarker.html
設值計算
Struts2中使用OGNL進行設值計算,就是指View層傳遞數據到Control層,並且能夠設置到相應的Java對象中。這個過程從邏輯上說需要分成兩步來完成:
1. 對於每個請求,都建立一個與相應Action對應的ActionContext作為OGNL的上下文環境和ValueStack,並且把Action壓入ValueStack
2. 在請求進入Action代碼前,通過某種通用的機制,搜集頁面上傳遞過來的參數,並調用OGNL相關的代碼,對Action進行設值。 上面的第一個步驟,在處理URL請求時完成,而第二個步驟由struts2內置的攔截器完成。
================================ Struts2教程:使用validate方法驗證數據 在Struts2中最簡單的驗證數據的方法是使用validate。我們從ActionSupport類的源代碼中可以看到,ActionSupport類實現了一個Validateable接口。這個接口只有一個validate方法。如果Action類實現了這個接口,Struts2在調用execute方法之前首先會調用這個方法,我們可以在validate方法中驗證,如果發生錯誤,可以根據錯誤的level選擇字段級錯誤,還是動作級錯誤。並且可使用addFieldError或addActionError加入相應的錯誤信息,如果存在Action或 Field錯誤,Struts2會返回“input”(這個並不用開發人員寫,由Struts2自動返回),如果返回了“input”,Struts2就不會再調用execute方法了。如果不存在錯誤信息,Struts2在最后會調用execute方法。
這兩個add方法和ActionErrors類中的add方法類似,只是add方法的錯誤信息需要一個ActionMessage對象,比較麻煩。除了加入錯誤信息外,還可以使用addActionMessage方法加入成功提交后的信息。當提交成功后,可以顯示這些信息。
以上三個add方法都在ValidationAware接口中定義,並且在ActionSupport類中有一個默認的實現。其實,在 ActionSupport類中的實現實際上是調用了ValidationAwareSupport中的相應的方法,也就是這三個add方法是在 ValidationAwareSupport類中實現的,代碼如下:
1. private final ValidationAwareSupport validationAware = new ValidationAwareSupport(); 2. 3. public void addActionError(String anErrorMessage) 4. { validationAware.addActionError(anErrorMessage); 5. } 6. public void addActionMessage(String aMessage) 7. { 8. validationAware.addActionMessage(aMessage); 9. } 10. public void addFieldError(String fieldName, String errorMessage) 11. { 12. validationAware.addFieldError(fieldName, errorMessage); 13. }
下面我們來實現一個簡單的驗證程序,來體驗一個validate方法的使用。
先來在Web根目錄建立一個主頁面(validate.jsp),代碼如下:
1. < %@ page language="java" import="java.util.*" pageEncoding="GBK"%> 2. < %@ taglib prefix="s" uri="/struts-tags" %> 3. < html> 4. < head> 5. < title>驗證數據< /title> 6. < /head>
7. 8. < body> 9. < s:actionerror/> 10. < s:actionmessage/> 11. < s:form action="validate.action" theme="simple"> 12. 輸入內容:< s:textfield name="msg"/> 13. < s:fielderror key="msg.hello" /> 14. < br/> 15. < s:submit/> 16. < /s:form> 17. < /body> 18. < /html>
在上面的代碼中,使用了Struts2的tag:< s:actionerror>、< s:fielderror>和< s:actionmessage>,分別用來顯示動作錯誤信息,字段錯誤信息,和動作信息。如果信息為空,則不顯示。
現在我們來實現一個動作類,代碼如下:
1. package action; 2. 3. import javax.servlet.http.*; 4. 5. import com.opensymphony.xwork2.ActionSupport; 6. import org.apache.struts2.interceptor.*; 7. 8. public class ValidateAction extends ActionSupport 9. { 10. private String msg; 11. public String execute() 12. { 13. System.out.println(SUCCESS); 14. return SUCCESS;
15. } 16. public void validate() 17. { 18. if(!msg.equalsIgnoreCase("hello")) 19. { 20. System.out.println(INPUT);
21. this.addFieldError("msg.hello", "必須輸入hello!"); 22. this.addActionError("處理動作失敗!"); 23. } 24. else 25. { 26. this.addActionMessage("提交成功"); 27. } 28. } 29. public String getMsg() 30. { 31. return msg; 32. } 33. public void setMsg(String msg) 34. { 35. this.msg = msg; 36. } 37. }
大家從上面的代碼可以看出,Field錯誤需要一個key(一般用來表示是哪一個屬性出的錯誤),而Action錯誤和Action消息只要提供一個信息字符串就可以了。
最后來配置一下這個Action,代碼如下:
1. < package name="demo" extends="struts-default"> 2. < action name="validate" class="action.ValidateAction"> 3. < result name="success">/error/validate.jsp< /result> 4. < result name="input">/error/validate.jsp< /result> 5. < /action>
6. < /package>
假設應用程序的上下文路徑為demo,則可通過如下的URL來測試程序:
http://localhost:8080/demo/validate.jsp
我們還可以使用ValidationAware接口的其他方法(由ValidationAwareSupport類實現)獲得或設置字段錯誤信息、動作錯誤信息以及動作消息。如hasActionErrors方法判斷是否存在動作層的錯誤,getFieldErrors獲得字段錯誤信息(一個Map 對象)。下面是ValidationAware接口提供的所有的方法:
1. package com.opensymphony.xwork2;
2. 3. import java.util.Collection; 4. import java.util.Map; 5.
6. public interface ValidationAware 7. { 8. void setActionErrors(Collection errorMessages); 9. Collection getActionErrors();
10. 11. void setActionMessages(Collection messages); 12. Collection getActionMessages(); 13. void setFieldErrors(Map errorMap); 14. Map getFieldErrors(); 15. void addActionError(String anErrorMessage); 16. void addActionMessage(String aMessage); 17. void addFieldError(String fieldName, String errorMessage); 18. boolean hasActionErrors(); 19. boolean hasActionMessages(); 20. boolean hasErrors(); 21. boolean hasFieldErrors(); 22. }
=========================== 實現com.opensymphony.xwork2.TextProvider接口 --需要導入xwork.jar 該接口主要提供讀取消息資源文件,獲取消息文本的功能。該接口的getText()用來獲取消息文本的內容。
一般繼承ActionSupport助手類,其實現了TextProvider接口並提供了默認實現 所以在,action/攔截器中(只要其繼承了actionSupport)要獲取資料文件(properties文件),可以直接放入以下代碼:
import com.opensymphony.xwork2.LocaleProvider; import com.opensymphony.xwork2.TextProvider; import com.opensymphony.xwork2.TextProviderFactory;
public class Log攔截器 extends AbstractInterceptor implements LocaleProvider { //初始化攔截器時,獲取資源文件 public void init() { protected TextProvider operateCodeProvider = new TextProviderFactory().createInstance( ResourceBundle.getBundle( "LogDefinitions資源文件名", getLocale()), this); }
/** * 獲取語言 */ public Locale getLocale() { ActionContext ctx = ActionContext.getContext(); if (ctx != null) { return ctx.getLocale(); } else { sysLogger.debug("Action context not initialized"); return null; } }
調用方法: this.operateCodeProvider.getText("hwj") -->便可獲取hwj的值. }
看看ActionSupport 是怎樣實現TextProvider的: public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class); private final transient TextProvider textProvider = new TextProviderFactory().createInstance (getClass(), this); //返回國際化信息的方法 public String getText(String aTextName) { return textProvider.getText(aTextName); } 文章出處:http://hi.baidu.com/%B1%F5%BA%A3%BB%C4%C1%D6/blog/item/35fa343ffe619bfe3c6d976e.html