我在服务器端使用Jersey 1.17来处理REST请求,使用JAXB 2来解组XML请求内容。
上下文
这是我使用的Jersey方法。 MyDTO 类使用@XmlRootElement注释(否则,我需要使用JAXBElement类型定义参数)。
@Path("/myService")
@POST
@Consumes(MediaType.APPLICATION_XML)
public void myService(MyDTO dto) throws Exception
{
// Shouldn't get this far if the XML content in the request was invalid
System.out.println(dto);
}
要求
默认情况下,Sun / Oracle JAXB实现在XML内容出错时不会抛出异常。例如,为Integer属性提供字符串值(例如ABC)只会将值保留为null而不是抛出异常。
在JAXB 2中,可以定义ValidationEvenHandler。使用以下处理程序处理程序,使XML解组以我需要的方式抛出异常。
public class UnmarshallerValidationEventHandler implements ValidationEventHandler {
@Override
public boolean handleEvent(ValidationEvent event) {
// This indicates JAXB that it should continue processing only if the
// severity level is less than error. NOTE: validation event constants
// go in ascending order in level of severity(i.e., 0 WARNING, 1: ERROR, 2 :FATAL_ERROR)
return event.getSeverity() < ValidationEvent.ERROR;
}
}
问题
如何让Jersey使用特定的JAXBContext实例,以便在我的自定义验证事件处理程序中使用unmarshaller?
或者,鉴于我的应用程序仅在Jersey方法中使用JAXB,因此为JVM实例全局定义特定的JAXBContext将是一个不错的选择。怎么可能这样做?
答案 0 :(得分:3)
泽西用户指南在Using custom JAXBContext章节中介绍了这一点。基本上你需要提供ContextResolver<T>之类的:
@Provider
public class PlanetJAXBContextProvider implements ContextResolver<JAXBContext> {
private JAXBContext context = null;
public JAXBContext getContext(Class<?> type) {
if(type != Planet.class)
return null; // we don't support nothing else than Planet
if(context == null) {
try {
context = JAXBContext.newInstance(Planet.class);
} catch (JAXBException e) {
// log warning/error; null will be returned which indicates that this
// provider won't/can't be used.
}
}
return context;
}
}
您可以在storage-service示例项目中看到示例用法(请参阅JAXBContextResolver)。
注意:您可以提供ContextResolver<JAXBContext>
或/和ContextResolver<Marshaller>
,而不是ContextResolver<Unmarshaller>
。