如何正确重用Jackson ObjectMapper?

nic*_*itt 55 java jackson

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

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

public class Utils {

    public final static ObjectMapper mapper = new ObjectMapper();

}
Run Code Online (Sandbox Code Playgroud)

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

JsonSimple jsonSimple = Utils.mapper.readValue(jsonString, JsonSimple.class);
Run Code Online (Sandbox Code Playgroud)

我遇到了另一个问题(我应该将Jackson的ObjectMapper声明为一个静态字段吗?),这促使了我的方法.我想也许关键的区别在于我想在多个不同的类中共享我的ObjectMapper实例,而不仅仅是在一个类中.

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

谢谢

Rok*_*okL 46

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

  • 是.另请注意,使用Jackson 2.x,您可以使用`ObjectMapper`作为轻量级和100%线程安全(不可变)`ObjectReader`和`ObjectWriter`对象的工厂 - 这些对象创建起来很便宜,而且总是线程安全,无论它们如何使用. (5认同)
  • 啊,对,我认为ObjectReader会更适合我的情况.干杯全都 (2认同)

Gil*_*zan 11

正如在其他答案中发布的那样,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读取器/写入器,请考虑在服务器上运行分析工具以查看线程在高负载下的行为方式.这是一个不伤害的简单步骤.

  • 不,描述没有任何意义 - 什么锁?哪里?由谁添加?`ObjectMapper`没有具有这种效果的全局锁,原始问题没有建议这样的锁定.因此,汇集的想法将增加复杂性,我无法看到任何好处. (10认同)
  • 我已经阅读了链接到答案,似乎是你不理解它 - 这个问题是(a)不是由于`ObjectMapper`(它是`JsonFactory`)和(b)总是被显示(所以远)由于其他问题,如开发人员没有关闭`JsonParser使用.它与你的主张完全正交; 这就是为什么我已经投了2个现有答案的原因; 它们基本上就是FUD. (4认同)
  • @StaxMan请参阅相关链接.我使用REST作为序列化器/反序列化程序,使用REST作为序列化器/反序列化程序,每秒测试自己一个包含数千个请求的应用程序,并分析我发现Jackson lib在内部锁定线程(确保线程安全)的代码.我认为开发人员在扩展应用程序时应该意识到这种问题.我只是不明白为什么你在这里投了所有的答案 - ****没有意义. (3认同)
  • 我遇到了与@GilbertoTorrezan相同的问题。当使用多个线程尝试进行序列化时,使用Jetty 8和Tomcat时会出现严重问题(JProfiler在调用ObjectMapper时在等待锁的线程发生了几百毫秒的事件)。我的解决方案是切换到Thrift,如果您分析它的生成/库代码,则没有任何Syncronized块,瞧!问题解决了! (2认同)
  • 这是否仍然成立,因为我看到它不需要任何同步。http://fasterxml.github.io/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ObjectReader.html _“使用流畅的(或类似的构建器)模式,使实例不可变(因此,完全是线程安全的**,而无需外部同步**);新实例是为不同的配置构造的。实例最初是由ObjectMapper构造的,并且可以重用,共享,缓存;这既出于线程安全性又因为实例相对轻巧。“ _ (2认同)

小智 6

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

  • @TalyssondeCastro问题的正确答案应该是:因为它们完全不可变且线程安全.因此,在基于单例ObjectMapper更改读取器或写入器上的配置时,您无需担心线程安全. (10认同)
  • 为什么我应该使用这些新对象? (3认同)