Jersey 2中的定制Jackson ObjectMapper,带Spring
我在将Jersey从1.x迁移到2.x时遇到一些问题。我的应用程序使用Jersey提供RESTWeb服务,通过Jackson和Spring4以JSON格式提供数据,以处理依赖注入 在Jersey 1.x中,我曾将JsonDeserializer作为Spring管理的组件编写,因此我可以访问我的服务,以便在反序列化过程中从持久层加载我的域对象,但在2.x中,我在反序列化器中的服务注入工作时遇到问题。我所采用的方法受到了以下博客文章的启发: 这是我的pom.xml的依赖项部分:Jersey 2中的定制Jackson ObjectMapper,带Spring,spring,jersey,jackson,jersey-2.0,Spring,Jersey,Jackson,Jersey 2.0,我在将Jersey从1.x迁移到2.x时遇到一些问题。我的应用程序使用Jersey提供RESTWeb服务,通过Jackson和Spring4以JSON格式提供数据,以处理依赖注入 在Jersey 1.x中,我曾将JsonDeserializer作为Spring管理的组件编写,因此我可以访问我的服务,以便在反序列化过程中从持久层加载我的域对象,但在2.x中,我在反序列化器中的服务注入工作时遇到问题。我所采用的方法受到了以下博客文章的启发: 这是我的pom.xml的依赖项部分: <depend
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Commons Codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons-codec.version}</version>
</dependency>
<!-- cut -->
<dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<module-name>myApp/module-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>it.mgt.myApp.config.ApplicationConfig</param-value>
</context-param>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>it.mgt.myApp.config.JerseyConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
这是我的泽西资源配置类:
@Configuration
@ComponentScan({"it.mgt.myApp"})
@PropertySource("classpath:myApp.properties")
public class ApplicationConfig {
// Cut
}
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("it.mgt.myApp");
register(MultiPartFeature.class);
register(RequestContextFilter.class);
register(ObjectMapperContextResolver.class);
register(JacksonFeature.class);
register(CorsRequestFilter.class);
register(SignatureProcessingFilter.class);
register(AuthorizationFeature.class);
register(CorsResponseFilter.class);
register(new UserBinder());
}
}
@Component
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
@Autowired
private SpringObjectMapper objectMapper;
public ObjectMapperContextResolver() {
super();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return objectMapper;
}
}
@Component
public class SpringObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1413033425692174337L;
@Autowired
ApplicationContext applicationContext;
public SpringObjectMapper() {
this.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
this.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
}
@Override
@Autowired
public void setHandlerInstantiator(HandlerInstantiator hi) {
super.setHandlerInstantiator(hi);
}
}
@Component
public class SpringBeanHandlerInstantiator extends HandlerInstantiator {
private ApplicationContext applicationContext;
@Autowired
public SpringBeanHandlerInstantiator(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public JsonDeserializer<?> deserializerInstance(DeserializationConfig dc, Annotated antd, Class<? extends JsonDeserializer<?>> type) {
try {
return (JsonDeserializer<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public KeyDeserializer keyDeserializerInstance(DeserializationConfig dc, Annotated antd, Class<? extends KeyDeserializer> type) {
try {
return (KeyDeserializer) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public JsonSerializer<?> serializerInstance(SerializationConfig sc, Annotated antd, Class<? extends JsonSerializer<?>> type) {
try {
return (JsonSerializer<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> mc, Annotated antd, Class<? extends TypeResolverBuilder<?>> type) {
try {
return (TypeResolverBuilder<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public TypeIdResolver typeIdResolverInstance(MapperConfig<?> mc, Annotated antd, Class<? extends TypeIdResolver> type) {
try {
return (TypeIdResolver) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
}
这是我的ObjectMapperContextResolver类:
@Configuration
@ComponentScan({"it.mgt.myApp"})
@PropertySource("classpath:myApp.properties")
public class ApplicationConfig {
// Cut
}
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("it.mgt.myApp");
register(MultiPartFeature.class);
register(RequestContextFilter.class);
register(ObjectMapperContextResolver.class);
register(JacksonFeature.class);
register(CorsRequestFilter.class);
register(SignatureProcessingFilter.class);
register(AuthorizationFeature.class);
register(CorsResponseFilter.class);
register(new UserBinder());
}
}
@Component
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
@Autowired
private SpringObjectMapper objectMapper;
public ObjectMapperContextResolver() {
super();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return objectMapper;
}
}
@Component
public class SpringObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1413033425692174337L;
@Autowired
ApplicationContext applicationContext;
public SpringObjectMapper() {
this.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
this.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
}
@Override
@Autowired
public void setHandlerInstantiator(HandlerInstantiator hi) {
super.setHandlerInstantiator(hi);
}
}
@Component
public class SpringBeanHandlerInstantiator extends HandlerInstantiator {
private ApplicationContext applicationContext;
@Autowired
public SpringBeanHandlerInstantiator(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public JsonDeserializer<?> deserializerInstance(DeserializationConfig dc, Annotated antd, Class<? extends JsonDeserializer<?>> type) {
try {
return (JsonDeserializer<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public KeyDeserializer keyDeserializerInstance(DeserializationConfig dc, Annotated antd, Class<? extends KeyDeserializer> type) {
try {
return (KeyDeserializer) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public JsonSerializer<?> serializerInstance(SerializationConfig sc, Annotated antd, Class<? extends JsonSerializer<?>> type) {
try {
return (JsonSerializer<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> mc, Annotated antd, Class<? extends TypeResolverBuilder<?>> type) {
try {
return (TypeResolverBuilder<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public TypeIdResolver typeIdResolverInstance(MapperConfig<?> mc, Annotated antd, Class<? extends TypeIdResolver> type) {
try {
return (TypeIdResolver) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
}
这是我的SpringBeanHandlerInstantiator课程:
@Configuration
@ComponentScan({"it.mgt.myApp"})
@PropertySource("classpath:myApp.properties")
public class ApplicationConfig {
// Cut
}
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("it.mgt.myApp");
register(MultiPartFeature.class);
register(RequestContextFilter.class);
register(ObjectMapperContextResolver.class);
register(JacksonFeature.class);
register(CorsRequestFilter.class);
register(SignatureProcessingFilter.class);
register(AuthorizationFeature.class);
register(CorsResponseFilter.class);
register(new UserBinder());
}
}
@Component
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
@Autowired
private SpringObjectMapper objectMapper;
public ObjectMapperContextResolver() {
super();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return objectMapper;
}
}
@Component
public class SpringObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1413033425692174337L;
@Autowired
ApplicationContext applicationContext;
public SpringObjectMapper() {
this.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
this.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
}
@Override
@Autowired
public void setHandlerInstantiator(HandlerInstantiator hi) {
super.setHandlerInstantiator(hi);
}
}
@Component
public class SpringBeanHandlerInstantiator extends HandlerInstantiator {
private ApplicationContext applicationContext;
@Autowired
public SpringBeanHandlerInstantiator(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public JsonDeserializer<?> deserializerInstance(DeserializationConfig dc, Annotated antd, Class<? extends JsonDeserializer<?>> type) {
try {
return (JsonDeserializer<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public KeyDeserializer keyDeserializerInstance(DeserializationConfig dc, Annotated antd, Class<? extends KeyDeserializer> type) {
try {
return (KeyDeserializer) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public JsonSerializer<?> serializerInstance(SerializationConfig sc, Annotated antd, Class<? extends JsonSerializer<?>> type) {
try {
return (JsonSerializer<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> mc, Annotated antd, Class<? extends TypeResolverBuilder<?>> type) {
try {
return (TypeResolverBuilder<?>) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
@Override
public TypeIdResolver typeIdResolverInstance(MapperConfig<?> mc, Annotated antd, Class<? extends TypeIdResolver> type) {
try {
return (TypeIdResolver) applicationContext.getBean(type);
} catch (Exception e) {
}
return null;
}
}
@组件
公共类SpringBeanHandlerInstantiator扩展HandlerInstantiator{
私有应用程序上下文应用程序上下文;
@自动连线
公共SpringBeanHandlerInstantiator(ApplicationContext ApplicationContext){
this.applicationContext=applicationContext;
}
@凌驾
公共JsonDeserializer反序列化器实例(反序列化配置dc,带注释的antd,类>类型){
试一试{
返回(JsonDeserializer)applicationContext.getBean(类型);
}捕获(例外e){
}
返回null;
}
@凌驾
public KeyDeserializer KeyDeserializer实例(反序列化配置dc,带注释的antd,类>类型){
试一试{
return(JsonSerializer)applicationContext.getBean(type);
}捕获(例外e){
}
返回null;
}
@凌驾
公共类型ResolverBuilder类型ResolverBuilderInstance(MapperConfig mc,带注释的antd,类>类型){
试一试{
return(TypeResolverBuilder)applicationContext.getBean(type);
}捕获(例外e){
}
返回null;
}
@凌驾
公共类型IDResolver类型IDResolverInstance(MapperConfig mc,Annotated antd,Class在进一步尝试后,发现ObjectMapperContextResolver上的@Component导致Jersey 2.x不使用提供程序,即使它已在Jersey配置类中显式注册。这与Jersey 1.x行为相反,后者需要@Component
移除它就成功了,这看起来很奇怪。ObjectMapperContextResolver中的@Autowired SpringObjectMapper仍然是由Jersey注入的
从jersey文档中,我无法判断这是设计造成的还是一个bug。我相信您遇到了bug(在jersey 2.15中已修复)。您可以使用@命名的注释,而不是@组件
(基本相当)在jersey和Spring中配置Jackson的漂亮说明。