本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188

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

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

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

一:自定义类型转换器

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

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

publicclass DefaultTypeConverter implements TypeConverter{        public DefaultTypeConverter(){            super();        }    /**     * @param context:类型转换的上下文     * @param value:需要转换的参数     * @param toType:转换后的目的类型    */    public Object convertValue(Map context,     Object value,     Class toType)        {            return OgnlOps.convertValue(value, toType);        }    public Object convertValue(Map context, Object target,     Member member, String propertyName,     Object value, Class toType)        {            return convertValue(context, value, toType);        }  }      

convertValue方法的作用:

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

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

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

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

2. 基于Struts2的类型转换器

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

publicabstractclass StrutsTypeConverter extends DefaultTypeConverter {       //重写DefaultTypeConverter类的convertValue方法     public Object convertValue(Map context, Object o, Class toClass) {            //如果需要把复合类型转换成字符串类型    if (toClass.equals(String.class)) {                return convertToString(context, o);            }      //如果需要把字符串转换成符合类型    elseif (o instanceof String[]) {                return convertFromString(context, (String[]) o, toClass);            }     //如果需要把字符串转换成符合类型    elseif (o instanceof String) {                return convertFromString(    context, new String[]{(String) o}, toClass);            } else {                return performFallbackConversion(context, o, toClass);            }        }    protected Object performFallbackConversion(Map context,     Object o, Class toClass) {            returnsuper.convertValue(context, o, toClass);        }    publicabstract Object convertFromString(Map context,     String[] values, Class toClass);    publicabstract String convertToString(Map context, Object o);    }    

该类已经实现了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;

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

Conversion02Action.java    public class Conversion02Action extends ActionSupport {         private List lists;         private Map maps;         public String execute()throws Exception{                  System.out.println(((Person)lists.get(0)).getGender());                  System.out.println(((Person)lists.get(0)).getSalary());                  System.out.println(((Person)maps.get("one")).getGender());                  System.out.println(((Person)maps.get("one")).getSalary());                  return SUCCESS;         }         public List getLists() {                  return lists;         }         public void setLists(List lists) {                  this.lists = lists;         }         public Map getMaps() {                  return maps;   }         public void setMaps(Map maps) {                  this.maps = maps;         }  }      

Conversion02Action-conversion.properties

Element_lists=org.person.Person      Key_maps=java.lang.String      Element_maps=org.person.Person      

页面表单:

<s:fielderror></s:fielderror>        <s:form action="conversion02" >             <s:textfield label="list1.salary" name="lists[0].salary"></s:textfield>              <s:textfield label="list1.gender" name="lists[0].gender"></s:textfield>              <s:textfield label="map1.gender" name="maps['one'].gender"></s:textfield>            <s:textfield label="map1.salary" name="maps['one'].salary"></s:textfield>            <s:submit value="提交"></s:submit>         </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中的配置信息:

<interceptor-stack name="defaultStack">         .. .. ..          <!—- 处理类型转换错误的拦截器 -->    <interceptor-ref name="conversionError"/>         <!—- 处理数据校验的拦截器 -->    <interceptor-ref name="validation">              <param name="excludeMethods">input,back,cancel,browse</param>         </interceptor-ref>         <interceptor-ref name="workflow">              <param name="excludeMethods">input,back,cancel,browse</param>         </interceptor-ref>    </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、将返回的值直接带出到要展示的页面当中去展示。

 

转载于:https://blog.51cto.com/javacsh/1129225

Java程序员从笨鸟到菜鸟之(四十四)细谈struts2(七)数据类型转换详解相关推荐

  1. java程序员从笨鸟到菜鸟_Java程序员从笨鸟到菜鸟之(十四)Html基础积累总结(上)...

    [新朋友]点击标题下面(↑)蓝色字"Java那些事"关注 [老朋友]点击右上角,转发或分享本页面内容 这是我以前写的<java程序员由笨鸟到菜鸟>系列博客,每天更新一篇 ...

  2. Java程序员从笨鸟到菜鸟之(十)枚举,泛型详解

    一:首先从枚举开始说起 枚举类型是JDK5.0的新特征.Sun引进了一个全新的关键字enum来定义一个枚举类.下面就是一个典型枚举类型的定义: public enum Color{ RED,BLUE, ...

  3. Java程序员从笨鸟到菜鸟之(九十四)深入java虚拟机(三)——类的生命周期(下)类的初始化...

    上接深入java虚拟机--深入java虚拟机(二)--类加载器详解(上),在上一篇文章中,我们讲解了类的生命周期的加载和连接,这一篇我们接着上面往下看. 类的初始化:在类的生命周期执行完加载和连接之后 ...

  4. Java程序员从笨鸟到菜鸟全部博客目录

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.NET/csh624366188 欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章 大 ...

  5. Java程序员从笨鸟到菜鸟之(序言)+全部链接

    http://blog.csdn.net/csh624366188 大学上了一年半,接触java也一年半了,虽然中间也有其他东西的学习,但是还是以java为主路线,想想这一年半,除去前半年几乎全玩了, ...

  6. Java程序员由笨鸟到菜鸟 电子版书正式发布 欢迎大家下载

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 欢迎关注 ...

  7. Java程序员从笨鸟到菜鸟之——总结和声明

    前段时间经过大约二十天的时间把javaSE的内容总结了一下,最近由于个人原因和一些乱七八糟的事情,一直没在更新,首先感谢那些一如既往支持我的朋友.最近不知道为什么,一直很懒,做东西也一直是效率很低,生 ...

  8. Java程序员从笨鸟到菜鸟之(五)java开发常用类(包装,数字处理集合等)(下)...

     本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 写在前面:由于前天项目老师建设局的项目快到验收阶段,所以,前天晚上通宵,昨天睡了大半天, ...

  9. Java程序员从笨鸟到菜鸟之(一百零九)一步一步学习webservice(三)开发第一个基于XFire的webservice

    在日常开发中,常用的webservice引擎主要有Axis,axis2,Xfire以及cxf(Xfire的升级版).现在只有axis2和cxf官方有更新.今天我们先以一个比较老的引擎为例.来讲诉一下w ...

  10. Java程序员从笨鸟到菜鸟之(一百零八)一步一步学习webservice(二)webservice基本原理

    本来这第二篇打算讲解"开发第一个基于XFire的webservice"的内容来着.但是想想.开发实例只是局限于了会用的层面上.如果想真正的理解webservice还是需要挖掘其原理 ...

最新文章

  1. sql文本编辑器_专业文本编辑工具
  2. mybatis学习笔记二(接口注解)
  3. java青蛙青蛙跳井_公务员行测技巧:青蛙跳井问题
  4. 【Android 安装包优化】Android 中使用 SVG 图片 ( Android 5.0 以下的矢量图方案 | 矢量图生成为 PNG 图片 )
  5. [mmu/cache]-ARMV8 MMU内存管理中的Memory attributes和Cache policies
  6. 数字开头的正则表达式_初学Web前端要注意什么 正则表达式是怎么回事
  7. VTK:图片之ImageNonMaximumSuppression
  8. 定义[nextTick、事件循环]
  9. 嵌入式linux系统中设备驱动程序
  10. oracle 之索引,同义词 ,关键词,视图 ,存储过程,函数,触发器
  11. 第一:MySQL安装和配置(超详细)
  12. C语言结构体内存对齐
  13. Nodejs KOA服务搭建打包
  14. matlab 文本框方向,ppt文本框文字方向为所有文字旋转的设置方法
  15. 蠢蛋秀:匠心独运的脑筋急转弯游戏
  16. 机器学习分类模型评价指标之混淆矩阵
  17. 校园网dns服务器可以自动么,校园网应有自己的DNS服务
  18. 甲骨文大数据利器:内存数据库和一体机
  19. Nvidia 英伟达的NSight GPU 调试如何下载
  20. 跨境购物,电商平台与保税仓对接时,如何推送订单金额?

热门文章

  1. mysql的联合索引_mysql联合索引
  2. MySQL退出选择表格_MySQL常用命令
  3. mac idea用自带的maven还是_苹果电脑自带截图工具怎么用?mac自带截屏工具使用技巧分享
  4. java 方法 参数 引用_Java 基础
  5. python聚类分析如何确定分类个数_Python数据挖掘—聚类—KMeans划分法
  6. MariaDB(MySQL)_MariaDB(Mysql)-主从搭建
  7. python埋点自动化_iOS自动化埋点的实现
  8. IIS6下PHP的ISAPI和FastCGI性能比较 期待ii7
  9. 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(二)
  10. Ubuntu编译安装VASP