struts中的action和Action類以及struts2中如何在Action類中獲得servlet api的域物件
1.Struts2的學習中大家都會遇到action和與action對應的Action類,那麼什麼是action什麼是action對應的Action類呢?
例如struts.xml的配置檔案如下:
action:代表一個struts2的請求,對應的是Action類的一個方法。
Action類:表示處理多個action請求的普通javabean。也就是配置檔案中<action>節點中對應的class配置的類。
在Action定義中有如下注意點:
①屬性的名字必須遵守JavaBean的屬性命名規則。
②必須有一個不帶引數的構造器,這樣才能通過反射機制將請求的引數對應設定到Action的物件中去。
③在Action類中至少有一個處理action請求的方法。
④同一個Action類中可以有多個處理action請求的方法。
⑤struts2會為每一個Http請求建立一個Action例項,所以Action物件不是單例,是執行緒安全的。
2.既然Action類是處理action請求的那麼難免在處理請求中需要呼叫Servlet API中的物件。那麼我們如何在普通javabean中呼叫Servlet API 的物件呢?struts2框架提供了兩種途徑。
①和Servlet API解耦的方式獲得Servlet API的物件,但是隻能完成少部分的功能(例如獲得請求引數,設定域物件的鍵值對和使域物件失效等)所以struts2框架為了和Servlet API解耦,方便Action單元測試,Struts2對HttpServletRequest,HttpSession,ServletContext做了封裝,構造了三個與之對應的Map<String,Object>物件來儲存和儲存資料。通過解耦的方式獲得Servlet API物件有兩種途徑。
1)通過ActionContext來獲得Servlet API的物件。ActionContext稱為Action上下文物件,通過這個物件可以獲得Action類所需要的所有物件,例如parameters,request,session,application等所對應的map物件。
java例子如下圖:
2)通過實現xxxAware介面實現獲得Servlet API的一系列物件java程式碼如下:package com.yd.action; import java.util.Map; import org.apache.struts2.dispatcher.SessionMap; import com.opensymphony.xwork2.ActionContext; import com.sun.xml.internal.bind.v2.runtime.Name; public class TestActionContextAction { public String getServeltObject(){ //獲得ActionContext物件 該物件可以獲得Action所需要的Servlet的原生域物件 ActionContext actionContext=ActionContext.getContext(); //1.獲得HttpServletRequest對應的map 對其做操作並且進行儲存 這個是獲得是attribute中的值 Map<String, Object> requestMap=(Map<String, Object>)actionContext.get("request"); String name=(String) requestMap.get("name"); System.out.println("name="+name); requestMap.put("cat", "My name is Tom"); //2.獲得HttpSession對應的Map 對該物件做操作 自動進行更行原生域物件 Map<String, Object> sessionMap=actionContext.getSession(); String price=(String) sessionMap.get("price"); SessionMap<String, Object> sessionMap1=(SessionMap<String, Object>)sessionMap; //SessionMap其實就是session對應的map 呼叫其invalidate方法 即可以使session失效 sessionMap1.invalidate(); System.out.println("price="+price); sessionMap.put("dog", "I am a dog"); //3.獲得ServletContext Map<String, Object> applicationMap=actionContext.getApplication(); Integer age=(Integer) applicationMap.get("age"); System.out.println("age="+age); applicationMap.put("person", "I have a lot of money"); //4.獲得paramters Map<String, Object> parameterMap=actionContext.getParameters(); String[] name1=(String[]) parameterMap.get("name"); //System.out.println("name="+name1[0]); parameterMap.put("key", "value"); return "success"; } }
package com.yd.action;
import java.util.Map;
import org.apache.struts2.interceptor.ApplicationAware;
public class TestRealizeAware implements ApplicationAware{
private Map<String, Object> application;
public String getServletObject(){
Integer age=(Integer)application.get("age");
System.out.println("age="+age);
application.put("key", "value");
return "success";
}
//當建立該Action物件時 struts機制自動呼叫該方法 實現將值注入
@Override
public void setApplication(Map<String, Object> application) {
this.application=application;
}
}
②通過和Servlet耦合的方式來獲得Servlet API的物件,通過耦合的方式獲得的物件則是原生的物件。當然通過Servlet耦合的方式獲得Servlet API物件同樣也有兩種途徑。
1)通過ServletActionContext物件獲得Servlet API原生物件。
java案列如下:
package com.yd.action;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
//處理請求的Action類
public class TestServletActionContext {
/*
* 通過耦合的方式獲得Servlet API中的物件
* 1.這種方式是通過ServletActionContext獲得
*
* */
public String getObject(){
HttpServletRequest request=ServletActionContext.getRequest();
//獲得session是通過request獲得的
HttpSession session=request.getSession();
//獲得上下文物件
ServletContext context=ServletActionContext.getServletContext();
System.out.println("request="+request+" getObject");
return "success";
}
}
2)通過實現ServletxxxAware介面來實現獲得原生的Servelt API物件。
java程式碼如下:
package com.yd.action;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
public class TestServletAware implements ServletRequestAware,ServletResponseAware,ServletContextAware{
/*
* 通過實現ServletxxxAware介面來實現 物件的注入
* */
@Override
public void setServletContext(ServletContext context) {
System.out.println(context);
}
@Override
public void setServletResponse(HttpServletResponse response) {
System.out.println(response);
}
@Override
public void setServletRequest(HttpServletRequest request) {
System.out.println(request);
}
public String getObject(){
return "success";
}
}
那麼通過Servle解耦和耦合Servlet方式獲得Servlet API的物件有什麼區別呢?
其實很容易理解,獲得原生的Servlet API物件就需要在Servlet容器中執行,那麼Action的單元測試就需要有Servlet容器的環境下才能進行測試,如果獲得的是原生物件的Map<String,Object>就不要在Servlet容器的環境下進行測試。這就是通過耦合和解耦的方式獲得Servelt API物件的區別。
那麼通過ActionContext和ServeltActionContext獲得物件和實現xxxAware介面和ServeltxxxAware介面獲得物件的區別是什麼呢?
其實最大的區別就是實現介面的方式獲得Servlet API物件更容易,當Struts2框架建立Action物件的時候就直接幫你把這寫物件建立好並通過方法注入到物件中去,而通過ActionContext和ServletActionContext的方式獲得需要自己手動來獲取物件。根據以上的例項可以很容易看的出來的。
以上還有幾個注意點是需要注意的:
①通過ActionContext物件獲得HttpServletRequest物件只能通過get("request")方法來獲得,這裡可以通過檢視ActionContext的API來看到。
②通過SessionMap物件的invalidate()方法可以使session失效,那麼我們通過解耦的方式獲得sessionMap通過強制轉換的方法即可實現session的實現,寫法如下((SessionMap)sessionMap).invalidate()。
3.那麼接下來說說配置檔案中result節點的屬性,以及詳細的配置檔案寫法
①result是action節點的子節點
②result代表action請求處理方法執行後可能要去的目的地。
③一個action節點可以有多個result子節點,也代表了action請求處理方法返回值的不同,去往的目的地不同。
④result節點的name屬性值代表了action請求對應的方法的一個返回值。
result節點還有一個非常重要的屬性就是type屬性,這個屬性是設定響應到目的地的型別,其值如下,這個在struts2框架jar包中的struts-default.xml的struts-default的包中可以看的到,如圖:
這裡主要總結其中的四個:
①redirect:表示重定向到一個web資源。response物件的重定向方法效果一致,可以通過此方法重定向到一個action請求處理方法。
②dispatcher:轉發,和request物件的轉發效果一致,但是通過此方法是不能實現轉發到一個action的。
③redirectAction:重定向到一個action。
④chain:轉發到一個action。
配置檔案的寫法如下:
重定向和轉發到一個action都需要配置兩個引數一個是actionName和namespace這樣才能準確的定位到action。