Java controller接口出入?yún)r(shí)間序列化轉(zhuǎn)換操作方法(兩種)
場景:在controller編寫的接口,在前后端交互過程中一般都會(huì)涉及到時(shí)間字段的交互,比如:后端給前端返的數(shù)據(jù)有時(shí)間相關(guān)的字段,同樣,前端也存在傳時(shí)間相關(guān)的字段給后端,最原始的方式就是前后端都先轉(zhuǎn)換成字符串和時(shí)間戳后進(jìn)行傳輸,收到后再進(jìn)行轉(zhuǎn)換,特別麻煩。
為了方便可以使用注解或者配置做到時(shí)間字段的自動(dòng)轉(zhuǎn)換,這里列舉兩種簡單的操作。
方式一、使用注解
就是在日期字段上添加對應(yīng)的注解(@JsonFormat),例:
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime2; @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime3;
優(yōu)點(diǎn):靈活、清晰。
缺點(diǎn):所有需要轉(zhuǎn)換的字段都需要手動(dòng)添加、并且只支持時(shí)間和指定格式字符串互轉(zhuǎn),不支持時(shí)間戳
方式二、統(tǒng)一配置
一勞永逸的方式,支持時(shí)間和 時(shí)間戳、字符串 之間的互轉(zhuǎn)
package com.zhh.demo.config; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.util.NumberUtil; 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.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; import java.math.BigInteger; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @Configuration // 表示通過aop框架暴露該代理對象,AopContext能夠訪問 //@EnableAspectJAutoProxy(exposeProxy = true) public class ApplicationConfig { /** 年-月-日 時(shí):分:秒 */ private static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; /** * 序列化 時(shí)間格式轉(zhuǎn)換類型 * timestamp:時(shí)間戳 * dateString: 時(shí)間字符串格式 * */ private static final String LOCAL_DATE_TIME_SERIALIZER_TYPE = "dateString"; /** * description:適配自定義序列化和反序列化策略 */ @Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { return builder -> { // 時(shí)間的序列化和反序列化 builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer()); builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer()); // 將long類型數(shù)據(jù)轉(zhuǎn)化為string給前端 避免前端造成的精度丟失 builder.serializerByType(Long.class, ToStringSerializer.instance); builder.serializerByType(BigInteger.class, ToStringSerializer.instance); }; } /** * description:序列化 * LocalDateTime序列化為毫秒級時(shí)間戳 */ public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value != null) { // 通過配置決定把時(shí)間轉(zhuǎn)換成 時(shí)間戳 或 時(shí)間字符串 if ("timestamp".equals(LOCAL_DATE_TIME_SERIALIZER_TYPE)) { // 13位時(shí)間戳 gen.writeNumber(LocalDateTimeUtil.toEpochMilli(value)); } else { // 指定格式的時(shí)間字符串 gen.writeString(value.format(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))); } } } } /** * description:反序列化 * 毫秒級時(shí)間戳序列化為LocalDateTime */ public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException { //2023年11月2日: 嘗試反序列增加更多的支持, 支持long輸入, 支持字符串輸入 if (p == null) { return null; } String source = p.getText(); return parse(source); } } /** * 時(shí)間戳字符串或格式化時(shí)間字符串轉(zhuǎn)換為 LocalDateTime * 例:1745806578000、2025-04-28 10:16:18 * @param source 13位時(shí)間戳 或格式化時(shí)間字符串 * @return */ private static LocalDateTime parse(String source) { // 如果是時(shí)間戳 if (NumberUtil.isLong(source)) { long timestamp = Long.parseLong(source); if (timestamp > 0) { return LocalDateTimeUtil.of(timestamp, ZoneOffset.of("+8")); } else { return null; } // 如果是格式化時(shí)間字符串 } else { if (StringUtils.isBlank(source)) { return null; } // 嘗試判斷能否解析 if (canParseByDateTimeFormatter(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))) { return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)); } return null; } } /** * 判斷是否能解析格式化時(shí)間字符串 * @param source 格式化時(shí)間字符串(格式 2025-04-28 10:16:18) * @param dateTimeFormatter 格式 yyyy-MM-dd HH:mm:ss * @return */ private static boolean canParseByDateTimeFormatter(String source, DateTimeFormatter dateTimeFormatter) { try { dateTimeFormatter.parse(source); } catch (DateTimeParseException e) { return false; } return true; } }
測試一下:
在上面配置的基礎(chǔ)上添加部分測試使用的代碼
用于前后端交互的bean對象:
@Data public class UserRO { private LocalDateTime createTime1; private LocalDateTime createTime2; @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime3; }
controller層接口:
@ApiOperation("時(shí)間測試") @PostMapping("/time") public UserRO show(@RequestBody UserRO userRO){ System.out.println("\n接收到的入?yún)ⅲ?); System.out.println(userRO.getCreateTime1()); System.out.println(userRO.getCreateTime2()); System.out.println(userRO.getCreateTime3()); System.out.println("\n出參:"); LocalDateTime newTime = LocalDateTime.now(); UserRO user = new UserRO(); user.setCreateTime1(newTime); user.setCreateTime2(newTime); user.setCreateTime3(new Date()); System.out.println(user.getCreateTime1()); System.out.println(user.getCreateTime2()); System.out.println(user.getCreateTime3()); System.out.println("\n"); return user; }
通過配置類,可以配置后端接口給調(diào)用方返的時(shí)間格式【字符串、時(shí)間戳】、接口調(diào)用方傳的入?yún)⒖梢允亲址部梢缘臅r(shí)間戳,后端會(huì)自動(dòng)解析。
到此這篇關(guān)于Java controller接口出入?yún)r(shí)間序列化轉(zhuǎn)換操作方法(兩種)的文章就介紹到這了,更多相關(guān)Java controller接口出入?yún)?nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java idea如何根據(jù)請求路徑url自動(dòng)找到對應(yīng)controller方法插件
- Java中Controller、Service、Dao/Mapper層的區(qū)別與用法
- Java實(shí)現(xiàn)一鍵生成表controller,service,mapper文件
- Java中Controller引起的Ambiguous?mapping問題及解決
- 詳解java封裝返回結(jié)果與RestControllerAdvice注解
- Java后臺(tái)Controller實(shí)現(xiàn)文件下載操作
- java springboot poi 從controller 接收不同類型excel 文件處理
- java模擬ajax訪問另一個(gè)項(xiàng)目的controller代碼實(shí)例
- Java Spring Controller 獲取請求參數(shù)的幾種方法詳解
相關(guān)文章
利用Java實(shí)現(xiàn)更改Word中的頁面大小和頁面方向
這篇文章主要為大家詳細(xì)介紹了一種高效便捷的方法——通過Java應(yīng)用程序,以編程方式更改Word中的頁面大小和頁面方向,感興趣的可以了解一下2023-03-03使用IDEA直接連接MySQL數(shù)據(jù)庫的方法
這篇文章主要介紹了如何使用IDEA直接連接MySQL數(shù)據(jù)庫,首先需要新建一個(gè)空項(xiàng)目,第一次連接 需要先下載驅(qū)動(dòng),文中給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-04-04logback-spring.xml的內(nèi)容格式詳解
這篇文章主要介紹了logback-spring.xml的內(nèi)容格式詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的的朋友參考下吧2023-11-11Java日期格式化的實(shí)現(xiàn)(@JsonFormat和@JSONField)
本文主要介紹了Java日期格式化的實(shí)現(xiàn),主要介紹了@JsonFormat和@JSONField兩種方式,具有一定的參考價(jià)值,感興趣的可以了解一下2024-05-05SpringBoot啟動(dòng)及自動(dòng)裝配原理過程詳解
這篇文章主要介紹了SpringBoot啟動(dòng)及自動(dòng)裝配原理過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Maven項(xiàng)目如何查找jar包是由哪個(gè)依賴引入的
這篇文章主要介紹了Maven項(xiàng)目如何查找jar包是由哪個(gè)依賴引入的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08