1.先给一个PointBean,要求对这个bean进行类型转换
- public class Point {
- private int x;
- private int 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;
- }
- }
2.两种转换器, 第一个侧重于告诉大家转换原理, 第二个侧重具体实践
- package edu.hust.common;
- import java.util.Map;
- import ognl.DefaultTypeConverter;
- import edu.hust.bean.Point;
- //较为底层的一个转换方法,一般项目中不直接继承DefaultTypeConverter实现转换,因为还有StrutsTypeConverter(继承自DefaultTypeConverter)进行了更好的封装。使我们更方便使用。
- //这里的例子为了大家理解这个机制。
- public class Converter extends DefaultTypeConverter {
- @SuppressWarnings("unchecked")
- @Override
- public Object convertValue(Map context, Object value, Class toType) {
- /*
- * toType: 当客户端提交数据时,要求String类型转换为自定义类型进行业务处理or存储(eg:String转为Point类);
- * 当客户端接收数据时,要求自定义类型转换为String类型进行显示输出。
- * toType起到了类型判断的作用。
- */
- //String转换为Point(Point为被转换(toType)类型, 也即目标类型)
- if (Point.class == toType) {
- Point point = new Point();
- //String[] paramValues = ((String)value).split(",");建议这一句用下面两句去替代。
- /*
- * 为什么要将value转换为String[]呢?
- * 我们在做表单时可以给2个or多个text的name属性赋予相同的值(即相同名字)。这样的话,server端接收name属性对应的表单属性时,接收过来的是一个数组(eg: 在Servlet中是用req.getParameterValues()接收这个数组的)。
- * 方法接口为:public String[] getParameterValues(String name);
- */
- String[] strTxt = (String[]) value;
- String[] paramValues = strTxt[0].split(",");
- int x = Integer.parseInt(paramValues[0]);
- int y = Integer.parseInt(paramValues[1]);
- point.setX(x);
- point.setY(y);
- return point;
- }
- //String为目标类型(当然不转换toString()方法会被调用,但我们不希望这样)
- if (String.class == toType) {
- Point point = (Point)value;
- int x = point.getX();
- int y = point.getY();
- String result = x + "," + y;
- return result;
- }
- return null;
- }
- }
- package edu.hust.common;
- import java.util.Map;
- import org.apache.struts2.util.StrutsTypeConverter;
- import edu.hust.bean.Point;
- public class Converter2 extends StrutsTypeConverter {
- @SuppressWarnings("unchecked")
- @Override
- public Object convertFromString(Map context, String[] values, Class toClass) {
- Point point = new Point();
- String[] paramValues = values[0].split(",");
- int x = Integer.parseInt(paramValues[0]);
- int y = Integer.parseInt(paramValues[1]);
- point.setX(x);
- point.setY(y);
- return point;
- }
- @SuppressWarnings("unchecked")
- @Override
- public String convertToString(Map context, Object o) {
- Point point = (Point)o;
- int x = point.getX();
- int y = point.getY();
- String result = "[x坐标:" + x + "],[y坐标:" + y +"]";
- return result;
- }
- }
3.action:请详细阅读下面这个action的中的注释
- package edu.hust.action;
- import java.util.Date;
- import com.opensymphony.xwork2.ActionSupport;
- import edu.hust.bean.Point;
- public class ConverterAction extends ActionSupport {
- /*
- * 如何让ConvertorAction知道Convertor类,并调用其中convertValue()方法进行类型转换呢?: 需要在ConvertorAction类所在的保内建立一个资源文件:ConvertorAction-conversion.properties.
- *
- * 在这个类中进行setter,getter方法时,ConvertorAction类会自动检测所在包内有没有(属性类型转换的)资源文件存在。如果存在则优先执行*.properties文件。
- * 在*.properties文件中调用edu.hust.common.Convertor类进行类型转换后,再执行setter,getter方法。
- *
- * 对于int,Date类型,struts2自动进行转化。不必我们去写转化代码。但如果我们也手工写了转化代码,则优先使用我们的转化代码。如果我们没有定义转化,struts2自动转化。
- * 对于自动转换的类型,struts2也会进行输入校验。对于int,Date类型的,如果我们输入字符串去提交,struts2自动校验并根据反射技术,把错误打印到对应输入表单之上(这里就必须使用struts2的表单,不能使用el进行输出)。
- * 在这里我们不推荐使用struts2的自动验证,其一其功能有限,其二其错误输出信息只是给程序员看的,而会让使用者一头雾水。
- * 解决方法:找到自动提示的错误信息,将错误信息内容覆盖为我们希望看到的--通过资源文件。
- *
- * 注:在result页面显示的时候,注意用<s:property>标签显示和用el显示的区别(区别很大)。
- *
- * */
- private static final long serialVersionUID = 1L;
- private Point point;
- private int age;
- private String username;
- private Date date;
- public Point getPoint() {
- return point;
- }
- public void setPoint(Point point) {
- this.point = point;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public Date getDate() {
- return date;
- }
- public void setDate(Date date) {
- this.date = date;
- }
- @Override
- public String execute() throws Exception {
- return SUCCESS;
- }
- }
4.类型转换的局部资源配置文件ConverterAction-conversion.properties
- # 局部的 --> 类型转换资源文件
- # 这个资源文件的文件名是有规定的:
- # 前半部分:ConvertorAction --> 必须与对应的Action一致。
- # 后半部分:-conversion.properties --> 固定格式,不能修改。
- # 书写内容:你对ConvertorAction中的哪个属性进行转换
- # 对ConvertorAction类中的point对象属性,用edu.hust.common.Convertor类进行转换
- # 局部convertion.properties和全局convertion.properties同时定义了对某一类型的转换时,局部有效、全局无效。
- point = edu.hust.common.Converter
类型转换的全局资源配置文件xwork-conversion.properties
- # 全局的 --> 类型转换资源文件
- # 这个资源文件的文件名是固定的,不能修改。
- # 对整个的PointBean进行转换,无论哪里用到Point类(即只要调用了PointBean),转换就会执行。
- # 局部convertion.properties和全局convertion.properties同时定义了对某一类型的转换时,局部有效、全局无效。
- edu.hust.bean.Point = edu.hust.common.Converter2
5.最后是struts.xml和jsp页面, 这些和普通struts2无异
- <%@ page contentType="text/html;charset=GBK"%>
- <%@ taglib prefix="s" uri="/struts-tags" %>
- <s:form action="converter" method="post">
- <s:textfield name="point" label="point" />
- <s:textfield name="age" label="age" />
- <s:textfield name="username" label="username" />
- <s:textfield name="date" label="date" />
- <s:submit label="submit" />
- </s:form>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <package name="struts2" extends="struts-default">
- <action name="converter" class="edu.hust.action.ConverterAction">
- <result>/result.jsp</result>
- </action>
- </package>
- </struts>
- <%@ page contentType="text/html;charset=GBK"%>
- <%@ taglib prefix="s" uri="/struts-tags" %>
- <html>
- <head><title>Login Page</title></head>
- <body bgcolor="#99ffff">
- <!-- 如果使用了*.properties进行类型转化,你会发现用el输出和用s标签输出效果完全不同, 建议使用s标签 -->
- <h2>使用s标签显示</h2>
- point: <s:property value="point" /><br>
- age: <s:property value="age" /><br>
- username: <s:property value="username" /><br>
- date: <s:property value="date" /><br><br>
- <h2>使用el显示</h2>
- point: ${point}<br>
- age: ${age}<br>
- username: ${username}<br>
- date: ${date}<br>
- </body>
- </html>