Spring Boot SOAP端点如何接收Java String而非JAXBElement?
实现Spring Boot SOAP端点接收String类型请求
当然可以实现这个需求!Spring Boot结合Spring WS确实支持让SOAP端点直接接收String类型的请求,不用依赖JAXBElement。下面给你两种实用的实现方式,你可以根据现有配置来选择:
方式一:通过Source参数转换为String
这种方式不需要修改全局配置,只需要在端点方法里接收Source类型的参数,再手动转换成String即可,对现有代码侵入性很小。
示例端点代码
@Endpoint public class CustomSoapEndpoint { // 替换成你自己的命名空间 private static final String NAMESPACE_URI = "http://your-domain.com/soap/namespace"; @PayloadRoot(namespace = NAMESPACE_URI, localPart = "YourRequestRootElement") public void handleSoapRequest(Source requestSource) throws IOException { // 将Source转换为完整的SOAP XML字符串 String fullSoapXml = convertSourceToString(requestSource); // 如果只需要SOAP Body里的内容,可以进一步提取(代码见下方) String bodyContent = extractSoapBodyContent(fullSoapXml); // 这里处理你的字符串请求逻辑 System.out.println("接收到的SOAP请求Body内容:" + bodyContent); } // 工具方法:将Source转为String private String convertSourceToString(Source source) throws IOException { StringWriter writer = new StringWriter(); try { TransformerFactory.newInstance().newTransformer().transform(source, new StreamResult(writer)); } catch (TransformerException e) { throw new IOException("转换SOAP请求为字符串失败", e); } return writer.toString(); } // 工具方法:提取SOAP Body中的内容(可选) private String extractSoapBodyContent(String fullSoapXml) throws IOException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); Document document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(fullSoapXml))); // 获取SOAP Body节点(注意SOAP信封的命名空间) Node bodyNode = document.getElementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Body").item(0); StringWriter writer = new StringWriter(); TransformerFactory.newInstance().newTransformer().transform(new DOMSource(bodyNode), new StreamResult(writer)); return writer.toString(); } catch (ParserConfigurationException | SAXException | TransformerException e) { throw new IOException("提取SOAP Body内容失败", e); } } }
方式二:自定义消息转换器(全局或局部)
如果你希望端点方法直接接收String参数,可以自定义MessageConverter,让Spring WS自动将SOAP请求转换为String。
步骤1:自定义消息转换器
public class StringSoapMessageConverter extends SaajSoapMessageConverter { @Override protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException { // 当目标类型是String时,直接转换为XML字符串 if (String.class.equals(clazz)) { StringWriter writer = new StringWriter(); try { TransformerFactory.newInstance().newTransformer().transform(source, new StreamResult(writer)); } catch (TransformerException e) { throw new IOException("转换SOAP请求为String失败", e); } return writer.toString(); } // 其他类型还是用默认逻辑处理 return super.readFromSource(clazz, headers, source); } }
步骤2:在SOAP配置类中注册转换器
@Configuration @EnableWs public class SoapWebServiceConfig extends WsConfigurerAdapter { @Override public void configureMessageConverters(List<MessageConverter> messageConverters) { // 添加自定义转换器到列表头部,优先使用 messageConverters.add(0, new StringSoapMessageConverter()); super.configureMessageConverters(messageConverters); } // 保留你现有的其他配置,比如DefaultWsdl11Definition、ServletRegistrationBean等 }
步骤3:修改端点方法接收String参数
@Endpoint public class CustomSoapEndpoint { private static final String NAMESPACE_URI = "http://your-domain.com/soap/namespace"; @PayloadRoot(namespace = NAMESPACE_URI, localPart = "YourRequestRootElement") public void handleSoapRequest(String requestXml) { // 直接处理String类型的请求XML System.out.println("接收到的完整SOAP请求:" + requestXml); } }
注意事项
- 以上两种方式都会拿到包含SOAP信封的完整XML字符串,如果只需要Body内的业务数据,记得用上面的工具方法提取。
- 跳过JAXB自动绑定后,你需要自己负责XML的解析、验证和业务对象转换(如果需要的话)。
- 如果你的现有配置已经使用了其他消息转换器,注意调整自定义转换器的优先级(方式二中的
add(0, ...)就是为了让自定义转换器优先生效)。
内容的提问来源于stack exchange,提问作者Conde
相关产品推荐
相关产品推荐

