struts2类型转换

一、概述

  • 从一个 HTML 表单到一个 Action 对象,类型转换是从字符串非字符串
    HTTP 没有 “类型” 的概念。每一项表单输入只可能是一个字符串或一个字符串数组。 在服务器端, 必须把 String 转换为特定的数据类型。

  • 在 struts2 中,把请求参数映射到action属性的工作由Parameters拦截器负责,它是默认的defaultStack拦截器中的一员。 Parameters 拦截器可以自动完成字符串和基本数据类型之间转换。

二、类型转换错误

  • 如果类型转换失败:
    (1)若 Action 类没有实现 ValidationAware 接口: Struts 在遇到类型转换错误时仍会继续调用其 Action 方法,就好像什么都没发生一样。
    (2)若 Action 类实现 ValidationAware 接口: Struts 在遇到类型转换错误时将不会继续调用其 Action 方法: Struts 将检查相关 action 元素的声明是否包含着一个 name=input 的 result。 如果有,Struts 将把控制权转交给那个 result 元素;若没有 input 结果,Struts 将抛出一个异常。

三、类型转换错误消息的定制

  • 作为默认的 default 拦截器的一员, ConversionError 拦截器负责添加与类型转换有关的出错消息(前提: Action 类必须实现了 ValidationAware 接口)和保存各请求参数的原始值.

  • 若字段标签使用的不是 simple 主题, 则非法输入字段将导致一条有着以下格式的出错消息:

      Invalid field value for field "fieldName"
    
  • 覆盖默认的出错消息

(1)在对应的 Action 类所在的包中新建 ActionClassName.properties 文件, ClassName 即为包含着输入字段的 Action 类的类名
在这里插入图片描述
Conversion类的实现:

package com.haiyang.struts2.app;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.DefaultActionInvocation;

import java.util.Date;

/**
 * @author thy
 * @create 2021-10-04 9:00
 */
public class ConversionAction extends ActionSupport {
    private int age;
    private Date birth;

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
    public String execute(){
        System.out.println("age=" + age);
        System.out.println("birth=" + birth);
        return "success";
    }
}

(2)在属性文件中添加如下键值对:

	invalid.fieldvalue.age=年龄格式错误
  • 定制出错消息的样式:
    每一条出错消息都被打包在一个 HTML span 元素里, 可以通过覆盖其行标为 errorMessage 的那个 css 样式来改变出错消息的格式.
  • 显示错误消息: 如果是 simple 主题, 可以通过 <s:fielderror fieldName=“filedname”></s:fielderror> 标签显示错误消息

四、定制类型转换器

  自定义类型转换器必须实现 ongl.TypeConverter 接口或对这个接口的某种具体实现做扩展

代码实现:

package com.haiyang.struts2.app.converters;

import org.apache.struts2.util.StrutsTypeConverter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author thy
 * @create 2021-10-04 9:26
 */
public class DateConverter extends StrutsTypeConverter {

    private DateFormat dateFormat;
    public DateConverter(){
        System.out.println("DateConverter's constructor...");
        dateFormat = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
    }
    @Override
    public Object convertFromString(Map map, String[] strings, Class aClass) {
        System.out.println("convertFromString");
        if(aClass == Date.class){
            if(strings != null && strings.length > 0){
                String value = strings[0];
                try {
                    return dateFormat.parseObject(value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        //若没有转换成功, 则返回 values
        return strings;
    }

    @Override
    public String convertToString(Map map, Object o) {
        System.out.println("convertToString");
        if(o instanceof Date){
            Date date = (Date) o;
            return dateFormat.format(date);
        }

        //若转换失败返回 null
        return null;
    }
}

1、配置自定义的类型转换器

  • 在应用程序里使用一个自定义的类型转换器之前, 必须先对它进行配置. 这种配置既可以基于字段, 也可以基于类型:

(1)基于字段配置: 可以为某个 Model(该 Model 类也可能是 Action) 的各个属性分别配置一个自定义的转换器.
1. 创建一个属性文件: ModelClassName-conversion.properties, 该文件需和相对应的 Model 类放在同一个目录下
在这里插入图片描述
2. 编辑属性文件:
field=转换器全类名
配置内容:
birth=com.haiyang.struts2.app.converters.DateConverter
扩展:
1.转换器类ConversionAction实现ModelDriven接口

package com.haiyang.struts2.app;

import com.haiyang.struts2.model.Customer;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.DefaultActionInvocation;
import com.opensymphony.xwork2.ModelDriven;

import java.util.Date;

/**
 * @author thy
 * @create 2021-10-04 9:00
 */
public class ConversionAction extends ActionSupport implements ModelDriven<Customer> {

    public String execute(){
        System.out.println("model: " + model);
        return "success";
    }

    private Customer model;

    @Override
    public Customer getModel() {
        model = new Customer();
        return model;
    }
}

2、Customer类的实现:

package com.haiyang.struts2.model;

import java.util.Date;

/**
 * @author thy
 * @create 2021-10-04 9:48
 */
public class Customer {
    private int age;
    private Date birth;

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "age=" + age +
                ", birth=" + birth +
                '}';
    }
}

3.在Customer类的同目录下创建配置文件:
在这里插入图片描述
配置文件内容:

birth=com.haiyang.struts2.app.converters.DateConverter

注:类型转换器是单实例的。
(2)基于类型配置:
1.在src 目录下创建 xwork-conversion.properties 文件。
在这里插入图片描述

2.在 xwork-conversion.properties 文件里把每一个需要进行类型转换的类与一个类型转换器关联起来。

java.util.Date=com.haiyang.struts2.app.converters.DateConverter

注:此方法在Struts2应用被加载前创建实例。

2、实现自定义的时间类型转换器:

(1)时间 pattern 需要以 web 应用的初始化参数配置在 web.xml 中 。

<context-param>
    <param-name>pattern</param-name>
    <param-value>yyyy-MM-dd hh:mm:ss</param-value>
</context-param>

(2)在转换器类中获取初始化参数。

package com.haiyang.struts2.app.converters;

import com.opensymphony.xwork2.ActionContext;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.util.StrutsTypeConverter;

import javax.servlet.ServletContext;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author thy
 * @create 2021-10-04 9:26
 */
public class DateConverter extends StrutsTypeConverter {

    private DateFormat dateFormat;
    public DateConverter(){
        System.out.println("DateConverter's constructor...");

    }

    public DateFormat getDateFormat(){
        if(dateFormat == null){
            //获取当前 WEB 应用的初始化参数 pattern
            ServletContext servletContext = ServletActionContext.getServletContext();
            System.out.println(servletContext);
            String pattern = servletContext.getInitParameter("pattern");
            dateFormat = new SimpleDateFormat(pattern);
        }

        return dateFormat;
    }
    @Override
    public Object convertFromString(Map map, String[] strings, Class aClass) {
        System.out.println("convertFromString");
        if(aClass == Date.class){
            if(strings != null && strings.length > 0){
                String value = strings[0];
                try {
                    return getDateFormat().parseObject(value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        //若没有转换成功, 则返回 values
        return strings;
    }

    @Override
    public String convertToString(Map map, Object o) {
        System.out.println("convertToString");
        if(o instanceof Date){
            Date date = (Date) o;
            return getDateFormat().format(date);
        }

        //若转换失败返回 null
        return null;
    }
}

3、类型转换与复杂对象配合使用

  form 标签的 name 属性可以被映射到一个属性的属性。

在这里插入图片描述

4、Struts 允许填充 Collection 里的对象, 常见于快速录入批量数据的场合

在这里插入图片描述

<%--
  Created by IntelliJ IDEA.
  User: haiyang
  Date: 2021/10/4
  Time: 16:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript" src="<%=request.getScheme()
            + "://"
            + request.getServerName()
            + ":"
            + request.getServerPort()
            + request.getContextPath()
            %>/scripts/jquery-1.4.2.js"></script>
    <script type="text/javascript">

        $(function(){

            var count = 0;

            $("#add").click(function(){
                count++;

                $("#button").before("<tr><td>Mgrs[" + count + "].Name:</td><td><input name='mgrs[" + count + "].name'/></td></tr>")
                    .before("<tr><td>Mgrs[" + count + "].Birth:</td><td><input name='mgrs[" + count + "].birth'/></td></tr>");

                return false;

            });

            $("#remove").click(function(){

                count--;

                $("#button").prev("tr").remove();
                $("#button").prev("tr").remove();

                return false;

            });

        });

    </script>
</head>
<body>

<form action="testConversion2.action">


    <table>

        <tbody>

        <tr>
            <td>Mgrs[0].Name:</td>
            <td><input name="mgrs[0].name"/></td>
        </tr>

        <tr>
            <td>Mgrs[0].Birth:</td>
            <td><input name="mgrs[0].birth"/></td>
        </tr>

        <tr id="button">
            <td><button id="add">新加一个</button></td>
            <td><button id="remove">删除一个</button></td>
        </tr>

        <tr>
            <td colspan="2" align="right">
                <input type="submit" value="Submit"/>
            </td>
        </tr>

        </tbody>

    </table>

</form>

</body>
</html>

package com.haiyang.struts2.app;

import com.haiyang.struts2.model.Manager;
import com.opensymphony.xwork2.ActionSupport;

import java.util.Collection;

/**
 * @author thy
 * @create 2021-10-04 16:00
 */
public class TestCollectionAction extends ActionSupport {


    private static final long serialVersionUID = 1L;

    private Collection<Manager> mgrs = null;

    public Collection<Manager> getMgrs() {
        return mgrs;
    }

    public void setMgrs(Collection<Manager> mgrs) {
        this.mgrs = mgrs;
    }

    public String execute() throws Exception {
        System.out.println(mgrs);
        return SUCCESS;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HEU_THY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值