Spring Boot SOAP端点无法接收application/xml请求返回500错误如何修复
问题根因
报错是因为SAAJ(SOAP with Attachments API for Java)的默认实现仅将text/xml识别为合法的SOAP请求Content-Type,对application/xml会直接抛出格式校验错误。
方案1:自定义SaajSoapMessageFactory扩展支持的Content-Type(推荐)
直接扩展Spring WS的SaajSoapMessageFactory,重写createWebServiceMessage方法,在创建SOAP消息前统一将application/xml的请求头替换为合法的text/xml即可,不需要修改现有业务端点逻辑。
自定义消息工厂代码:
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; import org.springframework.ws.transport.TransportInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.Map; public class CustomSaajSoapMessageFactory extends SaajSoapMessageFactory { @Override public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException { if (inputStream instanceof TransportInputStream transportInputStream) { Iterator<Map.Entry<String, String>> headers = transportInputStream.getHeaders(); while (headers.hasNext()) { Map.Entry<String, String> header = headers.next(); if ("Content-Type".equalsIgnoreCase(header.getKey()) && "application/xml".equalsIgnoreCase(header.getValue().trim())) { // 替换为SAAJ可识别的text/xml格式 header.setValue("text/xml"); break; } } } return super.createWebServiceMessage(inputStream); } }
注册自定义工厂到Spring容器:
在你的WS配置类中替换默认的SaajSoapMessageFactory即可:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; import com.sun.xml.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl; @Configuration public class WebServiceConfig { @Bean public SaajSoapMessageFactory messageFactory() { // 若你的SOAP版本为1.1,将SOAPMessageFactory1_2Impl替换为SOAPMessageFactory1_1Impl即可 CustomSaajSoapMessageFactory factory = new CustomSaajSoapMessageFactory(); factory.setMessageFactory(new SOAPMessageFactory1_2Impl()); return factory; } }
方案2:添加Servlet过滤器全局替换Content-Type
如果不想修改WS相关配置,也可以新增全局请求过滤器,在请求进入WS Servlet前就将Content-Type替换为text/xml:
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; public class ContentTypeRewriteFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; // 仅匹配你的SOAP端点路径,避免影响其他接口 if ("application/xml".equalsIgnoreCase(req.getContentType()) && req.getRequestURI().startsWith("/v1/serverEndpoint")) { HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(req) { private final Map<String, String> customHeaders = new HashMap<>(); { customHeaders.put("Content-Type", "text/xml"); } @Override public String getHeader(String name) { if ("Content-Type".equalsIgnoreCase(name)) { return customHeaders.get(name); } return super.getHeader(name); } @Override public Enumeration<String> getHeaders(String name) { if ("Content-Type".equalsIgnoreCase(name)) { return Collections.enumeration(Collections.singletonList(customHeaders.get(name))); } return super.getHeaders(name); } }; chain.doFilter(wrapper, response); return; } chain.doFilter(request, response); } }
将过滤器注册到Spring Boot容器后即可生效。
内容的提问来源于stack exchange,提问作者Devanjal Kotia
相关产品推荐
相关产品推荐

