如何使用Guice/Jersey将Jackson ObjectMapper挂钩

use*_*535 11 java jersey guice jackson

我似乎无法正确注册我的Jackson ObjectMapper模块.

我正在使用Guice + Jersey + Jackson(FasterXML)堆栈.

我已经按照如何基于各种问题自定义了ObjectMapper.特别是,我声明了一个ContextResolver,标记为@ javax.ws.rs.ext.Provider和@javax.inject.Singleton.

我有一个GuiceServletContextListener:

@Override
protected Injector getInjector() {

     Injector injector = Guice.createInjector(new DBModule(dataSource),
            new ServletModule()
            {
                @Override
                protected void configureServlets() {


                    // Mapper
                    bind(JacksonOMP.class).asEagerSingleton();

                    // ... 

                    Map<String, String> initParams = new HashMap<String, String>();
                    initParams.put("com.sun.jersey.config.feature.Trace",
                            "true");
                    initParams.put("com.sun.jersey.api.json.POJOMappingFeature", "true");

                    serve("/services/*").with(
                            GuiceContainer.class,
                            initParams);
                }
            });

    return injector;
}
Run Code Online (Sandbox Code Playgroud)

映射器已定义

import javax.inject.Singleton;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
@Singleton
@Produces
public class JacksonOMP implements ContextResolver<ObjectMapper> {

  @Override
  public ObjectMapper getContext(Class<?> aClass) {
    final ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new Hibernate4Module());
    return mapper;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是 - 仅使用此配置,从不调用getContext(),因此从不注册映射器.我陷入了一种典型的诡计 - 注释 - 神秘,它实际上无法实现我实际应该做的事情.Spring用户只报告注册组件,容器只是选择它.

这个答案谈到覆盖我自己的javax.ws.rs.core.Application实现.然而,这看起来很难在GuiceContainer的jersey-guice强制实现DefaultResourceConfig():

@Override
protected ResourceConfig getDefaultResourceConfig(Map<String, Object> props,
        WebConfig webConfig) throws ServletException {
    return new DefaultResourceConfig();
}
Run Code Online (Sandbox Code Playgroud)

我是否认为GuiceContainer是子类?还是有一些我遗漏的魔法注释?

这似乎是一件相当普遍的事情 - 我很惊讶这种guice组合有多么难以证明.

Vla*_*eev 24

我陷入了一种典型的诡计 - 注释 - 神秘,它实际上无法实现我实际应该做的事情.Spring用户只报告注册组件,容器只是选择它.

你真的应该阅读优秀的Guice文档.Guice非常易于使用,它具有非常少量的基本概念.你的问题在于你混合了Jersey JAX-RS依赖注入和Guice依赖注入.如果您正在使用,GuiceContainer那么您声明您将使用Guice 来处理所有 DI,因此您必须使用Guice添加绑定而不是使用JAX-RS.

例如,你不需要ContextResolver,你应该使用普通的Guice Provider:

import com.google.inject.Provider;

public class ObjectMapperProvider implements Provider<ObjectMapper> {
    @Override
    public ObjectMapper get() {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Hibernate4Module());
        return mapper;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你应该为你的模块添加相应的绑定:

bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class).in(Singleton.class);
Run Code Online (Sandbox Code Playgroud)

这将绑定ObjectMapper,但仅使用泽西与杰克逊是不够的.你需要某种MessageBodyReader/ MessageBodyWriter,例如JacksonJsonProvider.您将需要另一个提供商:

public class JacksonJsonProviderProvider implements Provider<JacksonJsonProvider> {
    private final ObjectMapper mapper;

    @Inject
    JacksonJsonProviderProvider(ObjectMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public JacksonJsonProvider get() {
        return new JacksonJsonProvider(mapper);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后绑定它:

bind(JacksonJsonProvider.class).toProvider(JacksonJsonProviderProvider.class).in(Singleton.class);
Run Code Online (Sandbox Code Playgroud)

这就是您需要做的 - 不需要子类化.

虽然有一个代码大小优化的空间.如果我是你,我会使用@Provides-methods:

@Provides @Singleton
ObjectMapper objectMapper() {
    final ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new Hibernate4Module());
    return mapper;
}

@Provides @Singleton
JacksonJsonProvider jacksonJsonProvider(ObjectMapper mapper) {
    return new JacksonJsonProvider(mapper);
}
Run Code Online (Sandbox Code Playgroud)

应将这些方法添加到您的某个模块中,例如匿名ServletModule.那么您将不需要单独的提供程序类.
顺便说一下,你应该使用JerseyServletModule而不是普通的ServletModule,它为你提供了很多有用的绑定.