Spring WS (DefaultWsdl11Definition) 带 void 的 HTTP 状态代码

Roy*_*ijn 5 spring soap web-services spring-ws http-status-codes

我们有一个基于 Spring WS 和DefaultWsdl11Definition的(工作的)SOAP Web 服务。

基本上是这样的:

@Endpoint("name")
public class OurEndpoint {

    @PayloadRoot(namespace = "somenamespace", localPart = "localpart")
    public void onMessage(@RequestPayload SomePojo pojo) {
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

它是在 Spring 中连接的,并且可以正确处理我们所有的 SOAP 请求。唯一的问题是该方法返回202 Accepted。这不是调用者想要的,他宁愿让我们返回204 No Content(或者如果不可能,则返回空的200 OK)。

我们的其他端点有一个有效的响应对象,并且返回200 OK。似乎 void 导致202,而204可能更合适?

是否可以更改 Spring WS 中的响应代码?我们似乎找不到正确的方法来做到这一点。

我们尝试过但不起作用的事情:

  • 将返回类型更改为:
    • HttpStatus.NO_CONTENT
    • org.w3c.dom.Element <- 不接受
  • 添加@ResponseStatus <- 这是用于 MVC,而不是 WS

有任何想法吗?

Roy*_*ijn 1

在寻找合适的解决方案时,我们遇到了一些丑陋的问题:

  • 创建自定义适配器/拦截器是有问题的,因为当您没有响应时,Spring 不会调用handleResponse方法(void)
  • 手动设置状态代码不起作用,因为HttpServletConnection保留了一个不会更新的布尔状态代码集

但幸运的是,我们设法通过以下更改使其正常工作:

/**
 * If a web service has no response, this handler returns: 204 No Content
 */
public class NoContentInterceptor extends EndpointInterceptorAdapter {

    @Override
    public void afterCompletion(MessageContext messageContext, Object o, Exception e) throws Exception {
        if (!messageContext.hasResponse()) {
            TransportContext tc = TransportContextHolder.getTransportContext();
            if (tc != null && tc.getConnection() instanceof HttpServletConnection) {
                HttpServletConnection connection = ((HttpServletConnection) tc.getConnection());
                // First we force the 'statusCodeSet' boolean to true:
                connection.setFaultCode(null);
                // Next we can set our custom status code:
                connection.getHttpServletResponse().setStatus(204);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来我们需要注册这个拦截器,这可以使用 Spring 的 XML 轻松完成:

<sws:interceptors>
    <bean class="com.something.NoContentInterceptor"/>
</sws:interceptors>
Run Code Online (Sandbox Code Playgroud)

非常感谢 @m-deinum 为我们指明了正确的方向!