如何在jersey2/hk2应用程序中获取对Jackson Object Mapper的引用

agn*_*nul 9 java json dependency-injection jersey-2.0 hk2

我有一个jersey2应用程序配置为通过杰克逊支持JSON,添加

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey.version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

在POM文件中

public MyApplication() {
    ...
    register(JacksonFeature.class)
    ...
}
Run Code Online (Sandbox Code Playgroud)

在我的申请中.一切正常,我的资源将反序列化的POJO作为参数

@POST @Consumes(MediaType.APPLICATION_JSON)
public void blah(MyPojo p) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在,其中一个资源需要提及杰克逊ObjectMapper自己做一些反序列化.我试过做类似的事情

@Inject
public MyResource(@Context ObjectMapper mapper) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

要么

@GET
public String foo(@Context ObjectMapper mapper) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

但在这两种情况下,引用都mapper为null.如何ObjectMapper在我的资源中注入引用?

Pau*_*tha 5

首先ObjectMapper,Jackson提供商没有使用默认值.它实际上根本不使用ObjectMapper.它利用其他Jackson API来处理(反)序列化.

如果你想使用/注入一个ObjectMapper实例,那么你应该只Factory为它创建一个

public class ObjectMapperFactory implements Factory<ObjectMapper> {

    final ObjectMapper mapper = new ObjectMapper();

    @Override
    public ObjectMapper provide() {
        return mapper;
    }

    @Override
    public void dispose(ObjectMapper t) {}   
}
Run Code Online (Sandbox Code Playgroud)

然后绑定它

register(new AbstractBinder(){
    @Override
    public void configure() {
        bindFactory(ObjectMapperFactory.class)
            .to(ObjectMapper.class).in(Singleton.class);
    }
});
Run Code Online (Sandbox Code Playgroud)

应该注意的一点是,任何配置都不ObjectMapper线程安全的.所以说你试图从资源方法配置它,这些操作不是线程安全的.

与杰克逊提供商另外要注意的是,如果我们提供了ContextResolver,像被@Laurentiu大号提到,那么杰克逊提供商将切换为使用我们的ObjectMapper.在这种情况下,如果你想使用相同的ObjectMapper,那么你可以在中查找Factory.例如

public class ObjectMapperFactory implements Factory<ObjectMapper> {

    private final Providers providers;
    final ObjectMapper mapper = new ObjectMapper();

    public ObjectMapperFactory(@Context Providers providers) {
        this.providers = providers;
    }

    @Override
    public ObjectMapper provide() {
        ContextResolver<ObjectMapper> resolver = providers.getContextResolver(
                ObjectMapper.class, MediaType.APPLICATION_JSON);
        if (resolver == null) { return mapper; }

        return resolver.getContext(null);
    }

    @Override
    public void dispose(ObjectMapper t) {}   
}
Run Code Online (Sandbox Code Playgroud)

要使上述工作(使用单个ObjectMapper),您需要确保实现ContextResolver<ObjectMapper>,并确保ContextResolver使用相应的@Produces@Consumes媒体类型注释.