【发布时间】:2014-03-15 10:02:09
【问题描述】:
我在将 Jersey 从 1.x 迁移到 2.x 时遇到了一些问题。我的应用程序使用 Jersey 来提供 REST Web 服务,通过 Jackson 和 Spring 4 以 JSON 格式提供数据来处理依赖注入。
在 Jersey 1.x 中,我曾经将 JsonDeserializer 编写为 Spring 管理的组件,因此我可以在反序列化期间访问我的服务以从我的域对象的持久层加载,但在 2.x 中我遇到了注入问题反序列化程序中的服务工作。我遵循的方法受到这篇博文的启发:http://www.runningasroot.com/blog/2012/05/02/autowiring-jackson-deserializers-in-spring/
这是我的 pom.xml 的依赖部分:
<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>
Jersey 版本是 2.7,Spring 4.0.2.RELEASE。
这是我的 web.xml:
<?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>
这是我的Spring配置类:
@Configuration
@ComponentScan({"it.mgt.myApp"})
@PropertySource("classpath:myApp.properties")
public class ApplicationConfig {
// Cut
}
这是我的 Jersey 资源配置 类:
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());
}
}
这是我的 ObjectMapperContextResolver 类:
@Component
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
@Autowired
private SpringObjectMapper objectMapper;
public ObjectMapperContextResolver() {
super();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return objectMapper;
}
}
我认为@Provider注解对于资源配置类中的registrationg来说是多余的。
这是我的 SpringObjectMapper 类:
@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);
}
}
这是我的 SpringBeanHandlerInstantiator 类:
@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;
}
}
这是我的域实体类,序列化器和反序列化器是静态内部类:
@JsonSerialize(using = User.Serializer.class)
@JsonDeserialize(using = User.Deserializer.class)
public class User {
@Component
public static class Serializer extends JsonSerializer<User> {
@Override
public void serialize(User obj, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
// Cut
}
}
@Component
public static class Deserializer extends JsonDeserializer<User> {
@Autowired
SomeService someService;
@Override
public User deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
User user = new User();
// Cut
// Use someService here
}
}
// Cut
}
我试图在 ObjectMapperContextResolver.getContext(Class type) 中设置一个制动点,但它从未受到打击,我怀疑这是问题的根源,但经过两天的尝试和研究球衣文档后,我的想法已经用完了。
任何人都可以指出如何正确实现这一目标?
【问题讨论】:
-
在 Jersey 和 Spring 中配置 Jackson 的很好的说明。
标签: spring jersey jackson jersey-2.0