SpringBoot中如何使用ObjectMapper,老鳥們都是這樣玩的?
來源:JAVA日知錄
1. 每次new一個
在SpringBoot專案中要實現物件與Json字串的互轉,每次都需要像如下一樣new 一個ObjectMapper物件:
public UserEntity string2Obj(String json) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, UserEntity.class);
}
public String obj2String(UserEntity userEntity) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(car)
}
這樣的程式碼到處可見,有問題嗎?
你要說他有問題吧,確實能正常執行;可你要說沒問題吧,在追求效能的同學眼裡,這屬實算是十惡不赦的程式碼了。
首先,讓我們用JMH對這段程式碼做一個基準測試,讓大家對其效能有個大概的瞭解。
基準測試是指透過設計科學的測試方法、測試工具和測試系統,實現對一類測試物件的某項效能指標進行定量的和可對比的測試。而JMH是一個用來構建,執行,分析Java或其他執行在JVM之上的語言的 納秒/微秒/毫秒/宏觀 級別基準測試的工具。
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 3, time = 1)
public class JsonJMHTest {
String json = "{\"id\":122345667,\"email\":\"jianzh5@163.com\",\"price\":12.25}";
UserEntity userEntity = new UserEntity(13345L,"jianzh5@163.com", BigDecimal.valueOf(12.25));
/**
* 測試String to Object
*/
@Benchmark
public UserEntity objectMapper2ObjTest() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, UserEntity.class);
}
/**
* 測試Object to String
*/
@Benchmark
public String objectMapper2StringTest() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(userEntity);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JsonJMHTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
測試環境
# JMH version: 1.36
# VM version: JDK 17.0.3, OpenJDK 64-Bit Server VM, 17.0.3+7-LTS
# Mac AppleM1/16GB
測試結果
透過測試結果可以看出,每次new一個ObjectMapper,在實現字串轉物件時每秒可以完成23萬多次,而實現物件轉Json字串每秒僅可完成2.7萬次。
那該如何最佳化,提升效能呢?
2. 單例化
老鳥們都知道,在建立工具類時要將工具類設定成單例的,這樣不僅可以保證執行緒安全,也可以保證在系統全域性只能建立一個物件,避免頻繁建立物件的成本。
所以,我們可以在專案中構建一個ObjectMapper的單例類。
@Getter
public enum ObjectMapperInstance {
INSTANCE;
private final ObjectMapper objectMapper = new ObjectMapper();
ObjectMapperInstance() {
}
}
再次使用JMH對其測試:
@Benchmark
public UserEntity singleten2ObjTest() throws JsonProcessingException {
ObjectMapper objectMapper = ObjectMapperInstance.INSTANCE.getObjectMapper();
return objectMapper.readValue(json, UserEntity.class);
}
@Benchmark
public String singleten2StringTest() throws JsonProcessingException {
ObjectMapper objectMapper = ObjectMapperInstance.INSTANCE.getObjectMapper();
return objectMapper.writeValueAsString(userEntity);
}
測試結果如下:
可以看到,使用單例模式,String轉物件的方法每秒可以執行420多萬次,比new ObjectMapper的方式快了18倍;而物件轉String的方法每秒可以執行830萬次,效能提升了300倍(看到結果的一瞬間我傻眼了,一度懷疑是寫錯程式碼了)!!!!
3. 個性化配置
當然,在專案中使用ObjectMapper時,有時候我們還需要做一些個性化配置,比如將Long和BigDemical型別的屬性都透過字串格式進行轉換,防止前端使用時丟失數值精度。
這些型別轉換的格式對映都可以在單例類中配置,程式碼如下:
@Getter
public enum ObjectMapperInstance {
INSTANCE;
private final ObjectMapper objectMapper;
ObjectMapperInstance() {
objectMapper = new ObjectMapper();
// 註冊自定義模組
initialize();
}
private void initialize() {
CustomJsonModule customJsonModule = new CustomJsonModule();
objectMapper.registerModule(customJsonModule);
}
}
在initialize()方法中給ObjectMapper註冊自定義序列化轉換器。
第一行是使用註冊自定義序列換轉換器後的效果,給id和price欄位都加上了引號。
再來一次JMH測試:
可以看到,給ObjectMapper額外註冊轉換型別以後效能會受到一定的影響,但對業務影響不大。(啥業務能這麼高的請求~)
4. 小結
透過上面的測試,結論已經很清晰了。使用單例模式進行字串轉物件時效能可以提升18倍,而物件轉String效能快了驚人的290萬倍,所以在Spring中如何正確的使用ObjectMapper不用我再說了吧~
DailyMart是一個基於領域驅動設計(DDD)和Spring Cloud Alibaba的微服務商城系統。我們將在該系統中整合博主其他專欄文章的核心內容。如果你對這兩大技術棧感興趣,可以在本公眾號回覆關鍵詞 DDD 以獲取相關原始碼。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2996283/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SpringBoot 如何統一後端返回格式?老鳥們都是這樣玩的!Spring Boot後端
- SpringBoot整合RocketMQ,老鳥們都是這麼玩的!Spring BootMQ
- Springboot 日誌、配置檔案、介面資料如何脫敏?老鳥們都是這樣玩的!Spring Boot
- SpringBoot 如何進行限流?老鳥們都這麼玩的!Spring Boot
- SpringBoot 如何進行引數校驗,老鳥們都這麼玩的!Spring Boot
- SpringBoot 如何實現非同步程式設計,老鳥們都這麼玩的!Spring Boot非同步程式設計
- 【Spring】原來SpringBoot是這樣玩的Spring Boot
- 深度分頁,我都是這麼玩的
- 如何寫一個好的缺陷,大牛都是這樣的做的
- 在哪裡採集自媒體素材?他們找素材都是這樣找的
- SpringBoot 專案中配置多個 Jackson 的 ObjectMapper ,以及配置遇到的坑Spring BootObjectAPP
- 如何使用objectMapper設定java.time.Instant的字串格式?ObjectAPPJava字串
- Java使用ObjectMapper的簡單示例JavaObjectAPP
- 使用者註冊這樣玩,保你平安
- 父母都是個體戶,沒有養老保險,應該怎樣養老?
- postMessage 還能這樣玩
- 同樣都是使用介面,JAVA 和 Go 差距咋就這麼大呢?JavaGo
- 7.13事故 | 我們是這樣崩的
- 工作中,你們是否遇到一個這樣的人。
- 如何使用 Redis 實現 陪玩原始碼中“附近的人” 這一功能?Redis原始碼
- JAVA 老鳥求兼職Java
- 遊戲社群新勢力,小紅書的使用者們這麼玩遊戲
- 菜鳥程式設計師都是怎樣寫程式碼的?你也可以學一手程式設計師
- 每日一問:Android 滑動衝突,你們都是怎樣處理的Android
- 優秀的機器學習開發者都是這樣做的!機器學習
- 網際網路公司都是這樣說話的,學著點!
- springboot自定義ObjectMapper序列化、配置序列化對LocalDateTime的支援Spring BootObjectAPPLDA
- springboot中如何使用執行緒池Spring Boot執行緒
- 知道這樣重新命名檔案都是大神級別!
- 開工第一天,遊戲人們都是怎樣幹活的?遊戲
- 這個春節玩家們在玩什麼
- SpringBoot 中 JPA 的使用Spring Boot
- springboot中RedisTemplate的使用Spring BootRedis
- 程式設計師們,你們再這樣下去會沒朋友的程式設計師
- 老司機告訴你,我們究竟想要怎樣的遊戲?遊戲
- 在 Ali Kubernetes 系統中,我們這樣實踐混沌工程
- 人工智慧下的音訊還能這樣玩!!!!人工智慧音訊
- 花式玩 Spring Security ,這樣的使用者定義方式你可能沒見過!Spring