Web Services 与Spring集成的SOAP代理

ldioqlga  于 2022-11-15  发布在  Spring
关注(0)|答案(3)|浏览(153)

我正在尝试将我的头脑围绕在Spring集成上,最好远离基于XML的配置。
我想做的事情如下:
1.在特定端点上接受SOAP请求
1.将此请求转发到下游SOAP服务,不做任何修改(目前我只想让基础工作正常进行)
1.将结果返回给客户端
这看起来应该很简单,但是我不知道从哪里开始。SI可能做到这一点吗?根据我的理解,如果我错了,请纠正我,SI主要用于异步数据流。
我确实检查了集成示例存储库,其中包括示例入站WS请求,但这些都是用XML配置的,正如我所说的,我最好远离XML。
任何指示将不胜感激;过去两天我一直在阅读文档,但我还是不明白!

ep6jt1vc

ep6jt1vc1#

这里是一个使用SimpleWebServiceInboundGateway的例子。在这个例子中,我们也将“ExtractPayload”设置为false,这样它就可以发送RAW soap消息。但是同意上面的说法,可能HTTPInboundRequest更适合你的用例。我也没有找到很多使用DSL的SoapInboundGateway的例子,所以想分享一下,希望它能帮助其他人。

@Configuration
@EnableIntegration
public class SoapGatewayConfiguration {

    /**
     * URL mappings used by WS endpoints
     */
    public static final String[] WS_URL_MAPPINGS = {"/services/*", "*.wsdl", "*.xsd"};
    public static final String GATEWAY_INBOUND_CHANNEL_NAME  = "wsGatewayInboundChannel";
    public static final String GATEWAY_OUTBOUND_CHANNEL_NAME = "wsGatewayOutboundChannel";

    /**
     * Register the servlet mapper, note that it uses MessageDispatcher
     */
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        servlet.setTransformSchemaLocations(true);
        servlet.setPublishEvents(true);
        ServletRegistrationBean servletDef = new ServletRegistrationBean(servlet, WS_URL_MAPPINGS);
        servletDef.setLoadOnStartup(1);
        return servletDef;
    }

    /**
     * Create a new Direct channels to handle the messages
     */
    @Bean
    public MessageChannel wsGatewayInboundChannel() {
        return MessageChannels.direct(GATEWAY_INBOUND_CHANNEL_NAME).get();
    }
    @Bean
    public MessageChannel wsGatewayOutboundChannel() {
        return MessageChannels.direct(GATEWAY_OUTBOUND_CHANNEL_NAME).get();
    }

    /**
     * Startup the WebServiceInboundGateway Endpoint, this will handle the incoming SOAP requests
     *  and place them onto the request channel
     */
    @Bean
    public SimpleWebServiceInboundGateway webServiceInboundGateway(
            @Value("${spring.ws.request.timeout:1000}") long requestTimeout,
            @Value("${spring.ws.reply.timeout:1000}") long replyTimeout,
            @Value("${spring.ws.should.track:true}") boolean shouldTrack
    ) {
        SimpleWebServiceInboundGateway wsg = new SimpleWebServiceInboundGateway();
        wsg.setRequestChannel(wsGatewayInboundChannel());
        wsg.setReplyChannel(wsGatewayOutboundChannel());
        wsg.setExtractPayload(false);  // Send the full RAW SOAPMessage and not just payload
        wsg.setLoggingEnabled(true);
        wsg.setShouldTrack(shouldTrack);
        wsg.setReplyTimeout(replyTimeout); // Do not believe this prop supported currently
        wsg.setRequestTimeout(requestTimeout); // Do not believe this prop is supported currently
        wsg.setCountsEnabled(true);
        return wsg;
    }

    /**
     * You must enable debug logging on org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor
     *  to see the logs from this interceptor
     */
    @Bean
    public EndpointInterceptor soapMessageLoggingInterceptor() {
        SoapEnvelopeLoggingInterceptor li = new SoapEnvelopeLoggingInterceptor();
        li.setLogRequest(true);
        li.setLogResponse(true);
        li.setLogFault(true);
        return li;
    }

    /**
     * Validate the incoming web service against the schema
     */
    @Bean
    public EndpointInterceptor payloadValidatingInterceptor(XsdSchema xsdSchema
            , @Value("${spring.ws.soap.validate.request:true}") boolean soapValidateRequest
            , @Value("${spring.ws.soap.validate.reply:true}") boolean soapValidateResponse
            , @Value("${spring.ws.soap.validate.addErrorDetail:true}") boolean soapAddValidationErrorDetail

    ) {
        PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
        interceptor.setXsdSchema(xsdSchema);
        interceptor.setValidateRequest(soapValidateRequest);
        interceptor.setValidateResponse(soapValidateResponse);
        interceptor.setAddValidationErrorDetail(soapAddValidationErrorDetail);
        return interceptor;
    }

    /**
     * Map the allowable service Uri's.
     */
    @Bean
    public EndpointMapping uriEndpointMapping(
             PayloadValidatingInterceptor payloadValidatingInterceptor
            , SimpleWebServiceInboundGateway webServiceInboundGateway
            , SoapEnvelopeLoggingInterceptor loggingInterceptor) {
        UriEndpointMapping mapping = new UriEndpointMapping();
        mapping.setUsePath(true);
        mapping.setDefaultEndpoint(webServiceInboundGateway);
        mapping.setInterceptors(new EndpointInterceptor[]{loggingInterceptor, payloadValidatingInterceptor});
        return mapping;
    }

    /**
     * Expose the wsdl at http://localhost:8080/services/myService.wsdl
     **/    
    @Bean
    public Wsdl11Definition myService() {
        SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
        wsdl11Definition.setWsdl(new ClassPathResource("META-INF/myService.wsdl"));
        return wsdl11Definition;
    }
    
    /**
     * Expose the xsd at http://localhost:8080/services/mySchema.xsd
     **/
    @Bean
    public XsdSchema mySchema() {
        return new SimpleXsdSchema(new ClassPathResource("META-INF/mySchema.xsd"));
    }    

    @Bean
    public IntegrationFlow itemLookupFlow() {
        return IntegrationFlows.from("wsGatewayInboundChannel")
                .log(LoggingHandler.Level.INFO)
                .handle(myBeanName, "execute")
                .log(LoggingHandler.Level.TRACE, "afterExecute")
                .get();
    }

}
inkz8wg9

inkz8wg92#

如果您的应用程序只是其他SOAP服务上的代理,则应考虑仅使用普通的HTTP入站网关和HTTP出站网关。
您从客户端接收XML并将其发送到下游服务,然后再次从那里接收XML并将其推回到客户端的响应中。
为此,我建议使用Java DSL的HTTP代理解决方案:

@Bean
    public IntegrationFlow httpProxyFlow() {
        return IntegrationFlows
                .from(Http.inboundGateway("/service"))
                .handle(Http.outboundGateway("/service/internal")
                                .expectedResponseType(String.class))
                .get();
    }

SimpleWebServiceInboundGatewaySimpleWebServiceOutboundGateway对的问题是,它们提取请求并解析响应,以将其 Package 到SOAP信封或从SOAP信封中展开。这看起来像是普通代理用例的开销。

rnmwe5a2

rnmwe5a23#

多亏了阿尔特姆的回答,我做了一个小小的调整,才让它工作起来。不知道为什么需要通道,但至少它现在能工作了。

package com.example.integration;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.http.Http;
import org.springframework.integration.http.config.EnableIntegrationGraphController;
import org.springframework.messaging.MessageChannel;

@SpringBootApplication
@EnableIntegration
@EnableIntegrationGraphController(allowedOrigins = "*")
public class IntegrationApplication {

    public static void main(String[] args) {
        SpringApplication.run(IntegrationApplication.class, args);
    }

    @Bean
    public DirectChannel directChannel() {
        return new DirectChannel();
    }

    @Bean
    public IntegrationFlow httpProxyFlow(MessageChannel directChannel) {
        return IntegrationFlows
                .from(Http.inboundGateway("/thing").requestChannel(directChannel).replyChannel(directChannel))
                .enrichHeaders(h -> h.header("Content-Type", "application/soap+xml; charset=utf-8"))
                .handle(Http.outboundGateway("http://www.webservicex.net/geoipservice.asmx").expectedResponseType(String.class))
                .channel(directChannel)
                .get();
    }
}

相关问题