`

《研磨struts2》第十一章 类型转换 之 11.3 自定义类型转换器

 
阅读更多

11.3  自定义类型转换器

11.3.1概述

虽然内建类型转换器能满足绝大多数的需求,但是,有的时候还是需要使用自定义类型转换器来实现特定的需求。

还是用前面的长方形来说明,如果用两个文本框分别输入长方形的高和宽,整个类型装换都没有问题,它可以工作的很好。

但是,如果我们想在一个文本框内同时输入宽和高(width:height),形如16:9,这个时候就需要自定义类型转换器了。

11.3.2实现自定义类型转换器

自定义类型转换器的实现非常简单,写一个类,继承StrutsTypeConverter抽象类,该类在org.apache.struts2.util包内,这个抽象类有两个方法需要我们实现:

  • public Object convertFromString(Map context, String[] values, Class toClass)方法,实现字符串向对象的转换,它有三个参数:

l         context:转换上下文,可以在里面引用各种对象,比如:可以通过context.get(ValueStack.VALUE_STACK)来引用值栈。

l         values:用户输入的字符串。

l         toClass:将要被转换成的对象类型。

  • public String convertToString(Map context, Object o)方法,实现对象向字符串的转换,它有两个参数:

l         context:同上,也是转换的上下文。

l         o:需要被转换的对象。

实现示例功能的自定义类型转换器,示例代码如下:

 

java代码:
  1. public class RectangleConverter extends StrutsTypeConverter {  
  2.     /** 
  3.      * 长方形向字符串转换 
  4.      */  
  5.     public Object convertFromString(Map context, String[] values, Class toClass) {  
  6.         //用户输入,比如16:9  
  7.         String userInput = values[0];  
  8.         String[] arr = userInput.split(":");  
  9.         //在真正的格式转换之前,先把所有的用户输入可能的错误拦截住  
  10.         if (arr.length!=2){  
  11.             throw new TypeConversionException("请输入正确的长方形格式如,width:height");  
  12.         }  
  13.         try{  
  14.             Rectangle rectangle = new Rectangle();  
  15.             int width = Integer.parseInt(arr[0]);  
  16.             int height = Integer.parseInt(arr[1]);  
  17.             rectangle.setWidth(width);  
  18.             rectangle.setHeight(height);  
  19.             return rectangle;  
  20.         }catch(RuntimeException e){  
  21.             throw new TypeConversionException("请输入正确的长方形格式如,width:height",e);  
  22.         }  
  23.     }  
  24.     /** 
  25.      * 字符串向长方形转换 
  26.      */  
  27.     public String convertToString(Map context, Object o) {  
  28.         Rectangle rectangle = (Rectangle) o;  
  29.         return "长方形:宽"+rectangle.getWidth()+",高"+rectangle.getHeight();  
  30.     }  
  31. }  

在这里,需要注意在convertFromString方法中,用户输入的字符串很可能是不符合要求的,所有的不符合要求的情况都要抛出TypeConversionException。这是个运行时异常,不需要在方法上声明抛出。

11.3.3注册和引用自定义类型转换器

已经有了自定义类型转换器,应该怎么引用它呢?

1:注册自定义类型转换器

首先要注册这个自定义类型转换器处理。在src下建立一个xwork-conversion.properties文件,这个文件中用“全类名=这个类对应的类型转换器全类名”,来建立类和类型转换器的关系,对于我们来说,只有一行:

 

java代码:
  1. cn.javass.convert.Rectangle=cn.javass.convert.RectangleConverter  

注册完了之后,整个项目所有的长方形,都可以用自定义的类型转换器来处理了。

2:示例用的Action

Action不需要做任何特殊的处理,也就是使用自定义类型转换器的时候,对Action没有影响,请大家记住。对应的Action的示例代码为:

 

java代码:
  1. public class ConverterAction extends ActionSupport {  
  2.     private Rectangle rectangle;  
  3.     public Rectangle getRectangle() {  
  4.         return rectangle;  
  5.     }  
  6.     public void setRectangle(Rectangle rectangle) {  
  7.         this.rectangle = rectangle;  
  8.     }  
  9.       
  10.     public String execute() throws Exception {  
  11.         return SUCCESS;  
  12.     }  
  13. }  

3:修改页面

       那么,使用了自定义类型转换器对哪里有影响呢?对页面有影响,既对提交页面有影响,也对展示页面有影响。

       在提交页面上,不需要再有两个文本框分别对应长方形的高和宽了,只需要一个文本框,而这个文本框对应的不再是长方形的属性(比如rectangle.width或rectangle.height),而是对应整个长方形对象(rectangle)了,而且这个文本框需要按照自定义类型转换器预定的字符串格式填写,这里定义的是宽:高。

提交页面示例代码如下:

 

java代码:
  1. <%@ taglib prefix="s" uri="/struts-tags"%>  
  2. <s:form action="/converterAction.action" method="post">  
  3.     <s:textfield name="rectangle" label="输入长和宽"/>  
  4.     <s:submit value="提交"/>  
  5. </s:form>  

显示结果的页面也需要跟随变动,示例代码如下:

 

java代码:
  1. <%@ taglib prefix="s" uri="/struts-tags" %>  
  2. <s:property value="rectangle"/>  

4:测试

       运行测试一下,在输入页面的文本框中填入16:9,然后点击提交,Action就可以正确接到这个长方形对象,然后转向输出页面,显示如下:

图11.1  示例自定义转换器

在展示页面上使用的<s:property value="rectangle"/>,就可以显示出自定义类型转换器中convertToString方法的返回值了。

注意:<s:property value="rectangle"/>这句话会引用自定义类型转换器,因为这时候要把一个字符串转换成Rectangle对象,而前面<s:textfield name=” rectangle.width”/>则不会引用自定义转换器,因为它只是要把一个字符串转换成Rectange对象的width属性而已,实际上只需要转换为int。

 

私塾在线网站原创《研磨struts2》系列

转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4100.html

欢迎访问http://sishuok.com获取更多内容

分享到:
评论
2 楼 chongdiyang 2014-01-18  
/**
     * 长方形向字符串转换
     */ 
    public Object convertFromString(Map context, String[] values, Class toClass) { 
        //用户输入,比如16:9 
        String userInput = values[0]; 
        String[] arr = userInput.split(":"); 
        //在真正的格式转换之前,先把所有的用户输入可能的错误拦截住 
        if (arr.length!=2){ 
            throw new TypeConversionException("请输入正确的长方形格式如,width:height"); 
        } 
        try{ 
            Rectangle rectangle = new Rectangle(); 
            int width = Integer.parseInt(arr[0]); 
            int height = Integer.parseInt(arr[1]); 
            rectangle.setWidth(width); 
            rectangle.setHeight(height); 
            return rectangle; 
        }catch(RuntimeException e){ 
            throw new TypeConversionException("请输入正确的长方形格式如,width:height",e); 
        } 
    } 

这么一段代码虽然说没有错,但是为了通用性:也要用上toClass,当转换的类型为数组的时候if(toClass.isArray()) ... 就可以进行处理,不会抛出转型失败。
1 楼 chongdiyang 2014-01-18  
/**
     * 字符串向长方形转换
     */ 
    public String convertToString(Map context, Object o) { 
        Rectangle rectangle = (Rectangle) o; 
        return "长方形:宽"+rectangle.getWidth()+",高"+rectangle.getHeight(); 
    } 


这里的强制转换是有问题的。。。。看StrutsTypeConverter源代码。
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);
        }
    }

上方的Object o是从Request.getParameter()或者是getParameterValues()传入的值。根本就不能强制转换。强制转换只会抛出ClassCastException异常。。。

相关推荐

    研磨Struts2配书视频对应的演示源代码

    2. **拦截器(Interceptors)**:Struts2的核心之一是其拦截器机制,它们在Action执行前后执行一系列预定义或自定义的操作。这些拦截器可以用于登录验证、日志记录、性能监控等。源代码中可能包含了不同类型的拦截器...

    研磨Struts2

    - **自定义转换器**:如果内置转换器无法满足需求,可以通过实现TypeConverter接口来自定义转换器。 ### 知识点十一:国际化 #### 11.1 国际化的意义 为了让应用程序能够适应不同的语言环境,Struts2提供了国际化...

    研磨struts2 高清版

    由于文件较大,我把这个文档切割为2部分,这是第一部分,请下载完第一部分后一定要下载第二部分,否则不能阅读。

    《研磨Struts 2》PDF版本下载.txt

    相比于第一代Struts框架,Struts 2提供了更多的功能,如拦截器、动态方法调用、更强大的表单处理机制等,并且它与Spring和Hibernate等其他Java EE技术栈的集成更加紧密。 ### Struts 2的特点 1. **强大的表单处理...

    研磨Struts2配书视频对应的PPT

    Struts2框架的拦截器是其一大特色,它允许开发者定义一系列预定义或自定义的行为,这些行为在请求被处理前和后执行。例如,登录验证、日志记录、性能监控等都可以通过拦截器实现。通过灵活的拦截器链,开发者可以...

    研磨struts

    11. **Interceptor**:拦截器是Struts2中的另一个重要特性,它们在Action执行前后插入,提供了日志、权限检查、事务控制等功能。拦截器链可以根据需要定制,提高了代码的复用性和可扩展性。 12. **其他重要知识**:...

    研磨Struts2 高清完整版.part2

    研磨Struts2 高清完整版,请和第一部分一起下载啊

    研磨Struts2_12859679_高清完整版.part2.rar

    研磨Struts2_12859679_高清完整版

    研磨Struts2-高清-完整目录-2011年10月

    研磨Struts2-高清-完整目录-2011年10月,分享给所有需要的人

    研磨设计模式(完整带书签).part2.pdf

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式-part2

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式(完整带书签).part1.pdf

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式.part2(共4个)

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    Java工程师三大框架面试题.pdf

    Java工程师三大框架面试题.pdf

Global site tag (gtag.js) - Google Analytics