禁用Jersey的ObjectMapper缓存?

时间:2014-06-27 06:13:31

标签: java rest caching jackson jersey-2.0

我使用Jersey 2.9和Jackson 2.5.1在RESTful API上生成JSON响应。

为了提供自定义ObjectMapper,我实现了ContextResolver,如下所示:

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

    @Context UriInfo uriInfo;

    private final ObjectMapper objectMapper;

    public ObjectMapperProvider() {
    objectMapper = new ObjectMapper();

    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
    objectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {

        // TODO: configure custom object mapper depending on query string params

        return objectMapper;
    }

}

第一次访问端点时效果很好:调用getContext方法,并根据用户提供的查询字符串对objectmapper执行自定义配置(可能返回一个新配置)。

但是,一旦端点被访问过一次,Jersey似乎会缓存该对象映射器,并且再也不会要求它再次调用getContext。我需要禁用或阻止此行为,因为查询字符串可能已更改,我可能需要为该请求返回不同的对象映射器。

这可能吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

请注意,对象映射器的创建成本相对较高。它是线程安全的designed to be reused。因此,您可以考虑在不创建新映射器实例的情况下为每个请求自定义the Jackson JAX-RS provider,而不是创建自己的上下文。

有几种方法可以实现这一目标。

您可以使用the Jackson specific annotations注释资源方法。例如:

@JacksonFeatures(serializationEnable 
        = { SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS })
public void foo() {}

但是,这并不允许将请求参数传递给对象映射器。

另一种选择是创建ObjectWriterModifier/ObjectReaderModifier的实例,并通过ObjectWriterInjector / ObjectReaderInjector通过线程本地注入来注册它。请参阅example

您还可以尝试组合per-request scope context provider和线程本地修改。