【问题标题】:Spring MVC - Automatically return 204 when rest controller response type is voidSpring MVC - 当休息控制器响应类型为空时自动返回 204
【发布时间】:2017-11-13 16:39:52
【问题描述】:

当控制器方法响应类型为void 时,我试图让 spring 自动返回 HTTP 状态 204。例如:

假设我有一个这样的控制器方法:

@DeleteMapping(value = "/{heroId}")
public void delete(@PathVariable Long heroId) {
    heroService.delete(heroId);
}

我正在寻找一种无需使用@ResponseStatus(value = HttpStatus.NO_CONTENT) 注释方法即可自动返回204 的方法。

是否可以使用处理程序或 AOP 或其他工具来执行此操作?

PS。我看到了这个答案,Return HTTP 204 on null with spring @RestController,但没有回答我关于如何为具有void 返回类型的方法实现这一点的具体问题。此外,此方法应适用于没有输入参数的方法。

【问题讨论】:

  • 不知道是否可以使用ResponseBodyAdvice 更改状态,但我看到了:stackoverflow.com/q/26756811/5473627。也许有帮助
  • 你明白,这样你会让所有其他控制器方法去思考一些AOP代码,对吧?似乎您只想这样做一次 - 假设在启动时并且所有这些注释只放置一次
  • @YoshuaNahar 我能够根据您的建议实施解决方案
  • 我真的很想知道为什么这不是spring web的默认行为?!这是良好 REST API 中的既定做法,可在没有内容时提供 resp 代码 204。

标签: java spring spring-mvc


【解决方案1】:

我能够根据 Yoshua 提供的链接实施解决方案。我不是 100% 确定实施细节,但它对我有用。

这会捕获来自所有返回类型为 void 的控制器方法的响应,并将其 HTTP 状态更改为 204。

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class NoContentControllerAdvice implements ResponseBodyAdvice<Void> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if(returnType.getParameterType().isAssignableFrom(void.class)) {
            return true;
        }

        return false;
    }



    @Override
    public Void beforeBodyWrite(Void body, MethodParameter returnType, MediaType mediaType,
            Class<? extends HttpMessageConverter<?>> converterType, ServerHttpRequest request, ServerHttpResponse response) {

        if(returnType.getParameterType().isAssignableFrom(void.class)) {
            response.setStatusCode(HttpStatus.NO_CONTENT);
        }

        return body;
    }
}

【讨论】:

  • 谢谢。在 beforeBodyWrite 中,我认为可以删除对 void.class 的检查。这已经由 support() 方法处理了。
【解决方案2】:

我看到这已经被回答了,但是这个解决方案更干净一点:

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class NoContentControllerAdvice implements ResponseBodyAdvice<Void> {

  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return returnType.getParameterType() == void.class;
  }

  @Override
  public Void beforeBodyWrite(Void body, MethodParameter returnType, MediaType selectedContentType,
      Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    response.setStatusCode(HttpStatus.NO_CONTENT);
    return body;
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    • 2016-08-30
    • 2020-07-14
    • 2016-08-04
    • 2018-02-28
    • 1970-01-01
    相关资源
    最近更新 更多