请求参数到表述层的类型转换——Struts2

一、简介

说明:HTTP 协议传输数据没有类型的概念,在服务器端是通过 request.getParameter()、request.getParameterValue() 方法得到请求参数为 String 或 String[] 类型。

但是这样使用起来不方便,我们希望开源框架能自动的完成类型转换,到使用的时候能直接获取目标类型。

二、Struts2 类型转换

1. Struts2 本身完成了字符串类型到基本数据类型的自动转换,其他情况需要我们定义自己的类型转换器。

2.类型转换失败时的处理方式

(1) 默认情况下 Struts2 对于类型转换失败后是不做任何处理的。

(2) 若请求参数到目标基本类型转化出错时,会对目标基本类型赋值为默认值。

(3) 若请求参数到目标基本类型包装类转化出错时,会对目标字段赋值为 null。

(4) 若希望在发生错误时给出提示,则需要让目标 Action 类实现 com.opensymphony.xwork2.ValidationAware 接口,这个接口 ActionSupport 已经帮我们实现。

说明:com.opensymphony.xwork2.ValidationAware

包含了 ActionErrors 和 FieldErrors 两个级别的错误消息,实现了该接口的 Action 类,在类型转换出错时,会前往 name=input 的 result,若没有配置,则返回404。

在类型转换出错时,不会到目标方法,而是直接返回。对应的是一个拦截器。

(5) 在错误显示页面,可以从值栈的 Action 类中获取到错误消息,且此错误消息可以自定义。

自定义错误提示消息:在当前 Action 类所在的包下添加 ActionName.properties 的属性文件,然后在该属性文件中添加如下键值对:

invalid.fieldvalue.目标字段名=定制的错误提示消息

(6) 在值栈中,错误消息的数据结构为:Map<String, List<String>>,可以通过 OGNL 表达式的方式来获取,也可以通过 Struts2 标签来获取,如下:

<s:fielderror fieldName="errorFiledName"></s:fielderror>

3.自定义类型转换器

继承 StrutsTypeConverter 类,两个抽象方法

public Object convertFromString(Map context, String[] values, Class toClass) : context 可以看做是 Map 栈,values 代表传入的请求参数, toClass 代表要转换的目标类。

public String convertToString(Map context, Object o) : 将传入的 o 转换为字符串。

(1) 类级别的

同包下创建包含要转换的属性的类简单类名 + "-conversion.properties", 如:TypeConverterTestAction-conversion.properties,TypeConverterTestAction 类中包含一个 person 属性。

在创建的类型转换资源文件中添加:要转换的属性=类型转换器全类名,如: person=com.nucsoft.struts2.convert.MyTypeConverter

(2) 全局级别的

在类路径的根目录下创建:xwork-conversion.properties 属性文件

内容:需要转换的类的全类名=类型转换器的全类名,如:com.nucsoft.struts2.helloworld.Person=com.nucsoft.struts2.convert.MyTypeConverter

自定义类型转换出错的处理方式也和之前一样。

4.复杂类型数据的类型转换

(1)目标 Action 不实现 ModelDriven 接口,也就是说栈顶对象是当前 Action 类的情况

[1]单独的一个复杂对象,表单标签与对象属性对应:person

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="person.userName" label="userName"/>
        <s:textfield name="person.age" label="age"/>
        <s:submit value="submit"/>
</s:form>

(2) 目标 Action 实现 ModelDriven 接口,栈顶对象为 getModel 返回值类型。

[1] 单独一个复杂类型,对应多个标签

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="userName" label="person"/>
        <s:textfield name="age" label="age"/>
        <s:submit value="submit"/>
</s:form>

[2]单独的一个复杂对象,只有一个表单标签,按照指定格式进行转换为对应的复杂对象:

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="person" label="person"/>
        <s:submit value="submit"/>
</s:form>

输入的格式:

AA,12

需要对目标 Action 自定义 person 类型转换器,或定义全局的类型转换器,如:

/**
 * @author solverpeng
 * @create 2016-07-09-11:00
 */
public class MyTypeConverter extends StrutsTypeConverter {
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
        Person person = null;
        if(Person.class == toClass)
            try {
                person = (Person) toClass.newInstance();
                String strs = values[0];
                person.setUserName(strs.split(",")[0]);
                person.setAge(Integer.parseInt(strs.split(",")[1]));
            } catch(InstantiationException e) {
                e.printStackTrace();
            } catch(IllegalAccessException e) {
                e.printStackTrace();
            }

        return person;
    }

    @Override
    public String convertToString(Map context, Object o) {
        return null;
    }
}

MyTypeConverter

[3]复杂对象中包含另一个复杂对象,如 Person 中包含 Address。

对应多个标签:

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="userName" label="person"/>
        <s:textfield name="age" label="age"/>
        <s:textfield name="address.addressName" label="addressName"/>
        <s:textfield name="address.location" label="location"/>
        <s:submit value="submit"/>
</s:form>

三个标签,固定格式:address 用一个标签,固定格式 addressName,location

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="userName" label="userName"/>
        <s:textfield name="age" label="age"/>
        <s:textfield name="address" label="address"/>
        <s:submit value="submit"/>
</s:form>

因为 Person 类中包含 Address 属性,所以在 Person 同包下新建 Person-conversion.properties 文件

内容:address=com.nucsoft.struts2.convert.MyTypeConverter

类型转换器:

/**
 * @author solverpeng
 * @create 2016-07-09-11:00
 */
public class MyTypeConverter extends StrutsTypeConverter {
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {

        if(Person.class == toClass) {
            Person person = null;
            try {
                person = (Person) toClass.newInstance();
                String strs = values[0];
                person.setUserName(strs.split(",")[0]);
                person.setAge(Integer.parseInt(strs.split(",")[1]));
            } catch(InstantiationException e) {
                e.printStackTrace();
            } catch(IllegalAccessException e) {
                e.printStackTrace();
            }
            return person;
        }

        if(Address.class == toClass) {
            Address address = null;
            try {
                address = (Address) toClass.newInstance();
                String strs = values[0];
                address.setAddressName(strs.split(",")[0]);
                address.setLocation(strs.split(",")[1]);
            } catch(InstantiationException e) {
                e.printStackTrace();
            } catch(IllegalAccessException e) {
                e.printStackTrace();
            }
            return address;
        }

        return null;

    }

    @Override
    public String convertToString(Map context, Object o) {
        return null;
    }
}

MyTypeConverter

5.集合元素对象中的类型转换

[1] 目标 Action 类包含 List 的复杂对象,如 List<Person>,其中 Address 进行类型转换时,还是使用 Person 转换器,且因为为 List<Person>,所以不需要实现 ModelDriven 接口,所以栈顶对象为 当前Action类对象。

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="persons[0].userName" label="userName[0]"/>
        <s:textfield name="persons[0].age" label="age[0]"/>
        <s:textfield name="persons[0].address" label="address[0]"/>

        <s:textfield name="persons[1].userName" label="userName[1]"/>
        <s:textfield name="persons[1].age" label="age[1]"/>
        <s:textfield name="persons[1].address" label="address[1]"/>
        <s:submit value="submit"/>
 </s:form>

[2] 只有一个复杂对象,但是该复杂对象包含 List 属性,如 Person 类存在 List<Address> 属性。因为只有一个复杂对象,所以实现 ModelDriven 接口

<s:form action="converter/typeConverter" method="post">
        <s:textfield name="userName" label="userName"/>
        <s:textfield name="age" label="age"/>
        <s:textfield name="addresses[0].addressName" label="address[0].addressName" />
        <s:textfield name="addresses[0].location" label="address[0].location" />
        <s:textfield name="addresses[1].addressName" label="address[1].addressName" />
        <s:textfield name="addresses[1].location" label="address[1].location" />
        <s:submit value="submit"/>
</s:form>

6.json类型的数据的类型转换

未完,待续

时间: 08-15

请求参数到表述层的类型转换——Struts2的相关文章

请求参数到表述层的类型转换——SpringMVC

一.不论是SpringMVC 的 JSR-303 数据校验还是自定义类型转换器,都需要配置 <mvc:annotation-driven/>,而添加这个配置后,会自动注册RequestMappingHandlerMapping. RequestMappingHandlerAdapter 与 ExceptionHandlerExceptionResolver  三个bean.在没添加前,正常的请求都是由 AnnotationMethodHandlerAdapter 进行处理的.我之前 的几篇文章

请求参数到表述层的数据类型转换

一.简介 说明:HTTP 协议传输数据没有类型的概念,在服务器端是通过 request.getParameter().request.getParameterValue() 方法得到请求参数为 String 或 String[] 类型. 但是这样使用起来不方便,我们希望开源框架能自动的完成类型转换,到使用的时候能直接获取目标类型. 二.Struts2 类型转换 1. Struts2 本身完成了字符串类型到基本数据类型的自动转换,其他情况需要我们定义自己的类型转换器.= 2.类型转换失败时的处理方

JAVAWEB开发之Struts2详解(二)——Action接受请求参数、类型转换器、使用Struts2的输入校验、以及遵守约定规则实现Struts2的零配置

Action接受请求参数 作为MVC框架,必须要负责解析HTTP请求参数,并将其封装到Model对象中 Struts2提供了非常强大的类型转换机制用于请求数据 到 model对象的封装 Struts2和MVC定义关系 StrutsPrepareAndExecuteFilter:控制器 在Struts2中action是什么?(Struts2是一个MVC框架) V:jsp M:action C:action StrutsPrepareAndExecuteFilter Struts2提供了三种数据封装

struts2的请求参数url的写法以及相关struts2与Spring集成时的情况

在使用struts2的时候,我们都知道以前的那种以离散的值作为传递的单位,他们的请求url是这么写的: localhost:8080/test/login?username=hello&password=world 以及其对应的action是这么写的 <span style="font-size:24px;">public class LoginAction extends ActionSupport { private String username ; priv

深入分析JavaWeb 45 -- Struts2封装请求参数与类型转换

作为MVC框架,必须要负责解析HTTP请求参数,并将其封装到Model对象中,Struts2提供了非常强大的类型转换机制用于请求数据 到 model对象的封装. 1.Struts2 提供三种数据封装的方式 Action 本身作为model对象,通过成员setter封装 创建独立model对象,页面通过ognl表达式封装 使用ModelDriven接口,对请求数据进行封装 1. 方式一:在动作类中成员变量给予初始值. 在配置文件中struts.xml中 <package name="p1&q

struts2 action接收请求参数和类型转换

1,action接收请求参数 在struts2中action是什么?(struts2是一个mvc框架)         V:jsp        M:action         C:action  StrutsPrepareAndExecuteFilter 在struts2中获取请求参数: a.属性驱动            1.直接将action做一个model,就可以得到请求参数.                问题1:action封装请求参数,会不会存在线程安全问题?          

Struts2(三)struts2处理请求参数及其校验

一.Action处理请求参数 1.Action处理请求参数三种方式 1.1.Action 本身作为model对象,通过成员setter封装 (属性驱动 ) // 页面: 用户名 <input type="text" name="username" /> <br/> // Action : public class RegistAction1 extends ActionSupport { private String username; pu

Struts2 -- 获取请求参数

1.直接将action做一个model,就可以得到请求参数. 缺点:需要单独定义javaBean,将action中属性copy到javaBean中.                     优点:简单.                                 这种方式 ,底层是通过反射来实现的. //获取请求参数 属性驱动 第一种,直接将action做为model public class DemoAction extends ActionSupport { private String

struts2 请求参数接收

1. 采用基本类型接受请求参数(get/post)在Action类中定义与请求参数同名的属性,struts2便能自动接收请求参数并赋予给同名的属性.请求路径:http://localhost:8080/action/register.action?id=33 public class HelloWorldAction { private Integer id; public Integer getId() { return id; } public void setId(Integer id)