2016-03-23 27 views
0

私のWebサービスは、!DOCTYPE宣言を含むサードパーティソースからxmlを受け取ります。したがって、私は最初のものは私にこの例外を与えて、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.]spring mvc xmlとdtdの相対パスを持つxml

私はどの記事アプリケーション、XMLを制御することはできませんので、私は解析する私のWebサービスを適応しなければなりませんそれはdtdと一緒です。

私の質問は、XMLReaderインスタンスにEntityResolverを注入するスプリングフレームワークの方法は何ですか?

@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

答えて

0

私はこの問題の根本原因を発見しました。最初にJaxb2Marshaller Beanを作成して設定しようとしましたが、うまくいかなかったのです。それから、私はHttpMessageConverterが必要であることを認識したので、WebMvcConfigurerAdapterクラスのextendMessageConvertersメソッドをオーバーライドし、必要なプロパティをJaxb2RootElementHttpMessageConverterに設定しなければなりませんでした。このメッセージコンバータはJaxb2Marshallerを使用していませんが、内部動作は非常に似ています。

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

setProcessExternalEntities(false)は必須です。このプロパティがfalseの場合、メソッド2と同様にコンバータでは空白のEntityResolverが使用されるためです。

@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); 
     } 
    } 
    } 
} 
関連する問題