@DateTimeFormat 前端入参报错分析


前言

项目前端时间传参报错,于是百度亿下,众说纷纭,写此文章纠正自己和各位大坑们的错误见解,也助其他猿们少掉头发。

一、异常信息

Caused by: java.time.format.DateTimeParseException: Text '2021-06-23 12:20:12' could not be parsed, unparsed text found at index 16
	at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2055)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
	at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:494)
	at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer._fromString(LocalDateTimeDeserializer.java:177)
	... 102 common frames omitted

从异常信息可以看出为时间格式转换错误,具体分析如下

二、异常分析,误区解读

1.pattern不匹配

前端传参格式: yyyy-MM-dd HH:mm:ss
后台接收格式: @DateTimeFormat(pattern = “yyyy-MM-dd HH:mm”)

2.@DateTimeFormat可用格式受限


现象:@DateTimeFormat作用是前后到后台的时间格式的转换,使用"yyyy-MM-dd"格式的字符串传入日期类型数据是入参转换没有问题,使用"yyyy-MM-dd HH:mm:ss"格式时间字符串就会报错

原因:springboot默认采用jackson,而jackson只能识别以下几种日期格式

"yyyy-MM-dd'T'HH:mm:ss.SSSZ""yyyy-MM-dd'T'HH:mm:ss.SSS'Z'""yyyy-MM-dd";
"EEE, dd MMM yyyy HH:mm:ss zzz";
long类型的时间戳(毫秒时间戳)

此时你可以让前端传 yyyy-MM-dd’T’HH:mm:ss.SSSZ 中间带 ’T‘ 的时间格式保证解决此类报错,但不保证前端可能会打你;

3.@DateTimeFormat 和 @JsonFormat 误区解读

误区解读引用出处:https://blog.csdn.net/a1035434631/article/details/109740122
实在看不下去网上千篇一律的回答都是

@DateTimeFormat用于前端传给后端的时间格式转换,

@JsonFormat用于后端传给前端的时间格式转换
这种以偏盖全的荒谬理论真的是误人子弟!为此本人将自己调查理解的浅陋见解分享给大家,如有错误请大家多多指教

@JsonFormat注解
出处: com.fasterxml.jackson.annotation.JsonFormat;

作用:将日期类型数据在JSON格式和java.util.Date对象之间转换。约束时间的接收格式和响应格式 (接收和响应的都是JSON字符串) .与传输方向没有关系(前端到后端or后端到前端都可以使用)

常用注解属性:

名称 作用
pattern 时间格式:pattern=“yyyy-MM-dd HH:mm:ss”
timezone 指定具体时区: timezone = “GMT+8” or timezone = “Asia/Shanghai”
注意因为我们是东八区(北京时间),使用时需要加上时区( timezone = “GMT+8”),不然所得值会比实际时间晚8小时;

举个例子

@Data
public class pojo{
    @JsonFormat(pattern = "yyyy-MM-dd hh", timezone = "GMT+8")
    private Date date;
}

@DateTimeFormat注解
出处:org.springframework.format.annotation.DateTimeFormat

作用:主要对Date、Calendar、Long及Joda时间类型的属性进行格式化处理,主要处理前端时间类型与后端pojo对象中的成员变量进行数据绑定,所约束的时间格式并不会影响后端返回前端的时间类型数据格式;

常用注解属性:

名称 作用
iso 类型为DateTimeFormat.ISO,常用值:
DateTimeFormat.ISO.DATE:格式为yyyy-MM-dd
DateTimeFormat.ISO.DATE_TIME:格式为yyyy-MM-dd hh:mm:ss.SSSZ
DateTimeFormat.ISO.TIME:格式为hh:mm:ss.SSSZ
DateTimeFormat.ISO.NONE:表示不使用ISO格式的时间(默认值)
pattern 类型为String,使用自定义时间格式化字符串,如"yyyy-MM-dd hh:mm:ss"
style 类型为String,通过样式指定日期时间的格式,由两位字符组成,
第一位表示日期的样式,第二位表示时间的格式,以下是几个常用的可选值:
S:短日期/时间的样式
M:中日期/时间的样式
L:短日期/时间的样式
F:完整日期/时间的样子
-:忽略日期或时间的样式
默认值 style=“SS”
注意事项:前端入参数据的时间格式必须与注解中定义的时间格式相同

举个例子:

@Data
public class query{
    @DateTimeFormat(pattern = "yyyy-MM-dd hh")
    private Date date;
}

@JsonFormat 和 @DateTimeFormat 区别

  • @JsonFormat既可以约束前端传入的时间类型参数格式,也可以约束后端响应前端的时间类型格式;与请求的数据类型有关,必须为json类型
    目前大部分java项目都是使用json的方式传输前后端数据(即前端使用json提交,后端使用@RequestBody注解接收参数的形式),使用
    @JsonFormat即可
  • @DateTimeFormat只能约束前端传入的时间类型参数格式,且如果单独使用@DateTimeFormat时,响应给前端的时间会比实际时间晚8个小时(时区原因)。
    仅支持**【表单键值对】**这种提交方式,而且只能格式化前端->后端数据,不能用于json格式的提交方式,也不能用于后端->前端的格式化

三、解决方案

  1. 采用long时间戳,如:1537191968000

  2. 在传参的对象上加上@JsonFormat注解并且指定时区
    @JsonFormat(locale=“zh”, timezone=“GMT+8”, pattern=“yyyy-MM-dd HH:mm:ss”) 如果项目中使用json解析框架为fastjson框架,在实体字段上使用@JsonFormat注解格式化日期

    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern=“yyyy-MM-dd HH:mm:ss”)

  3. 采用全局处理方式统一处理,推荐这个做法,重写springboot默认转换
    参考https://blog.csdn.net/qq906627950/article/details/79503801

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小野猪佩奇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值