<%@ 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来判断咱们是从字符串转换成对象,仍是从对象转换成字符串,使得代码更加健壮。