如何正确重用Jackson ObjectMapper?

时间:2013-09-04 10:38:55

标签: java jackson

我对ObjectMapper如何工作以及在我的应用程序中的一般用途感到满意。我想了解的是实现ObjectMapper的最佳方法,以确保它被重用,我不是在我的应用程序中创建不必要的实例?

我的想法是我可以在Utils类中声明ObjectMapper,如下所示:

public class Utils {

    public final static ObjectMapper mapper = new ObjectMapper();

}

然后我可以从我需要使用代码的各个地方引用它,例如:

JsonSimple jsonSimple = Utils.mapper.readValue(jsonString, JsonSimple.class);

我遇到了另一个提示我的方法的问题(Should I declare Jackson's ObjectMapper as a static field?)。我想可能关键的区别在于我想在多个不同的类中共享我的ObjectMapper实例,而不仅仅是在一个类中。

这种方法听起来合适还是我错过了什么?

由于

4 个答案:

答案 0 :(得分:41)

每个应用程序使用一个实例是很好的,前提是你在任何配置方法可见之后都不会调用它,即你应该在静态块中进行所有初始化。

答案 1 :(得分:8)

正如其他答案所述,ObjectMapper确实是Thread安全的。但重用相同的对象会降低应用程序的性能,因为在给定时间可以锁定所有1个线程,等待锁的所有者完成JSON的序列化/反序列化。

这对于Jetty或Tomcat等Web服务器尤其重要:例如,如果使用单例ObjectMapper作为REST服务的入口/出口点,整个服务器的整体性能可能会受到影响 - 当然,这取决于在您的访问负载上。

所以,我的建议是使用一个ObjectMappers池,允许多个线程使用它,并且在某种程度上你不必在每次需要时重新创建映射器。池中ObjectMappers的编号应与应用程序的工作线程数相同。

更多关于:http://jackson-users.ning.com/forum/topics/pooling-objectmapper-for-performance

- 编辑 -

好吧,有些用户真的对Jackson lib充满热情,以至于他们甚至没有查看链接的网站就会回答这个问题。无论如何,这个答案是基于我在没有任何修改的情况下使用lib的经验(仅使用ObjectMapper,没有额外的类,没有自定义序列化器,没有自定义JSONFactory,没有),在回答时(2013)。我不再在我的项目上使用它,所以我不知道更新的版本 - 但我想它现在应该解决了。

作为开发人员,如果您要在项目中直接或间接使用Jackson或任何其他JSON读取器/写入器,请考虑在服务器上运行性能分析工具,以查看线程在高负载下的行为方式。这是一个不会造成伤害的简单步骤。

答案 2 :(得分:5)

使用最新版本的Jackson并使用ObjectReaderObjectWriter代替ObjectMapper

答案 3 :(得分:1)

您在问题中提出的普通静态单例是正确的。另一种方法是使用单例模式(the use of singleton pattern been discussed at length in answer comments to a similar question)。这是一个简单的例子:

public enum Mapper {
  INSTANCE;
  private final ObjectMapper mapper = new ObjectMapper();

  private Mapper(){
    // Perform any configuration on the ObjectMapper here.
  }

  public ObjectMapper getObjectMapper() {
    return mapper;
  }
}

然后您可以使用(并重复使用)ObjectMapper单例,如下所示:

ObjectMapper mapper = Mapper.INSTANCE.getObjectMapper();
JsonSimple jsonSimple = mapper.readValue(jsonString, JsonSimple.class);

这是安全的,因为ObjectMapperthread-safe after configuration

警告:正如@StaxMan在答案评论中指出的那样,这并不保证不会对返回的单例进行进一步(重新)配置。