`

struts2 converter 之类型转换器

 
阅读更多

1. 前面讲的自定义类型转换器是基于 OGNL 的 DefaultTypeConverter 类并实现 convertValue() 方法,两个转换方向的逻辑都写在这一个方法中。而 Struts 2 为我们提供了一个 DefaultTypeConverter 的抽象子类 StrutsTypeConverter 来继承,并实现其中两个抽象方法 convertFromString() 和 convertToString(),这要简单易懂。对比 Struts 1 的转换器是要实现 org.apache.commons.beanutils.Converter 接口,以及它的 convert() 方法的。

2. 注意,上面的 convertFromString() 的第二个参数是一个字符串数组,所以可为请求的数组(如请求串为 ?u=1&u=2&u=3)定义转换器,Action 中相应的属性就应为数组或 List,这一方法的返回值也该为相应的类型(数组或List,要通过第三个参数 toClass 来判断是返回数组还是 List 了)。

3. 字符串(如 "user,pass") 转换成 Action 中的复合属性(如 User user) 前面是自定了类型转换器。除此之外,还可以 Struts 2 内置的 OGNL 表达式,更简单的转换,不用写转换器。例如,你的 Action 有属性 User user,只要在 jsp 页面的输入框命名为 user.name  和 user.pass 即可:
        <input type="text" name="user.name"/> 或用标签:<s:textfield name="user.name" label="用户名"/>
        <input type="text" name="user.pass"/>  或用标签:<s:textfield name="user.pass" label="密 码"/>
    提交后,Struts 2 即会帮你构造 User 对象(user = new User()),并赋上属性值(user.setName(),user.setPass()),最后 user 对象赋给 Action (xxxAction.setUser(user))。所以要明白有三个必备的东西:
        1) User 要用一个默认构造方法 2) User 要有对应 name 和 pass 的设置方法 setName() 和 setPass() 3) Action 要有 user 属性的设置方法 setUser(),getUser() 也是要的,至于功用后面能看到。
其实在 Struts 1 中也有这种用法,不过那是在 BeanUtils 中实现的。

4. 如果 Action 中的属性是 Map<String, User> users; 那么与此对应的表单写法就是:(用标签来写)
        <s:textfield name="users['one'].name" label="第一个用户名"/>
        <s:textfield name="users['one'].name" label="第一个密码"/>
        <s:textfield name="users['two'].name" label="第二个用户名"/>
        <s:textfield name="users['two'].name" label="第二个密码"/>
    应该不难想像,这个表单提交后,users  中存储的是什么吧!
    如果是对于 Action 中的  List 属性,List<User> users; 那么与此对应的表单写法就是:
        <s:textfield name="users[0].name" label="第一个用户名"/>
        <s:textfield name="users[0].name" label="第一个密码"/>
        <s:textfield name="users[1].name" label="第二个用户名"/>
        <s:textfield name="users[1].name" label="第二个密码"/>

5. 归纳前面3、4、5 几点,Struts2 的 Action 在设置每一个属性时都会 get 一下相应的元素 getUser() 或 getUsers()。
    对于 3,在设置 user.name 和 user.pass 之前都会 getUser() 来获取 user 属性,如果 user 为 null 就构造 User 对象,然后设置相应的值。假如声明的时候就已构造好 User 对象,如有其他属性如 age=18,并不会被覆盖。 
   对于 4 和 5,也是在设置每一个属性前都会调用 getUsers() 判断声明的 Map 或 List 是否为 null,是则构造对应的 HashMap 或  ArrayList() 对象;接着根据 Key 或下标去获取相应位置的元素,如果不存在或为 null 则构造之,然后设置相应属性值。由此可见,若某元素的某个属性未重设值则保留原值,若原来Map或List 已有多个元素,也只会改变到 Key 或索引所对应元素的某个属性。对于 List 有可能出现跳空的情况,如页面只有索引不从 0 开始
         <s:textfield name="users[1].name" label="第二个用户名"/>
        <s:textfield name="users[1].name" label="第二个密码"/>
提交后就会发现,List 属性 users 的第一个元素为 null 了。同时如果尝试一下,你就会发现这里的 List 不能替代为数组 User[] users。 
    这种样法,可在 Struts 1 中实现,但要略施些小节,见我的另一篇日志:提交多行数据到Struts的ActionForm的List属性中 ,行为表现完全一致,只是换到 Struts 2 中一切都不用自己操心。

6. 看第四点,Action 之所以知道该构造什么类型的元素完全是由泛型告诉它的。如果不用泛型(比如用的是 JDK1.4),Action 中仅仅声明的是 Map users; 或 List users; Action 该如何处理呢?它也不知道,只能够帮你构造出无类型的 HashMap 和 ArrayList(),填充不了元素。这就必须在局部类型转换的配置文件中来指定集合元素的类型。例如 Action 为 LoginAction,就要在 LoginAction-conversion.properties 中声明了,格式如下:

    #Element_xxx=复合类型,基中 Element 是固定的,xxx 为属性名
    #下面表示为 List 属性 users 的元素为 com.unmi.vo.User 类型
     Element_users=com.unmi.vo.User

    对于 Map,须分别指定 Key 的类型和 Value 的类型
    #Key_xxx=复合类型,基中 Key 是固定的,xxx 为 map 属性名,下面写成 String 都不行的
    Key_users=java.lang.String
    指定 Map 的 Value 的类型与指定 List 元素类型是一样的
    Element_users=com.unmi.vo.User

难 怪 Struts 2 要与 1.5 以上 JDK  使用,泛型比配置来得方便。如果硬要用 1.4 JDK,就只有配置类型了,会多很多 conversion 文件的。在 提交多行数据到Struts的ActionForm的List属性中 中类型的确定由 AutoArrayList() 的构造参数完成。

7. Set 是无序集合,所以无法像 List 那样用数字下标来访问,幸好 Struts 2 可为其指定索引属性。例如,LoginAction 声明为 Set users; (这里好像用泛型只能省得了 Element_users 说明,KeyProperty_users 少不了)。则需在 LoginAction-conversion.properties 中写下:
    #指定 Set 的元素类型
    Element_users=com.unmi.vo.User

    #KeyProperty_集合属性名=集合元素的索引属性名,这里为 User 的 name 属性
    KeyProperty_users=name

此时提交页面这么写,最好提交前能根据输入的用户名自动修动输入框的 name。
        用户名: <input name="users('scott').name"/>
        密 码: <input name="users('scott').pass"/>
显示的时候页面可用标签
        用户名: <s:property value="users('scott').name"/>
        密 码: <s:property value="users('scott').pass"/>
注意前面,访问 Set 元素是用的圆括号,而不同于 Map、List、数组是用中括号。我想一般也犯不着非要用 Set 而不用 List,Struts 2 中用 Set 比在 Struts 1 中似乎还麻烦。

8. Struts 2 内建了一批转换器:boolean、char、int、long、float、double 和它们的包装类型;Date,日期格式使用请求所在 Locale 的 SHORT 格式;数组,默认元素为字符串,其他类型则要转换每一个元素?(好像是一次性转换完成的); 集合,默认元素为字符串 XWorkList(String.class, Object[]),其他如 List<Integer> ids,类型为 XWorkList(Integer.class, Object[]),XWorkList 继承自 ArrayList。

9. 类型转换出错由 Struts 来帮你处理,在默认拦截器栈中提供了 conversionError 拦截器,不用你写一点代码逻辑。conversionError 在出错时将错误封装成 fieldError,并放在 ActionContext 中。你所要做的就是遵循它的规则,1) 你的 Action 要继承自 ActionSupport,2)在 struts.xml 中声明名为 "input" 的 result,出错时会在 input 逻辑视图显示信息。3)尽量用标签来写输入域(如<s:textfield name="number" label="数量"/>),这样转换出错后,就会像校验失败一样把错误信息显示在每个输入框上面(视模板而定),否则要手工用 <s:fielderror/> 输出在某处。
默认时输出错误信息为(比如是属性 number,输入的是字符串时):Invalid field value for field "number".你可以改变默认显示,在全局国际化资源文件中加上xwork.default.invalid.fieldvalue={0}字段类型转换失败!。在某些时候,可能还需要对特定字段指定特别的提示信息,那么在名为 ActionName.properties 的局部资源文件中加上 invalid.fieldvalue.属性名=提示信息 (如 invalid.fieldvalue.number=数量格式错误)

10. 最后是集合属性转换错误时的显示,对于页面中的同名输入框,有多个出错误,如果手工用 <s:fieldError/> 只会显示一条错误,但要是输入页是用标签(如<s:textfield name="number" label="数量"/>),仍会在每一个出错的输入框上都提示。至此类型转换的内容也就完结了。

 

分享到:
评论

相关推荐

    自己写的struts2类型转换器

    服务器可以接收到的来自用户的数据只能是字符串或者是字符串数组,而在服务器上的对象中 ,这些数据往往有多种不同的类型,如日期(Date) 整数(int) 浮点数... 要实现 上述的转换 ,Struts2中 提供了 converter。

    转换器(Converter),struts 实例学习

    转换器(Converter),struts 实例学习,一步步教你如何实现一个示例

    个人认为目前最完备的Struts2教程

    05 转换器(Converter)——Struts 2.0中的魔术师 06 在Struts 2.0中实现表单数据校验(Validation) 07 Struts 2的基石——拦截器(Interceptor) 08 在Struts 2中实现IoC 09 在Struts 2中实现文件上传 10 在Struts...

    struts2.0中文教程

    05 转换器(Converter)——Struts 2.0中的魔术师 06 在Struts 2.0中实现表单数据校验(Validation) 07 Struts 2的基石——拦截器(Interceptor) 08 在Struts 2中实现IoC 09 在Struts 2中实现文件上传 10 在Struts...

    struts2入门教程

    ·Struts2.0转换器(Converter) ·Struts 2.0中实现表单数据校验(Validation) ·拦截器(Interceptor) ·Struts 2中实现IoC ·Struts 2中实现文件上传 ·Struts 2中的OGNL ·Strus 2的新表单标签的使用 ...

    Struts 2.0系列(MAX)

    转换器(Converter)——Struts 2.0中的魔术师 在Struts 2.0中实现表单数据校验(Validation) Struts 2的基石——拦截器(Interceptor) 在Struts 2中实现IoC 在Struts 2中实现文件上传 在Struts 2中实现CRUD ...

    Struts2.0中文教程权威版

    05 转换器(Converter)——Struts 2.0中的魔术师 06 在Struts 2.0中实现表单数据校验(Validation) 07 Struts 2的基石——拦截器(Interceptor) 08 在Struts 2中实现IoC 09 在Struts 2中实现文件上传 10 在Struts...

    Struts2例子6

    example6 : 转换器(Converter)——Struts 2_0中的魔术师

    Struts2 入门培训

    4 1.3.2. 受控目录 5 2. 入门例子 5 2.1. 项目 5 2.2. 在WEB.XML中,配置FILTERDISPATCHER过滤器 6 2.3. 配置STRUTS.PROPERTIES 6 2.4. 编写一个简单的ACTION类 7 2.5. STRUTS.XML配置文件 8...

    struts2教程word文档格式

    1-helloworld 2-常用标签 3-action 4-I18N国际化 5-转换器Converter 6-表单数据验证 ... 15-AJAX

    转换器(Converter)——Struts 2.0中的魔术师

    NULL 博文链接:https://corrinejtt.iteye.com/blog/548160

    尚硅谷stuts2练习-converter-address

    尚硅谷stuts2练习中的自定义类型转换器练习

    自己做的struts2的小例子

    struts2的小例子,包括切换语言,converter(转换器),CRUD(新增,读取,更新,删除),文件上传,interceptor(拦截器),OGNL(Object-Graph Navigation Language),springIOC,validation(验证框架)

    struts2.0很全面的中文教程

    1.为Struts 2.0做好准备 2.常用的Struts 2.0的标志(Tag)介绍 3.Struts 2.0的Action讲解 ...5.转换器(Converter)——Struts 2.0中的魔术师 在6.Struts 2.0中实现表单数据校验(Validation) 7....... 8.......

    拦截器和控制器的区别

    converter 转换器 i18n struts2 spring MVC 拦截器 interceptor 过滤器 filter web.xml implements filter filterchain arg2.doFilter(req,resp); 监听器 servlet application /session /request 6/8 个 ...

    JavaServer Faces 2.0完全参考手册(JSF2.0中文版) 1/2

    8.3.3 关联转换器与UI Component实例 8.3.4 转换器的生命周期 8.3.5 定制转换器 8.4 Faces验证系统 8.4.1 Long Range Validator 8.4.2 Double Range Validator 8.4.3 Length Validator 8.4.4 必需的工具Required ...

    JavaServer Faces 2.0完全参考手册(JSF2.0中文版).part1

    8.3.3 关联转换器与UI Component实例 8.3.4 转换器的生命周期 8.3.5 定制转换器 8.4 Faces验证系统 8.4.1 Long Range Validator 8.4.2 Double Range Validator 8.4.3 Length Validator 8.4.4 必需的工具Required ...

Global site tag (gtag.js) - Google Analytics