Spring Boot WS-Server自定义响应HTTP状态码实现求助(Spring Boot 2.2.7)
为Spring Boot WS SOAP服务设置自定义HTTP响应状态码
我之前也碰到过这种“不符合标准但业务必须”的需求,在Spring Boot 2.2.7版本的Spring WS里,确实有可行的实现方式,下面分享两个经过验证的方案:
方案一:自定义EndpointInterceptor拦截器(推荐)
通过Spring WS的拦截器机制,在响应发送前直接修改HTTP状态码,这是最灵活且侵入性最低的方式。
1. 实现自定义拦截器
创建一个实现EndpointInterceptor的类,在handleResponse方法中获取HTTP响应对象并设置状态码:
import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; import org.springframework.ws.transport.context.TransportContext; import org.springframework.ws.transport.context.TransportContextHolder; import org.springframework.ws.transport.http.HttpServletConnection; import javax.servlet.http.HttpServletResponse; public class CustomSoapStatusInterceptor implements EndpointInterceptor { @Override public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception { return true; // 放行请求继续处理 } @Override public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { // 获取当前请求的HTTP连接上下文 TransportContext transportContext = TransportContextHolder.getTransportContext(); HttpServletConnection connection = (HttpServletConnection) transportContext.getConnection(); HttpServletResponse response = connection.getHttpServletResponse(); // 设置你需要的自定义状态码,比如SC_BAD_REQUEST(400)、SC_INTERNAL_SERVER_ERROR(500) response.setStatus(HttpServletResponse.SC_BAD_REQUEST); return true; } @Override public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { return true; // 处理Fault时也可根据需要设置状态码 } @Override public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception { // 可选:添加清理逻辑 } }
2. 注册拦截器到Spring WS配置
在你的Spring WS配置类中,将自定义拦截器加入拦截器列表:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ws.config.annotation.EnableWs; import org.springframework.ws.config.annotation.WsConfigurerAdapter; import org.springframework.ws.server.EndpointInterceptor; import java.util.List; @EnableWs @Configuration public class WebServiceConfig extends WsConfigurerAdapter { // 你的其他配置,比如DefaultWsdl11Definition、EndpointMapping等... @Bean public EndpointInterceptor customSoapStatusInterceptor() { return new CustomSoapStatusInterceptor(); } @Override public void addInterceptors(List<EndpointInterceptor> interceptors) { interceptors.add(customSoapStatusInterceptor()); super.addInterceptors(interceptors); } }
方案二:自定义MessageDispatcherServlet(底层控制)
如果拦截器无法满足需求(比如需要根据响应内容动态判断状态码),可以通过自定义Spring WS核心Servlet来实现更底层的控制:
1. 自定义Servlet类
继承MessageDispatcherServlet,重写doService方法,在父类处理完请求后修改状态码:
import org.springframework.ws.transport.http.MessageDispatcherServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class CustomWsDispatcherServlet extends MessageDispatcherServlet { @Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // 先让父类处理SOAP请求和响应 super.doService(request, response); // 这里可以根据请求参数、响应内容等动态设置状态码 // 示例:如果响应包含SOAP Fault,设置500状态码 // 你可以根据实际需求替换逻辑 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } }
2. 注册自定义Servlet
在Spring Boot配置类中替换默认的MessageDispatcherServlet:
import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class WsServletConfig { @Bean public ServletRegistrationBean<CustomWsDispatcherServlet> customWsDispatcherServlet() { CustomWsDispatcherServlet servlet = new CustomWsDispatcherServlet(); servlet.setTransformWsdlLocations(true); // 保持原有WS配置特性 ServletRegistrationBean<CustomWsDispatcherServlet> registrationBean = new ServletRegistrationBean<>(servlet, "/ws/*"); registrationBean.setLoadOnStartup(1); return registrationBean; } }
注意事项
- 这种修改HTTP状态码的做法确实不符合SOAP标准(SOAP规范中错误应该通过SOAP Fault消息体传递,而非HTTP状态码),请确认业务需求确实无法通过标准方式满足后再使用。
- 如果之前尝试的方案没生效,大概率是没有正确获取到
HttpServletResponse对象,或者拦截器注册顺序有问题,方案一中的拦截器注册方式是Spring WS推荐的正确方式。
内容的提问来源于stack exchange,提问作者BartekS
相关产品推荐
相关产品推荐

