配置 Wildfly 10 以使用 Jackson(作为 JSON 提供商)
Configure Wildfly 10 to use Jackson (as JSON provider)
我有一个使用 Jersey 和 Jackson 作为 JSON 提供商构建的网络服务的应用程序,所有这些都在 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(泽西岛)下考虑了注释,我的猜测是在 Wildfly 中不考虑我的排除项。除了检查响应之外,还有什么方法可以检查考虑了哪个 JSON 提供商?
我很好奇你为什么使用 Jackson 1.x 而不是 2.x?两者的说明相似,但 Jackson 配置必须更改。以下是 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;
}
}
我的杰克逊 Object 看起来像这样:
@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 来请求 json =42=]:
<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/Whosebug-sandbox/Q42416036
解决方法是将排除项和依赖项放入子部署中,而不是像我所做的那样将部署标记放入。
<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>
我有一个使用 Jersey 和 Jackson 作为 JSON 提供商构建的网络服务的应用程序,所有这些都在 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(泽西岛)下考虑了注释,我的猜测是在 Wildfly 中不考虑我的排除项。除了检查响应之外,还有什么方法可以检查考虑了哪个 JSON 提供商?
我很好奇你为什么使用 Jackson 1.x 而不是 2.x?两者的说明相似,但 Jackson 配置必须更改。以下是 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;
}
}
我的杰克逊 Object 看起来像这样:
@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 来请求 json =42=]:
<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/Whosebug-sandbox/Q42416036
解决方法是将排除项和依赖项放入子部署中,而不是像我所做的那样将部署标记放入。
<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>