在項目中日期格式化是最常見的問題,之前涉及的 java.util.Date 和 java.util.Calendar 類易用性差,不支持時區,非線程安全,對日期的計算方式繁瑣,而且容易出錯,因為月份是從0開始的,從 Calendar 中獲取的月份需要加一才能表示當前月份。
在 JDK8 中,一個新的重要特性就是引入了全新的時間和日期API,它被收錄在 java.time 包中,借助新的時間和日期API可以以更簡潔的方法處理時間和日期。
下面我們通過一些配置實現對日期類型LocalDateTime的格式化
導入依賴
新建一個spring boot項目導入web依賴即可
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
配置方案一
定義一個配置類,在里面定義兩個 Bean
即可完成全局日期格式化處理,同時還兼顧了 Date
和 LocalDateTime
並存
package com.carry.config; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; @Configuration public class LocalDateTimeSerializerConfig { @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}") private String pattern; // 方案一 @Bean public LocalDateTimeSerializer localDateTimeDeserializer() { return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)); } @Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer()); } }
實體類
package com.carry.dto; import java.time.LocalDateTime; public class Order { private LocalDateTime createTime; public LocalDateTime getCreateTime() { return createTime; } public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } }
控制層
package com.carry.controller; import java.time.LocalDateTime; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.carry.dto.Order; @RestController @RequestMapping("/orders") public class OrderController { @GetMapping public Order query() { Order order = new Order(); order.setCreateTime(LocalDateTime.now()); return order; } }
測試
啟動項目並在瀏覽器中訪問 http://localhost:8080/orders
配置方案二
有時候,我們對日期格式要做特殊的處理,全局的格式化方式無法滿足我們需求是,使用該方案是非常好的選擇,通過 @JsonFormat
注解我們可以更為精准的為日期字段格式化,它的優先級比方案一高,二者可結合使用
package com.carry.dto; import java.time.LocalDateTime; import com.fasterxml.jackson.annotation.JsonFormat; public class Order { @JsonFormat(pattern = "yyyy-MM-dd") private LocalDateTime createTime; public LocalDateTime getCreateTime() { return createTime; } public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } }
重新啟動項目並在瀏覽器中訪問 http://localhost:8080/orders
配置方案三
其實和第一種類似,只不過第一種的寫法更加優雅簡潔,如果有多種類型需要做統一格式化處理,這種方案也不是不可以考慮(經測試不能與方案二同時使用)
package com.carry.config; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @Configuration public class LocalDateTimeSerializerConfig { @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}") private String pattern; // 方案三 @Bean @Primary public ObjectMapper serializingObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer()); objectMapper.registerModule(javaTimeModule); return objectMapper; } public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeString(value.format(DateTimeFormatter.ofPattern(pattern))); } } public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException { return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern(pattern)); } } }
訪問 http://localhost:8080/orders,發現 @JsonFormat 配置無效
推薦使用方案一與方案二