spring-mvc处理xml与dtd的相对路径

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

My webservice从第三方源接收xml,其中包含!DOCTYPE声明。因此,我必须使用控制器中的第二个方法来解析xml文档,第一个方法给了我以下异常:
读取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(列表转换器){
对于(最终迭代器)