Spring 集成 Web 服务 - Jaxb2Marshaller - 如何使用 SAX 解析器?

Spring Integration Web Service - Jaxb2Marshaller - How I can use SAX Parser?

我正在使用 Jaxb2Marshaller 与 Spring 集成。我有一个入站网关 Web 服务,当有人调用它时,它会自动解析为生成的 JAXB 类.

但是当我调试源代码时,我看到 Jaxb2Marshaller 使用 DOM。我认为它会使用 SAX 将 XML 数据绑定到 Java 对象,SAX 更快。为什么 Jaxb2Marshaller 默认使用 DOM ?如何配置它以使用 SAX?

当我查看文档时

The unmarshaller requires an instance of Source. If the message payload is not an instance of Source, conversion will be attempted. Currently String, File and org.w3c.dom.Document payloads are supported. Custom conversion to a Source is also supported by injecting an implementation of a SourceFactory. Note If a SourceFactory is not set explicitly, the property on the UnmarshallingTransformer will by default be set to a DomSourceFactory

关于 SourceFactory

http://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/SourceFactory.html

我们可以看到,目前只有DomSourceFactoryStringSourceFactory。没有SaxSourceFactory.

所以我们不能将 SAX 与 Jaxb2Marshaller 一起使用,对吗?

以后会有SaxSourceFactory吗?或者永远不会?

奇怪的是当我检查 Jaxb2Marshaller 时,我看到代码已经处理了 SAX

XMLReader xmlReader = null;
    InputSource inputSource = null;

    if (source instanceof SAXSource) {
        SAXSource saxSource = (SAXSource) source;
        xmlReader = saxSource.getXMLReader();
        inputSource = saxSource.getInputSource();
    }
    else if (source instanceof StreamSource) {
        StreamSource streamSource = (StreamSource) source;
        if (streamSource.getInputStream() != null) {
            inputSource = new InputSource(streamSource.getInputStream());
        }
        else if (streamSource.getReader() != null) {
            inputSource = new InputSource(streamSource.getReader());
        }
        else {
            inputSource = new InputSource(streamSource.getSystemId());
        }
    }

所以,最后一个问题是我可以配置使用 Spring 集成 Web 服务与 JAXB 和 SAX 吗?我错过了什么吗?

这是我的配置:

<ws:inbound-gateway id="inbound-gateway" request-channel="RequestChannel" reply-channel="ResponseChannel" 
        marshaller="marshaller"        unmarshaller="marshaller"  />
<int:channel id="RequestChannel" />
<int:channel id="ResponseChannel" />

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="contextPath" value="com.example.webservice.api"/>
</bean>

谢谢你和最诚挚的问候,

芽原

尝试使用名称 MessageDispatcherServlet.DEFAULT_MESSAGE_FACTORY_BEAN_NAME 配置 AxiomSoapMessageFactory bean。

默认情况下是 SaajSoapMessageFactory,它在解组之前执行此操作:

public Source getPayloadSource() {
    SOAPElement bodyElement = SaajUtils.getFirstBodyElement(getSaajBody());
    return bodyElement != null ? new DOMSource(bodyElement) : null;
}

其中 Axiom 基于 STaX:

XMLStreamReader streamReader = getStreamReader(payloadElement);
return StaxUtils.createCustomStaxSource(streamReader);

class StaxSource extends SAXSource {

我正在使用 WebServiceGatewaySupport classes 并尝试将 AxiomSoapMessageFactory 作为 Bean 添加到应用程序上下文,直到我发现 WebServiceTemplate 不从应用程序上下文加载 WebServiceMessageFactory。所以我最后添加了一个构造函数:

public class SomeServiceImpl extends WebServiceGatewaySupport implements SomeService {

    public SomeServiceImpl(WebServiceMessageFactory messageFactory) {
        super(messageFactory);
    }
}

并使用 @Configuration class:

自己构建服务
@Configuration
public class WebServicesConfiguration {

    private WebServiceMessageFactory webServiceMessageFactory = new AxiomSoapMessageFactory();

    @Bean
    public SomeService someService() {
        return new SomeServiceImpl(webServiceMessageFactory);
    }
}