【问题标题】:Set Jackson DeserializationContext Attribute in per-request, thread-safe manner以每个请求、线程安全的方式设置 Jackson DeserializationContext 属性
【发布时间】:2023-03-04 17:22:02
【问题描述】:

我希望能够添加一个请求范围的属性(一个 JAX-RS ContainerRequestContext,因为我宁愿使用 Jackson 将我的参数转换为对象,而不是 JAX-RS 构思不当和笨拙的 ParameterConverterProviders)到DeserializationContext 以便可以从 JsonDeserializer 中获取。我必须调用convertValue() 而不是简单地调用readValue()(不处理实际的JSON),所以我无法在每个线程中创建ObjectReader,除非我愿意先将我的地图序列化为JSON字符串然后读取它back - 这将是非常低效的。

我希望能够以按请求的方式完成以下任务:

ObjectMapper om = new ObjectMapper();

//in request-scoped context:
om.getDeserializationContext().setAttribute("requestContext",containerRequestContext)
Map<String,Object> mapOfRequestParameters = ...

BeanOfVastImportance bean = om.convertValue(mapOfRequestParameters,BeanOfVastImportance.class)

我怎样才能做到这一点,而不需要为每个单独的请求线程创建一个新的 ObjectMapper 的大量、多余的开销?

【问题讨论】:

  • 配置映射器并不安全。您可以根据所有可能的配置创建一定数量的映射器,然后查找您需要的映射器吗?
  • 这在技术上是可行的,但基本上会消除杰克逊的便利性。我真的只需要能够在不可变的 ObjectReader 上调用 convertValue (可以设置上下文属性),但目前这是不可能的,所以寻找一个可以让我完成同样事情的解决方案。

标签: web-services jackson thread-safety jax-rs jersey-2.0


【解决方案1】:

这可以通过以下方式实现:

objectMapper.reader().forType(Request.class)
    .withAttribute("key", "value").readValue<Request>("source")

【讨论】:

  • +1。创建一个新的 ObjectReader 会产生一些开销,但它保留了相同的引用,除了您正在自定义的引用,因此它的占用空间很小,并且由于它绑定到请求,它的生命周期非常短暂。如果您尝试传递的上下文特定于每个请求,那么这看起来是正确的解决方案。
猜你喜欢
  • 1970-01-01
  • 2019-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
  • 2010-10-11
  • 1970-01-01
  • 2012-08-20
相关资源
最近更新 更多