15 时间格式的转换
|-------------|------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|---|
| 方向 | 技术 | 控制方式 | 关键点 |
| 前端 → 后端 | 表单提交 (application/x-www-form-urlencoded) | 1.注解 :@DateTimeFormat(pattern = "yyyy-MM-dd") 2.全局配置 :spring.mvc.format.date=yyyy-MM-dd 3. 代码定制 : addFormatters中重写Formatter的parse(String,Locale) 方法 | 后端解析格式必须与前端发送的字符串格式一致。三种方式均可,优先级:注解 > 代码定制 > 全局配置。 |
| 前端 → 后端 | JSON 提交 (@RequestBody) | 1.注解 : @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") 2.全局配置 : spring.jackson.date-format=yyyy-MM-dd和 spring.jackson.time-zone=GMT+8 | 后端解析格式必须与 JSON 中的字符串格式一致。Formatter对此场景无效 。 | |
| 后端 → 前端 | JSON 响应 (@ResponseBody) | 1.注解 : @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") 2.全局配置 :spring.jackson.date-format=yyyy-MM-dd和spring.jackson.time-zone=GMT+8 | 后端可以定义任意友好的展示格式,前端直接接收字符串并展示。Formatter对此场景无效 。 |
| 后端 → 前端 | 视图渲染 (如 Thymeleaf, JSP) | 代码定制 : addFormatters中重写Formatter的print(Date, Locale) 方法 | 后端可以定义任意格式。当Date对象被直接渲染到视图模板时,Spring MVC 会使用此方法将其格式化为指定字符串。这是Formatter独有的场景,用于统一页面上所有日期的显示格式。 |
注:对于Jackson库可以换成其他Json库,比如Fastjson,此时注解@JsonFormat应该换成Fastjson对应的@JSONField 注解。换了之后,除了注解和库变了,其他的规则同@JsonFormat。如何换库,具体见 ++14 SpringBoot整合SpringMVC++14.2.3。
15.1 前端 → 后端 (表单提交)
-
场景:用户通过 标签提交数据,其中包含日期。
-
前端行为: 会将日期以 yyyy-MM-dd 格式的字符串发送给后端。
-
后端解析方式:
-
方式一 (全局配置):在 application.yml 中配置 spring.mvc.format.date。
spring:
mvc:
format:
date: yyyy-MM-dd # 必须与前端传来的格式一致 -
方式二 (局部注解):在实体类的日期字段上使用 @DateTimeFormat 注解。
public class User {
@DateTimeFormat(pattern = "yyyy-MM-dd") // 必须与前端传来的格式一致
private Date birthday;
// ...
} -
方式三(代码定制):创建一个配置类实现WebMvcConfigurer接口,并在重写addFormatters这个方法。修改这个方法中的 Formatter 的 parse(String, Locale) 方法。
- 优先级:@DateTimeFormat 注解 (局部) > 代码定制 > spring.mvc.format.date (全局)。
- 结论:如果你想使用除 yyyy-MM-dd 之外的格式(例如 yyyy/MM/dd),你必须在前端通过 JavaScript 将日期字符串格式化为你想要的格式,然后再提交给后端。后端的配置或注解必须与前端最终发送的格式保持一致。
15.2 前端 → 后端 (JSON 提交)
- 场景:前端通过 AJAX (如 fetch, axios) 发送 JSON 数据给后端,后端使用 @RequestBody 注解接收。
- 前端行为:前端构造一个 JSON 对象,其中日期是一个字符串,例如 {"username": "张三", "birthday": "2025-11-19"}。
- 后端解析方式:
-
方式一 (全局配置):在 application.yml 中配置 Jackson 的日期格式。
spring:
jackson:
date-format: yyyy-MM-dd # 必须与 JSON 中的日期字符串格式一致
time-zone: GMT+8 -
方式二 (局部注解):在实体类的日期字段上使用 @JsonFormat 注解。
public class User {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") // 必须与 JSON 中的日期字符串格式一致
private Date birthday;
// ...
}
-
优先级:@JsonFormat 注解 (局部) > spring.jackson.date-format (全局)。
-
错误示例:如果 JSON 中的日期是 "2025-11-19",而你的配置或注解是 yyyy/MM/dd,就会遇到下面这个提到的错误:
JSON parse error: Cannot deserialize value of type
java.util.Datefrom String "2025-11-19": expected format "yyyy/MM/dd"
15.3 后端 → 前端 (JSON 响应)
- 场景:后端通过 @ResponseBody 注解返回一个 Java 对象(如 User),Spring Boot 会自动将其转换为 JSON 字符串。
- 后端行为:Spring Boot 使用 Jackson 库进行序列化。
- 控制 JSON 格式的方式:
- 方式一 (全局配置):在 application.yml 中配置 spring.jackson.date-format。这会影响所有 Date 类型字段的序列化。
- 方式二 (局部注解):在实体类的日期字段上使用 @JsonFormat 注解。这只影响该字段的序列化。
- 注意:后端到前端 日期格式想是什么就是什么 都可以正常转。
- 原因:在这个场景中,后端是 "格式的定义者"。Jackson 会按照你指定的格式(通过 @JsonFormat 或全局配置),将 Date 对象转换成一个字符串。前端接收到的就是这个格式化好的字符串,它不需要进行任何解析,直接展示即可。
15.4 后端 → 前端(视图渲染)
-
场景:后端 Controller 方法返回一个逻辑视图名称(如 "user/profile")和一个包含 Date 对象的模型(Model)。Spring MVC 会将模型数据传递给视图模板(如 Thymeleaf, FreeMarker, JSP)进行渲染,最终生成 HTML 页面返回给前端。
-
后端行为:Spring MVC 在将模型中的 Date 对象传递给视图模板之前,会检查是否存在一个注册的 Formatter。如果存在,它会调用该格式化器的 print 方法。
-
控制日期显示格式的方式:
方式一 (全局代码配置):通过实现 WebMvcConfigurer 接口并重写 addFormatters 方法,注册一个自定义的 Formatter。在该格式化器的 print(Date date, Locale locale) 方法中,定义你希望的日期字符串格式(如 "yyyy年MM月dd日")。@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new Formatter<Date>() {
@Override
public String print(Date date, Locale locale) {
// 当Date对象被渲染到视图时,格式化为 "yyyy年MM月dd日"
return new SimpleDateFormat("yyyy年MM月dd日").format(date);
}// parse方法在此场景下不发挥作用 @Override public Date parse(String text, Locale locale) throws ParseException { return null; } });}
-
后端可以定义任意格式。