75

我对 ObjectMapper 在我的应用程序中的工作方式和一般用途感到满意。我想了解的是实现 ObjectMapper 以确保它被重复使用并且我没有在我的应用程序中创建不必要的实例的最佳方式?

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

public class Utils {

    public final static ObjectMapper mapper = new ObjectMapper();

}

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

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

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

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

谢谢

4

4 回答 4

59

可以为每个应用程序使用单个实例,前提是您在其可见后不调用任何配置方法,即您应该在静态块内进行所有初始化。

于 2013-09-04T13:55:31.883 回答
17

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

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

因此,我的建议是使用 ObjectMappers 池,以允许多个线程使用它,并且您不必在每次需要映射器时都重新创建它们。池中 ObjectMappers 的数量应与应用程序的工作线程数相同。

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

- 编辑 -

好的,一些用户对 Jackson 库非常热情,以至于他们甚至不看链接的网站就对这个答案投了反对票。无论如何,这个答案是基于我在回答时(2013 年)没有任何修改(仅使用 ObjectMapper,没有额外的类,没有自定义序列化程序,没有自定义 JSONFactory,什么都没有)的 lib 经验。我不再在我的项目中使用它,所以我不知道新版本 - 但我想它现在应该解决了。

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

于 2013-09-04T16:13:03.540 回答
7

使用最新版本的 Jackson 并使用ObjectReaderandObjectWriter而不是ObjectMapper

于 2015-01-22T15:47:44.187 回答
3

您在问题中提出的普通静态单例是正确的。另一种方法是使用单例模式(在对类似问题的回答评论中详细讨论了单例模式的使用)。这是一个简单的例子:

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);

这是安全的,因为在配置之后ObjectMapper线程安全的

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

于 2013-09-04T15:59:49.737 回答