SpringBoot中如何使用ObjectMapper,老鸟们都是这样玩的?
创始人
2025-07-07 04:40:48
0

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

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...