我有一个jersey2应用程序,通过Jackson配置为JSON支持,添加
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
POM文件中的和
public MyApplication() {
...
register(JacksonFeature.class)
...
}
在我的申请中。一切正常,我的资源将反序列化的POJO作为参数
@POST @Consumes(MediaType.APPLICATION_JSON)
public void blah(MyPojo p) {
...
}
现在,其中一个资源需要引用杰克逊的ObjectMapper
来自行进行反序列化。我尝试过像
@Inject
public MyResource(@Context ObjectMapper mapper) {
...
}
或
@GET
public String foo(@Context ObjectMapper mapper) {
...
}
但在这两种情况下,对mapper
的引用都为空。如何在我的资源中注入对ObjectMapper
的引用?
答案 0 :(得分:6)
首先,Jackson提供商没有使用默认ObjectMapper
。它实际上根本不使用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) {}
}
然后绑定它
register(new AbstractBinder(){
@Override
public void configure() {
bindFactory(ObjectMapperFactory.class)
.to(ObjectMapper.class).in(Singleton.class);
}
});
应该注意的一点是,ObjectMapper
的任何配置都是非线程安全。所以说你试图从资源方法配置它,那些操作不是线程安全的。
杰克逊提供商需要注意的另一件事是,如果我们提供ContextResolver
,例如mentioned by @Laurentiu L,那么杰克逊提供商将转而使用我们的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) {}
}
要使上述工作(使用单个ObjectMapper
),您需要确保实施ContextResolver<ObjectMapper>
,并确保使用相应的{{1}注释ContextResolver
}和@Produces
媒体类型。
答案 1 :(得分:3)
除了JacksonFeature之外,您还需要为ObjectMapper注册ContextResolver。
来自Documentation 9.1.4.2的简单示例。配置并注册
@Provider public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> { final ObjectMapper defaultObjectMapper; public MyObjectMapperProvider() { defaultObjectMapper = createDefaultMapper(); } @Override public ObjectMapper getContext(Class<?> type) { return defaultObjectMapper; } private static ObjectMapper createDefaultMapper() { final ObjectMapper result = new ObjectMapper(); result.configure(Feature.INDENT_OUTPUT, true); return result; } // ... }
完整的代码示例 available on Github
您还需要注册
.register(MyObjectMapperProvider.class)