如何在 jersey2 / hk2 应用程序中获取对 Jackson Object Mapper 的引用
How do I get a reference to the Jackson Object Mapper in a jersey2 / hk2 application
我有一个 jersey2 应用程序配置为 JSON 通过 Jackson 的支持,添加
<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) {
...
}
现在,其中一个资源需要引用 Jackson 的 ObjectMapper
才能自行进行一些反序列化。我试过做类似
的事情
@Inject
public MyResource(@Context ObjectMapper mapper) {
...
}
或
@GET
public String foo(@Context ObjectMapper mapper) {
...
}
但在这两种情况下,对 mapper
的引用都是空的。如何在我的资源中插入对 ObjectMapper
的引用?
除了 JacksonFeature 之外,您还需要为 ObjectMapper 注册一个 ContextResolver。
9.1.4.2 Documentation 中的简单示例。配置并注册
@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)
首先,Jackson 提供商没有使用默认值 ObjectMapper
。它实际上根本不使用 ObjectMapper
。它利用其他 Jackson API 来处理(反)序列化。
如果你想use/inject一个单一的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
的任何配置 不是线程安全的 。所以说你试图从你的资源方法配置它,那些操作不是线程安全的。
Jackson 提供者需要注意的另一件事是,如果我们提供 ContextResolver
,例如 ,那么 Jackson 提供者将切换到使用我们的 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>
,并确保用相应的[注释ContextResolver
=25=] 和 @Consumes
媒体类型。
我有一个 jersey2 应用程序配置为 JSON 通过 Jackson 的支持,添加
<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) {
...
}
现在,其中一个资源需要引用 Jackson 的 ObjectMapper
才能自行进行一些反序列化。我试过做类似
@Inject
public MyResource(@Context ObjectMapper mapper) {
...
}
或
@GET
public String foo(@Context ObjectMapper mapper) {
...
}
但在这两种情况下,对 mapper
的引用都是空的。如何在我的资源中插入对 ObjectMapper
的引用?
除了 JacksonFeature 之外,您还需要为 ObjectMapper 注册一个 ContextResolver。
9.1.4.2 Documentation 中的简单示例。配置并注册
@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)
首先,Jackson 提供商没有使用默认值 ObjectMapper
。它实际上根本不使用 ObjectMapper
。它利用其他 Jackson API 来处理(反)序列化。
如果你想use/inject一个单一的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
的任何配置 不是线程安全的 。所以说你试图从你的资源方法配置它,那些操作不是线程安全的。
Jackson 提供者需要注意的另一件事是,如果我们提供 ContextResolver
,例如 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>
,并确保用相应的[注释ContextResolver
=25=] 和 @Consumes
媒体类型。