Spring WS技术问题:接收MTOM请求,如何返回非MTOM响应?
解决方案:接收MTOM请求并返回纯SOAP响应
问题核心在于你当前共用了一个Jaxb2Marshaller处理请求和响应:开启MTOM时响应会自动生成multipart/xop+xml格式,关闭MTOM则无法解析传入的MTOM请求。要实现需求,需要分别配置两个Marshaller,一个用于解析MTOM请求,另一个用于生成纯SOAP响应。
具体实现步骤
1. 配置两个独立的Jaxb2Marshaller
创建两个Marshaller实例,各自对应请求和响应的处理规则:
- 开启MTOM的Marshaller:用于解析请求中的二进制附件
- 关闭MTOM的Marshaller:用于生成纯XML格式的SOAP响应
2. 绑定请求/响应专属处理器
为两个Marshaller创建对应的MarshallingPayloadMethodProcessor,分别绑定到请求参数解析器和响应返回值处理器,实现请求和响应的差异化处理。
修改后的配置类代码
@Configuration public class MyWebServiceConfig { @Value("${config1}") private String contextPath; @Value("${config2}") private String namespace; @Value("${config3}") private String wsdl; @Bean ServletRegistrationBean<?> webServicesRegistration(ApplicationContext ctx) { MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet(); messageDispatcherServlet.setApplicationContext(ctx); messageDispatcherServlet.setTransformWsdlLocations(true); return new ServletRegistrationBean<>(messageDispatcherServlet, contextPath, "*.wsdl"); } // 处理MTOM请求的Marshaller(开启MTOM) @Bean("requestMarshaller") public Jaxb2Marshaller requestMarshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setContextPath(namespace); marshaller.setMtomEnabled(true); return marshaller; } // 生成纯SOAP响应的Marshaller(关闭MTOM) @Bean("responseMarshaller") public Jaxb2Marshaller responseMarshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setContextPath(namespace); marshaller.setMtomEnabled(false); return marshaller; } // 请求处理器:绑定开启MTOM的Marshaller @Bean public MarshallingPayloadMethodProcessor requestProcessor(@Qualifier("requestMarshaller") Jaxb2Marshaller marshaller) { return new MarshallingPayloadMethodProcessor(marshaller); } // 响应处理器:绑定关闭MTOM的Marshaller @Bean public MarshallingPayloadMethodProcessor responseProcessor(@Qualifier("responseMarshaller") Jaxb2Marshaller marshaller) { return new MarshallingPayloadMethodProcessor(marshaller); } @Bean DefaultMethodEndpointAdapter endpointAdapter(MarshallingPayloadMethodProcessor requestProcessor, MarshallingPayloadMethodProcessor responseProcessor) { DefaultMethodEndpointAdapter adapter = new DefaultMethodEndpointAdapter(); // 参数解析使用请求处理器,解析MTOM请求 adapter.setMethodArgumentResolvers(Collections.singletonList(requestProcessor)); // 返回值处理使用响应处理器,生成纯SOAP响应 adapter.setMethodReturnValueHandlers(Collections.singletonList(responseProcessor)); return adapter; } @Bean public SimpleWsdl11Definition contentStore() { SimpleWsdl11Definition definition = new SimpleWsdl11Definition(); definition.setWsdl(new ClassPathResource(wsdl)); return definition; } }
端点代码无需修改
你的端点业务逻辑保持原样即可,请求解析和响应生成的差异化逻辑已由配置中的处理器完成:
@Endpoint public class MyEndpoint { private ObjectFactory objectFactory; public MyEndpoint() { this.objectFactory = new ObjectFactory(); } @PayloadRoot(localPart = "SendMyRequest", namespace = "somenamespace") @ResponsePayload public JAXBElement<MyReceipt> store(@RequestPayload JAXBElement<MyRequest> storeContentRequest) throws IOException { MyReceipt receipt = new MyReceipt(); receipt.setf1(123); receipt.setf2(456); return this.objectFactory.createMyResponse(receipt); } }
原理说明
- 请求阶段:
requestMarshaller开启MTOM,能够正确解析multipart/related格式的MTOM请求,提取二进制附件并绑定到JAXB对象 - 响应阶段:
responseMarshaller关闭MTOM,将JAXB对象序列化为纯XML格式的SOAP响应,响应的Content-Type会变为text/xml或application/soap+xml,不再是multipart类型
内容的提问来源于stack exchange,提问作者Ziggy000
相关产品推荐
相关产品推荐

