我参与了一个旧版Jersey(1.19)和老杰克逊(1.19.13)的项目。 我想切换到新的杰克逊(2.x)反序列化,但仅适用于新的端点(以及逐渐的旧端点),因为一步到杰克逊2和/或泽西2的迁移将非常困难(哦,巨石! )。
我已经看过一些关于如何在Jersey中为杰克逊提供商提供自定义配置的ObjectMapper的话题,或者如何在1.x泽西岛中安装新的杰克逊,但这不是我在寻找,至少不是全部。
我想象的一个解决方案,是(最好)用@ UseJackson2注释我的新JAX-RS端点,或者使用一些基类来从正确的包中检索ObjectMapper,对于这个特定的端点并在以后扩展它 - 换句话说,强制给定端点使用其他(反)序列化提供程序而不是正常情况。
我已经看过使用不同配置的ObjectMappers的提供程序的示例(例如此处Using Jackson in Jersey with multiple configured ObjectMappers),但在我的情况下,ObjectMappers将来自完全不同的包/ maven工件。
答案 0 :(得分:3)
你可以做的是创建一个MessageBodyReader/Writer
来处理杰克逊的2.x版本。 isReadable
和isWritable
方法确定它可以处理哪些实体。您可以检查的是将Jersey的ExtendedUriInfo
注入提供程序并检查资源类以查找@Jackson2
注释。如果注释不存在,则提供者忽略该实体,并且运行时移动到下一个提供者并检查它是否可以处理它;在这种情况下是1.x提供者。
而不是完全创建自己的,你只需要扩展杰克逊已经提供的提供者
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.9.2</version>
</dependency>
您可以延长JacksonJaxbJsonProvider
。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Jackson2 {
}
@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MyProvider extends JacksonJaxbJsonProvider {
@Context
private ExtendedUriInfo info;
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
if (!info.getMatchedMethod().getDeclaringResource().isAnnotationPresent(Jackson2.class)) {
return false;
}
return super.isReadable(type, genericType, annotations, mediaType);
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
if (!info.getMatchedMethod().getDeclaringResource().isAnnotationPresent(Jackson2.class)) {
return false;
}
return super.isWriteable(type, genericType, annotations, mediaType);
}
}
然后使用@Jackson2
注释您的资源类。
我在试图让这个工作时更早出现问题,因为我使用的是Jackson 2.8.4。它接缝整条2.8线都有问题。不知道它是什么,但2.8,我的提供商根本不会注册。我测试了2.2-2.9的次要版本(不包括2.8),它们都可以工作。
就优先级而言,我不确定泽西岛如何确定优先权。如果首先调用1.x提供程序,那么这个解决方案将全部崩溃。解决这个问题的一种方法是使用组合而不是继承,您只需确定在readFrom
和writeTo
方法中使用哪个读取器/写入器(1.x或2.x)。 1.x版本也是JacksonJaxbJsonProvider
,但它使用了codehaus
包装。从我测试的内容来看,我的提供者总是先被调用,所以这可能不需要。不幸的是,我不能确认这是设计上的。
答案 1 :(得分:1)
根据Paul Samsotha的解决方案,创建2个提供者对我来说很好。
public class Main {
public static void main(final String[] args) {
ResourceConfig config = new ResourceConfig();
config.register(Service1.class)
.register(Service2.class)
.register(JacksonV1Provider.class)
.register(JacksonV2Provider.class);
GrizzlyHttpServerFactory.createHttpServer(URI.create("http://0.0.0.0:8123"), config);
}
}
@Provider
public class JacksonV1Provider extends org.codehaus.jackson.jaxrs.JacksonJsonProvider {
@Context
private ExtendedUriInfo uriInfo;
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return uriInfo.getPath().contains("/v1/");
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return uriInfo.getPath().contains("/v1/");
}
}
@Provider
public class JacksonV2Provider extends com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider {
@Context
private ExtendedUriInfo uriInfo;
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return uriInfo.getPath().contains("/v2/");
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return uriInfo.getPath().contains("/v2/");
}
}
dependencies {
compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-grizzly2-http', version: '2.17'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.17'
compile group: "org.codehaus.jackson", name: "jackson-mapper-asl", version: "$jackson1_version"
compile group: "org.codehaus.jackson", name: "jackson-jaxrs", version: "$jackson1_version"
compile group: "org.codehaus.jackson", name: "jackson-xc", version: "$jackson1_version"
compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson2_vervion"
compile "com.fasterxml.jackson.core:jackson-core:$jackson2_vervion"
compile "com.fasterxml.jackson.core:jackson-annotations:$jackson2_vervion"
}