類型轉換是Struts 2的一個很是重要的部分,經過類型轉換可以將表單參數轉換成Java中的各類類型,本文將詳細介紹Struts 2的內建類型轉換器和自定義類型轉換器。html
第一節 Struts 2內建類型轉換器java
1.1 類型轉換的意義apache
Web應用程序的交互是創建在HTTP之上的,互相傳遞的都是字符串,也就是說服務器接收到的來自用戶的數據只能是字符串或者是字符數組,而在Web應用的對象中,每每使用了多種不一樣的類型,如整數(int)、浮點數(float)、日期(Date)或者是自定義數據類型等,所以在服務器端必須將字符串轉換成合適的數據類型,服務器端完成業務邏輯處理後,又需將其餘數據類型轉換爲String,而後傳遞給客戶端進行顯示,具體流程如圖所示:數組
1.2 內建類型轉換器簡介服務器
Struts 2爲經常使用的數據類型提供了內建的類型轉換器,Struts在遇到這些類型時,會自動去調用相應的轉換器進行類型轉換,Struts 2提供了以下一些內建的類型轉換器:app
A、基本數據類型以及其封裝類jsp
B、日期類型post
C、集合(Collection)類型測試
D、集合(Set)類型ui
E、數組類型
下面幾小節內容將對上述內建類型轉換器進行簡單介紹
1.3 基本數據類型轉換器
經過基本數據類型轉換器可以完成字符串和基礎數據類型之間的轉換,其中基礎數據類型包括boolean、char、byte、short、int、long、float和double八種。
下面經過一個簡單的計算器示例來演示如何經過基本數據類型轉換器完成字符串和double類型數據之間的轉換:
CounterInput.jsp:
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>計算器</title> </head> <body> <form action="count.action" method="post"> 第一個操做數:<input type="text" name="num1"><br><!--第一個操做數--> 運算符:<select name="operation"> <option value="add">+</option><!--加法運算符--> <option value="minus">-</option><!--減法運算符--> <option value="multiply">*</option><!--乘法運算符--> <option value="division">/</option><!--除法運算符--> </select><br> 第二個操做數:<input type="text" name="num2"><br><!--第二個操做數--> <input type="submit" value="運算"> <input type="reset" value="重置"> </form> </body> </html>
CounterOutput.jsp:
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>計算結果</title> </head> <body> <s:property value="num1"/> <s:property value="operation"/> <s:property value="num2"/>= <s:property value="sum"/> </body> </html>
CountAction.java:
package com.sanqing.action; import com.opensymphony.xwork2.ActionSupport; public class CountAction extends ActionSupport { private double num1; //第一個操做數 private double num2; //第二個操做數 private double sum; //運算結果 private String operation; //運算符 public double getNum1() { //得到第一個操做數 return num1; } public void setNum1(double num1) { //設置第一個操做數 this.num1 = num1; } public double getNum2() { //得到第二個操做數 return num2; } public void setNum2(double num2) { //設置第二個操做數 this.num2 = num2; } public String getOperation() { //得到運算符 return operation; } public void setOperation(String operation) {//設置運算符 this.operation = operation; } public double getSum() { //得到運算結果 return sum; } public void setSum(double sum) { //設置運算結果 this.sum = sum; } public String execute() throws Exception { if("add".equals(operation)) { //若是運算符爲加法 sum = num1 + num2; }else if("minus".equals(operation)) { //若是運算符爲減法 sum = num1 - num2; }else if("multiply".equals(operation)) {//若是運算符爲乘法 sum = num1 * num2; }else { //若是運算符爲除法 sum = num1 / num2; } return this.SUCCESS; } }
測試:訪問http://localhost:8080/StrutsPro/CounterInput.jsp,其中計算器輸入頁面以下圖所示:
注:在字符串類型和double數據類型之間進行轉換時,若是輸入一個非數字的數據,如「a」,這時將沒法進行類型轉換,程序將出現類型轉換異常。
1.4 基本數據類型的封裝類轉換器
Struts 2的內置轉換器不但能轉換基本數據類型,還可以轉換基本數據類型的封裝類,包括Boolean、Character、Byte、Short、Integer、Long、Float和Double八種。
在下面這段代碼中修改上述案例,其運行結果與上例相同:
package com.sanqing.action; import com.opensymphony.xwork2.ActionSupport; public class CountAction2 extends ActionSupport { private Double num1; //第一個操做數 private Double num2; //第二個操做數 private Double sum; //運算結果 private String operation; //運算符 public double getNum1() { //得到第一個操做數 return num1; } public void setNum1(Double num1) { //設置第一個操做數 this.num1 = num1; } public double getNum2() { //得到第二個操做數 return num2; } public void setNum2(Double num2) { //設置第二個操做數 this.num2 = num2; } public String getOperation() { //得到運算符 return operation; } public void setOperation(String operation) {//設置運算符 this.operation = operation; } public double getSum() { //得到運算結果 return sum; } public void setSum(Double sum) { //設置運算結果 this.sum = sum; } public String execute() throws Exception { if("add".equals(operation)) { //若是運算符爲加法 sum = num1 + num2; }else if("minus".equals(operation)) { //若是運算符爲減法 sum = num1 - num2; }else if("multiply".equals(operation)) {//若是運算符爲乘法 sum = num1 * num2; }else { //若是運算符爲除法 sum = num1 / num2; } return this.SUCCESS; } }
注:在JDK 5.0之後,Java提供了自動封包和解包(也稱爲自動裝箱和拆箱),使得基本數據類型與其封裝類之間能夠互相自動轉換
1.5 數組類型轉換器
Struts 2還提供了一個數組類型的轉換器,這個轉換器很是經常使用,好比多個表單元素的name屬性相同,那麼提交的參數就再也不是字符串而是一個字符串數組。經過Sturts 2提供的數組類型的轉換器就能很方便的將多個相同name屬性的表單元素的值封裝到Action中的一個數組中。
下面這段代碼主要演示Struts 2的數組類型轉換器,將多個相同name屬性的表單元素的值封裝到Action中的一個數組中,須要注意的是表單元素的name必須與Action中的屬性名稱一致
(1)我的愛好輸入頁面LikeInput.jsp
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>我的愛好</title> </head> <body> <form action="mylike.action" method="post"> 請輸入您的我的愛好: <br> <input type="checkbox" name="mylike" value="basketball">籃球 <input type="checkbox" name="mylike" value="football">足球 <input type="checkbox" name="mylike" value="pingpang">乒乓球 <input type="checkbox" name="mylike" value="billiards">檯球<br> <input type="submit" value="提交"> <input type="reset" value="重置"> </form> </body> </html>
(2)我的愛好輸出頁面LikeOutput.jsp
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>顯示我的愛好</title> </head> <body> 你輸入的我的愛好包括: <s:property value="mylike"/> </body> </html>
(3)
package com.sanqing.action; import com.opensymphony.xwork2.ActionSupport; public class MyLikeAction extends ActionSupport{ private String[] mylike; //數組類型用來封裝全部的我的愛好 public String[] getMylike() { //得到數組 return mylike; } public void setMylike(String[] mylike) {//設置數組 this.mylike = mylike; } public String execute() throws Exception { return this.SUCCESS; //返回success字符串 } }
(4)測試
1.6 集合類型轉換器
集合類型轉換器和數組類型轉換器相似,能夠經過集合類型來接受參數值。Struts 2提供的集合類型轉換器,會將參數值自動添加到集合類型屬性中,不一樣的是將集合類型轉換成字符串類型時,輸出了一對中括號
package com.sanqing.action; import java.util.ArrayList; import com.opensymphony.xwork2.ActionSupport; public class MyLikeAction2 extends ActionSupport{ private ArrayList<String> mylike; //ArrayList類型用來封裝全部的我的愛好 public ArrayList<String> getMylike() { //得到mylike屬性值 return mylike; } public void setMylike(ArrayList<String> mylike) {//設置mylike屬性值 this.mylike = mylike; } public String execute() throws Exception { return this.SUCCESS; //返回success字符串 } }
1.7 日期類型轉換器
經過日期類型轉換器可以自動完成字符串類型與日期類型之間的轉換,不過字符串類型必須符合日期格式規範,不然將出現類型轉換錯誤。
下面這段代碼主要演示Struts 2的日期類型轉換器,經過輸入用戶出生日期,提交後自動輸出用戶年齡
(1)出生日期輸入頁面DateInput.jsp
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>輸入出生日期</title> </head> <body> <form action="date.action" method="post"> 請輸入您的出生日期: <br> <input type="text" name="mybirth"> <input type="submit" value="提交"> <input type="reset" value="重置"> </form> </body> </html>
(2)出生日期輸出頁面DateOutput.jsp
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>當前年齡</title> </head> <body> 經計算,年齡爲<s:property value="age"/> </body> </html>
(3)Action
package com.sanqing.action; import java.util.Date; import com.opensymphony.xwork2.ActionSupport; public class DateAction extends ActionSupport{ private Date mybirth; //出生日期 private Long age; //年齡 public Date getMybirth() { //得到出生日期 return mybirth; } public void setMybirth(Date mybirth) { //設置出生日期 this.mybirth = mybirth; } public Long getAge() { //得到年齡信息 return age; } public void setAge(Long age) { //設置年齡信息 this.age = age; } public String execute() throws Exception { Date now = new Date(); //得到當前日期 long nowTime = now.getTime(); //得到當前日期毫秒數 long birthTime = mybirth.getTime(); //得到生日的毫秒數 long difference = nowTime - birthTime; //得到毫秒差 long differenceDay = difference/(1000*60*60*24);//計算出總天數 age = differenceDay/365+1; //計算出年數差加一 return this.SUCCESS; //返回success字符串 } }
注:在測試上述代碼時,輸入出生日期時必須嚴格按照日期格式進行輸入,日期格式爲yyyy-MM-dd,其中yyyy爲年份,如1998;MM爲月份,如12;dd爲該月的某一天,如03。
第二節 自定義類型轉換器
Struts 2已經實現了一些經常使用的類型轉換,可是畢竟這些類型轉換器仍是有限的,若是是開發者本身定義的數據類型,就必須自定義類型轉換器來進行轉換,Struts 2的類型轉換器是基於OGNL實現的,在lib目錄下的ognl-2.6.11.jar中能夠找到TypeConverter類,此處略去其詳細內容。
下面來看如何建立自定義的類型轉換器,假如如今有一個自定義的類Point類,包括x和y兩個屬性,分別表明x座標值和y座標值。那麼若是經過表單的參數值來設置Point類的屬性呢,這時就必須經過自定義類型轉換器來完成。
2.1 實現自定義類型轉換器
package com.sanqing.converter; import java.util.Map; import ognl.DefaultTypeConverter; import com.sanqing.bean.Point; public class PointConverter extends DefaultTypeConverter { public Object convertValue(Map context, Object value, Class toType) { if(Point.class == toType) {//首先判斷若是要轉換的類型是否爲Point String[] paramStrs = (String[])value;//將請求參數值轉換成String數組 String[] pointArray = paramStrs[0].split(",");//經過逗號分隔字符串 Point point = new Point();//新建一個Point實例 point.setX(Integer.parseInt(pointArray[0]));//設置x座標 point.setY(Integer.parseInt(pointArray[1]));//設置y座標 return point;//返回轉換後的Point實例 } if(String.class == toType) {//若是要轉換的類型爲String Point point = (Point)value;//經過強制轉換把value轉換成Point實例 int x = point.getX();//得到x座標 int y = point.getY();//得到y座標 StringBuilder sb = new StringBuilder();//實例化一個StringBuilder用來構造字符串 sb.append("x座標爲").append(x).append(",y座標爲").append("y");//構造字符串 return sb.toString();//返回StringBuilder的字符串形式 } return null; } }
2.2 使用Struts 2提供的StrutsTypeConverter
package com.sanqing.converter; import java.util.Map; import org.apache.struts2.util.StrutsTypeConverter; import com.sanqing.bean.Point; public class PointConverter2 extends StrutsTypeConverter{ //從字符串類型轉換成自定義數據類型 public Object convertFromString(Map context, String[] values, Class toClass) { String[] pointArray = values[0].split(",");//經過逗號分隔字符串 Point point = new Point();//新建一個Point實例 point.setX(Integer.parseInt(pointArray[0]));//設置x座標 point.setY(Integer.parseInt(pointArray[1]));//設置y座標 return point;//返回轉換後的Point實例 } //從自定義數據類型轉換成字符串類型 public String convertToString(Map context, Object o) { Point point = (Point)o;//經過強制轉換把o轉換成Point實例 int x = point.getX();//得到x座標 int y = point.getY();//得到y座標 StringBuilder sb = new StringBuilder();//實例化一個StringBuilder用來構造字符串 sb.append("x座標爲").append(x).append(",y座標爲").append("y");//構造字符串 return sb.toString();//返回StringBuilder的字符串形式 } }
2.3 註冊局部類型轉換器
(1)PointInput.jsp
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>輸入座標</title> </head> <body> <form action="point.action" method="post"> 請輸入點座標(如:12,13): <br> <s:fielderror name="point"/> <input type="text" name="point"><br> <input type="submit" value="提交"> <input type="reset" value="重置"> </form> </body> </html>
(2)PointOutput.jsp
<%@page language="java" pageEncoding="gb2312"%> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>輸出座標</title> </head> <body> <s:property value="point"/> </body> </html>
(3)
package com.sanqing.action; import com.opensymphony.xwork2.ActionSupport; import com.sanqing.bean.Point; public class PointAction extends ActionSupport { private Point point; //point屬性 public Point getPoint() { //得到point屬性值 return point; } public void setPoint(Point point) { //設置point屬性值 this.point = point; } public String execute() throws Exception { return SUCCESS; } }
2.4 註冊全局類型轉換器
2.5 類型轉換執行流程
2.6 類型轉換中錯誤處理
2.7 輸出指定的錯誤信息
若是類型轉換出錯,Struts 2將自動調用ConversionError攔截器將錯誤提示信息保存到FieldError中