十三、Struts2的處理流程
request—>StrutsPrepareAndExecuteFilteràInterceptor(Struts2內置的一些攔截器或用戶自定義攔截器)àAction(用戶編寫的Action,類似Struts1中的Action)àResult(類似Struts1中的forward)àJsp/Htmlàresponse
StrutsPrepareAndExccuterFilter是Struts2框架的核心控制器,它負責攔截由<url-pattern>/*</url-pattern>指定的所有用戶請求,當用戶請求到達時,該Filter會過濾用戶的請求。默認情況下,如果用戶請求的路徑不帶后綴或者后綴以.action結尾,這時請求將被轉入Struts2框架處理,否則Struts2框架將過濾該請求的處理。當請求轉入Struts2框架處理時會經過一系列的攔截器,然后再轉到Action。與Struts1不同,Struts2對用戶每一次請求都會創建一個Action,所以Struts2的Action是線程安全的
十四、Struts2指定多個配置文件
將配置文件以模塊進行劃分,然后通過include導入
<?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>
<include file="struts-user.xml"></include>
<include file="struts-trade.xml"></include>
</struts>
十五、Struts2動態方法調用(在Struts2.1版本文檔中已經不推薦使用了)
如果在action中存在多個方法時,我們可以使用!+方法方法名調用指定的方法,如下:
public class HelloWorldAction{
private String message;
public String getMessage(){
return message;
}
public String execute() throws Exception{
this.message = “我是execute方法”
return “success”;
}
public String other() throw Exception{
this.message = “我是other方法”;
}
}
假設訪問上面的action的URL路徑為:/struts2/test/helloworld.action
要訪問action的other方法,我們可以這樣調用:
/struts2/test/helloworld!other.action
如果不想使用動態方法調用,我們可以通過常量
struts.enable.DynamicMethodInvocation關閉動態方法調用.
<constant name=”struts.enable.DynamicMethodInvocation” value=”false”/>
Struts2使用通配符定義action(官方推薦)
<package name=”employee”
namespace=”/control/employee” extends=”struts-default”>
<action name=”list_*”
class=”cn.itcast.action.HellWorldAction method=”{1}”>
<result name=”success”>
/WEB-INF/page/message.jsp
</result>
</action>
</package>
注:
a). *通配符可以添加多個如: list_*_*_*
b). method=”{1}” 表示取第一個*
c). 通配符可以放置多個地方如 class、result中
十六、Struts2 請求參數的接受
以下兩種方法,當參數比較多的時候,用第一種方法,將會發現action中有很多setter、getter方法,這樣不利于閱讀action,所以建議使用第二種。
a). 采用基本類型接收請求參數(get/post)
在Action類中定義與請求參數同名的屬性,Struts2便能接受請求參數并賦值給同名屬性:
如:請求路徑,http://localhost:8080/test/view.action?id=78
public class ProductAction{
private Integer id;
//struts2通過反射技術調用與請求參數同名的屬性的setter方法來獲取請求參數值
public void setId(Integer id) {
this.id = id;
}
public Integer getId{
return id;
}
}
b). 采用符合類型接收請求參數
如:請求路徑,http://localhost:8080/test/view.action?product.id=78
public class ProductAction{
private Product product;
public void setProduct(Product product) {
this.product = product;
}
public Product getProduct() {
return product;
}
}
Struts2首先通過反射技術調用Product的默認構造器創建product對象然后在通過反射技術調用product中與請求參數同名的屬性的setter方法來獲取請求參數
十七、Struts2有兩種類型轉換器
局部類型轉換器/全部類型轉換器
a). 自定義轉換類型
package cn.itcast.type.converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
publicclass DateTypeConverter extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
try {
if(toType == Date.class){//當字符串向Date類型轉換時
String[] params = (String[]) value;// request.getParameterValues()
return dateFormat.parse(params[0]);
}elseif(toType == String.class){//當Date轉換成字符串時
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {}
returnnull;
}
}
完成具體的雙向轉化代碼后,需要將上面的類型注冊為局部類型轉換器:
在Action類所有的包下放置ActionClassName-conversion.properties文件,ActionClassName是Action的類名,后面的-conversion.properties是固定寫法,對于本例而言,文件的名稱應為HelloWroldAction-conversion.properties。
properties文件中的內容為:
birthday=cn.itcast.type.converter.DateTypeConverter
b).自定義全局類型轉換器
將上面的局部類型轉換器注冊為全局類型轉換器:
在WEB-INF/classes下放置xwork-conversion.properties文件。在properties文件中的內容為:
待轉換的類型=類型轉換器的全類名
java.util.Date=cn.itcast.conversion.DateConverter
十八、訪問或添加request/session/application屬性
import java.util.Arrays;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
public class HelloWorldAction {
public String execute(){
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "應用范圍");//往ServletContext里放入app
ctx.getSession().put("ses", "session范圍");//往session里放入ses
ctx.put("req", "request范圍");//往request里放入req
ctx.put("names", Arrays.asList("老張", "老黎", "老方"));
return "message";
}
public String rsa() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
ServletContext servletContext = ServletActionContext.getServletContext();
request.setAttribute("req", "請求范圍屬性");
request.getSession().setAttribute("ses", "會話范圍屬性");
servletContext.setAttribute("app", "應用范圍屬性");
//HttpServletResponse response = ServletActionContext.getResponse();
return "message";
}
}
備注:ognl表達式其實完全可以通過JSTL、EL結合來代替ognl