当前位置: 首页 > article >正文

SpringBoot项目里LocalDateTime传参总报错?一个配置搞定前后端日期格式统一(含表单提交场景)

SpringBoot项目中LocalDateTime传参的终极解决方案一网打尽所有日期格式问题当你信心满满地在SpringBoot项目中配置好Jackson的日期格式化以为从此可以高枕无忧时前端同事突然告诉你这个表单提交又报错了你查看日志发现熟悉的ConversionFailedException异常再次出现——明明JSON接口工作正常为什么传统表单提交就失效这个问题困扰过无数开发者今天我们将彻底揭开SpringBoot中日期处理的层层面纱。1. 为什么Jackson配置对表单提交无效许多开发者容易陷入一个认知误区认为配置了Jackson的日期格式化后所有类型的日期参数转换都会自动生效。实际上SpringBoot处理不同类型请求时采用了完全不同的机制JSON请求RequestBody使用Jackson进行序列化/反序列化表单/URL参数RequestParam/ModelAttribute使用Spring的WebDataBinder进行类型转换// 典型的Jackson配置仅对JSON有效 Bean public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { return builder - { DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); JavaTimeModule module new JavaTimeModule(); module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter)); module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter)); builder.modules(module); }; }关键区别Jackson是专门处理JSON的库而表单提交使用的是Spring的转换服务(ConversionService)2. 全局解决方案注册类型转换器要一劳永逸地解决所有类型的日期转换问题我们需要在Spring的转换服务中注册自定义转换器。以下是三种等效的实现方式2.1 方式一声明Converter BeanConfiguration public class DateTimeConverterConfig { Bean public ConverterString, LocalDateTime stringToLocalDateTimeConverter() { return source - { if (StringUtils.isEmpty(source)) return null; DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); return LocalDateTime.parse(source, formatter); }; } Bean public ConverterString, LocalDate stringToLocalDateConverter() { return source - { if (StringUtils.isEmpty(source)) return null; return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE); }; } }2.2 方式二实现WebMvcConfigurer接口Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new ConverterString, LocalDateTime() { Override public LocalDateTime convert(String source) { DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); return LocalDateTime.parse(source, formatter); } }); } }2.3 方式三使用InitBinder注解如果只需要在特定控制器中生效可以使用控制器级别的绑定器RestController RequestMapping(/api) public class MyController { InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() { Override public void setAsText(String text) { setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss))); } }); } PostMapping(/submit) public ResponseEntity? handleSubmit(RequestParam LocalDateTime eventTime) { // 处理逻辑 } }3. 高级场景处理技巧3.1 处理多种日期格式实际项目中前端可能传递不同格式的日期字符串。我们可以增强转换器的兼容性Bean public ConverterString, LocalDateTime flexibleDateTimeConverter() { return source - { if (StringUtils.isEmpty(source)) return null; // 尝试解析多种格式 for (String pattern : Arrays.asList( yyyy-MM-dd HH:mm:ss, yyyy/MM/dd HH:mm:ss, yyyy.MM.dd HH:mm:ss)) { try { return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(pattern)); } catch (DateTimeParseException ignored) {} } throw new IllegalArgumentException(无法识别的日期格式: source); }; }3.2 时区处理策略当系统需要处理多时区时可以在转换器中明确指定时区Bean public ConverterString, ZonedDateTime zonedDateTimeConverter() { return source - { DateTimeFormatter formatter DateTimeFormatter.ISO_ZONED_DATE_TIME; return ZonedDateTime.parse(source, formatter) .withZoneSameInstant(ZoneId.of(Asia/Shanghai)); }; }3.3 表单与JSON的统一配置为了实现真正的全局统一我们需要同时配置Jackson和转换器Configuration public class DateTimeConfig implements WebMvcConfigurer { private final String dateTimePattern yyyy-MM-dd HH:mm:ss; private final String datePattern yyyy-MM-dd; // Jackson配置 Bean public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { return builder - { JavaTimeModule module new JavaTimeModule(); module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimePattern))); module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimePattern))); builder.modules(module); }; } // 转换器配置 Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new ConverterString, LocalDateTime() { Override public LocalDateTime convert(String source) { return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(dateTimePattern)); } }); } }4. 实战完整项目配置示例下面是一个生产级项目的完整日期处理配置方案Configuration Slf4j public class DateTimeConfiguration implements WebMvcConfigurer { // 从配置文件中读取格式提供默认值 Value(${app.format.datetime:yyyy-MM-dd HH:mm:ss}) private String dateTimeFormat; Value(${app.format.date:yyyy-MM-dd}) private String dateFormat; // Jackson序列化配置 Bean public Module javaTimeModule() { JavaTimeModule module new JavaTimeModule(); module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat))); return module; } // 全局类型转换器 Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new ConverterString, LocalDateTime() { Override public LocalDateTime convert(String source) { try { return parseDateTime(source); } catch (Exception e) { log.warn(日期时间解析失败: {}, source); throw new IllegalArgumentException(日期格式应为: dateTimeFormat); } } }); } private LocalDateTime parseDateTime(String source) { if (source null || source.trim().isEmpty()) return null; // 智能处理不同长度的输入 switch (source.length()) { case 10: // yyyy-MM-dd return LocalDate.parse(source, DateTimeFormatter.ofPattern(dateFormat)) .atStartOfDay(); case 16: // yyyy-MM-dd HH:mm return LocalDateTime.parse(source :00, DateTimeFormatter.ofPattern(dateTimeFormat)); default: return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(dateTimeFormat)); } } }在application.yml中配置app: format: datetime: yyyy-MM-dd HH:mm:ss date: yyyy-MM-dd5. 常见问题排查指南当日期转换仍然不工作时可以按照以下步骤排查确认转换器是否注册成功Autowired private ConversionService conversionService; PostConstruct public void checkConverters() { boolean canConvert conversionService.canConvert(String.class, LocalDateTime.class); log.info(String-LocalDateTime转换器存在: {}, canConvert); }检查请求Content-TypeJSON请求application/json表单请求application/x-www-form-urlencoded或multipart/form-data调试WebDataBinderInitBinder public void initBinder(WebDataBinder binder) { log.info(使用的ConversionService: {}, binder.getConversionService()); }验证日期格式try { LocalDateTime.parse(testString, DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)); } catch (DateTimeParseException e) { log.error(日期格式不匹配, e); }检查时区设置Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { return new Jackson2ObjectMapperBuilder() .timeZone(TimeZone.getTimeZone(Asia/Shanghai)); }记住日期时间处理是业务系统中常见的痛点但通过合理的全局配置完全可以构建出健壮、统一的解决方案。关键在于理解Spring框架中不同类型转换机制的工作范围并针对性地进行增强。

相关文章:

SpringBoot项目里LocalDateTime传参总报错?一个配置搞定前后端日期格式统一(含表单提交场景)

SpringBoot项目中LocalDateTime传参的终极解决方案:一网打尽所有日期格式问题 当你信心满满地在SpringBoot项目中配置好Jackson的日期格式化,以为从此可以高枕无忧时,前端同事突然告诉你:"这个表单提交又报错了!&…...

别再只会用多边形了!Maya NURBS挤出命令的三种玩法,轻松搞定复杂曲面建模

解锁Maya NURBS挤出命令的隐藏潜力:从基础到高阶的曲面建模实战 在三维建模领域,NURBS(非均匀有理B样条)技术一直是创建精确曲面的黄金标准。许多设计师在掌握了多边形建模后,面对NURBS工具时却感到无从下手。实际上&a…...

对话引擎实战:基于状态机与规则引擎构建智能对话系统

1. 项目概述:一个对话引擎的诞生最近在社区里看到不少朋友在讨论如何构建自己的对话系统,从简单的客服机器人到复杂的多轮交互应用,需求五花八门。恰好,我前段时间深度研究并实践了Rubonnek/dialogue-engine这个项目,它…...

使用 Taotoken 后,在 Ubuntu 上开发 AI 应用的可观测性得到显著提升

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用 Taotoken 后,在 Ubuntu 上开发 AI 应用的可观测性得到显著提升 在 Ubuntu 环境下进行 AI 应用开发时,…...

golembot:在聊天平台集成AI编程助手的框架设计与实战

1. 项目概述与核心价值 如果你和我一样,经常在 Slack、Discord 或者飞书这些团队协作工具里讨论技术问题,或者希望有一个能随时调用的 AI 编程助手,那么 golembot 这个项目绝对值得你花时间研究一下。简单来说,它是一个能让你在…...

Go语言实现LLaMA推理:从零构建本地大模型引擎

1. 项目概述:用Go语言实现LLaMA推理的野心与实践如果你是一名Golang开发者,同时对大语言模型(LLM)的运行原理和本地部署充满好奇,那么你很可能和我一样,曾对那个用C写成的、性能卓越但门槛不低的llama.cpp项…...

Neovim集成GitHub Copilot:gp.nvim插件深度配置与实战指南

1. 项目概述:一个为Neovim量身打造的GitHub Copilot客户端如果你和我一样,是个重度Neovim用户,同时又对GitHub Copilot这类AI编程助手带来的效率提升欲罢不能,那你肯定也经历过一段纠结的时光。一边是VSCode里Copilot丝滑的代码补…...

免费解锁B站4K大会员视频下载:三步完成离线观看的终极指南

免费解锁B站4K大会员视频下载:三步完成离线观看的终极指南 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 还在为B站大会员…...

3分钟完成Windows和Office激活的终极指南:KMS_VL_ALL_AIO智能脚本

3分钟完成Windows和Office激活的终极指南:KMS_VL_ALL_AIO智能脚本 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统激活而烦恼吗?KMS_VL_ALL_AIO是一款开…...

【Linux】从源码到应用:手把手编译部署 Tcl/Tk 8.6.10

1. 为什么需要手动编译Tcl/Tk? 很多Linux发行版自带了Tcl/Tk的软件包,但版本往往比较老旧。我在维护一个老项目时就遇到过这种情况——系统自带的Tcl 8.5缺少我们需要的几个关键特性,导致程序频繁崩溃。更麻烦的是,直接使用包管理…...

3分钟搞定编码难题:GBKtoUTF-8编码转换工具让文件乱码成为历史

3分钟搞定编码难题:GBKtoUTF-8编码转换工具让文件乱码成为历史 【免费下载链接】GBKtoUTF-8 To transcode text files from GBK to UTF-8 项目地址: https://gitcode.com/gh_mirrors/gb/GBKtoUTF-8 当你在Windows系统创建的文档,在Mac或Linux上打…...

Go语言开发的MySQL binlog解析利器my2sql:除了闪回,它的统计功能更值得DBA关注

Go语言开发的MySQL binlog解析利器my2sql:统计功能如何重塑DBA工作流 当大多数DBA将my2sql视为又一款闪回工具时,它的统计模块正在悄然改变数据库性能分析的范式。这个用Go语言编写的高效工具,能在90秒内解析1.1GB的binlog文件,其…...

从真值到补码:计算机如何用0和1表示正负与运算

1. 为什么计算机需要表示负数? 当你用计算器做减法时,可能从没想过计算机内部其实只会做加法。我第一次接触这个概念时也很惊讶——原来计算机用补码表示负数,就是为了把减法变成加法运算。这就像魔术师的手法,看似简单的0和1背后…...

手把手教你:误删pyvenv.cfg后,如何快速重建Python虚拟环境(附详细步骤)

手把手教你:误删pyvenv.cfg后,如何快速重建Python虚拟环境(附详细步骤) 虚拟环境是Python开发中的"隔离舱",而pyvenv.cfg文件则是这个隔离舱的"控制面板"。当你发现误删这个关键文件后&#xff0c…...

FortiWeb VM 6.3.4初体验:除了当防火墙,还能怎么玩?

FortiWeb VM 6.3.4进阶玩法:解锁WAF的隐藏技能树 当大多数人还在把Web应用防火墙(WAF)当作简单的流量过滤工具时,你已经可以把它变成安全实验室的瑞士军刀。FortiWeb VM 6.3.4这个220MB的虚拟机镜像里,藏着比基础防护更有趣的可能性——从自动…...

终极网盘直链解决方案:八大主流网盘文件下载地址一键获取指南

终极网盘直链解决方案:八大主流网盘文件下载地址一键获取指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘…...

fanqienovel-downloader:一键永久保存番茄小说的终极解决方案

fanqienovel-downloader:一键永久保存番茄小说的终极解决方案 【免费下载链接】fanqienovel-downloader 下载番茄小说 项目地址: https://gitcode.com/gh_mirrors/fa/fanqienovel-downloader 你是否曾经为心爱的小说突然下架而烦恼?是否希望在网络…...

别再死记硬背了!用一张图帮你理清Spring全家桶里那些让人头疼的注解(@Autowired, @Transactional, @Value等)

Spring注解全解析:从零构建高效开发思维图谱 1. 引言:为什么需要系统性理解Spring注解? 每次打开Spring项目的代码,你是否会被各种以符号开头的注解弄得眼花缭乱?Autowired、Transactional、Value这些注解看似简单&…...

如何在5分钟内实现Figma界面全中文汉化?

如何在5分钟内实现Figma界面全中文汉化? 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma复杂的英文界面而头疼吗?作为一名中文设计师,面对…...

为AI Agent构建文件交付通道:OpenClaw File Links Tool部署与集成指南

1. 项目概述:为AI Agent构建专属文件交付通道如果你正在开发或使用AI Agent,比如AutoGPT、Claude Desktop的MCP工具,或者任何需要执行文件操作(如数据分析、文档生成、网页抓取)的自动化程序,那么一个核心痛…...

3分钟让模糊录音变清晰:VoiceFixer语音修复神器使用指南

3分钟让模糊录音变清晰:VoiceFixer语音修复神器使用指南 【免费下载链接】voicefixer General Speech Restoration 项目地址: https://gitcode.com/gh_mirrors/vo/voicefixer 你是否曾经因为录音质量太差而烦恼?那些充满杂音的会议录音、模糊不清…...

别再死记硬背电路图了!用PLC(西门子S7-1200)轻松实现电机正反转,附梯形图与实物接线

西门子S7-1200 PLC实战:电机正反转控制的智能化改造 在工业自动化领域,电机正反转控制是最基础也最经典的应用场景之一。传统继电器-接触器控制方案虽然可靠,但存在布线复杂、故障排查困难、功能扩展受限等痛点。我曾在一个老旧车间改造项目中…...

3个步骤如何为Unity应用集成Perseus原生库功能扩展

3个步骤如何为Unity应用集成Perseus原生库功能扩展 【免费下载链接】Perseus Azur Lane scripts patcher. 项目地址: https://gitcode.com/gh_mirrors/pers/Perseus Perseus是一个专为Unity Android应用设计的原生库补丁框架,通过无偏移地址设计实现功能扩展…...

构建一体化自动化媒体中心:从Docker容器化部署到全流程整合实践

1. 项目概述与核心价值最近在整理一些个人数据归档和媒体资源管理的工作时,我重新审视了“Leech-AIO-APP-EX”这个项目。这个名字听起来可能有点技术化,但它的核心目标非常明确:构建一个高度集成、自动化且易于管理的“一站式”数据抓取与媒体…...

从克拉坡振荡器到丙类功放:深入拆解一个调频发射机的每个模块(含原理、选型与实测分析)

从克拉坡振荡器到丙类功放:深入拆解一个调频发射机的每个模块(含原理、选型与实测分析) 在射频电路设计的进阶领域,调频发射机是一个兼具经典理论和工程实践价值的项目。不同于基础教程中简单的电路搭建,本文将带您深入…...

构建认知智能体:从任务分解到工程落地的全流程指南

1. 项目概述:当开源大模型遇上“认知大脑”最近在AI社区里,一个名为“Cognithor”的项目引起了我的注意。这个项目由开发者Alex8791-cyber发起,其核心目标直指当前大语言模型(LLM)应用中的一个痛点:如何让模…...

STM32新手避坑指南:正点原子、野火、慧净、小马飞控的Systick延时函数到底差在哪?

STM32开发板Systick延时函数深度对比:从原理到避坑实战 第一次接触STM32开发时,我对着四块不同品牌的开发板愣了半天——正点原子、野火、慧净、小马飞控,每家的例程里Systick延时函数实现都不一样。有的用72MHz时钟,有的用9MHz&a…...

网盘下载太慢?这款神器帮你一键获取9大网盘直链地址

网盘下载太慢?这款神器帮你一键获取9大网盘直链地址 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…...

技术架构深度解析:douyin-downloader抖音下载器 - 多策略异步下载与智能队列管理方案

技术架构深度解析:douyin-downloader抖音下载器 - 多策略异步下载与智能队列管理方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplicatio…...

Simulink 模型注释实战指南:从静态标注到动态交互

1. Simulink注释的进阶价值:从说明书到智能助手 第一次打开Simulink模型时,我常被密密麻麻的连线图吓到——就像面对一本没有目录的教科书。直到学会用注释做"书签",才发现原来模型可以像交互式电子书一样友好。注释不只是写备注的…...