在spring boot應(yīng)用中,當需要深度克隆包含非序列化字段(如`multipartfile`及其數(shù)組)的dto時,傳統(tǒng)的`objectoutputstream`方法不可行。本文將探討如何利用jackson的`objectmapper`和`addmixin`機制,巧妙地忽略這些不可控dto中的特定類型數(shù)組屬性,從而實現(xiàn)dto的順利克隆,并指出處理集合類型時的局限性。
在開發(fā)過程中,我們經(jīng)常需要對DTO(數(shù)據(jù)傳輸對象)進行深度克隆,例如在處理請求參數(shù)時。然而,當DTO中包含如org.springframework.web.multipart.MultipartFile這類非序列化接口的字段時,傳統(tǒng)的Java序列化(ObjectOutputStream和ObjectInputStream)方法會失效。更具挑戰(zhàn)性的是,有時我們無法修改這些DTO的定義,例如通過添加transient關(guān)鍵字或@JsonIgnore注解來排除字段。
Jackson庫提供了一種靈活的解決方案,即通過ObjectMapper的addMixIn()方法結(jié)合@JsonIgnoreType注解,在不修改原始類定義的情況下,指示Jackson忽略特定類型的字段。
為了忽略DTO中的MultipartFile字段,我們可能會嘗試以下Jackson配置:
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.annotation.JsonIgnoreType; import org.springframework.web.multipart.MultipartFile; public class DtoCloner { private Object makeClone(Object obj) { ObjectMapper mapper = new ObjectMapper(); // 添加針對 MultipartFile 類型的 MixIn mapper.addMixIn(MultipartFile.class, JacksonMixInForIgnoreType.class); try { // 將對象序列化為JSON字符串,再反序列化回對象 return mapper.readValue(mapper.writeValueAsString(obj), obj.getClass()); } catch (JsonProcessingException e) { throw new RuntimeException("DTO克隆失敗", e); } } // 定義一個空的 MixIn 接口或類,并用 @JsonIgnoreType 標記 @JsonIgnoreType static class JacksonMixInForIgnoreType {} // 示例DTO,可能包含 MultipartFile 字段 static class DeepCopyDto { private String name; private MultipartFile singleFile; // ... 其他字段 } }
上述代碼對于DTO中包含單個MultipartFile字段的情況通常是有效的。然而,當DTO中包含MultipartFile的數(shù)組,例如MultipartFile[] fileArray;時,這種策略會失敗,并拋出InvalidDefinitionException異常,指出無法找到java.io.FileDescriptor的序列化器,錯誤信息大致如下:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor ... (through reference chain: com.example.uploadingfiles.DeepCopyDto["fileArray"]->org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile[0]->org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])
這表明Jackson在處理數(shù)組類型時,并未將MultipartFile[]視為與MultipartFile相同的類型進行忽略,而是嘗試深入數(shù)組內(nèi)部,最終遇到無法序列化的底層IO流對象。
問題的根源在于Jackson在應(yīng)用MixIn時,將MultipartFile和MultipartFile[]視為兩種不同的類型。因此,要忽略MultipartFile數(shù)組,我們需要為數(shù)組類型本身也添加一個MixIn。
修正后的makeClone方法如下:
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.annotation.JsonIgnoreType; import org.springframework.web.multipart.MultipartFile; public class DtoCloner { private Object makeClone(Object obj) { ObjectMapper mapper = new ObjectMapper(); // 1. 添加針對 MultipartFile 類型的 MixIn mapper.addMixIn(MultipartFile.class, JacksonMixInForIgnoreType.class); // 2. 額外添加針對 MultipartFile 數(shù)組類型的 MixIn mapper.addMixIn(MultipartFile[].class, JacksonMixInForIgnoreType.class); // 關(guān)鍵改動 try { return mapper.readValue(mapper.writeValueAsString(obj), obj.getClass()); } catch (JsonProcessingException e) { throw new RuntimeException("DTO克隆失敗", e); } } @JsonIgnoreType static class JacksonMixInForIgnoreType {} // 示例DTO,現(xiàn)在可以包含 MultipartFile 數(shù)組 static class DeepCopyDto { private String name; private MultipartFile singleFile; private MultipartFile[] fileArray; // 包含 MultipartFile 數(shù)組 // ... 其他字段 } }
通過在ObjectMapper中額外添加一行mapper.addMixIn(MultipartFile[].class, JacksonMixInForIgnoreType.class);,我們明確告訴Jackson:當遇到MultipartFile類型或MultipartFile數(shù)組類型時,都應(yīng)該應(yīng)用JacksonMixInForIgnoreType,從而忽略這些字段的序列化。
當需要深度克隆包含不可控的非序列化類型(如MultipartFile)及其數(shù)組的DTO時,Jackson的ObjectMapper結(jié)合addMixIn提供了一個強大的解決方案。關(guān)鍵在于理解Jackson對類型匹配的精確性要求,并為原始類型及其數(shù)組類型分別配置MixIn。然而,對于泛型集合類型,此方法存在局限性,通常需要結(jié)合其他策略來解決。掌握這些技巧,能夠幫助開發(fā)者在處理復(fù)雜DTO克隆場景時更加靈活和高效。
以上就是Jackson深度克隆DTO時忽略特定類型數(shù)組屬性的策略的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進程會占用資源并降低性能。幸運的是,許多工具可以讓 Windows 保持平穩(wěn)運行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號