ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Spring Boot @ResponseBody 中返回 404 响应状态 - 方法返回类型是响应?

我正在使用 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());新的响应实体(HttpStatus.BAD_REQUEST);

但我需要返回 Response

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


d
dur

这很简单,只需抛出 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 端点。
c
chrylis -cautiouslyoptimistic-

使用 @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) 注释
d
dur

您的原始方法可以返回 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 会。
但是随后您会丢失 Response 上的类型,这与 Swagger 生成的文档无法正常工作。
M
Michał

您可以像这样在 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
 ...
}