-
spring + mysql, 日期年份大于9999带来的灾难
- 网站名称:spring + mysql, 日期年份大于9999带来的灾难
- 网站分类:技术文章
- 收录时间:2025-06-30 16:10
- 网站地址:
“spring + mysql, 日期年份大于9999带来的灾难” 网站介绍
灾难:
某日,生产环境,有一接口,也不知道是恶意请求还是故意请求,日期时间传入字符串"20232023-08-03 11:23:07", MySQL时间索引失效,全表扫描,由于数据量比较大,当场宕机,绩效被扣,当场吐血,内心万马奔腾。
初一看,年份"20232023",多了一个"2023", 照理在spring中,会直接报一个异常:参数无效,格式无法转换。
细一想,年份"20232023",是一个合理的年份,只是我们活在了"2023"年,格局小了,忘了子孙后代有可能活在"20232023"年。
最后查了nginx的accesslog,并没发现有"20232023-08-03 11:23:07"的日志,不出意外,是内部开发写的程序,直接通过ip:port调用的。
那么,为什么在程序中使用了@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 和 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")限定了请求报文的实体的时间格式,还能接受"20232023"? 请看下文。
问题代码:
这里说明一下:
代码中使用了@JsonFormat和@DateTimeFormat注解来定义日期格式,但在Spring中,这两个注解的作用域略有不同:
- @JsonFormat:只会在序列化/反序列化Json时生效,也就是说只对从Json字符串转换为Java对象时有效
- @DateTimeFormat:会在任何日期转换时生效,包括从字符串转换为Date对象等
所以GET请求,传入的参数beginTime=20232023-08-03%2011:23:07&endTime=2023-08-03%2011:23:07,实际上是是通过@DateTimeFormat进行解析的,而不是@JsonFormat。@DateTimeFormat默认会使用一定的容错机制进行解析,这和Spring的日期转换操作一致。
尝试过添加以下配置项:
spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss
spring.mvc.format.date=yyyy-MM-dd
程序仍然能正常解析"20232023-08-03 11:23:07"
最后将请求报文实体的Date类型,改为LocalDateTime类型,满足了需求,即改为如下代码:
满足了我们的期望,传入参数beginTime=20232023-08-03%2011:23:07,返回异常:
参数无效:beginTime Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'beginTime'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@
com.fasterxml.jackson.annotation.JsonFormat @
org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value '20232023-08-03 11:23:07'; nested exception is
java.lang.IllegalArgumentException: Parse attempt failed for value [20232023-08-03 11:23:07]
for why:
为什么在@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")注解下Date类型能解析"20232023-08-03 11:23:07",而LocalDateTime类型不能解析"20232023-08-03 11:23:07"?
Date类型中的year用的是int类型,而LocalDateTime类型中的year用的是long类型,不应该支持的年份范围更广吗?
看下ai claude的回答:
看下ai claude2的回答:
再看下chatgpt的回答:
总感觉回答不对,有没有大神知道的,欢迎在评论区中指点一二。
更多相关网站
- MySQL 数据库恢复:如何执行时间点恢复(PITR)以挽救受损数据?
- 如何正确查询mysql的启动和关闭时间?
- 您对MySQL常用内置日期时间函数认识多少?
- mysql备份脚本:自己设定用户名密码及数据保留时间
- 阿里二面:最讨厌的问题来了,MySQL 保存日期用哪种数据类型?
- mysql——日期操作
- 牛哇!MySQL中的日志“binlog”的三种格式这么好玩
- MySQL 中时间函数详解,及加减计算总结和使用!
- MySQL计算两个日期(两个时间)相差的天数、月数、年数
- Mysql日期格式化显示“年月”
- MySQL 保存日期,用哪种数据类型合适
- 分享一个小技巧——mysql统一处理创建时间和更新时间
- 最近发表
- 标签列表
-
- c++论坛 (14)
- 前端论坛 (11)
- mysql 时间索引 (13)
- mydisktest_v298 (35)
- sql 日期比较 (33)
- document.appendchild (35)
- 头像打包下载 (35)
- 二调符号库 (23)
- acmecadconverter_8.52绿色版 (25)
- throttlestop防止降频 (9)
- f12019破解 (16)
- 流星蝴蝶剑修改器 (18)
- 联想杜比音效驱动下载 (10)
- np++ (17)
- 算法第四版pdf (14)
- 梦幻诛仙表情包 (36)
- https://www.zxzj.me/ (9)
- 魔兽模型 (23)
- java面试宝典2019pdf (26)
- beamoff下载 (17)
- disk++ (30)
- vncviewer破解版 (20)
- word文档批量处理大师破解版 (19)
- pk10牛牛 (20)
- mysql 昨天的日期 (13)