Struts2之类型转换器
一、类型转换器的应用场景
类型转换是OGNL的一部分,默认的八种基本类型、String、Date会使用类型转换,但是更复杂的类型转换就需要我们自定义了(虽然这个东西一般根本用不到),OGNL可以应用在很多领域,但是在web领域,因为在客户端到服务器端传输的只是字符串,所以这里就有一个需求收缩,我们的需求就变为完成String和复杂对象之间的互相转换。
在Struts2中的类型转换则是在客户端的请求参数往Action的成员属性中设置的时候会被调用。
二、如何使用?
1.理论部分
所有的类型转换器都要实现TypeConverter接口,Struts2有需求收缩,只满足 String<-->复杂对象 就可以了,所以它提供了一个抽象类叫做StrutsTypeConverter,我们自定义的类型转换器只要继承这个类然后实现它的两个抽象接口就可以了。
我们写完了这个类型转换器的代码,但是怎么才能让Struts2知道去使用它呢?这里分为了两种情况:
Action级别
在Action的同级别目录下放置“ActionName-conversion.properties”,在此文件使用“propertyName=typeConverterClassName”的格式为属性指定类型转换器。
比如:
文件名:PointAction-conversion.properties
内容:point=struts_practice_005.PointTypeConverter
全局级别
在类路径下放置“xwork-conversion.properties”,在此文件中使用“ObjectName=typeConverterClassName”的格式为对象指定类型转换器。
比如:
文件名:xwork-conversion.properties
内容:struts_practice_006.Circle=struts_practice_006.CircleTypeConverter
总结一下:
定义一个类型转换器分为两步:
1.继承StrutsTypeConverter,实现它的两个抽象方法。
2.写properties文件告诉Struts2应该如何使用。
2.实践部分
两个例子(Action级别类型转换器 & 全局级别类型转换器):
2.1 一个字符串到Point对象的转换。(使用Action级别)
结构如下:
Point:
/** * 表示一个点 * @author CC11001100 * */ public class Point { private double x; private double y; public Point() { } public Point(double x, double y) { super(); this.x = x; this.y = y; } @Override public String toString() { //toString--> (x,y) return "("+x+","+y+")"; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } }
Action:
import com.opensymphony.xwork2.ActionSupport; public class PointAction extends ActionSupport { private Point point; @Override public String execute() throws Exception { System.out.println(point); return super.execute(); } public Point getPoint() { return point; } public void setPoint(Point point) { this.point = point; } }
类型转换器PointTypeConverter :
import java.util.Map; import org.apache.struts2.util.StrutsTypeConverter; /** * 完成 Point对象<-->String 的互相转换 * * @author CC11001100 * */ public class PointTypeConverter extends StrutsTypeConverter { /** * 这个方法完成从String-->Point的类型转换 */ @Override public Object convertFromString(Map context, String[] values, Class toClass) { if (values.length > 0) { String s = values[0]; String ss[] = s.split(","); if (ss.length != 2) return null; double x = Double.parseDouble(ss[0].substring(1, ss[0].length())); double y = Double .parseDouble(ss[1].substring(0, ss[1].length() - 1)); return new Point(x, y); } else { return null; } } /** * 这个方法完成从Point-->String的转换 */ @Override public String convertToString(Map context, Object o) { // 偷个懒,直接调用toString() if (o != null) return o.toString(); return null; } }
配置PointAction-conversion.properties(Action级别):
point=struts_practice_005.PointTypeConverter
struts.xml:
<struts> <package name="default" namespace="/" extends="struts-default"> <action name="pointAction" class="struts_practice_005.PointAction"> <result >/result.jsp</result> </action> </package> </struts>
前端页面:
<form action="pointAction" method="post"> <input type="text" name="point" /> <input type="submit" value="提交" /> </form>
结果当然是转换成功啦,可以看到控制台的打印结果:
前端页面的显示结果:
当客户端发来的请求参数point=(1,2)发送到服务器的时候,它设置之前会看一下是否给这个对象设置了类型转换器,如果设置了就交给类型转换器就可以了,所以这里是调用了PointTypeConverter的convertFromString()方法。
概览:
Circle:
/** * 表示一个圆 * * @author CC11001100 * */ public class Circle { // 圆的半径 private double r; public Circle() { } public Circle(double r) { super(); this.r = r; } @Override public String toString() { // toString() --> "C:rxx" return "C:r" + r; } public double getR() { return r; } public void setR(double r) { this.r = r; } }
CircleAction:
import com.opensymphony.xwork2.ActionSupport; public class CircleAction extends ActionSupport { private Circle circle; @Override public String execute() throws Exception { return SUCCESS; } public Circle getCircle() { return circle; } public void setCircle(Circle circle) { this.circle = circle; } }
CircleTypeConverter:
/** * 完成从 String<-->Circle 的互相转换. * @author CC11001100 * */ public class CircleTypeConverter extends StrutsTypeConverter { @Override public Object convertFromString(Map context, String[] values, Class toClass) { if (values.length > 0) { String s = values[0]; if(s.indexOf("C:r")==-1) return null; s=s.substring(3,s.length()); double r=Double.parseDouble(s); return new Circle(r); } else { return null; } } @Override public String convertToString(Map context, Object o) { if(o!=null) return o.toString(); return null; } }
struts.xml
<struts> <package name="default" namespace="/" extends="struts-default"> <action name="circleAction" class="struts_practice_006.CircleAction"> <result >/result.jsp</result> </action> </package> </struts>
xwork-conversion.properties:
struts_practice_006.Circle=struts_practice_006.CircleTypeConverter
前端:
<form action="circleAction" method="post"> <input type="text" name="circle" /> <input type="submit" value="提交" /> </form>
result.jsp:
<s:property value="circle" /> <s:debug />
输入:
输出:
<s:property value="circle" /> 得到的值使用了类型转换器,<s:debug />显示的ValueStack中的值没有使用类型转换器,证明:
给类型转换器的convertToString加点料。如下:
public class CircleTypeConverter extends StrutsTypeConverter { ... @Override public String convertToString(Map context, Object o) { if(o!=null) return o.toString()+"类型转换器"; return null; } }
如图:
待更、