SpringBoot中这样用ObjectMapper,才够优雅!

2024-04-09 04:04

本文主要是介绍SpringBoot中这样用ObjectMapper,才够优雅!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 背景
  • 步骤
    • 在SpringBoot项目中要实现对象与Json字符串的互转,每次都需要像如下一样new 一个ObjectMapper对象:
    • 这样的代码到处可见,有问题吗?
    • 我们要使用jmh测试几种方式的区别:
    • 所以在我们真正使用的时候不要在方法中去new ObjectMapper了,使用单例模式实现上述功能。
  • 总结

背景

借助ObjectMapper实现map转对象太慢了,如何解决?

步骤

在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测试几种方式的区别:

1、引入jar包

        <dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.23</version></dependency><!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-generator-annprocess  --><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.23</version></dependency>

2、

@BenchmarkMode({Mode.Throughput})
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(10)
public class ObjectMapperTest {String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";@State(Scope.Benchmark)public static class BenchmarkState {ObjectMapper GLOBAL_MAP = new ObjectMapper();ThreadLocal<ObjectMapper> GLOBAL_MAP_THREAD = new ThreadLocal<>();}@Benchmarkpublic Map globalTest(BenchmarkState state) throws Exception{Map map = state.GLOBAL_MAP.readValue(json, Map.class);return map;}@Benchmarkpublic Map globalTestThreadLocal(BenchmarkState state) throws Exception{if(null == state.GLOBAL_MAP_THREAD.get()){state.GLOBAL_MAP_THREAD.set(new ObjectMapper());}Map map = state.GLOBAL_MAP_THREAD.get().readValue(json, Map.class);return map;}@Benchmarkpublic Map localTest() throws Exception{ObjectMapper objectMapper = new ObjectMapper();Map map = objectMapper.readValue(json, Map.class);return map;}public static void main(String[] args) throws Exception {Options opts = new OptionsBuilder().include(ObjectMapperTest.class.getSimpleName()).resultFormat(ResultFormatType.CSV).build();new Runner(opts).run();}
}

结果:
在这里插入图片描述
这是一个性能测试的结果,具体是使用JMH(Java Microbenchmark Harness)或其他类似的性能测试工具进行JSON解析(很可能是使用Jackson库的ObjectMapper)的性能测试。以下是每一列的解释:

Benchmark:测试的名称或描述。这里有三个测试:
ObjectMapperTest.globalTest:可能是一个全局的ObjectMapper实例的解析性能测试。
ObjectMapperTest.globalTestThreadLocal:可能是使用ThreadLocal存储的ObjectMapper实例的解析性能测试,这样每个线程都有自己的实例,避免了线程间的竞争。
ObjectMapperTest.localTest:可能是每次解析时都创建新的ObjectMapper实例的性能测试。
Mode:测试的模式。在这里,thrpt代表吞吐量(throughput),即单位时间内完成的操作数。
Cnt:运行的次数或迭代的次数。在这里,每个测试都运行了5次。
Score:测试的平均得分。对于吞吐量测试,这通常表示每秒完成的操作数(ops/s)。
ObjectMapperTest.globalTest的平均得分是6148814.405 ops/s。
ObjectMapperTest.globalTestThreadLocal的平均得分是6584146.770 ops/s。
ObjectMapperTest.localTest的平均得分是447976.202 ops/s。
Error:测试得分的误差范围。这通常表示测试结果的波动或不确定性。
从这些结果中,我们可以得出以下结论:

使用ThreadLocal存储的ObjectMapper实例(globalTestThreadLocal)在性能上稍优于全局的ObjectMapper实例(globalTest)。
每次解析时都创建新的ObjectMapper实例(localTest)的性能远低于前两者。

所以在我们真正使用的时候不要在方法中去new ObjectMapper了,使用单例模式实现上述功能。

在创建工具类时要将工具类设置成单例的,这样不仅可以保证线程安全,也可以保证在系统全局只能创建一个对象,避免频繁创建对象的成本。

所以,我们可以在项目中构建一个ObjectMapper的单例类。

@Getter
public enum ObjectMapperInstance {INSTANCE;private final ObjectMapper objectMapper = new ObjectMapper();ObjectMapperInstance() {}
}
使用方式:ObjectMapper objectMapper = ObjectMapperInstance.INSTANCE.getObjectMapper();
然后进行调用

总结

通过上面的测试,结论已经很清晰了。所以在Spring中如何正确的使用ObjectMapper不用我再说了吧~

这篇关于SpringBoot中这样用ObjectMapper,才够优雅!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/887133

相关文章

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过