【问题标题】:spring mvc processing xml with relative path to dtdspring mvc处理带有dtd相对路径的xml
【发布时间】:2016-03-23 13:16:04
【问题描述】:

我的网络服务从第三方来源接收到一个 xml,其中包含一个 !DOCTYPE 声明。因此我必须在我的控制器中使用第二种方法来解析 xml 文档,第一种方法给了我这个异常: Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not unmarshal to [class com.example.MeterBusXml]: null; nested exception is javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 48; DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.]

我无法控制发布 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 示例,请参阅以下文档。 http://prevodniky.sk/products/product_EthMBus_common/download/Ethernet_converters_exports_v1_02_EN.pdf

【问题讨论】:

    标签: spring spring-mvc xml-parsing saxparser dtd-parsing


    【解决方案1】:

    我找到了问题的根源。首先,我尝试创建和配置 Jaxb2Marshaller bean,但没有成功。然后我意识到,我需要一个HttpMessageConverter,所以我必须重写WebMvcConfigurerAdapter类中的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);
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-19
      • 1970-01-01
      • 2011-01-29
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多