0

私の Web サービスは、!DOCTYPE 宣言を含む xml をサードパーティ ソースから受け取ります。したがって、コントローラーで 2 番目のメソッドを使用して 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 を送信するアプリケーションを制御できないため、dtd で解析するように Web サービスを調整する必要があります。

私の質問は、春のフレームワークが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

4

1 に答える 1

0

問題の根本を見つけました。最初に Jaxb2Marshaller Bean を作成して構成しようとしましたが、うまくいきませんでした。その後、HttpMessageConverter が必要であることに気付きました。そのためextendMessageConverters、クラスでメソッドをオーバーライドしWebMvcConfigurerAdapter、必要なプロパティを に設定する必要がありましたJaxb2RootElementHttpMessageConverter。このメッセージ コンバーターは を使用しませんがJaxb2Marshaller、内部の仕組みは非常に似ています。

パーサーに !DOCTYPE 宣言を強制的に受け入れるようにするには、setSupportDtd(true) が必要です。

setProcessExternalEntities(false) が必要です。このプロパティが false の場合、EntityResolverメソッド 2 で行ったのと同じように、コンバーターは blank を使用するためです。

@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);
      }
    }
  }
}
于 2016-03-31T18:50:41.960 に答える