【问题标题】:How to return 404 response status in Spring Boot @ResponseBody - method return type is Response?如何在 Spring Boot @ResponseBody 中返回 404 响应状态 - 方法返回类型是响应?
【发布时间】:2014-10-14 20:18:28
【问题描述】:

我正在使用 Spring Boot 和基于 @ResponseBody 的方法,如下所示:

@RequestMapping(value = VIDEO_DATA_PATH, method = RequestMethod.GET)
public @ResponseBody Response getData(@PathVariable(ID_PARAMETER) long id, HttpServletResponse res) {
    Video video = null;
    Response response = null;
    video = videos.get(id - 1);
    if (video == null) {
      // TODO how to return 404 status
    }
    serveSomeVideo(video, res);
    VideoSvcApi client =  new RestAdapter.Builder()
            .setEndpoint("http://localhost:8080").build().create(VideoSvcApi.class);
    response = client.getData(video.getId());
    return response;
}

public void serveSomeVideo(Video v, HttpServletResponse response) throws IOException  {
    if (videoDataMgr == null) {
        videoDataMgr = VideoFileManager.get();
    }
    response.addHeader("Content-Type", v.getContentType());
    videoDataMgr.copyVideoData(v, response.getOutputStream());
    response.setStatus(200);
    response.addHeader("Content-Type", v.getContentType());
}

我尝试了一些典型的方法:

res.setStatus(HttpStatus.NOT_FOUND.value());
新的 ResponseEntity(HttpStatus.BAD_REQUEST);

但我需要返回Response

如果视频为空,如何在这里返回 404 状态码?

【问题讨论】:

    标签: java spring http-status-code-404 retrofit


    【解决方案1】:

    这很简单,只需抛出 org.springframework.web.server.ResponseStatusException

    throw new ResponseStatusException(
      HttpStatus.NOT_FOUND, "entity not found"
    );
    

    它与@ResponseBody 和任何返回值兼容。需要 Spring 5+

    【讨论】:

    • 有没有办法做到这一点而不导致 Springboot 发出警告?我得到`WARN 27604 --- [nio-8081-exec-9] .wsmaResponseStatusExceptionResolver : Resolved [org.springframework.web.server.ResponseStatusException: 404 NOT_FOUND `,它不合理地进入警报等:这不是问题.
    • @GreenAsJade 我不确定这个警告在哪里记录(我没有在我的日志中看到这个警告)但也许你可以使用 log4j 设置或与你的警报系统交谈来避免这种情况。跨度>
    • 这不是最好的,您的访问者会看到错误堆栈信息。
    • @BuffK 这是用于网络服务(与机器对话)
    • 这需要覆盖 /error 端点。
    【解决方案2】:

    创建一个带有@ResponseStatus(HttpStatus.NOT_FOUND) 注释的NotFoundException 类并将其从控制器中抛出。

    @ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "video not found")
    public class VideoNotFoundException extends RuntimeException {
    }
    

    【讨论】:

    • 需要标准导入方式:import org.springframework.http.HttpStatus;
    • @andrej 有时这是一个很好的解决方案,但是 (1) ResponseStatusException 直到 Spring 5 才添加; (2) NotFoundException 可用于被抓到或用于带有@ExceptionHandler 的双栈 HTML UI。
    • 此解决方案将异常紧密耦合到您的 REST-Controller 层。我想避免的事情。我会在 @AroundAdvice 组件中使用 @ExceptionHandler 来代替
    • 如果有人想使用 Spring 自带的预先存在的异常,org.springframework.data.rest.webmvc.ResourceNotFoundException 已经用 @ResponseStatus(HttpStatus.NOT_FOUND) 注释
    【解决方案3】:

    您的原始方法可以返回 ResponseEntity(不会改变您的方法行为):

    @RequestMapping(value = VIDEO_DATA_PATH, method = RequestMethod.GET)
    public ResponseEntity getData(@PathVariable(ID_PARAMETER) long id, HttpServletResponse res{
    ... 
    }
    

    并返回以下内容:

    return new ResponseEntity(HttpStatus.NOT_FOUND);
    

    【讨论】:

    • 准确地说,您应该返回 ResponseEntity,其中 T 是例如 Response(有问题的第一种情况)。当它是正确的响应时,您将返回 new ResponseEntity(myResponse, HttpStatus.OK)。
    • 这种方式也可以设置标题,ResponseStatus 不行,哇!
    • 另一个好处是它不会导致日志中出现警告,而抛出 ResponseStatusException 会。
    • 但是您会丢失响应上的类型,这与 Swagger 生成的文档无法正常工作。
    【解决方案4】:

    你可以像这样在 res 上设置 responseStatus:

    @RequestMapping(value = VIDEO_DATA_PATH, method = RequestMethod.GET)
    public ResponseEntity getData(@PathVariable(ID_PARAMETER) long id,
                                                HttpServletResponse res) {
    ...
        res.setStatus(HttpServletResponse.SC_NOT_FOUND); 
        // or res.setStatus(404)
        return null; // or build some response entity
     ...
    }
    

    【讨论】:

      猜你喜欢
      • 2013-01-20
      • 2021-02-20
      • 2018-06-19
      • 2015-01-09
      • 2017-08-10
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      • 2019-07-27
      相关资源
      最近更新 更多