十三、Struts2的處理流程
request—>StrutsPrepareAndExecuteFilteràInterceptor(Struts2內(nèi)置的一些攔截器或用戶自定義攔截器)àAction(用戶編寫的Action,類似Struts1中的Action)àResult(類似Struts1中的forward)àJsp/Htmlàresponse
StrutsPrepareAndExccuterFilter是Struts2框架的核心控制器,它負責攔截由<url-pattern>/*</url-pattern>指定的所有用戶請求,當用戶請求到達時,該Filter會過濾用戶的請求。默認情況下,如果用戶請求的路徑不帶后綴或者后綴以.action結(jié)尾,這時請求將被轉(zhuǎn)入Struts2框架處理,否則Struts2框架將過濾該請求的處理。當請求轉(zhuǎn)入Struts2框架處理時會經(jīng)過一系列的攔截器,然后再轉(zhuǎn)到Action。與Struts1不同,Struts2對用戶每一次請求都會創(chuàng)建一個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動態(tài)方法調(diào)用(在Struts2.1版本文檔中已經(jīng)不推薦使用了)
如果在action中存在多個方法時,我們可以使用!+方法方法名調(diào)用指定的方法,如下:
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方法”;
}
}
假設(shè)訪問上面的action的URL路徑為:/struts2/test/helloworld.action
要訪問action的other方法,我們可以這樣調(diào)用:
/struts2/test/helloworld!other.action
如果不想使用動態(tài)方法調(diào)用,我們可以通過常量
struts.enable.DynamicMethodInvocation關(guān)閉動態(tài)方法調(diào)用.
<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 請求參數(shù)的接受
以下兩種方法,當參數(shù)比較多的時候,用第一種方法,將會發(fā)現(xiàn)action中有很多setter、getter方法,這樣不利于閱讀action,所以建議使用第二種。
a). 采用基本類型接收請求參數(shù)(get/post)
在Action類中定義與請求參數(shù)同名的屬性,Struts2便能接受請求參數(shù)并賦值給同名屬性:
如:請求路徑,http://localhost:8080/test/view.action?id=78
public class ProductAction{
private Integer id;
//struts2通過反射技術(shù)調(diào)用與請求參數(shù)同名的屬性的setter方法來獲取請求參數(shù)值
public void setId(Integer id) {
this.id = id;
}
public Integer getId{
return id;
}
}
b). 采用符合類型接收請求參數(shù)
如:請求路徑,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首先通過反射技術(shù)調(diào)用Product的默認構(gòu)造器創(chuàng)建product對象然后在通過反射技術(shù)調(diào)用product中與請求參數(shù)同名的屬性的setter方法來獲取請求參數(shù)
十七、Struts2有兩種類型轉(zhuǎn)換器
局部類型轉(zhuǎn)換器/全部類型轉(zhuǎn)換器
a). 自定義轉(zhuǎn)換類型
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類型轉(zhuǎn)換時
String[] params = (String[]) value;// request.getParameterValues()
return dateFormat.parse(params[0]);
}elseif(toType == String.class){//當Date轉(zhuǎn)換成字符串時
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {}
returnnull;
}
}
完成具體的雙向轉(zhuǎn)化代碼后,需要將上面的類型注冊為局部類型轉(zhuǎn)換器:
在Action類所有的包下放置ActionClassName-conversion.properties文件,ActionClassName是Action的類名,后面的-conversion.properties是固定寫法,對于本例而言,文件的名稱應(yīng)為HelloWroldAction-conversion.properties。
properties文件中的內(nèi)容為:
birthday=cn.itcast.type.converter.DateTypeConverter
b).自定義全局類型轉(zhuǎn)換器
將上面的局部類型轉(zhuǎn)換器注冊為全局類型轉(zhuǎn)換器:
在WEB-INF/classes下放置xwork-conversion.properties文件。在properties文件中的內(nèi)容為:
待轉(zhuǎn)換的類型=類型轉(zhuǎn)換器的全類名
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", "應(yīng)用范圍");//往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", "應(yīng)用范圍屬性");
//HttpServletResponse response = ServletActionContext.getResponse();
return "message";
}
}
備注:ognl表達式其實完全可以通過JSTL、EL結(jié)合來代替ognl