如何在同一个Jersey JAX-RS应用程序中使用Jackson的两个版本(1.x和2.x)? [英] How to use two versions of Jackson (1.x and 2.x) in the same Jersey JAX-RS application?

查看:234
本文介绍了如何在同一个Jersey JAX-RS应用程序中使用Jackson的两个版本(1.x和2.x)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个项目中使用旧版本的Jersey(1.19)和旧版本的Jackson(1.19.13). 我想切换到新的Jackson(2.x)反序列化,但仅适用于新端点(逐渐恢复旧端点),因为要一步一步迁移到Jackson 2和/或Jersey 2真的很困难(哦,整体方案! ).

I work in a project with an old version of Jersey (1.19) along with old Jackson (1.19.13). I would like to switch, to new Jackson (2.x) deserialization, but only for new endpoints (and old ones gradually) because migration in one step to Jackson 2 and/or Jersey 2 would be really difficult (oh, the monolith!).

我已经看到了一些主题,这些主题涉及如何在Jersey的Jackson提供程序中提供自定义配置的ObjectMapper,或者如何在1.x Jersey中安装新的Jackson,但这不是我想要的,至少不是全部.

I've seen some topics about how to provide custom-configured ObjectMapper with Jackson providers in Jersey, or how to install new Jackson in 1.x Jersey but that's not I'm looking for, at least not all.

我想作为一种解决方案,(最好)使用@ UseJackson2之类的注释我的新JAX-RS终结点,或者使用一些魔术从正确的包中检索一些对象基类,以用于该特定终结点并在以后扩展它-换句话说,强制给定端点使用非正常的其他(反序列化)提供程序.

What I imagine as a solution, is (preferably) annotating my new JAX-RS endpoint with something like @UseJackson2 , or having some base class with some magic retrieving ObjectMapper from the correct package, for this particular endpoint and extending it later - in other words forcing given endpoint to use other (de)serialization provider than normally.

我已经看到了具有不同配置的ObjectMappers的提供程序的示例(例如使用泽西岛的杰克逊(Jackson)和多个已配置的ObjectMappers ),但在我的情况下,ObjectMappers将来自完全不同的包/行家工件.

I've seen examples with providers for differently configured ObjectMappers (like here Using Jackson in Jersey with multiple configured ObjectMappers), but in my case, the ObjectMappers would come from completely different packages/maven artifacts.

推荐答案

您可以做的是创建一个处理2.x版本的Jackson的MessageBodyReader/Writer. isReadableisWritable方法确定它可以处理的实体.您可以检查的是将Jersey的ExtendedUriInfo注入提供程序,并检查@Jackson2批注的资源类.如果注释不存在,则您的提供程序将忽略该实体,运行时将移至下一个提供程序并检查其是否可以处理它;在这种情况下,是1.x提供程序.

What you can do is create a MessageBodyReader/Writer that handles the 2.x version of Jackson. The isReadable and isWritable methods determine which entities it can handle. What you can do to check is inject Jersey's ExtendedUriInfo into the provider and check the resource class for your @Jackson2 annotation. If the annotation is not present than your provider ignores the entity and the runtime moves on to the next provider and checks if it can handle it; in this case the 1.x provider.

您不会完全创建自己的,而只是扩展Jackson已经提供的工件中的提供程序

Instead of completely creating your own, you would just extend the provider that Jackson already provides in it artifact

<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注释资源类.

Then just annotate your resource classes with @Jackson2.

由于要使用Jackson 2.8.4,我在尝试使其工作时遇到了一些问题.它接缝了整个2.8线的问题.不知道是什么,但是使用2.8时,我的提供程序根本不会注册.我使用次要版本2.2-2.9(不包括2.8)进行了测试,它们都可以正常工作.

I had problems earlier while trying to get this to work, because I was using Jackson 2.8.4. It seams the whole 2.8 line has a problem. Not sure what it is, but with 2.8, my provider would not register at all. I tested with minor versions 2.2-2.9 (excluding 2.8) and they all work.

就优先级而言,我不确定泽西如何确定优先级.如果首先调用1.x提供程序,则此解决方案将全部瓦解.解决此问题的一种方法是使用合成而不是继承,您只需确定在readFromwriteTo方法中使用哪个读取器/写入器(1.x或2.x). 1.x版本也是JacksonJaxbJsonProvider,但它使用的是codehaus包装.从我的测试来看,我的提供者总是被首先调用,因此可能不需要.不幸的是,我无法确定这是设计使然.

As far as priority, I'm not sure about how Jersey determines precedence. If the 1.x provider were to be called first, then this solution would all fall apart. One way around this would be to use composition instead of inheritance, where you would Just determine which reader/writer (1.x or 2.x) to use inside your readFrom and writeTo methods. The 1.x version is also JacksonJaxbJsonProvider but it used the codehaus packaging. From what I tested though, my provider always gets called first, so this may not be needed. Unfortunately, I cannot confirm that this is by design.

这篇关于如何在同一个Jersey JAX-RS应用程序中使用Jackson的两个版本(1.x和2.x)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆