spring-mvc处理xml与dtd的相对路径
My webservice从第三方源接收xml,其中包含!DOCTYPE声明。因此,我必须使用控制器中的第二个方法来解析xml文档,第一个方法给了我以下异常:spring-mvc处理xml与dtd的相对路径,spring,spring-mvc,xml-parsing,saxparser,dtd-parsing,Spring,Spring Mvc,Xml Parsing,Saxparser,Dtd Parsing,My webservice从第三方源接收xml,其中包含!DOCTYPE声明。因此,我必须使用控制器中的第二个方法来解析xml文档,第一个方法给了我以下异常: 读取HTTP消息失败:org.springframework.HTTP.converter.httpMessageNodeTableException:无法解组到[class com.example.MeterBusXml]:null;嵌套异常是javax.xml.bind.UnmarshalException -除此之外: [org.x
读取HTTP消息失败:org.springframework.HTTP.converter.httpMessageNodeTableException:无法解组到[class com.example.MeterBusXml]:null;嵌套异常是javax.xml.bind.UnmarshalException
-除此之外:
[org.xml.sax.SAXParseException;行号:1;列号:48;当功能“”时,不允许使用DOCTYPEhttp://apache.org/xml/features/disallow-doctype-decl“设置为真。]
我无法控制发布xml的应用程序,因此我必须调整我的Web服务以使用dtd解析它
我的问题是,spring框架将EntityResolver
注入每个XMLReader
实例的方式是什么?
@RestController
public class MeterBusDataController {
@RequestMapping (
consumes = APPLICATION_XML_VALUE,
method = POST,
path = "/meterbus1"
)
public void method1(@RequestBody MeterBusXml xml) {
System.out.println(xml);
}
@RequestMapping(
method = POST,
path = "/meterbus2"
)
public void method2(HttpServletRequest rq) throws IOException, ParserConfigurationException, SAXException, JAXBException {
JAXBContext jc = newInstance(MeterBusXml.class);
Unmarshaller um = jc.createUnmarshaller();
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(true);
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
xr.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
return new InputSource(new StringReader(""));
}
});
BufferedReader reader = rq.getReader();
InputSource inputSource = new InputSource(reader);
SAXSource saxSource = new SAXSource(xr, inputSource);
MeterBusXml xml = (MeterBusXml)um.unmarshal(saxSource);
System.out.println(xml);
}
}
请参阅下面的文档,以获取我试图解组的mbus.xml示例。
我找到了问题的根源。首先,我尝试创建和配置一个Jaxb2Marshaller bean,但没有成功。然后我意识到,我需要一个HttpMessageConverter,因此我必须重写
WebMVCConfigureAdapter
类中的extendMessageConverters
方法,并在Jaxb2RootElementHttpMessageConverter
上设置所需的属性。此消息转换器不使用Jaxb2Marshaller
,但其内部工作原理非常相似
setSupportDtd(true)是必需的,以强制解析器接受!DOCTYPE声明
setProcessExternalEntities(false)是必需的,因为如果此属性为false,则转换器将使用空白的EntityResolver
,就像我在方法2中所做的那样
@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Override
public void extendMessageConverters(List<HttpMessageConverter<Jaxb2RootElementHttpMessageConverter?>> converters) {
for (final Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); iterator.hasNext();) {
HttpMessageConverter<?> next = iterator.next();
if (next instanceof Jaxb2RootElementHttpMessageConverter) {
Jaxb2RootElementHttpMessageConverter jaxbConverter = (Jaxb2RootElementHttpMessageConverter) next;
jaxbConverter.setProcessExternalEntities(false);
jaxbConverter.setSupportDtd(true);
}
}
}
}
@配置
公共类网络配置扩展了WebMVCConfigureAdapter{
@凌驾
public void extendMessageConverters(列表转换器){
对于(最终迭代器)