当前位置: 首页 > 知识库问答 >
问题:

如何将Jackson ObjectMapper与Guice/泽西挂钩

田慈
2023-03-14

我似乎无法正确注册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;
}

映射器定义

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

然而,仅此配置就不会调用getContext(),因此映射器也不会注册。我被困在一个典型的伪装中——注释之谜,它几乎无法追踪到我实际应该做的事情。Spring用户只需报告注册组件,而容器只需接收它。

这个答案讨论了如何覆盖我自己的javax.ws.rs.core.Application实现。然而,这在GuiceContainer的球衣伪装中看起来是LudefResourceConfig():

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

我应该是GuiceContainer的子类吗?还是有其他我遗漏的神奇注释?

这似乎是想做的一件相当普通的事情——我惊讶地发现,用这种guice组合来做这件事是多么困难。

共有1个答案

龙才俊
2023-03-14

我陷入了一个典型的伪装 - 注释 - 神秘,它实际上无法追踪到我实际上应该做的事情。Spring用户只需报告注册组件,容器就会拿起它。

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

例如,您不需要ContextResolver,您应该使用纯GuiceProvider代替:

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

然后,您应该向模块添加相应的绑定:

bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class).in(Singleton.class);

这将绑定 ObjectMapper,但仅仅将 Jersey 与 Jackson 一起使用是不够的。您将需要某种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);
    }
}

然后绑定它:

bind(JacksonJsonProvider.class).toProvider(JacksonJsonProviderProvider.class).in(Singleton.class);

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

不过,代码大小优化有一个空间。如果我是你,我会使用@Provides方法:

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

这些方法应添加到您的一个模块中,例如匿名ServletModule。这样就不需要单独的提供者类
顺便说一句,您应该使用JerseyServletModule而不是普通的ServletModule,它为您提供了许多有用的绑定。

 类似资料:
  • 问题内容: 我的问题是:为什么在创建部署在某种servlet容器(如jetty或tomcat)上的应用程序时执行JavaSE应用程序和ServletModule时需要创建AbstractModule?它们之间有什么区别? 我需要将Jersey与Guice集成在一起。是否需要注册Guice的存在才能以某种方式使用它?我是否可以仅启用注入并在我想要的任何地方(常规类,过滤器,处理程序,服务,DAO等)

  • 我正在尝试使用JAX-RS(Jersey)构建JSON RESTful Webservice。我也在使用Maven构建应用程序。 我的第一个方法是 pom之后。xml- 所以我补充道 到我的pom文件。其他lib文件(例如jackson-cors-asl-1.7.1.jar、jackson-jaxrs-1.7.1.jar、jaxb impl,…)也可以在生成的war文件中找到//编辑:它还下载st

  • 我正在开发一个REST Web服务,其中我使用URL中的ID来指定患者,如下所示: <代码>WS/服务/患者/1 其中“1”是患者的id。所以,在代码中,我这样指定: 我在一个例子中看到了它,但是我的失败了。我得到了这个错误: 通用域名格式。太阳运动衫应用程序编程接口。容器ContainerException:方法,public void PresentationLayer。PatientReso

  • 问题内容: 分析了整个互联网,但无法弄清楚为什么会发生这种情况。我有一个最简单的项目(使用jersey-quickstart- grizzly2原型),并且只有一个Jersey资源。我将Guice用作DI,因为CDI也不想与Jersey合作。问题在于,Guice在注入Jersey的资源时无法解析要使用的类。它在外面很好用,但不适用于泽西岛。这是泽西岛的资源: 传输接口: 它的实现: 遵循Googl

  • 有没有示例代码演示如何在Jersey 2.0中使用guice-servlet?

  • 我正在尝试使用hk2 DI在泽西岛,我已经读了一些关于这件事的文本。(我想大多数已经过时了)目前我有一个扩展ResourceConfig的类: 更新: 我应该添加我将应用程序包添加到web.xml中的扫描路径: