<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h3>輸入座標值,格式爲x,y,x和y的類型是int類型</h3> <s:form method="post" action="point" namespace="/"> <!-- 輸入座標值,格式爲x,y,x和y的類型是int類型 --> <s:textfield label="point" name="point"></s:textfield> <s:submit value="submit"></s:submit> </s:form> </body> </html>
Struts2的自定義類型轉換能夠經過重寫繼承DefaultTypeConverter類來完成,也能夠經過Struts2提供的模版重寫方法來完成。而且有局部類型轉換和全局類型轉換兩種,首先來看一下經過繼承DefaultTypeConverter類來實現類型轉換的方法。創建一個頁面,其中有一個文本框,須要輸入座標值,用','來分割x和y,如圖:css
代碼以下:html
接着,編寫一個Point類,有x和y兩個字段,用int表示,代碼以下:java
package cn.net.bysoft.lesson3; public class Point { public Point() { } public Point(int x, int y) { super(); this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } private int x; private int y; }
而後開始編寫繼承DefaultTypeConverter類的轉換類,這裏命名爲PointConverter.java,代碼以下:apache
package cn.net.bysoft.lesson3; import java.util.Map; import ognl.DefaultTypeConverter; public class PointConverter extends DefaultTypeConverter { @Override public Object convertValue(Map context, Object value, Class toType) { if (Point.class == toType) { // 用實體的類型與toType比較,等於客戶端傳遞到服務端數據。 Point point = new Point(); // 客戶端傳遞過來的數據爲String數組,由於控件的(好比input空間)name能夠有多個。 // 此處其實和HttpServletRequest.getParameterValues(String name)方法效果相同。 String[] strArray = (String[]) value; // 解析字符串。 String[] paramValues = strArray[0].split(","); int x = Integer.parseInt(paramValues[0]); int y = Integer.parseInt(paramValues[1]); point.setX(x); point.setY(y); return point; } if (String.class == toType) { // 用String類型與toType比較,等於服務器發送到客戶端數據。 Point point = (Point) value; int x = point.getX(); int y = point.getY(); StringBuffer sb = new StringBuffer(); sb.append("[x = "); sb.append(x); sb.append(", y = "); sb.append(y); sb.append("]"); return sb.toString(); } return null; } }
其中重寫convertValue方法進行類型轉換,這個方法參數,toType類型若等於"某某類名".class則表明要將Object value轉換成Java實體類,也就是客戶端傳遞到服務端的數據須要進行類型轉換。假如toType類型等於String.class則等於服務器像客戶端發送數據,須要將對象轉換成字符串。具體的轉換方法可根據實際狀況編寫。數組
接下來能夠建立一個Action用於控制服務端與客戶端的請求了,代碼與配置以下:服務器
package cn.net.bysoft.lesson3; import com.opensymphony.xwork2.ActionSupport; public class PointAction extends ActionSupport { /** * */ private static final long serialVersionUID = -2035413550978816228L; @Override public String execute() throws Exception { return SUCCESS; } public Point getPoint() { return point; } public void setPoint(Point point) { this.point = point; } private Point point; }
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="struts2_3_24_1" extends="struts-default"> <action name="helloWorld" class="cn.net.bysoft.lesson1.HelloWorldAction"> <result>lesson1/hello.jsp</result> </action> <action name="login" class="cn.net.bysoft.lesson2.LoginAction"> <result name="success">/lesson2/success.jsp</result> <result name="input">/lesson2/login.jsp</result> </action> <action name="point" class="cn.net.bysoft.lesson3.PointAction"> <result name="success">/lesson3/output.jsp</result> <result name="input">/lesson3/index.jsp</result> </action> </package> </struts>
最後,最關鍵的是要編寫一個配置文件來聲明轉換的信息,使用局部轉換須要在Action的包下創建一個同名的加-conversion.properties屬性文件,如PointAction-conversion.properties。內容以下:app
point=cn.net.bysoft.lesson3.PointConverter
等號左側是Action中的字段名稱,右側是使用咱們的PointConverter類進行轉換。以上工做完成後,能夠進行類型轉換,編寫一個輸出頁面測試類型轉換,代碼以下:less
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'output.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> point:<s:property value="point"/> </body> </html>
有一點須要注意的是,在PointConverter.java類中,在客戶端向服務端請求類型轉換時,參數Object value是一個字符串數組(String[]),由於頁面中控件的name屬性能夠有多個,一次向服務端發送多個Point對象存放到數組中,請看以下代碼:jsp
<h3>輸入座標值,格式爲x,y,x和y的類型是int類型</h3> <s:form method="post" action="point" namespace="/"> <!-- 輸入座標值,格式爲x,y,x和y的類型是int類型 --> <s:textfield label="point" name="point"></s:textfield> <s:textfield label="point" name="point"></s:textfield> <s:textfield label="point" name="point"></s:textfield> <s:submit value="submit"></s:submit> </s:form>
因此,在處理類型轉換時,能夠一次進行多個對象的類型轉換,新建立一個局部類型轉換類,實現轉換客戶端傳遞過來多個Point並放到集合中,代碼以下:ide
package cn.net.bysoft.lesson3; import java.util.ArrayList; import java.util.List; import java.util.Map; import ognl.DefaultTypeConverter; public class PointConverter2 extends DefaultTypeConverter { @Override public Object convertValue(Map context, Object value, Class toType) { if (List.class == toType) { // 用實體的類型與toType比較,等於客戶端傳遞到服務端數據。 List<Point> points = new ArrayList<Point>(); // 客戶端傳遞過來的數據爲String數組,由於控件的(好比input空間)name能夠有多個。 String[] strArray = (String[]) value; for (String str : strArray) { // 解析字符串。 String[] paramValues = str.split(","); int x = Integer.parseInt(paramValues[0]); int y = Integer.parseInt(paramValues[1]); Point point = new Point(); point.setX(x); point.setY(y); points.add(point); } return points; } if (String.class == toType) { // 用String類型與toType比較,等於服務器發送到客戶端數據。 List<Point> points = (List<Point>) value; int count = 0; StringBuffer sb = new StringBuffer(); sb.append("["); for (Point point : points) { count++; int x = point.getX(); int y = point.getY(); sb.append("point").append(count).append(":").append("{x = ") .append(x).append(", y=").append(y).append("}"); } sb.append("]"); return sb.toString(); } return null; } }
在Struts2中添加相關字段和get/set方法,並配置屬性文件:
public List<Point> getPoints() { return points; } public void setPoints(List<Point> points) { this.points = points; } private List<Point> points;
points=cn.net.bysoft.lesson3.PointConverter2
結果以下:
若是有不少Action中都有一個Poin,那局部轉換就麻煩,由於要爲每個Action都編寫一個屬性文件,Struts2提供了全局的轉換方 式,能夠編寫全局屬性文件實現效果。屬性文件命名爲固定的xwork- conversion.properties,屬性值等號左側是實體類的全名,右側是制定的轉換類。例如:
cn.net.bysoft.lesson3.Point=cn.net.bysoft.lesson3.PointConverter
Struts2還提供了內置的轉換類StrutsTypeConverter,他是一個抽象類,提供了兩個抽象方法讓咱們重寫:
繼承這個抽象類,並重寫convertFormString方法和convertToString方法,顧名思義,convertFromString是將客戶端請求傳遞過來的字符串轉換成服務端對象,而convertToString是將服務端對象轉換成字符串以備發送到客戶端。具體代碼以下:
package cn.net.bysoft.lesson3; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.struts2.util.StrutsTypeConverter; public class PointConverter3 extends StrutsTypeConverter { @Override public Object convertFromString(Map arg0, String[] values, Class toClass) { // 用實體的類型與toType比較,等於客戶端傳遞到服務端數據。 List<Point> list = new ArrayList<Point>(); System.out.println(list.getClass()); // 客戶端傳遞過來的數據爲String數組,由於控件的(好比input空間)name能夠有多個。 for (String value : values) { // 解析字符串。 Point point = new Point(); String[] paramValues = value.split(","); int x = Integer.parseInt(paramValues[0]); int y = Integer.parseInt(paramValues[1]); point.setX(x); point.setY(y); list.add(point); } return list; } @Override public String convertToString(Map arg0, Object o) { // 用String類型與toType比較,等於服務器發送到客戶端數據。 List<Point> points = (List<Point>) o; int count = 0; StringBuffer sb = new StringBuffer(); sb.append("["); for (Point point : points) { count++; int x = point.getX(); int y = point.getY(); sb.append("point").append(count).append(":").append("{x = ") .append(x).append(", y=").append(y).append("}"); } sb.append("]"); return sb.toString(); } }
這段代碼相對於以前的代碼,將兩個if判斷拆分紅兩個方法,更加優雅,而且由Starts來判斷咱們是從字符串轉換成對象,仍是從對象轉換成字符串,使得代碼更加健壯。