Struts2之類型轉換器
Struts2之類型轉換器
- 在我們接收表單的請求參數的時候其實默認的都是String類型,但是有時候我們需要其他的數據類型,比如int,double,float,Date。
- 其實前面表單的傳值都是字元串形式的,但是為什麼我們在JavaBean中定義了不同的類型的數據,Struts還是會正確接收表單傳遞過來的值呢,因為使用了Struts中的內建的類型轉換器
傳統的類型轉換器
- 在Servlet中我們可以自己獲取請求參數自己轉換類型,通常使用request.getParamerter(String name) 獲取請求的參數 如下:
String username= requst.getParameter("username");//獲取年齡然後轉換成了整數int age=Integer.parseInt(requst.getParameter("age"));
內建的類型轉換器
- 其實內建的類型轉換器已經可以完成大部分的功能了,比如表單傳值,其實傳遞的是字元串,但是我們在JavaBean中定義的卻是不同類型的數據,內部原理就是用了內置的類型轉換器
- 內建類型轉換器可以完成基本類型之前的轉換
自定義類型轉換器
- 前面說的內建的類型轉換器只是在普通的類型之間的轉換,都是一些基本的類型可以實現自動轉換,並不用自己定義類型轉換器。但是我們現在需要將輸出的字元串轉換為複合對象,比如一個User(username,password)類,那麼現在就不能使用內建的類型轉換器自動轉換了,現在需要自己定義類型轉換器了。
- 實現類型轉換器也是基於OGNL實現的,在OGNL中有一個
TypeConverter
介面,但是這個介面太複雜了,因此OGNL還提供了一個類DefaultTypeConverter
,通過繼承這個類就可以實現類型轉換器了。 - 假設我們在登錄界面需要在一個text中輸入用戶名和密碼用逗號隔開,現在我們可以使用自定義的轉換器。現在登錄的JSP如下:
<form action="http://localhost:8080/web3/login" method="post"> <label>請輸入用戶名和密碼(逗號隔開):</label> <input type="text" name="user"> <input type="submit" value="提交"> </form>
- 定義的User類如下
public class User { private String username; //用戶名 private String password; //密碼 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
- Action類
import com.opensymphony.xwork2.Action;import com.user.User;public class LoginAction implements Action { private User user; // User對象 public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String execute() throws Exception { return SUCCESS; }}
- UserConverter(轉換器類)
import java.util.Map;import com.user.User;import ognl.DefaultTypeConverter;public class UserConverter extends DefaultTypeConverter { /* * context:類型轉換的上下文環境 * value: value是需要轉換的參數,隨著轉換的方向不同,value的參數值也是不一樣的,因此需要強制轉化 * toType: 表示轉換後的目標類型 */ public Object convertValue(Map context, Object value, Class toType) { System.err.println("調用了"); // 有字元串轉http://download.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#sum換為User類 // toType表示轉向的類型 if (toType == User.class) { String[] params = (String[]) value; // 將字元串轉換為數組 User user = new User(); // 創建User對象 // 利用逗號將數組中的第一個字元串分割為兩個字元串,設置成username,password user.setUsername(params[0].split(",")[0]); user.setPassword(params[0].split(",")[1]); return user; // 最後一定要返回User對象 } // 如果是從複合類轉換為字元串 else if (toType == String.class) { User user = (User) value; // 將value轉換為User對象 // 最後返回一個字元串表現的形式 return user.getUsername() + "," + user.getPassword(); } else { return null; // 沒有相互轉換的條件返回null } }}
- 從上面的代碼可以看出有兩類的轉換:一是從字元串轉換為User類,二是從User類轉換為字元串,這個都是使用toType來控制的。
ConverterValue方法參數和返回值的含義
- context: 是類型轉換環境的上下文
- value :是需要轉換的類型參數。隨著轉換方向的不同,value參數的值也是不一樣的,當把字元串類型轉換為User類型時,value就是原始字元串。當需要把User類型向字元串類型轉換時,value是User的實例。當然無論向哪一個方向轉換,value都是需要強制轉換的。
- toType: 是轉換後的目標類型。
- 為什麼自己當向User類轉換的時候,value要轉換為一個字元數組呢?
- 因為這裡對應的是一個文本,如果我們對應的是一個多選框,那麼此時就是一個數組了,因此這裡強制轉換為數組是一個通用的寫法
局部轉換器
- 轉換器分為局部轉換器和全局轉換器,局部轉換器是針對指定的Action類,但是全局轉換器是針對的是該項目中所有需要轉換的Action類。
- 前面已經實現了Action類,現在我們只需要定義一個ActionName-conversion.properties文件和Action放在一個目錄下即可,其中的ActionName是Action的類名,比如上面的Action類是LoginAction,那麼這裡的文件就是LoginAction-conversion,.properties。其中的內容如下:
- user是Action中定義User對象,com.converter.UserConverter是對應的轉換的類,一定要定義到包名。
user=com.converter.UserConverter
全局轉換器
- 全局轉換器是作用於全部需要轉換的Action的,只需要定義一個xwork-conversion. Properties。這個的名字就不需要改變了,放在src目錄下即可,這樣才可以作用到全局中。內容如下:
com.user.User=com.converter.UserConvertercom.date.Date=com.converter.Date
- 其中的內容是一鍵值對存在的,com.user.User對應的是定義的JavaBean類,這裡不再是action類中的定義的User對象了,是需要轉換對象的類,com.converter.UserConverter這個是定義轉換器的類。
- 從上面我們可以看出來定義兩個轉換器,最後一個是將字元串轉換為日期類型的轉換器。其實其中可以定多個類型轉換器,並且只要是一鍵值對的形式寫出即可。
基於Struts2的類型轉換器
- 上面的類型轉換器都是基於OGNL的DefaultTypeConverter類實現的,基於該類實現轉換時都要實現ConverterValue()方法,無論是從字元串轉換為複合類型還是從複合類型轉換為字元串都是在這個方法中實現。
- 為了簡化類型轉換器的實現,Struts2提供了一個StrutsTypeConverter抽象類,這個抽象類是DefaultTypeConverter的子類。其中重要的方法如下:
- public Object convertFromString(Map context, String[] values, Class toClass)將字元串轉換為複合類型個方法。
- context是上下文環境,value是字元串數組,toClass是要轉換的類型
- public String convertToString(Map context, Object values) 將複合類型轉換為字元串
- values是複合類對象,context是上下文環境
- public Object convertValue(Map context, Object values, Class toClass)實現DefaultTypeConverter方法,其中的變數還是上面的意思
- 下面實現上面的登錄轉換,如下:
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
import com.user.User;public class UserConverterStruts extends StrutsTypeConverter { protected Object performFallbackConversion(Map context, Object o,Class toClass) {
return super.performFallbackConversion(context, o, toClass); } // 將字元串轉換為複合類型的方法 public Object convertFromString(Map context, String[] values, Class toClass) {User user = new User(); //創建User對象
String[] userValues = values[0].split(","); // 將字元串數組中的第一個字元串分隔開 user.setUsername(userValues[0]); user.setPassword(userValues[1]); return user;}
// 將複合類型轉換為字元串 public String convertToString(Map context, Object values) { User user = (User) values; //強制轉換成User類型的String username = user.getUsername(); //獲取username和password
String password = user.getPassword(); return "<" + username + "," + password + ">"; }}- 有了上面的轉換器,那麼局部轉換器和全局轉換器的配置還是和上面的一樣,這裡就不在贅述了。
數組屬性的類型轉換器
- 數組類型的轉換器是用於提交的參數為數組的類型的,也就是同時Action中有一個屬性為數組。
- 現在我們要同時輸入兩個用戶的信息,jsp如下:
<form action="http://localhost:8080/web3/login" method="post"> <label>請輸入用戶名和密碼(逗號隔開):</label> <input type="text" name="users"> <input type="text" name="users"> <input type="submit" value="提交"> </form>
- 從上面的代碼我們可以看出這裡text中有兩個name屬性相同的表單,這個同時提交上去就是一個數組。
- Action類:(定義一個User數組):
import com.opensymphony.xwork2.Action;import com.user.User;public class LoginSAction implements Action { private User[] users; //定義數組類型User public User[] getUsers() { return users; } public void setUsers(User[] users) { this.users = users; } public String execute() throws Exception { System.out.println(getUsers()[0].getUsername()); return SUCCESS; }}
- 數組轉換器:
import java.util.Map;import org.apache.struts2.util.StrutsTypeConverter;import com.user.User;public class UsersConverterStruts extends StrutsTypeConverter { // 將字元串轉換複合類型 public Object convertFromString(Map context, String[] values, Class toClass) { if (values.length > 1) { User[] results= new User[values.length]; // 創建對象,這裡是創建和字元串數組一樣的長度 // 遍歷所有的字元串數組,然後將其填入每一個User對象中 for (int i = 0; i < values.length; i++) { User user=new User(); //創建user對象 String[] uservalues = values[i].split(","); user.setUsername(uservalues[0]); // 將其設置為User的屬性 user.setPassword(uservalues[1]); results[i]=user; //將實例化的user對象,填入數組 } return results; } else { // 這裡表示數組中只有一個字元串 User user = new User(); // 創建對象 String[] uservalues = values[0].split(","); user.setUsername(uservalues[0]); user.setPassword(uservalues[1]); return user; } } // 將複合類型轉換為字元串 public String convertToString(Map context, Object values) { // 只是一個單個的User類型的 if (values instanceof User) { User user = (User) values; String username = user.getUsername(); String password = user.getPassword(); return "<" + username + "," + password + ">"; } // User數組 else if (values instanceof User[]) { User[] users = (User[]) values; //轉換為User數組 String results = "["; for (User user : users) { String username = user.getUsername(); String password = user.getPassword(); results += "<" + username + "," + password + ">"; } return results + "]"; //返回全部的字元串 } else { return ""; } }}
推薦閱讀:
※Struts 2 中 <s:form> 標籤和 HTML 的 <form> 標籤有什麼區別?
※<s:iterator>標籤遍歷動態數組<泛型>:ArrayList<對象>,怎樣批量修改數據並一起提交到後台
TAG:Struts |