springMVC中Date类型作为对象参数前台格式转换问题

前言:

在springMVC中对于Date类型数据前台格式要求默认只能是“2021/1/1”,否则会发生请求错误:

由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者虚拟的请求路由),服务器无法或不会处理当前请求。

如何实现前台多种日期格式请求。

示例:

前台:

<body>
    <form action="/user/getUser.action" method="post">
        用户名:<input type="text" name="name"><br>
        密码:<input type="text" name="password"><br>
        日期:<input type="text" name="date"><br>
        <input type="submit" value="提交">
    </form>
</body>

实体

public class User {
    private String name;
    private String password;
    private Date date;
}

Controller

@RequestMapping("/getUser.action")
public String getUser(User user){
    System.out.println("User---->"+user);
    return "/home.html";
}

错误演示:

 错误原因是在springMVC中默认只能对“2021/1/1”这种格式进行解析。

解决方案:

方案一:@DateTimeFormat注解

 在Date类型字段上加上@DateTimeFormat注解,并指定格式

public class User {
    private String name;
    private String password;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date date;
}

 

缺点:实体类每个Date类型字段都要写该注解,并且只能指定一种格式

方案二:@InitBinder

在Controller类中写一个方法指定格式,并加上注解@InitBinder,代码如下:

@InitBinder
public void initBinder(WebDataBinder binder){
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    binder.registerCustomEditor(Date.class,new CustomDateEditor(dateFormat,true));//需要指定Date类型
}

 缺点:多个Controller不能公用,并且只能指定一种格式

方案三:解决多种格式问题

可以看到在方案二中的方法里我们创建了一个指定格式的DateFormat对象,并将dateFormat对象传入CustomDateEditor构造中。想象如果CustomDateEditor构造中能够传入一个dateFormat数组,是不是就能解决只能指定一种格式的问题。代码如下:

第一步:创建DateFormat数组,指定多种格式

@InitBinder
protected void initBinder(WebDataBinder binder){
    DateFormat[] dateFormat = {
        new SimpleDateFormat("yyyy-MM-dd"),
        new SimpleDateFormat("yyyy/MM/dd"),
        new SimpleDateFormat("yyyy:MM:dd"),
        new SimpleDateFormat("yyyy年MM月dd日"),
    };
    binder.registerCustomEditor(Date.class,new MyCustomDateEditor(dateFormat,true));
}

第二步:查看CustomDateEditor类的源码,改写CustomDateEditor类,写一个我们自己的MyCustomDateEditor类。

改写CustomDateEditor 类:

1.将成员属性dareFormat改为数组

2.改构造函数

3.参考源码改setAsText方法和getAsText方法,将原本的处理一个DareFormat对象改写为处理一组DareFormat对象

package com.fwk.editor;

import java.beans.PropertyEditorSupport;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;

import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

//改写的数据处理
public class MyCustomDateEditor extends PropertyEditorSupport {

    private final DateFormat[] dateFormat;

    private final boolean allowEmpty;

    private final int exactDateLength;

    public MyCustomDateEditor(DateFormat[] dateFormat, boolean allowEmpty) {
        this.dateFormat = dateFormat;
        this.allowEmpty = allowEmpty;
        this.exactDateLength = -1;
    }

    public MyCustomDateEditor(DateFormat[] dateFormat, boolean allowEmpty, int exactDateLength) {
        this.dateFormat = dateFormat;
        this.allowEmpty = allowEmpty;
        this.exactDateLength = exactDateLength;
    }

    @Override
    public void setAsText(@Nullable String text) throws IllegalArgumentException {
        if (this.allowEmpty && !StringUtils.hasText(text)) {
            // Treat empty String as null value.
            setValue(null);
        }
        else if (text != null && this.exactDateLength >= 0 && text.length() != this.exactDateLength) {
            throw new IllegalArgumentException(
                    "Could not parse date: it is not exactly" + this.exactDateLength + "characters long");
        }
        else {
            for (int i = 0; i < dateFormat.length; i++) {
                try {
                    setValue(dateFormat[i].parse(text));
                    break;
                }
                catch (ParseException ex) {
                    if (i==dateFormat.length-1){
                        throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);
                    }else {
                        continue;
                    }
                }
            }
        }
    }

    @Override
    public String getAsText() {
        Date value = (Date) getValue();
        for (int i = 0; i < dateFormat.length; i++) {
            try {
                String s = dateFormat[i].format(value);
                return s;
            }catch (Exception e){
                continue;
            }
        }
        return "";
    }

}

方案三增强:解决多个Controller共用问题

单独写一个类,类上加上@ControllerAdvice,进行全局数据预处理,并将@InitBinder注解标志的方法放在里面

@ControllerAdvice
public class DateAdvice {
    @InitBinder
    protected void initBinder(WebDataBinder binder){
        System.out.println("date");
        DateFormat[] dateFormat = {
                new SimpleDateFormat("yyyy-MM-dd"),
                new SimpleDateFormat("yyyy/MM/dd"),
                new SimpleDateFormat("yyyy:MM:dd"),
                new SimpleDateFormat("yyyy年MM月dd日"),
        };
        binder.registerCustomEditor(Date.class,new MyCustomDateEditor(dateFormat,true));
    }
}

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值