深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践

简介: 在 Spring Boot 开发中,日期时间格式化是前后端交互的常见痛点。本文详细解析了 **@DateTimeFormat** 和 **@JsonFormat** 两个注解的用法,分别用于将前端传入的字符串解析为 Java 时间对象,以及将时间对象序列化为指定格式返回给前端。通过完整示例代码,展示了从数据接收、业务处理到结果返回的全流程,并总结了解决时区问题和全局配置的最佳实践,助你高效处理日期时间需求。

theme: cyanosis

在开发 Spring Boot 应用时,我们经常会遇到一个问题:如何在与前端交互时,既能正确解析前端传来的日期字符串,又能以指定格式把日期数据返回给前端。其实,要解决这个问题并不难,关键在于两个非常有用的注解—— @DateTimeFormat@JsonFormat。今天就让我们以博客的形式,深入聊聊这两个注解的来龙去脉,并通过详细的代码案例,从浅入深讲解它们的用法和注意细节。


ChatGPT Image 2025年4月8日 03\_13\_10.png

为什么需要格式化日期时间?

在前后端开发中,日期和时间一直都是一个容易出错的点。前端可能会以不同的格式(比如 2025-04-08 14:30:152025/04/08 或者 ISO 8601 标准的 2025-04-08T14:30:15)发送数据,而后端在反序列化时必须清楚如何解析才能转换成 Java 的日期类型(如 LocalDateTimeLocalDateDate)。同样,当我们的后端需要返回数据时,为了让前端能够方便地展示也需要确定特定的日期格式。Spring Boot 刚好为我们提供了两个注解来分别应对这两个环节:

  • @DateTimeFormat 用于【数据绑定】阶段,即接收前端传来的字符串,并将其转换为 Java 时间对象。
  • @JsonFormat 用于【序列化】阶段,即当对象返回给前端时,把 Java 时间对象转换为指定格式的字符串。

一、@DateTimeFormat:精准解析前端传入的日期数据

@DateTimeFormat 可以应用在 Controller 方法参数、表单对象字段或者实体类的属性上。当前端传来的日期字符串与我们定义的 pattern 匹配时,Spring 会自动将其转换成对应的日期类型。

示例代码

假如我们有一个用户注册的请求,前端传来用户的生日信息。我们可以构建如下的 DTO 类:

import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;

/**
 * 用户数据传输对象,用于接收前端传来的参数
 */
public class UserDTO {
   

    // 用户姓名
    private String name;

    /**
     * 用户生日
     * 说明: 当前端传过来的字符串类似 "2025-04-08 14:30:15" 时,
     * 使用 @DateTimeFormat 注解指定的 pattern 将会被用来解析成 LocalDateTime 对象
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthday;

    // 省略 getter 和 setter 方法
}

在 Controller 中,我们可以直接使用这个 DTO 对象接收前端数据:

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {
   

    @PostMapping("/register")
    public String registerUser(@RequestBody UserDTO userDTO) {
   
        // userDTO.getBirthday() 已经自动解析成 LocalDateTime 类型
        // 这里可以添加你的业务逻辑处理,比如保存到数据库
        return "用户注册成功!";
    }
}

注意

  • @DateTimeFormat 只能影响反序列化,即把字符串转换为 Java 时间对象,而不会影响返回给前端的格式化。
  • 如果前端发送的时间格式与 pattern 不一致,会导致解析失败并报 400 错误。

二、@JsonFormat:定义返回给前端的日期格式

当你准备好将数据返回给前端时,希望看到的日期格式与前端的要求或者 UI 设计一致。这时就需要利用 @JsonFormat 注解来对日期进行格式化。通常,我们会同时在同一字段上添加两个注解,从而分别控制数据输入和输出。

示例代码

我们修改上述 DTO 类,新增一个 createTime 字段,并同时使用 @DateTimeFormat@JsonFormat 注解:

import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;

/**
 * 用户视图对象,用于数据交互
 */
public class UserVO {
   

    // 用户姓名
    private String name;

    /**
     * 用户生日:只参与数据绑定(输入)时的解析
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthday;

    /**
     * 用户创建时间:接收时使用 @DateTimeFormat 解析,返回时通过 @JsonFormat 格式化
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;

    // getter 与 setter 方法
}

在这个例子中:

  • 当我们接收前端传来的 "birthday": "2025-04-08 14:30:15" 字符串时,会使用 @DateTimeFormat 转化为 LocalDateTime 对象。
  • 当系统返回 createTime 字段时,通过 @JsonFormat 指定的 "yyyy/MM/dd HH:mm:ss" 格式将其序列化,比如返回 "2025/04/08 15:22:10"
  • timezone = "GMT+8" 确保了时区正确,避免因默认时区导致的时间偏差问题。

三、完整示例:从前端数据接收、业务处理到返回结果

为了让你直观地理解整个流程,我们把 Controller、Service 和 DTO 结合起来,构建一个完整的示例。这里我们设计一个新建用户的功能,既包含接收前端传来的日期字符串,也包含生成并返回格式化后的创建时间。

1. 数据传输对象 UserDTO

import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;

/**
 * 用户数据传输对象,用于接收前端数据与返回结果的格式化
 */
public class UserDTO {
   

    // 用户姓名
    private String name;

    /**
     * 用户生日,前端通过 JSON 字符串传递,
     * 使用 @DateTimeFormat 进行解析
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthday;

    /**
     * 用户创建时间,后台生成,并且在返回时格式化展示
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;

    // Constructors、getter 与 setter 方法
}

2. Service 层处理用户数据

import org.springframework.stereotype.Service;
import java.time.LocalDateTime;

@Service
public class UserService {
   

    /**
     * 模拟创建用户的业务逻辑
     * @param userDTO 接收前端传来的用户数据
     * @return 返回处理后的用户数据,其中包含创建时间
     */
    public UserDTO createUser(UserDTO userDTO) {
   
        // 模拟保存到数据库操作,此处只做简单处理
        // 手动设置创建时间为当前系统时间
        userDTO.setCreateTime(LocalDateTime.now());

        // 可能还会做一些校验、赋值、日志记录等操作

        return userDTO;
    }
}

3. Controller 层暴露 REST 接口

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class UserController {
   

    @Autowired
    private UserService userService;

    /**
     * 新建用户接口
     * 接收 JSON 数据,并返回格式化后的用户信息
     * 前端请求例子:
     * POST /api/users
     * {
     *   "name": "张三",
     *   "birthday": "2025-05-08 10:10:10"
     * }
     */
    @PostMapping("/users")
    public UserDTO createUser(@RequestBody UserDTO userDTO) {
   
        // userDTO.getBirthday() 会使用 @DateTimeFormat 解析成 LocalDateTime 对象
        // 在 Service 层中,生成 createTime 字段
        UserDTO savedUser = userService.createUser(userDTO);
        // 返回的 savedUser 中,createTime 将通过 @JsonFormat 格式化为指定格式
        return savedUser;
    }
}

在这个完整示例中:

  1. 前端以以下 JSON 数据请求用户创建接口:

    {
         
        "name": "张三",
        "birthday": "2025-05-08 10:10:10"
    }
    
  2. Spring Boot 根据 @DateTimeFormat 解析 birthday 并封装到 UserDTO 中。

  3. Service 层自动设置 createTime 为当前时间,传回 Controller。

  4. Controller 返回时,Jackson 处理 createTime 字段时会应用 @JsonFormat 指定的格式,确保前端看到正确的时间格式。


四、常见问题与实践经验

在实际开发中,你可能会遇到以下一些问题:

  1. 返回格式不对:\
    如果你在实体上只使用了 @DateTimeFormat 而没有添加 @JsonFormat,那么返回的 JSON 可能仍然使用 ISO-8601 格式(例如 "2025-04-08T14:30:15")。解决方法是确保需要格式化的字段上同时加上 @JsonFormat 注解。
  2. 解析失败:\
    当前端传入的字符串格式和 @DateTimeFormat 定义的 pattern 不一致时,会出现解析错误。务必确保前端传输的日期格式和后端预期格式完全匹配;或者使用 ISO 枚举例如 @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) 以提高容错率。
  3. 时区问题:\
    由于不同环境的默认时区可能不同,建议在 @JsonFormat 中明确指定 timezone,比如 timezone = "GMT+8",以防服务器默认时区导致时间显示偏差。
  4. 全局配置 vs 局部注解:\
    为了避免每个实体类都写重复的注解,部分团队会在全局配置 Jackson 序列化/反序列化的日期格式。但有时某些字段需要特殊格式时,直接在字段上添加注解即可。两者可以灵活搭配使用。

五、总结

这篇文章详细讲解了如何使用 @DateTimeFormat@JsonFormat 来解决 Spring Boot 应用中日期时间格式化的常见问题。

  • @DateTimeFormat 主要用于【数据绑定】阶段,将前端传来的字符串转换为 Java 时间对象。
  • @JsonFormat 则用于【序列化】阶段,将 Java 时间对象以特定格式输出给前端。

两者合用可确保前后端无缝对接,既方便了数据输入,也优化了数据输出的格式。希望这篇博客能帮助你在项目中更游刃有余地处理日期时间相关的需求,避免踩坑。

目录
相关文章
|
1月前
|
存储 Java 数据库
Spring Boot 注册登录系统:问题总结与优化实践
在Spring Boot开发中,注册登录模块常面临数据库设计、密码加密、权限配置及用户体验等问题。本文以便利店销售系统为例,详细解析四大类问题:数据库字段约束(如默认值缺失)、密码加密(明文存储风险)、Spring Security配置(路径权限不当)以及表单交互(数据丢失与提示不足)。通过优化数据库结构、引入BCrypt加密、完善安全配置和改进用户交互,提供了一套全面的解决方案,助力开发者构建更 robust 的系统。
64 0
|
1月前
|
Java 开发者 微服务
Spring Cloud OpenFeign详解与实践
总结起来说,Spring Cloud OpenFeign提供了一种简单易懂且高效的方式去实现微服务之间通信.它隐藏了许多复杂性,并且允许开发者以声明式方式编写HTTP客户端代码.如果你正在开发基于Spring Cloud 的微服务架构系统,Spring Cloud Open Feign是一个非常好用且强大工具.
157 33
|
1月前
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,处理前后端日期交互是一个常见问题。本文通过 **@DateTimeFormat** 和 **@JsonFormat** 两个注解,详细讲解了如何解析前端传来的日期字符串以及以指定格式返回日期数据。文章从实际案例出发,结合代码演示两者的使用场景与注意事项,解决解析失败、时区偏差等问题,并提供全局配置与局部注解的实践经验。帮助开发者高效应对日期时间格式化需求,提升开发效率。
276 2
|
SQL Java 数据库
Springboot 全局日期格式化,只需要几行小代码
Springboot 全局日期格式化,只需要几行小代码
154 0
Springboot 全局日期格式化,只需要几行小代码
|
17天前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
|
24天前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
116 7
|
18天前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
4月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的留守儿童爱心网站设计与实现(计算机毕设项目实战+源码+文档)
博主是一位全网粉丝超过100万的CSDN特邀作者、博客专家,专注于Java、Python、PHP等技术领域。提供SpringBoot、Vue、HTML、Uniapp、PHP、Python、NodeJS、爬虫、数据可视化等技术服务,涵盖免费选题、功能设计、开题报告、论文辅导、答辩PPT等。系统采用SpringBoot后端框架和Vue前端框架,确保高效开发与良好用户体验。所有代码由博主亲自开发,并提供全程录音录屏讲解服务,保障学习效果。欢迎点赞、收藏、关注、评论,获取更多精品案例源码。
|
4月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的家政服务管理平台设计与实现(计算机毕设项目实战+源码+文档)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
|
4月前
|
JavaScript 搜索推荐 Java
基于SpringBoot+Vue实现的家乡特色推荐系统设计与实现(源码+文档+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!