配置 Wildfly 10 以使用 Jackson(作为 JSON 提供程序)

Posted

技术标签:

【中文标题】配置 Wildfly 10 以使用 Jackson(作为 JSON 提供程序)【英文标题】:Configure Wildfly 10 to use Jackson (as JSON provider) 【发布时间】:2017-07-13 22:49:51 【问题描述】:

我有一个应用程序,它具有使用 Jersey 和 Jackson 作为 JSON 提供程序构建的 Web 服务,所有这些都在 Tomcat 应用程序服务器中。

我需要让这个应用程序在 Wildfly 10 上运行,并且一切正常,除了没有考虑 Jackson 注释的 web 服务响应。根据我的阅读,Wildfly 默认使用 Jettison,而在较新的版本中使用的是 Jackson2。

首选的解决方案是让 RestEasy(来自 Wildfly 10)使用 Jackson,为此我尝试排除 Jackson2 和 Jettison,并在 (META-INF\jboss-deployment-structure.xml) 中对 Jackson 建立依赖关系,如下:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
    <exclusions>
        <module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
        <module name="org.jboss.resteasy.resteasy-jettison-provider"/>
    </exclusions>
    <dependencies>
        <module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
    </dependencies>
</deployment>
</jboss-deployment-structure>

显然这还不够,因为它的行为与以前一样。 我还应该尝试什么?

更新:

由于我的应用程序在 Tomcat(使用 Jersey)和 Wildfly(使用 RestEasy)上的工作方式应该相同,因此我不能依赖在我的应用程序中使用来自 resteasy 的 jackson,因此我正在导入 org.codehaus.jackson

所以,我这样注册我的应用程序:

import javax.ws.rs.core.Application;
public class RestApplication extends Application

   @Override
   public Set<Class<?>> getClasses() 
       Set<Class<?>> classes = new HashSet<Class<?>>();

       classes.add(RestObjectMapperProvider.class);
       classes.add(GeneratedService.class);

       return classes;
   

其余对象映射器提供者:

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.ObjectMapper;
@Provider
public class RestObjectMapperProvider implements ContextResolver<ObjectMapper>

   private final ObjectMapper objectMapper;

   public RestObjectMapperProvider()
   
       this.objectMapper = new ObjectMapper();

       this.objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
   

   @Override
   public ObjectMapper getContext(Class<?> type)
   
       return this.objectMapper;
   

我正在使用 Gradle 构建我的应用程序,下面是 Jackson 依赖项:

compile group: 'org.codehaus.jackson', name: 'jackson-jaxrs', version: '1.9.+'

由于在 Tomcat (Jersey) 下考虑了注释,我的猜测是在 Wildfly 中我的排除不被考虑。除了检查响应之外,还有什么方法可以检查考虑了哪个 JSON Provider?

【问题讨论】:

您是继续使用 Jersey 还是打算使用 Jax-RS/Resteasy? 【参考方案1】:

我很好奇您为什么使用 Jackson 1.x 而不是 2.x?两者的说明相似,但杰克逊配置必须更改。以下是 1.x 的说明。

jboss-deployment-structure.xml(和你的一样):

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
    <exclusions>
        <module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
        <module name="org.jboss.resteasy.resteasy-jettison-provider"/>
    </exclusions>
    <dependencies>
        <module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
    </dependencies>
</deployment>
</jboss-deployment-structure>

使用@Application 注册您的应用程序:

@ApplicationPath("/api/v1")
public class V1Application extends Application 

    @Override
    public Set<Class<?>> getClasses() 
        Set<Class<?>> classes = new HashSet<Class<?>>();

        classes.add(JacksonConfigurationProvider.class);
        classes.add(TestResource.class);

        return classes;
    


使用 jackson 配置提供程序,例如:

@Provider
@Consumes(MediaType.APPLICATION_JSON, "text/json")
@Produces(MediaType.APPLICATION_JSON, "text/json")
public class JacksonConfigurationProvider extends ResteasyJacksonProvider 

    private static final Logger LOGGER = LoggerFactory.getLogger(JacksonConfigurationProvider.class);

    public JacksonConfigurationProvider() 
        super();

        LOGGER.info("loading jackson configurator");

        JacksonObjectMapper mapper = JacksonObjectMapper.get();
        setMapper(mapper);

    

然后,在您的 JacksonObjectMapper 中,您告诉它读取注释:

public class JacksonObjectMapper extends ObjectMapper 
    public static JacksonObjectMapper get() 
        JacksonObjectMapper mapper = new JacksonObjectMapper();

        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
        mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);

        JacksonAnnotationIntrospector jacksonAnnotationIntrospector = new JacksonAnnotationIntrospector();
        mapper.setDeserializationConfig(mapper.getDeserializationConfig().withAnnotationIntrospector
                (jacksonAnnotationIntrospector));
        mapper.setSerializationConfig(mapper.getSerializationConfig().withAnnotationIntrospector
                (jacksonAnnotationIntrospector));

        return mapper;
    

我的 Jackson 对象如下所示:

@JsonRootName("foobar")
public class TestType 

    @JsonProperty("goodbye")
    String hello;

    public String getHello() 
        return hello;
    

    public void setHello(String hello) 
        this.hello = hello;
    

为了方便起见,我的 web.xml 中也有这个,它允许您通过将 .json 放在 URL 上而不是设置标头来请求 json:

<context-param>
    <param-name>resteasy.media.type.mappings</param-name>
    <param-value>json : application/json, xml : application/xml</param-value>
</context-param>

当我打电话给http://127.0.0.1:8080/api/v1/test.json 时,我得到:


    "foobar": 
        "goodbye": "Here is some random string"
    

我在这里发布了我的完整工作代码:https://github.com/teacurran/java-experiments/tree/master/***-sandbox/Q42416036

【讨论】:

感谢您的回复。我正在使用 Jackson1,因为这是很久以前开发应用程序的方式,我只需要通过更改注释使其与 Wildfly 兼容 不幸的是还没有工作。我分享了我的代码(与您的代码相似),希望您可能知道可能出了什么问题。我怀疑没有考虑排除项,但我不知道如何检查以 100% 确认这个理论(除了 REST 响应)【参考方案2】:

解决方法是将排除项和依赖项放在子部署中,而不是像我所做的那样部署标签。

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<sub-deployment name="axis.war">
    <exclusions>
        <module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
        <module name="org.jboss.resteasy.resteasy-jettison-provider"/>
    </exclusions>
    <dependencies>
        <module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
    </dependencies>
</sub-deployment>

【讨论】:

以上是关于配置 Wildfly 10 以使用 Jackson(作为 JSON 提供程序)的主要内容,如果未能解决你的问题,请参考以下文章

Wildfly 10 - 以编程方式读取配置参数

Jackson marshal/unmarshal 在 jaxrs wildfly 15 中表现不同

如何配置wildfly以使用EclipseLink?

Wildfly - 配置 ActiveMQ 以使用 Postgres 日志

从 Wildfly 11 升级到 Wildfly 15 时的日期序列化问题

Wildfly14 的 Resteasy:并非所有字段都返回