基于Spring Integration实现SOAP服务代理:请求头体拦截日志与WSDL生成技术咨询
Hey Frank, great question! Let's break this down into two clear parts to solve your requirements: intercepting request details and handling WSDL exposure for your proxy.
1. Intercepting and Logging Request Headers & Body
Your existing proxy flow is a solid foundation, and adding logging without modifying the request is straightforward with Spring Integration's built-in tools. Here are two clean approaches:
Option 1: Use WireTap (Non-intrusive Monitoring)
A WireTap lets you siphon off a copy of the incoming message for logging (or auditing) without disrupting the main proxy flow. This is ideal for keeping your core logic clean:
import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.dsl.MessageChannels; import org.springframework.messaging.Message; @Bean public IntegrationFlow httpProxyFlow() { return IntegrationFlows .from(Http.inboundGateway("/service") .requestPayloadType(String.class)) // Ensure SOAP body is accessible as String .wireTap(this::buildLoggingSubFlow) // Route a copy to logging flow .handle(Http.outboundGateway("http://target-soap-service.com/service/internal") .expectedResponseType(String.class)) .get(); } // Separate sub-flow dedicated to logging private IntegrationFlow buildLoggingSubFlow() { return flow -> flow.handle(message -> { // Log request headers (filter sensitive ones if needed) log.info("Incoming SOAP Request Headers: {}", message.getHeaders()); // Log raw SOAP body log.info("Incoming SOAP Request Body:\n{}", message.getPayload()); }); }
Option 2: Add an Explicit Logging Handler in the Main Flow
If you prefer to keep logging directly in the main flow, insert a custom handler before forwarding to the target service:
@Bean public IntegrationFlow httpProxyFlow() { return IntegrationFlows .from(Http.inboundGateway("/service") .requestPayloadType(String.class)) .handle(this::logRequestDetails) // Log before forwarding .handle(Http.outboundGateway("http://target-soap-service.com/service/internal") .expectedResponseType(String.class)) .get(); } // Custom handler to log and pass through the original message private Message<?> logRequestDetails(Message<?> message) { log.info("SOAP Request Headers: {}", message.getHeaders()); log.info("SOAP Request Body:\n{}", message.getPayload()); return message; // Return unchanged message to continue the flow }
Note: Setting
requestPayloadType(String.class)ensures the SOAP body is parsed as a String for easy logging. If you need to inspect specific SOAP elements, you can use aSoapMessageConverterto unmarshal the payload into a DOM object or JAXB class.
2. WSDL Support for the Proxy
Spring Integration doesn't generate WSDLs natively, but you can expose the target service's WSDL through your proxy with minimal setup:
Option 1: Forward WSDL Requests to the Target Service
Add a dedicated flow to handle ?wsdl requests and forward them directly to the target service:
@Bean public IntegrationFlow wsdlProxyFlow() { return IntegrationFlows .from(Http.inboundGateway("/service?wsdl") .requestPayloadType(String.class)) .handle(Http.outboundGateway("http://target-soap-service.com/service/internal?wsdl") .expectedResponseType(String.class)) .get(); }
Now clients can hit http://your-proxy-domain.com/service?wsdl and receive the target service's WSDL directly.
Option 2: Serve a Local WSDL Copy
If the target service's WSDL isn't publicly accessible, host a local copy in your project (e.g., src/main/resources/static/target-service.wsdl) and serve it via a simple flow:
import java.nio.file.Files; import java.nio.file.Paths; import org.springframework.core.io.ClassPathResource; @Bean public IntegrationFlow staticWsdlFlow() { return IntegrationFlows .from(Http.inboundGateway("/service?wsdl")) .handle((request, response) -> { // Load and return the local WSDL file ClassPathResource wsdlResource = new ClassPathResource("target-service.wsdl"); return Files.readString(Paths.get(wsdlResource.getURI())); }) .get(); }
Pro Tip: If you need to rewrite endpoint URLs in the WSDL (e.g., replace the target service's URL with your proxy's URL), add a transformer step to modify the WSDL content before returning it to clients.
内容的提问来源于stack exchange,提问作者Frank

