第一天下午學習目錄列表:
六、Struts2的處理流程與Action的管理方式
七、動態方法調用和使用通配符定義action
八、自定義類型轉換器
九、自定義攔截器
十、文件上傳(改成一個專題來講)
六、Struts2的處理流程與Action的管理方式
6.1struts2處理請求圖
StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器(相當於strtuts1.x的ActionServlet類的作用),它負責攔截由<url-pattern>/*</url-pattern>指定的所有用戶請求,當用戶請求到達時,該Filter會過濾用戶的請求。默認情況下,如果用戶請求的路徑不帶後綴或者後綴以.action結尾,這時請求將被轉入Struts 2框架處理,否則Struts 2框架將略過該請求的處理。當請求轉入Struts 2框架處理時會先經過一系列的攔截器,然後再到Action。與Struts1不同,Struts2對用戶的每一次請求都會創建一個Action,所以Struts2中的Action是線程安全的。也正因爲如此,Struts2裏可以定義成員變量,從而廢棄了Struts1.x裏的Form Bean.即Struts2的Action已具備了Struts1.x裏的Form Bean的功能.
七、動態方法調用和使用通配符定義action
7.1 動態方法調用
如果Action中存在多個業務方法時,我們可以使用!+方法名調用指定方法。 我們在HelloWorldAction裏添加兩個業務方法,如下:
public String del() {
message = "調用del()刪除方法";
return "success";
}
public String add() {
message = "調用add()添加方法";
return "success";
}
如果要訪問action的del() 方法,我們可以這樣調用:/struts2.1/test/helloworld!del ,動態方法調用就是那麼簡單,它實現了跟struts1.x 的DispatchAction一樣的作用.
注意: struts2的官方文檔已經不建議我們這樣使用,建議我們使用另外一種方式來實現:使用通配符定義action來替代
7.2 使用通配符定義action
即用*號來表示在動態改變的字符或字符串.在struts.xml的test包中添加一個action,如下:
<action name="*User" class="cn.gkit.action.HelloWorldAction" method="{1}" > <param name="message">屬性注入</param> <result name="success">/WEB-INF/jsp/helloworld.jsp</result> </action>
此時如果要訪問action的del() 方法,我們可以這樣調用:/struts2.1/test/delUser 即可調用到del()方法.
知識提示:{1}表示與第一個*號匹配,{1}不但可以在method屬性上使用,還可以在其他地方使用,如在<result>使用:
<result name="success">/WEB-INF/jsp/{1}.jsp</result>
八、自定義類型轉換器
問題引入:對於Date類型的屬性,可以接收格式爲2009-12-20的請求參數值,並將其自動轉換成Date類型.但如果項目需求要接收形如:20091220格式的日期該怎麼辦,在struts1.x中我們可以通過定義類型轉換器來實現,同樣在Struts2.x裏我們也可以定義類似的轉換器,並且比struts1.x的轉換器要強大,它實現了雙向轉換的功能.
8.1 定義局部類型轉換器
首先在HelloWorldAction裏增加一個java.util.Date 類型的birthday字段,並提供getter和setter方法.如下:
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
然後:定義Date類型轉換器,定義轉器有兩種方式:
第一種是繼承com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter類,重寫它的convertValue方法,實現如下:
public class 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]);
}else if(toType == String.class){//當Date轉換成字符串時
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {}
return null;
}
}
第二種方式是繼承org.apache.struts2.util.strutsTypeConverter類,並實現它的兩個抽象方法,實現代碼如下:
public class DateTypeConverter extends StrutsTypeConverter {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
@Override
public Object convertFromString(Map context, String[] value, Class toType) {
String[] params = (String[]) value;// Request.getParameterValues()
try {
return dateFormat.parse(params[0]);
} catch (ParseException e) {}
return null;
}
@Override
public String convertToString(Map context, Object value) {
Date date = (Date) value;
return dateFormat.format(date);
}
}
知識提示:查找StrutsTypeConverter的源碼發現,它本身也繼承了DefaultTypeConverter類.StrutsTypeConverter類使用的一種設計模式是模板方法設計模式,在http://yulon.iteye.com/admin/blogs/550501這裏有講到模板方法模式在項目中的應用.
最後,配置要使用該轉換器的action類
在HelloWorldAction同一包內新建HelloWorldAction-conversion.properties文件.文件名的後半部分是固定不變的
*-conversion.properties,*表示的是對應的Action的簡單類名(即不帶包名),在該文件裏如下定義:
birthday=cn.gkit.type.converter.DateTypeConverter
birthday表示要轉換的屬性,右邊對應一個轉換器.
此時訪問路徑:/struts2.1/test/helloworld.action?birthday=20091220,Struts框架就是使用剛纔定義的轉換器將String類型轉換成java.util.Date類型.
8.2 定義全局類型轉換器
全局類型轉換器的配置文件名是固定的:xwork-conversion.properties,並將該文件放到src目錄,編譯後會自動WEB-INF\classes目錄下.在該文件裏如下定義:
java.util.Date=cn.gkit.type.converter.DateTypeConverter
左邊定義的是要轉換的類型,作用了全部Action類.
注意: 如果同時定義了局部和全局的類型轉換器,對於同一個類型,局部會覆蓋全局的轉換器
相關文章:http://yulon.iteye.com/admin/blogs/551982(struts2.1兩天快速入門(第一天上午))