Appearance
Spring Integration Web Services 支持教程
概述
本教程将介绍 Spring Integration 对 Web Services 的支持,包括入站/出站网关配置、消息处理等核心功能。采用现代 Spring 最佳实践,优先使用注解和 Kotlin DSL,避免 XML 配置。
kotlin
// 添加必要依赖 (build.gradle.kts)
dependencies {
implementation("org.springframework.integration:spring-integration-ws:6.5.1")
}
一、核心概念
1.1 Web Services 网关类型
网关类型 | 作用 | 适用场景 |
---|---|---|
入站网关 | 接收外部 Web 服务请求 | 创建服务端点 |
出站网关 | 调用外部 Web 服务 | 服务消费 |
编组网关 | 处理对象-XML 转换 | 复杂数据结构处理 |
类比理解
将网关视为邮局:
- 入站网关 = 接收邮件的信箱
- 出站网关 = 寄出邮件的邮筒
- 编组网关 = 翻译国际信件的专员
二、出站网关配置
2.1 基础出站网关
kotlin
@Configuration
class WsOutboundConfig {
@Bean
fun simpleOutboundGateway(): IntegrationFlow {
return IntegrationFlow.from("requestChannel")
.handle(
Ws.simpleOutboundGateway("https://api.example.com/service")
.id("simpleGateway")
)
.get()
}
}
2.2 编排出站网关 (处理对象-XML转换)
kotlin
@Bean
fun marshallingOutboundGateway(marshaller: Marshaller): IntegrationFlow {
return IntegrationFlow.from("marshallingChannel")
.handle(
Ws.marshallingOutboundGateway("https://api.example.com/data")
.marshaller(marshaller)
.unmarshaller(marshaller)
.headerMapper(SoapHeaderMapper())
)
.get()
}
TIP
最佳实践建议:
- 使用
WebServiceTemplate
复用连接资源 - 对动态 URI 使用
DestinationProvider
- 设置超时:
.setReplyTimeout(Duration.ofSeconds(30))
三、入站网关配置
3.1 基础入站网关
kotlin
@Bean
fun simpleInboundGateway(): IntegrationFlow {
return IntegrationFlow.from(
Ws.simpleInboundGateway()
.id("inboundGateway")
)
.channel("processingChannel")
.get()
}
3.2 编排入站网关
kotlin
@Bean
fun marshallingInboundGateway(marshaller: Marshaller): IntegrationFlow {
return IntegrationFlow.from(
Ws.marshallingInboundGateway(marshaller)
.extractPayload(false) // 获取完整消息
)
.transform { payload: Source ->
// 自定义XML处理逻辑
extractDataFromSource(payload)
}
.get()
}
重要注意事项
入站网关必须注册到 Spring WS 端点映射:
kotlin
@Bean
fun endpointMapping(): SimpleMethodEndpointMapping {
val mapping = SimpleMethodEndpointMapping()
mapping.endpoints = setOf(marshallingInboundGateway())
return mapping
}
四、高级配置技巧
4.1 动态 URI 配置
kotlin
@Bean
fun dynamicUriGateway(registry: ServiceRegistry): IntegrationFlow {
return IntegrationFlow.from("dynamicChannel")
.handle(
Ws.simpleOutboundGateway()
.destinationProvider {
registry.getServiceUri("targetService")
}
.encodingMode(DefaultUriBuilderFactory.EncodingMode.NONE)
)
.get()
}
4.2 自定义头部处理
kotlin
class CustomSoapHeaderMapper : DefaultSoapHeaderMapper() {
init {
// 映射自定义头部
setRequestHeaderNames("STANDARD_REQUEST_HEADERS", "custom*")
setReplyHeaderNames("STANDARD_REPLY_HEADERS", "!internal*")
}
override fun fromSoapHeaders(headers: SoapHeaders): Map<String, Any> {
val map = super.fromSoapHeaders(headers)
// 添加自定义处理逻辑
map["processedAt"] = Instant.now()
return map
}
}
CAUTION
安全警告: 当处理 X-Forwarded-*
头部时,务必验证来源 IP,防止头部注入攻击
五、MTOM 附件支持
kotlin
@Bean
fun mtomInboundGateway(): IntegrationFlow {
return IntegrationFlow.from(
Ws.marshallingInboundGateway(jaxbMarshaller())
.messageFactory(soapMessageFactory())
)
.enrichHeaders {
it.header("attachments",
{ message ->
(message.payload as SoapMessage).attachments
}
)
}
.get()
}
@Bean
fun soapMessageFactory(): SaajSoapMessageFactory {
val factory = SaajSoapMessageFactory(MessageFactory.newInstance())
factory.isMtomEnabled = true
return factory
}
MTOM 附件发送示例
kotlin
fun sendWithAttachment(payload: Any, attachment: Resource) {
webServiceTemplate.send { message: WebServiceMessage ->
val soapMessage = message as SoapMessage
// 添加XML负载
marshaller.marshal(payload, soapMessage.payloadResult)
// 添加附件
soapMessage.addAttachment("doc1",
InputStreamResource(attachment.inputStream),
"application/pdf"
)
}
}
六、常见问题解决
问题1:空响应处理
症状:出站网关未收到响应消息
解决方案:
kotlin
Ws.simpleOutboundGateway(uri)
.ignoreEmptyResponses(false)
问题2:URI 编码错误
症状:特殊字符被错误编码
解决方案:
kotlin
.destinationProvider {
"https://example.com/path?param=${URLEncoder.encode(value, "UTF-8")}"
}
.encodingMode(DefaultUriBuilderFactory.EncodingMode.NONE)
问题3:头部丢失
症状:自定义SOAP头部未被传递
检查点:
- 确认
headerMapper
配置了正确的头部模式 - 验证头部名称未被排除(如使用
!internal*
) - 检查是否超过最大头部大小限制
总结
Spring Integration 的 Web Services 支持提供了:
- ✅ 声明式配置:通过 Kotlin DSL 简化网关设置
- ⚡️ 灵活的消息转换:支持对象-XML自动编组
- 🔒 企业级特性:MTOM附件、头部映射、URI控制
IMPORTANT
生产环境建议:
- 为所有出站调用添加熔断机制
- 使用
WebServiceTemplate
连接池 - 启用 SOAP 消息日志记录
- 对动态 URI 实现速率限制