对于前台界面向后台传送的数据,strtus2可以帮助我们自动的转换其中的一些,包括:java中8中原生数据类型以及像String、Date等常见数据类型,但对于自定义的数据类型还需要我们自己写转换器进行转换。
前台界面提交的表单:
<form action="user"> 姓名:<input type="text" name="username" /><br/> 年龄:<input type="text" name="age" /><br/> 生日:<input type="text" name="birthday" /><br/> 身高:<input type="text" name="stature"/><br/> <input type="submit" value="submit" /> </form>struts.xml配置文件:
<struts> <package name="struts2" extends="struts-default"> <action name="user" class="com.dr.action.UserAction" method="method1"> <result name="success">/result.jsp</result> </action> </package> </struts>UserAction方法:(属性名与表单name可以不一致,但set方法名必须一致,但一般情况下我们都是让属性名与name一致,自动生成get&set方法)
public class UserAction extends ActionSupport{ private String username; private int age; private Date birthday; private float stature; /* * 此处省略get & set 方法 * 注意set方法名需要和表单中的name名一致, * 否则,struts无法自动完成类型转换 * */ public String method1(){ return SUCCESS; } }result.jsp输出数据类型转换的结果:
<body> 姓名:${requestScope.username }<br/> 年龄:${requestScope.age} <br/> 生日: ${requestScope.birthday }<br/> 身高:${requestScope.stature }<br/> </body>运行,访问前台界面:
result输出的结果:
姓名:dr 年龄:20 生日: Sat Jul 31 00:00:00 GMT+08:00 1993 身高:176.0显然,这里对于String、int、Date以及float型的变量是Struts2自动帮助我们的转换的。
但是,对于上面的例子,如果我们在生日框内只输入年份,而不是按照上述格式输入,就会报错,无法完成转换;抑或我们想把前台传来的数据转成我们自定义的数据类型,struts2就不能自动帮助我们完成,这时就需要我们自己编写转换器完成转换。
对于前台提交的表单:(输入:dr;20;1993;176)
<h2>姓名;年龄;出生年份;身高 (数据之间用分好;隔开)</h2> <form action="user2"> userinfo:<input type="text" name="user" /><br/> <input type="submit" value="submit" /> </form>struts.xml配置文件中:
<action name="user2" class="com.dr.action.UserAction2" method="method1"> <result name="success">/result2.jsp</result> </action>
public class User {
private String username;
private int age;
private Date birthday;
private float stature; //此处省略了get&set方法 }
UserAction2中我们希望直接转成User对象过来,当然我们可以利用request.getparameter()方法,解析字符串,但这样显然跟我们使用struts2的初衷相违,这里我们利用ognl自定义一个类型转换器,使数据进入action方法的时候是以一个user对象。
自定义User类型转换器UserConverter:(继承了ognl的DefaultTypeConverter类,重写了它的convertValue方法,把前台数据转换成目标数据)
public class UserConverter extends DefaultTypeConverter{ /** * value:前台框架传过来的数据 * toType:需要转换成的目标对象类型 */ @Override public Object convertValue(Map context, Object value, Class toType) { if(User.class == toType){ //由前台向后台转换 String[] str = (String[])value; String userinfo = str[0]; StringTokenizer st = new StringTokenizer(userinfo,";"); String username = st.nextToken(); int age = Integer.parseInt(st.nextToken()); String birthday = st.nextToken(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); Date birth = null; try { birth = sdf.parse(birthday); } catch (ParseException e) { e.printStackTrace(); } String firstStature = st.nextToken(); float stature = Float.parseFloat(firstStature); User user = new User(); user.setUsername(username); user.setBirthday(birth); user.setStature(stature); user.setAge(age); return user; }else if(String.class == toType){ //从后台向前台转换 User user = (User)value; String userinfo = "username: "+user.getUsername()+",age: "+user.getAge()+ "birthday: "+user.getBirthday()+",stature: "+user.getStature(); return userinfo; } return null; } }这样只是定义了转换类,还需要一个属性文件告诉struts2,何时去调用这个转换,我们在action的同级目录下建一个UserAction2-conversion.properties的文件,里面的内容是:user=com.dr.converter.UserConverter 。说明:文件名必须是相应的Action名+conversion.properties,形式:xxx-conversion.properties,内容中:key:action中需要转换的属性名,value是转换器的包名,格式必须完全一致。
所以,在UserAction2中我们直接使用User类:(运行可以进入action类的时候,已经是user对象,而不需要再次转换)
public class UserAction2 extends ActionSupport{ private User user; /* * 此处省略get & set 方法 * */ public String method1(){ System.out.println("username: "+user.getUsername()); System.out.println("age: "+user.getAge()); System.out.println("birthday: "+user.getBirthday().toString()); System.out.println("stature: "+user.getStature()); return SUCCESS; } }前台的输出界面:
userinfo: username: dr,age: 20birthday: Fri Jan 01 00:00:00 GMT+08:00 1993,stature: 176.0
public class UserConverter2 extends StrutsTypeConverter { @Override public Object convertFromString(Map arg0, String[] arg1, Class arg2) { String[] str = (String[])arg1; String userinfo = str[0]; StringTokenizer st = new StringTokenizer(userinfo,";"); String username = st.nextToken(); int age = Integer.parseInt(st.nextToken()); String birthday = st.nextToken(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); Date birth = null; try { birth = sdf.parse(birthday); } catch (ParseException e) { e.printStackTrace(); } String firstStature = st.nextToken(); float stature = Float.parseFloat(firstStature); User user = new User(); user.setUsername(username); user.setBirthday(birth); user.setStature(stature); user.setAge(age); return user; } @Override public String convertToString(Map arg0, Object arg1) { User user = (User)arg1; String userinfo = "username: "+user.getUsername()+",age: "+user.getAge()+ "birthday: "+user.getBirthday()+",stature: "+user.getStature(); return userinfo; } }这里我们继承了struts2的一个StrutsTypeConverter,实现它的两个抽象方法,方法内容就是我们之前的if和else的内容,所以,我们知道这两个方法一个负责前台到后台的转换,一个负责后台到前台的转换,只不过这里不需要我们判断,其实这是因为strtus2在底层包装的时候已经做了判断,我们只需重写即可。
我们不妨看看strutsTypeConverter的源码:
public abstract class StrutsTypeConverter extends DefaultTypeConverter { public Object convertValue(Map context, Object o, Class toClass) { if (toClass.equals(String.class)) { return convertToString(context, o); } else if (o instanceof String[]) { return convertFromString(context, (String[]) o, toClass); } else if (o instanceof String) { return convertFromString(context, new String[]{(String) o}, toClass); } else { return performFallbackConversion(context, o, toClass); } }
.....
}
真想大白。。
还有一种全局的类型转换区别在于,属性文件是xwork-conversion.properties,放在src目录下,内容中:key=类名(含包名),value和以前一样