Spring Boot 3缺失StaX支持,寻求无需迁移Apache CXF的解决方案
Spring Boot 3 + Spring WS 启用StaX的替代方案
可行解决办法
1. 直接配置Spring WS内置的StaxMessageFactory
Spring WS本身原生支持StaxMessageFactory,无需依赖已被移除的Axiom,直接配置即可启用流式XML处理:
@Configuration public class SoapWebServiceConfig extends WsConfigurerAdapter { @Bean public StaxMessageFactory messageFactory() { return new StaxMessageFactory(); } @Bean public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName("CountriesPort"); wsdl11Definition.setLocationUri("/ws"); wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service"); wsdl11Definition.setSchema(countriesSchema); return wsdl11Definition; } @Bean public XsdSchema countriesSchema() { return new SimpleXsdSchema(new ClassPathResource("countries.xsd")); } }
该配置会让Spring WS采用StAX解析/生成XML,避免DOM将整个文档加载到内存,大幅提升大报文场景下的性能。
2. 自定义StAX解析器参数优化
如果需要更精细的性能调优,可以自定义XMLInputFactory和XMLOutputFactory的参数:
@Bean public StaxMessageFactory messageFactory() { StaxMessageFactory factory = new StaxMessageFactory(); // 配置输入工厂,关闭验证、启用命名空间支持等 XMLInputFactory inputFactory = XMLInputFactory.newInstance(); inputFactory.setProperty(XMLInputFactory.SUPPORT_NAMESPACES, true); inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false); inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true); factory.setXmlInputFactory(inputFactory); // 配置输出工厂,按需启用缩进等 XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); outputFactory.setProperty(XMLOutputFactory.INDENT, "yes"); factory.setXmlOutputFactory(outputFactory); return factory; }
可根据业务场景调整参数,比如关闭XML验证、合并文本节点等,进一步降低资源消耗。
3. 基于PayloadEndpoint实现手动流式处理
针对超大型XML报文场景,可直接实现PayloadEndpoint,手动用StAX API读写XML,完全控制流式逻辑:
@Endpoint public class CountryEndpoint { private static final String NAMESPACE_URI = "http://spring.io/guides/gs-producing-web-service"; @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest") public void handleGetCountryRequest(@RequestPayload XMLStreamReader reader, @ResponsePayload XMLStreamWriter writer) throws XMLStreamException { // 读取请求参数 String countryName = null; while (reader.hasNext()) { int event = reader.next(); if (event == XMLStreamReader.START_ELEMENT && "name".equals(reader.getLocalName())) { countryName = reader.getElementText(); break; } } // 生成响应流 writer.writeStartDocument(); writer.writeStartElement(NAMESPACE_URI, "getCountryResponse"); writer.writeStartElement(NAMESPACE_URI, "country"); writer.writeStartElement(NAMESPACE_URI, "name"); writer.writeCharacters(countryName); writer.writeEndElement(); writer.writeStartElement(NAMESPACE_URI, "population"); writer.writeCharacters("1000000"); writer.writeEndElement(); writer.writeEndElement(); writer.writeEndElement(); writer.writeEndDocument(); } }
这种方式绕过对象绑定,直接操作XML流,是性能敏感场景下的最优选择。
额外优化建议
可以引入性能更优的StAX实现(如Woodstox),Spring会自动优先使用:
<dependency> <groupId>org.codehaus.woodstox</groupId> <artifactId>woodstox-core</artifactId> <version>6.5.1</version> </dependency>
内容的提问来源于stack exchange,提问作者Peter S.
相关产品推荐
相关产品推荐

