一、型別轉換的意義
對於一個智慧的MVC框架而言,不可避免的需要實現類型轉換.因為B/S(瀏覽器/伺服器)結構應用的請求參數是透過瀏覽器發送到伺服器的,這些參數不可能有豐富的資料類型,因此必須在伺服器端完成資料型別的轉換
MVC框架是一個表現層解決方案,理應提供類型轉換的支援,Struts2提供了功能非常強大的類型轉換支援.
二、表現層資料的處理
1.對於web應用而言,表現層主要用於與用戶互動,包括收集用戶輸入數據,向用戶呈現伺服器的狀態。因此表現層的資料的流向主要有兩個方向:輸入資料和輸出資料。
2.對於輸入資料:則需要完成由字串資料轉換為多種類型資料的工作。程式通常無法自動完成,需要在程式碼中手動轉化
3.對於輸出資料:不管是java或jsp都支援多種資料型別的直接輸出。
4.表現層另外一個資料處理是:資料校驗,分為客戶校驗和伺服器端校驗.後邊會重點講解
三、類型轉換
1、HTTP參數都是字串型別。 保存的資料可能是字串、數字、布林、日期時間等或JavaBean類型。 手工的類型轉換,例如將字串轉換為日期,透過: 透過request.getParameter方法取得字串; 檢查是否為空; 透過DateFormat.parse方法將字串轉換為Date對象
2、Struts2型轉換
Struts2內建的型別轉換
String和boolean 完成字串與布林值之間的轉換
String和char 往常字串與字元之間的轉換
String與int、Integer 完成字串與整數之間的轉換
String與Long 完成字串與長整數值之間的轉換
String與double、Double 完成字串與雙精確度浮點值的轉換
String和Float 完成字串和單精確度浮點之間的轉換
String和Date 完成字串和日期類型之間的轉換,日期格式使用格式使用者請求所在Locale的SHORT格式
String和陣列在預設的情況,陣列元素是字串,如果使用者定義類型轉換器,也可以是其它複合資料類型
String和Map、List
Struts2內建的型別轉換
String和boolean 完成字串與布林值之間的轉換
String和char 往常字串與字元之間的轉換
String與int、Integer 完成字串與整數之間的轉換
String與Long 完成字串與長整數值之間的轉換
String與double、Double 完成字串與雙精確度浮點值的轉換
String和Float 完成字串和單精確度浮點之間的轉換
String和Date 完成字串和日期類型之間的轉換,日期格式使用格式使用者請求所在Locale的SHORT格式
String和陣列在預設的情況,陣列元素是字串,如果使用者定義類型轉換器,也可以是其它複合資料類型
String和Map、List
3、內建類型轉換
4、Struts類型轉換的API
Struts2的類型轉換器其實是基於OGNL實現的,在OGNL專案中有一個ognl.TypeConverter介面,這個介面就是實現類型轉換器必須實現的介面。此介面定義如下:
public interface TypeConverter {
public Object convertValue(Map arg0, Object arg1, Member arg2, String arg3,
Object arg4, Class arg5) {
return null;
}
實作型別轉換器必須實作上面的TypeConverter,不過上面的介面裡的方法過於複雜,所以OGNL專案也提供了一個該介面實作類別:ognl.DefaultTypeConverter,透過繼承該類別實作自己型別轉換器.該類別定義如下:
public class DefaultTypeConverter extends Object implements TypeConverter{
public Object convertValue(Map<String,Object>context, Objectvalue, ClasstoType) {
}
……//其他的方法
}
ConvertValue方法的作用該方法完成類型轉換,不過這種類型轉換是雙向的,當需要把字符串轉化對象實例時,通過該方法實現,當把對象實例轉換成字符串時也通過該方法實現。這種轉換是透過toType參數類型是需要轉換的目標類型。所以可以根據toType參數來判斷轉換方向。
ConvertValue方法參數與回傳意義第一個參數:context是型別轉換環境的上下文第二個參數:value是需要轉換的參數,根據轉換方向的不同value參數的值也是不一樣的。
第三個參數:toType是轉換後的目標類型該方法的回傳值是型別轉換後的值。該值的類型也會隨著轉換的方向的改變而改變。由此可見轉換的convertValue方法接受需要轉換的值,需要轉換的目標類型為參數,然後傳回轉換後的目標值
Value為什麼是一個字串陣列?
對於DefaultTypeConverter轉換器而言,它必須考慮到最通用的情形,因此他把所有請求參數都視為字串陣列而不是字串。相當於getParameterValues()取得的參數值
四、型別轉換器的實現
1、第一步註冊頁面
2.第二步驟:實作User封裝類
3.第三步:實作Action類
5.第五步驟:實作型別轉換器的註冊,註冊方式有以下三種:
1.註冊局部型別轉換器:局部型別轉換器僅對某個Action的屬性其作用
2.註冊全域類型轉換器:全域型別轉換器對所有Action的特定屬性都會生效
3.使用JDK1.5的註解來註冊型別轉換器:透過註冊方式來產生型別轉換器
6.局部型別轉換器註冊註冊檔名格式:ActionName-conversion.properties:ActionName是需要轉換器生效的Action的類別名稱,後面的-conversion.properties字串是固定部分以上檔案時典型的properties檔案,文件有key-value對組成。檔案內容為:propertyName=型別轉換器類別下面是UserAction-conversion.properties檔案的內容:
#指定UserAction中的user屬性需要使用redarmy.user.UserConverter類別完成類型轉換
user=redarmy.user.UserConverter
注意:以上properties檔案一定要與UserAction在同一個套件中即上述案例可採用上面的方式實現局部型別轉換
7.全域類型轉換器註冊名的文件格式:xwork-conversion.properties文件該文件也是properties文件,其內容也是由”複合類型=對應的類型轉換器類別”項目組成的。
以下是xwork-conversion.properties檔案內容:
#指定所有redarmy.user.User類別的型別轉換器為redarmy.user.UserConverter
redarmy.user.User=redarmy.user.UserConverter
注意:xwork-conversion.properties檔案必須為class資料夾下即在src下面建立
五、Struts2自訂型別轉換
在Struts2中提供了StrutsTypeConverter類別來簡化自訂類型轉換的設計,這個類別有兩個抽象方法需要實作:
(1) public Object convertFromString(Map context, String[] values, Class toClass) ;
用於String類型資料轉成自訂類型的處理方法參數:
context --- 與Action有關的上下文訊息
values --- 從請求中取得的參數值
toClass --- 要轉換的目標類型
(2) public String convertToString(Map context, Object obj) ;
用於自訂類型轉換成String
參數:
context --- 與Action有關的上下文訊息
obj --- 自訂類型對象
實例分析:一個日期類型轉換的設計與配置
(1) 設計MyDateTypeConverter,繼承StrutsTypeConverter,覆寫其中的兩個方法,參考程式碼如下:
public Object convertFromString(Map context, String[] values, Class toClass) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try{
Date v = sdf.parse(values[0]);
return v;
}catch(Exception e){
e.printStackTrace();
return new Date();
}
}
續
public String convertToString(Map context, Object obj) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date v = (Date)obj;
return sdf.format(v);
}
雖然Struts2預設可支援String和Date的轉換,但僅支援短格式和在地化有關日期格式轉換,不一定符合自己的需求,我們需要實作自己的型別轉換。
(2) 為UserInfo類別增加一個birthday屬性,其類型為java.util.Date
public class UserInfo {
private Integer id;
private String name;
private String password;
private Date birthday;
…
}
(3)為UserInfo這個元件配置此型別轉換器首先,以UserInfo元件的類別名稱為基礎建立特性文件,文件命名格式為類別名稱-conversion.properties
例如UserInfo-conversion.properties
該檔案必須和UserInfo元件在同一個套件下。
該特性文件內容格式如下:
birthday=demo.converter.MyDateTypeConverter
說明:
birthday 為UserInfo元件中java.util.Date類型的屬性名
demo.converter.MyDateTypeConverter為自訂轉換實作類
Strus2框架為我們考慮到這一點,提供了一種簡單的處理方式。
將類型轉換器配置為全域級別,只需編寫一個名為xwork-conversion.properties的特性文件,該文件必須位於/WEB-INF/classes目錄下,內容如下:
java.util.Date=demo.converter.MyDateTypeConverter
六、自訂類型轉換器
java.util.Date類型的屬性可以接收格式為2009-07-20的請求參數值。但如果我們需要接收格式為20091221的請求參數,我們必須定義型別轉換器,否則struts2無法自動完成型別轉換。
import java.util.Date;
public class HelloWorldAction {
private Date createtime;
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
}
public class DateConverter extends DefaultTypeConverter {
@Override public Object convertValue(Map 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;
}
}
將上面的類型轉換器註冊為局部類型轉換器:
在Action類別所在的套件下方放置ActionClassName-conversion.properties文件,ActionClassName是Action的類別名,後面的-conversion.properties是固定寫法,對於本例而言,檔案的名稱應為HelloWorldAction-conversion.properties 。在properties檔案中的內容為:
屬性名稱=型別轉換器的全類別名稱對於本例而言, HelloWorldAction-conversion.properties檔案中的內容為:
createtime= cn.csdn.conversion.DateConverter
將上面的類型轉換器註冊為全域類型轉換器:
在WEB-INF/classes下放置xwork-conversion.properties檔案。在properties檔案中的內容為:
待轉換的型別=型別轉換器的全類別名稱對於本例而言, xwork-conversion.properties檔案中的內容為:
java.util.Date= cn.csdn.conversion.DateConverter
java.util.Date類型的屬性可以接收格式為2009-07-20的請求參數值。但如果我們需要接收格式為20091221的請求參數,我們必須定義型別轉換器,否則struts2無法自動完成型別轉換。
import java.util.Date;
public class HelloWorldAction {
private Date createtime;
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
}
public class DateConverter extends DefaultTypeConverter {
@Override public Object convertValue(Map 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;
}
}
將上面的類型轉換器註冊為局部類型轉換器:
在Action類別所在的套件下方放置ActionClassName-conversion.properties文件,ActionClassName是Action的類別名,後面的-conversion.properties是固定寫法,對於本例而言,檔案的名稱應為HelloWorldAction-conversion.properties 。在properties檔案中的內容為:
屬性名稱=型別轉換器的全類別名稱對於本例而言, HelloWorldAction-conversion.properties檔案中的內容為:
createtime= cn.csdn.conversion.DateConverter
將上面的類型轉換器註冊為全域類型轉換器:
在WEB-INF/classes下放置xwork-conversion.properties檔案。在properties檔案中的內容為:
待轉換的型別=型別轉換器的全類別名稱對於本例而言, xwork-conversion.properties檔案中的內容為:
java.util.Date= cn.csdnconversion.DateConverter