• 1. 第十章:Struts 2类型转换 主讲:刘雷
  • 2. 学习目标了解类型转换的概念 创建自定义类型转换器
  • 3. 什么是类型转换所有页面与控制器传递的数据均为String类型,而我们在对其进行处理时可能会用到各种数据类型,程序无法自动完成数据类型的转换,需要我们在代码中手动完成,这个过程称为类型转换。
  • 4. 举例电话号码和日期转换页面中的生日字段,就需要相应的转换,传统的手动类型转换如下: SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd”); Date birthday = null; try{ birthday = sdf.parse(request.getParameter(“birthday”)); }catch(ParseException e){ e.printStackTrace(); }
  • 5. 创建自定义类型转换器Struts2有内置的类型转换器, 如果内置类型转换器无法满足你的应用需求,你可以开发自己的类型转换器。要创建一个类型转换器,你需要实现ognl.TypeConverter接口,该接口中只有一个方法,如下所示: public Object convertValue(Map context, Object target, Member member, String propertyName,Object value, Class toType) 该方法过于复杂,所以在OGNL中还提供了一个工具类ognl.DefaultTypeConverter,该项类实现了TypeConverter接口,并提供了一个简化的converValue()方法,如下所示: public Object convertValue(Map context, Object target,Class toType) 参数context是表示OGNL上下文的Map对象,target是需要转换的对象,toType是要转换的目标类型。
  • 6. 编写类型转换器编写类型转换器时, 除了可以继承OGNL中的DefaultTypeConverter类外,还可以继承struts2中给出的org.apache.struts2.util.StrutsTypeConverter抽象类。StrutsTypeConverter继承自ognl.DefaultTypeConverter类,它提供了两个抽象的方法用于字符串和其它类型的相互转换。这两个方法如下所示: public Object convertFromString(Map context, String[] values, Class toClass) 将一个或多个字符串值转换为指定的类型。 参数context是表示action上下文的Map对象, 参数values是要转换的字符串值, 参数toClass是要转换的目标类型。 public String convertToString(Map context, Object obj) 将指定的对象转换为字符串。 参数context是表示action上下文的Map对象。 参数obj是要转换的对象。
  • 7. 配置类型转换器在struts2中提供了两种方式来配置转换器,一种是应用于全局范围的类型转换器, 另一种是应用于特定类的类型转换器。 1:应用于全局范围的类型转换器 要指定应用于全局范围的类型转换器,需要在CLASSPATH的根路径下(通常是WEB-INF/classes目录)创建一个名为xwork-conversion.properties的文件,并提供一个属性定义,属性名是要转换的类的名称,属性值是类型转换器的类名称。例如,为所有的java.util.Date对象提供一个DateTypeConverter转换器,你需要在xwork-conversion.properties文件中添加下列内容: Java.util.Date=com.ibm.converter.DateTypeConverter 2:应用于特定类的类型转换器 如果你的类型转换器只是针对某个类的属性,那么可以采用这种方式,配置针对某个特定类的类型转换器,方法是在类所在的包中创建ClassName-conversion.properties文件(ClassName替换为实际的类名),并提供一个属性定义,左边是要转换的类的属性名,右边是类型转换器的类名称。例如:要为User类指定一个类型转换器,你需要在该类所在的包中创建User-conversion.properties文件,并添加下列内容: birthday=com.ibm.converter.DateTypeConverter
  • 8. 日期转换DateTypeConverter.java
  • 9. LoginAction.java与login.jsp
  • 10. 转换器配置struts.xml成功页面
  • 11. 电话转换一User.javaTel.java
  • 12. 电话转换二LoginAction.javalogin.jsp
  • 13. 电话转换三
  • 14. 电话转换四convSuc.jsp
  • 15. 类型转换错误的处理一用户在填写表单时,经常会输入一些格式不正确的数据,例如,在需要int数据的地方输入了abc,或者在需要日期格式是1983-1-2的地方,输入了1983/1/2。格式不正确转换的数据在类型转换过程中会导致错误的发生。当发生了类型转换错误后,struts2会将转换错误放到ActionContext中一个名为conversionErrors的Map对象中。在出现类型转换错误后,你可以选择是否向用户提示转换错误。
  • 16. 类型转换错误的处理二在struts2中有两个拦截器负责类型转换错误,如下所示: com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor: conversionErrorInterceptor把在ActionContext的conversionErrors Map中找到的所有错误都添加为action的字段错误(Action需要实现ValidationAware接口,ActionSupport基类实现了该接口),此外,它还把有转换错误的字段的原始值保存下来,这样之后对这个值的请求得到的就是原始值而不是action中的值。这有什么好处呢?假如你在user.age字段上输入abc,由于类型错误,User对象的age属性将是0。由于出现了错误,你把请求重新导向到输入页面,此时表达式user.age将会调用getUser().getAge()方法,于是在表单字段上用户看到的是0,而不是原始的错误值。显然,这很容易让用户迷惑,这不是一种用户友好的提示方式。 org.apache.struts2.interceptor.StrutsConversionErrorInterceptor StrutsConversionErrorInterceptor继承自ConversionErrorInterceptor类,但是它只在字段值不是null、不是“”或者不是{“”}(表示只有一个空字符串元素的字符串数组)的情况下,把转换错误从ActionContext添加到action的字段错误。这在Web环境下是有用的。 在struts-default.xml文件中定义了conversionError拦截器,类型是StrutsConversionErrorInterceptor,这个拦截器已经包含在defaultStack拦截器栈中。 当发生了转换错误后, struts2会将请求导向到“input”结果代码映射的视图,因此要向用户提示转换错误信息,你还需要在Action的配置中添加input结果映射。
  • 17. 类型转换错误的处理总结总结一下:要向用户报告类型错误,需要实现下面三个步骤: 1、引用defaultStack拦截器栈(包含了conversionError拦截器) 2、让Action类从ActionSupport继承(实现了ValidationAware接口) 3、为Action配置添加input结果映射
  • 18. 修改错误信息显示内容输出错误信息可以使用fielderror标签来输出字段的错误信息。 当填写内容格式不正确时会在页面上出现Invalid field value for field “xxx.xxx”,很显然这不是我们想要的,我们自定义错误信息,步骤如下: 1、在src下新建资源属性文件夹ApplicationResources.properties,并添加下列内容:xwork.default.invalid.fieldvalue=字段”{0}”的值无效。 在输出类型转换错误消息时,占位符{0}将自动被字段名所替换。 2、编辑struts.xml文件,使用struts.custom.i18n.resources属性设置默认的资源包,如下所示: I18N消息键xwork.default.invalid.fieldvalue对所有字段的类型转换错误都适用,如果你想为某个特定字段定制错误消息,则可以在Action相关的资源文件中添加I18N消息键invalid.fieldvalue.xxx来指定错误消息,xxx是字段名称。资源文件的组织和加载顺序可以I18N章节。 举例: 在com.ibm.action.LoginAction相应的包新建LoginAction.properties文件,并添加下列内容:invalid.fieldvalue.user.birthday=无效字段值 或者在com.ibm.vo.User相应的包中新建User.properties文件,并添加下列内容: invalid.fieldvalue.birthday=无效字段值
  • 19. 谢谢!