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不用我再说了吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/801192.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript 书写位置

JS 分为三种使用方法&#xff0c;分别为行内&#xff0c;内嵌&#xff0c;外部。 行内式&#xff08;不推荐使用&#xff09; 行内就是 将 JS 代码直接写在 HTML 标签上 &#xff0c;这种方式的结构、行为分离不够彻底&#xff0c;不利于后 期维护&#xff0c;复用性不强…

2024年3月30日~2024年4月7日周报

文章目录 一、前言二、创意收集2.1 多任务学习2.1.1 多任务学习的定义与优势2.1.2 多任务学习的分类 2.2 边缘检测2.2.1 基础理论2.2.2 sobel代码介绍2.2.3 canny代码介绍 三、《地震速度模型超分辨率的多任务学习》3.1 M-RUDSR架构3.2 详细介绍3.3 实验设置 四、实验五、小结5…

揭秘程序员面试技巧,助你轻松拿offer!

上文 程序员面试是求职者展现自身技术实力、沟通能力和职业素养的关键环节。为了在面试中脱颖而出&#xff0c;求职者需要掌握一些实用的面试技巧。以下将详细阐述程序员面试技巧&#xff0c;助您在面试中取得更好的成绩。 一、面试前准备 了解公司及职位 在面试前&#xff0…

操作系统与编程系列专栏(一):导言

在一间充满了键盘敲击声和低语讨论的办公室内&#xff0c;两位资深程序员&#xff0c;老马和老王&#xff0c;围绕着一个永恒的话题展开了讨论。他们的对话不仅引发了思考&#xff0c;也为那些在软件开发道路上前行的人提供了不少启示。 老马&#xff1a;“我觉得深入了解操作系…

【leetcode面试经典150题】18.整数转罗马数字(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

【LeetCode题解】2009. 使数组连续的最少操作数

文章目录 [2009. 使数组连续的最少操作数](https://leetcode.cn/problems/minimum-number-of-operations-to-make-array-continuous/)思路&#xff1a;一、排序去重滑动窗口代码&#xff1a; 2009. 使数组连续的最少操作数 思路&#xff1a;一、排序去重滑动窗口 1.对数组进行…

C语言代码块及块级作用域

代码块 所谓代码块&#xff0c;就是由{ }包围起来的代码。代码块在C语言中随处可见&#xff0c;例如函数体、选择结构、循环结构等。不包含代码块的C语言程序根本不能运行&#xff0c;即使最简单的C语言程序也要包含代码块。C语言允许在代码块内部定义变量&#xff0c;这样的变…

P8794 [蓝桥杯 2022 国 A] 环境治理

P8794 [蓝桥杯 2022 国 A] 环境治理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include <iostream> using namespace std; #define ll long long const int N150; const int inf0x7fffffff; int n,q; int d[N][N],l[N][N]; int t[N][N]; void floyd() {for(int k0…

nandgame中的asm编程 Escape Labyrinth(逃离迷宫)

先翻译题目&#xff1a; 逃离迷宫计算机被困在火星上的迷宫中。编写一个程序&#xff0c;让它逃离迷宫。计算机配备了连接的轮子和前方障碍物探测器。与轮子和探测器的输入/输出是内存映射在地址7FFF上&#xff1a;对外设的输出信号&#xff1a; 位 设置为1代表&#xff1a; 2…

UE4_动画基础_ 使用分层动画(Using Layered Animations)

完成在移动过程中武器发射的角色制作&#xff01; 动画混合仅仅意味着在一个角色或骨架网格体上的两个或多个动画之间进行平滑过渡。在虚幻引擎4中&#xff0c;有多种方法可以应用这种混合&#xff0c;要么通过混合空间&#xff0c;或通过实际组合两个基于加权偏差或alpha值的…

C语言的数组

一、数组的赋值 对单个元素赋值 int a[3]; a[0] 3; a[1] 100; a[2] 34;整体赋值&#xff08;不指明数组长度&#xff09; float b[] { 23.3, 100.00, 10, 0.34 };整体赋值&#xff08;指明数组长度&#xff09; int m[10] { 100, 30, 234 };字符数组赋值 char str1[] &qu…

Java数组详解

​TOC 第一章、数组的概念介绍 1.1&#xff09;数组的概念 ①数组就是用来储存数据的容器,可以存储同一种类型的数据&#xff0c;是同一种数据类型的集合。实现对这些数据的统一管理。如果数组中存储的是基本类型数据&#xff0c;我就不能往里面存引用类型数据。数组中存储的…

全量知识系统 程序详细设计 “三次演算” 再探(QA)之1 (百度文库)

说明&#xff1a;以下关于全知系统中程序详细设计的沟通是基于今天正在完成中的全量知识系统 程序详细设计之“命名法” “正文”的" 前言" 之1 “前提”篇 中提出的所有程序要求的基础上的。 Q1.这些规则 在程序被设计为 λ表达式的三个转换规则&#xff0c;分别适…

CLIPSeg如果报“目标计算机积极拒绝,无法连接。”怎么办?

CLIPSeg这个插件在使用的时候&#xff0c;偶尔会遇到以下报错&#xff1a; Error occurred when executing CLIPSeg: (MaxRetryError("HTTPSConnectionPool(hosthuggingface.co, port443): Max retries exceeded with url: /CIDAS/clipseg-rd64-refined/resolve/main/toke…

【前端】深度选择器

升级vue2项目到vue3时候发现 the >>> and /deep/ combinators have been deprecated. Use :deep() instead.这是因为项目使用的 css 扩展语言是 dart-sass&#xff0c;不支持 /deep/ &#xff08;less/node-sass&#xff09;和 >>>&#xff08;css&#xff0…

14届蓝桥杯 C/C++ B组 T5 接龙排序 (最长上升子序列DP+优化)

不难发现这是一个LIS问题&#xff0c;但是如果直接套用LIS的模版&#xff0c;在数据范围到达 1 e 5 1e5 1e5 的情况下&#xff0c;就只能够得到一半的分数&#xff0c;所以我们需要对其进行优化。 首先给出暴力的代码&#xff1a; #include<iostream> using namespace…

知识管理系统|基于Springboot和vue的知识管理系统设计与实现(源码+数据库+文档)

知识管理 目录 基于Springboot和vue的知识管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台&#xff1a; 5.2.2 文章信息 5.3.1 论坛交流 2、后台 用户管理 5.1.2 文章分类 5.2.1 资料分类 四、数据库设计 五、核心代码 六、论文参考 七、最…

Python模拟退火算法

模拟退火算法&#xff08;Simulated Annealing, SA&#xff09;是一种启发式搜索算法&#xff0c;用于在一个大的搜索空间中寻找问题的近似全局最优解。它受到物理退火过程的启发&#xff0c;通过模拟物理退火过程中的冷却来逐步减少搜索空间&#xff0c;并在一定概率下接受劣解…

2024年上半年WSK-PETS5报名及考试时间公布

4月1日&#xff0c;中国教育考试网发布了2024年上半年全国外语水平考试WSK&#xff08;PETS5&#xff09;的报名及考试通知&#xff0c;为方便关注者&#xff0c;知识人网小编特做全文转载。 国家公派留学人员全国外语水平考试&#xff08;WSK-PETS5&#xff09;成绩作为国家留…

MySql命令汇总

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…