Web应用程序的交互都是建立在HTTP之上的,互相传递的都是字符串。也就是说服务器接收到的来自用户的数据只能是字符串或者是字符数组,而在Web应用的对象中,往往使用了多种不同的类型,如整数(int)、浮点数(float)、日期(Date)或者是自定义数据类型等。因此在服务器端必须将字符串转换成合适的数据类型。

Struts2框架中为我们提供了一些简单类型的转换器,比如转换为int、float等简单数据类型是不需要我们自己定义转换器去转换的,struts2内部本身就为我们提供了转换的方法,但像一些复杂的类型和我们自定义的数据类型还是需要我们自己去写转换器去转换的。在转换工程中,如果在类型转换中出现异常,类型转换器开发者无需关心异常处理逻辑,Struts2的conversionError拦截器会自动处理该异常,并且提示在页面上生成提示信息。

下面我们就一步步的实现和注册一个我们自己的转换器,也就是自定义类型转换器的几个步骤:

一:自定义类型转换器

实现自定义类型转换器我们一般有两种方式:

1.实现OGNL提供的TypeConvert接口以及实现了TypeConvert接口的DefaultTypeConvert类来实现自定义的类型转换器。我们来看一下DefaultTypeConvert类的源码:

  1. publicclass DefaultTypeConverter implements TypeConverter{
  2. public DefaultTypeConverter(){
  3. super();
  4. }
  5. /**
  6. * @param context:类型转换的上下文
  7. * @param value:需要转换的参数
  8. * @param toType:转换后的目的类型
  9. */
  10. public Object convertValue(Map context,
  11. Object value,
  12. Class toType)
  13. {
  14. return OgnlOps.convertValue(value, toType);
  15. }
  16. public Object convertValue(Map context, Object target,
  17. Member member, String propertyName,
  18. Object value, Class toType)
  19. {
  20. return convertValue(context, value, toType);
  21. }
  22. }

convertValue方法的作用:

该方法负责完成类型的双向转换,为了实现双向转换,我们通过判断toType的类型即可判断转换的方向。toType类型是需要转换的目标类型,如:当toType类型是User类型时,表明需要将字符串转换成User实例;当toType类型是String类型时,表明需要把User实例转换成字符串类型。通过toType类型判断了类型转换的方向后,我们就可以分别实现两个方向的转换逻辑了。实现类型转换器的关键就是实现conertValue方法,该方法有三个参数:

第一个参数 context:类型转换的上下文

第二个参数 value:需要转换的参数

第三个参数 toType:转换后的目的类型

2. 基于Struts2的类型转换器

Struts 2提供了一个StrutsTypeConverter的抽象类,这个抽象类是DefaultTypeConverter类的子类。开发时可以直接继承这个类来进行转换器的构建。通过继承该类来构建类型转换器,可以不用对转换的类型进行判断(和第一种方式的区别),下面我们来看一下StrutsTypeConverter类的源码:

  1. publicabstractclass StrutsTypeConverter extends DefaultTypeConverter {
  2. //重写DefaultTypeConverter类的convertValue方法
  3. public Object convertValue(Map context, Object o, Class toClass) {
  4. //如果需要把复合类型转换成字符串类型
  5. if (toClass.equals(String.class)) {
  6. return convertToString(context, o);
  7. }
  8. //如果需要把字符串转换成符合类型
  9. elseif (o instanceof String[]) {
  10. return convertFromString(context, (String[]) o, toClass);
  11. }
  12. //如果需要把字符串转换成符合类型
  13. elseif (o instanceof String) {
  14. return convertFromString(
  15. context, new String[]{(String) o}, toClass);
  16. } else {
  17. return performFallbackConversion(context, o, toClass);
  18. }
  19. }
  20. protected Object performFallbackConversion(Map context,
  21. Object o, Class toClass) {
  22. returnsuper.convertValue(context, o, toClass);
  23. }
  24. publicabstract Object convertFromString(Map context,
  25. String[] values, Class toClass);
  26. publicabstract String convertToString(Map context, Object o);
  27. }

该类已经实现了DefaultTypeConverter的convertValue方法。实现该方法时,它将两个不同转换方向替换成不同方法——当需要把字符串转换成复合类型时,调用convertFromString抽象方法;当需要把复合类型转换成字符串时,调用convertToString抽象方法,下图展示了其对应关系:

二.注册自定义类型转换器:

实现了自定义的类型转换器之后,将该类型转换器注册在Web应用中,Struts2框架才可以正常使用该类型转换器,类型转换器的注册分为两种

1.注册局部类型转换器。

局部类型转换器仅仅对某个Action起作用。局部类型转换器非常简单,只需要在相应的Action目录下新建一个资源文件。该资源文件名格式如下。ActionName-conversion.properties。其中ActionName表示需要进行转换的Action的类名,“-conversion.properties”字符串则是固定格式的。该文件也是一个典型Properties文件,文件由键值对组成:propertyName = 类型转换器类

如:name=util.NameConvert

name:表示要进行转换的属性

util.NameConvert:表示要进行转换的自定义类型转换器。

注意:该属性文件应该与ActionName.class放在相同位置。

2.注册全局类型转换器。对所有Action的特定类型的属性都会生效。

全局类型转换器,必须提供一个xwork-conversion.properties文件。文件必须保存在classes目录下。该资源文件名格式如下:

复合类型=对应的类型转换器

复合类型:指定需要完成类型转换的复合类

对应的类型转换器:指定所指定类型转换的转换器。

如:注册User类的全局类型转换器为:UserConverter

cn.wjz.bean.User = cn.wjz.util.UserConverter

注意:如果局部类型转换和全局类型转换同时存在的话,局部类型转换具有较高的优先级,也就是以局部类型转换器为主。

三.集合类型的类型转换
对于List元素来说,内容如: Element_attributeName=typeName;

对于Map元素来说,

(1)如果表示key的类型,则:Key_attributeName=typeName;

(2)如果表示value的类型,则为:Element_attributeName=typeName;

比如,此处没有使用泛型,而是使用了局部类型转换文件:

  1. Conversion02Action.java
  2. public class Conversion02Action extends ActionSupport {
  3. private List lists;
  4. private Map maps;
  5. public String execute()throws Exception{
  6. System.out.println(((Person)lists.get(0)).getGender());
  7. System.out.println(((Person)lists.get(0)).getSalary());
  8. System.out.println(((Person)maps.get("one")).getGender());
  9. System.out.println(((Person)maps.get("one")).getSalary());
  10. return SUCCESS;
  11. }
  12. public List getLists() {
  13. return lists;
  14. }
  15. public void setLists(List lists) {
  16. this.lists = lists;
  17. }
  18. public Map getMaps() {
  19. return maps;
  20. }
  21. public void setMaps(Map maps) {
  22. this.maps = maps;
  23. }
  24. }

Conversion02Action-conversion.properties

  1. Element_lists=org.person.Person
  2. Key_maps=java.lang.String
  3. Element_maps=org.person.Person

页面表单:

  1. <s:fielderror></s:fielderror>
  2. <s:form action="conversion02" >
  3. <s:textfield label="list1.salary" name="lists[0].salary"></s:textfield>
  4. <s:textfield label="list1.gender" name="lists[0].gender"></s:textfield>
  5. <s:textfield label="map1.gender" name="maps['one'].gender"></s:textfield>
  6. <s:textfield label="map1.salary" name="maps['one'].salary"></s:textfield>
  7. <s:submit value="提交"></s:submit>
  8. </s:form>

四.Struts 2内建的类型转换器 :

Sturts 2为常用的数据类型提供了内建的类型转换器,所以根本不用自定义转换器。对于内建的转换器,Struts在遇到这些类型时,会自动去调用相应的转换器进行类型转换。

Struts 2全部的内建转换器:

·基本数据类型以及其封装类。包括:boolean和Boolean、char和Character、int和Integer、long和Integer、float和Float、double和Double。完成字符串和基本数据类型或其封装类之间的转换。

·日期类型。使用当前区域的短格式转换,即DateFormat.getInstance(DateFormat.SHORT)完成字符串和日期类型之间的转换。

·集合(Collection)类型。将request.getParameterValues(String arg)返回的字符串数据与Java.util.Collection转换。集合元素为String类型。

·集合(Set)类型。与Collection的转换相似,只是去掉了相同的值。集合元素为String类型。

·数组类型。将request.getParameterValues(String arg)返回的字符串数组中的每个字符串值取出组成一个数组。数组元素为String类型。

注意:Struts 2提供的全部内建转换器都是双向的,也就是说从用户输入页到服务器端时会将字符串类型转换成相应的数据类型。在显示输出时,又会将相应的数据类型转换成字符串类型来显

数组类型的转换器。这个转换器非常有用,比如多个表单元素的name属性相同,那么提交的参数就不再是字符串而是一个字符串数组。通过Sturts 2提供的数组类型的转换器就能很方便的将多个相同name属性的表单元素的值封装到Action中的一个数组中。

五.类型转换中错误处理:

1.类型转换的错误处理流程:

Struts2提供了一个名为conversionError的拦截器,这个拦截器被注册在默认的拦截器栈中,在Struts-default.xml中的配置信息:

  1. <interceptor-stack name="defaultStack">
  2. .. .. ..
  3. <!—- 处理类型转换错误的拦截器 -->
  4. <interceptor-ref name="conversionError"/>
  5. <!—- 处理数据校验的拦截器 -->
  6. <interceptor-ref name="validation">
  7. <param name="excludeMethods">input,back,cancel,browse</param>
  8. </interceptor-ref>
  9. <interceptor-ref name="workflow">
  10. <param name="excludeMethods">input,back,cancel,browse</param>
  11. </interceptor-ref>
  12. </interceptor-stack>

如果Struts2的类型转换器执行类型转换时出现错误,该拦截器将负责将对应的错误封装成表单域错误(fieldError),并将这些错误信息放入ActionContext中。

Struts2的错误处理流程:

2、错误信息的友好显示

在进行类型转换中,如果出现错误将会提示错误信息。Struts 2默认提供了错误信息提示,但是这些错误信息提示不够友好,下面将介绍如何自定义错误信息来取代Struts 2的默认错误信息。

·定义全局类型转换错误处理信息:

在应用的国际化资源文件中增加如下的信息:

xwork.default.invalid.fieldvalue = key

key的值就是用户希望在页面中显示的提示信息。  例如:

#改变默认的类型转换失败后的提示信息

xwork.default.invalid.fieldvalue = {0}字段类型转换失败!!

因为包含非西欧字符,因此使用 native2ascii 命令处理

xwork.default.invalid.fieldvalue =

{0}\u5b57\u6bb5\u7c7b\u578b\u8f6c\u6362\u5931\u8d25\uff01\uff01

·定义局部类型转换错误处理信息:

在某些时候可能还需要对特定的字段指定特别的提示信息,此时可以提供该Action的局部资源文件,文件名:ActionName.properties , 在文件中增加如下一项:

invalid.fieldvalue.属性名 =提示信息

例如:

#改变Action中birth属性类型转换错误后的提示信息

invalid.fieldvalue.birth = 生日信息必须满足yyyy-MM-DD格式

使用 native2ascii 命令处理

invalid.fieldvalue.birth =

\u751f\u65e5\u4fe1\u606f\u5fc5\u987b\u6ee1

\u8db3yyyy-MM-DD\u683c\u5f0f

 

六.类型转换的流程

1、用户进行请求,根据请求名在struts.xml中寻找Action

2、在Action中,根据请求域中的名字去寻找对应的set方法。找到后在赋值之前会检查这个属性有没有自定义的类型转换。没有的话,按照默认进行转换;如果某个属性已经定义好了类型转换,则会去检查在Action同一目录下的action文件名-conversion.properties文件。

3、从文件中找到要转换的属性及其转换类。

4、然后进入转换类中,在此类中判断转换的方向。我们是先从用户请求开始的,所以这时先进入从字符串到类的转换。返回转换后的对象。流程返回Action。

5、将返回的对象赋值给Action中的属性,执行Action中的execute()

6、执行完execute()方法,根据struts.xml的配置转向页面

7、在jsp中显示内容时,根据页面中的属性名去调用相应的get方法,以便输出

8、在调用get方法之前,会检查有没有此属性的自定义类型转换。如果有,再次跳转到转换类当中。

9、在转换类中再次判断转换方向,进入由类到字符串的转换,完成转换后返回字符串。

10、将返回的值直接带出到要展示的页面当中去展示。

struts2数据类型转换详解的更多相关文章

  1. 关于Struts2的类型转换详解

    详细出处参考:http://www.jb51.net/article/35465.htm 一.类型转换的意义 对于一个智能的MVC框架而言,不可避免的需要实现类型转换.因为B/S(浏览器/服务器)结构 ...

  2. ContentProvider数据访问详解

    ContentProvider数据访问详解 Android官方指出的数据存储方式总共有五种:Shared Preferences.网络存储.文件存储.外储存储.SQLite,这些存储方式一般都只是在一 ...

  3. 【HANA系列】SAP HANA XS使用JavaScript数据交互详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Jav ...

  4. struts2常用标签详解(申明:来源于网络)

    struts2常用标签详解(申明:来源于网络) 地址:http://blessht.iteye.com/blog/1184960

  5. JVM 运行时数据区详解

    一.运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同数据区域. 1.有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,所有的线程共享这些数据区. 2.第二种则 ...

  6. struts2基本配置详解2

    接上篇struts2基本配置详解,还有一些配置没有讲到,下面将继续. struts.xml <package name="com.amos.web.action" names ...

  7. 学习《深度学习与计算机视觉算法原理框架应用》《大数据架构详解从数据获取到深度学习》PDF代码

    <深度学习与计算机视觉 算法原理.框架应用>全书共13章,分为2篇,第1篇基础知识,第2篇实例精讲.用通俗易懂的文字表达公式背后的原理,实例部分提供了一些工具,很实用. <大数据架构 ...

  8. 【HANA系列】【第一篇】SAP HANA XS使用JavaScript数据交互详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第一篇]SAP HANA XS ...

  9. 3dTiles 数据规范详解[1] 介绍

    版权:转载请带原地址.https://www.cnblogs.com/onsummer/p/12799366.html @秋意正寒 Web中的三维 html5和webgl技术使得浏览器三维变成了可能. ...

随机推荐

  1. xpath与css基本使用方法

    path使用方法 1.工具Firefox50版本以下,安装插件firebug.firepath

  2. bin/mysqld: error while loading shared libraries: libnuma.so.1: 安装mysql

    如果安装mysql出现了以上的报错信息.这是却少numactl这个时候如果是Centos就yum -y install numactl就可以解决这个问题了. ubuntu的就sudo apt-get ...

  3. 创建新的C++工程来调用Caffe对图片进行识别

    前段时间一直在跑Caffe训练数据.之前用训练好的caffemodel对图片进行分类都是用的命令行指令,于是就想着自己新建一个工程来调用caffe,结合classification的代码来对图片进行分 ...

  4. bootstrap获取总条目数

    $('#table').on('load-success.bs.table', function () {alert($('#table').bootstrapTable('getOptions'). ...

  5. E - Rails (栈)

    E - Rails Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description The ...

  6. JS HTML DOM---Document对象

    Document 对象 当浏览器载入 HTML 文档, 它就会成为 document 对象. document 对象是HTML文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点). ...

  7. 巨蟒python全栈开发linux之centos5

    1.nginx安装使用 2.nginx访问日志和压测命令 3.nginx反向代理配置 nginx的404页面 访问:淘宝官网的一个错误地址:http://taobao.com/eeeeeeee 淘宝的 ...

  8. Ajax 处理json的方法不同

    json字符串从从后台传递到前台的方法有两种 1.使用context.Response(); 2.使用webmethod 方法调用静态函数 返回的字符串 前者返回的json是obj类型,而后者返回的是 ...

  9. What are DESC and ASC Keywords?

    What are DESC and ASC Keywords? ASC is the short form for ascending DESC is the short form for desce ...

  10. 怎样使用Chrome模拟手机浏览器測试移动端网站

    作者:zhanhailiang 日期:2014-10-10 环境说明: Chrome 37.0.2062.124 m 1. 通过[菜单→工具→开发人员工具|Javascript控制台]或[快捷键Ctr ...