java 如何使用 Guice / Jersey 挂钩 Jackson ObjectMapper
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16757724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to hook Hymanson ObjectMapper with Guice / Jersey
提问by user340535
I can't seem to get my Hymanson ObjectMapper Module registered correctly.
我似乎无法正确注册我的 Hymanson ObjectMapper 模块。
I'm using a Guice + Jersey + Hymanson (FasterXML) stack.
我正在使用 Guice + Jersey + Hymanson (FasterXML) 堆栈。
I've followed how to customise the ObjectMapper based on various question here. In particular, I have a ContextResolver declared, marked as an @javax.ws.rs.ext.Provider and a @javax.inject.Singleton.
我遵循了如何根据此处的各种问题自定义 ObjectMapper。特别是,我声明了一个 ContextResolver,标记为 @javax.ws.rs.ext.Provider 和 @javax.inject.Singleton。
I have a GuiceServletContextListener along the lines of:
我有一个 GuiceServletContextListener 沿着以下几行:
@Override
protected Injector getInjector() {
Injector injector = Guice.createInjector(new DBModule(dataSource),
new ServletModule()
{
@Override
protected void configureServlets() {
// Mapper
bind(HymansonOMP.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;
}
Mapper defined
映射器定义
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 HymansonOMP implements ContextResolver<ObjectMapper> {
@Override
public ObjectMapper getContext(Class<?> aClass) {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate4Module());
return mapper;
}
}
However - with this configuration alone, getContext() is never called, so the mapper is never registered. I'm stuck in a typical guice--annotations-mystery, where it's practically untraceable to what I'm actually supposed to be doing. Spring users just report registering the component, and the container just picks it up.
但是 - 仅使用此配置,永远不会调用 getContext(),因此永远不会注册映射器。我被困在一个典型的 guice--注释-神秘中,在那里它实际上无法追踪到我实际上应该做的事情。Spring 用户只报告注册了组件,容器就直接捡起来了。
Thisanswer talks about overriding my own javax.ws.rs.core.Application implementation. However, this looks hard-wired in the jersey-guice impementation of GuiceContainer to be DefaultResourceConfig():
这个答案谈论覆盖我自己的 javax.ws.rs.core.Application 实现。然而,在 GuiceContainer 的 jersey-guice 实现中,这看起来是 DefaultResourceConfig():
@Override
protected ResourceConfig getDefaultResourceConfig(Map<String, Object> props,
WebConfig webConfig) throws ServletException {
return new DefaultResourceConfig();
}
Am I supposed subclass GuiceContainer here? Or is there some other magic annotation that I'm missing?
我应该在这里继承 GuiceContainer 吗?还是我缺少其他一些神奇的注释?
This seems a fairly common thing to want to do - I'm surprised at how hard it's proving to do with this guice combination.
这似乎是一件很常见的事情 - 我很惊讶用这种 guice 组合来证明它是多么困难。
回答by Vladimir Matveev
I'm stuck in a typical guice--annotations-mystery, where it's practically untraceable to what I'm actually supposed to be doing. Spring users just report registering the component, and the container just picks it up.
我被困在一个典型的 guice--注释-神秘中,在那里它实际上无法追踪到我实际上应该做的事情。Spring 用户只报告注册了组件,容器就直接捡起来了。
You really should read excellent Guice documentation. Guice is very easy to use, it has very small number of basic concepts. Your problem is in that you mixed Jersey JAX-RS dependency injection and Guice dependency injection. If you are using GuiceContainer
then you declare that you will be using Guice for allof your DI, so you have to add bindings with Guice and not with JAX-RS.
您真的应该阅读优秀的 Guice 文档。Guice 非常易于使用,它的基本概念很少。您的问题在于您混合了 Jersey JAX-RS 依赖注入和 Guice 依赖注入。如果您正在使用,GuiceContainer
那么您声明您将在所有DI 中使用 Guice ,因此您必须使用 Guice 而不是 JAX-RS 添加绑定。
For instance, you do not need ContextResolver
, you should use plain Guice Provider
instead:
例如,您不需要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;
}
}
Then you should add corresponding binding to your module:
然后你应该为你的模块添加相应的绑定:
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class).in(Singleton.class);
This will bind ObjectMapper
, but it is not enough to use Jersey with Hymanson. You will need some kind of MessageBodyReader
/MessageBodyWriter
, e.g. HymansonJsonProvider
. You will need another provider for it:
这将绑定ObjectMapper
,但将 Jersey 与 Hymanson 一起使用是不够的。您将需要某种MessageBodyReader
/ MessageBodyWriter
,例如HymansonJsonProvider
. 您将需要另一个提供者:
public class HymansonJsonProviderProvider implements Provider<HymansonJsonProvider> {
private final ObjectMapper mapper;
@Inject
HymansonJsonProviderProvider(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public HymansonJsonProvider get() {
return new HymansonJsonProvider(mapper);
}
}
Then bind it:
然后绑定:
bind(HymansonJsonProvider.class).toProvider(HymansonJsonProviderProvider.class).in(Singleton.class);
This is all you need to do - no subclassing is needed.
这就是您需要做的全部 - 不需要子类化。
There is a room for code size optimization though. If I were you I would use @Provides
-methods:
不过,代码大小仍有优化空间。如果我是你,我会使用@Provides
-methods:
@Provides @Singleton
ObjectMapper objectMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate4Module());
return mapper;
}
@Provides @Singleton
HymansonJsonProvider HymansonJsonProvider(ObjectMapper mapper) {
return new HymansonJsonProvider(mapper);
}
These methods should be added to one of your modules, e.g. to anonymous ServletModule
. Then you won't need separate provider classes.
BTW, you should use JerseyServletModule
instead of plain ServletModule
, it provides a lot of useful bindings for you.
这些方法应该添加到您的模块之一,例如匿名ServletModule
。那么您将不需要单独的提供程序类。
顺便说一句,您应该使用JerseyServletModule
而不是 plain ServletModule
,它为您提供了许多有用的绑定。