在Rest API中找不到处理资源

时间:2018-11-03 13:28:05

标签: java spring spring-boot

我正在Spring Boot中开发Rest API。当找不到资源实例时,以下哪种方法是最好的处理方法?

FormatException

我很清楚,当在Db中找不到资源集合时,要传递一个空集合而不是null,但是我不清楚如何处理资源实例。

我还在StackOverflow上读过,当条件下的资源不存在而不是Db中不存在时,应使用 @GetMapping(value="/book/{id}") public ResponseEntity<Book> getBook(@PathVariable String id){ Book book = bookService.getBook(); // Which is best Approach for resource instance not found ? if(book == null) { // This one return new ResponseEntity<>(book, HttpStatus.NO_CONTENT); //OR return new ResponseEntity<>(book, HttpStatus.NOT_FOUND); //OR throw new DataNotFoundException("Book with id " + id + " Does not exist"); } return new ResponseEntity<>(book , HttpStatus.OK); }

处理此问题的最佳方法是什么?

5 个答案:

答案 0 :(得分:3)

使用Spring MVC时,返回结果时通常有两种选择,要么使用普通对象,要么使用ResponseEntity类。这些都不比另一个更好。此外,您可以决定是否使用异常将错误处理分开。

鉴于此,您抛出异常的第三个场景与前两个选项之一基本相同。默认情况下,引发异常将导致500内部服务器错误,但是可以使用@ResponseStatus批注来更改它,例如:

 @ResponseStatus(HttpStatus.NOT_FOUND) // Or @ResponseStatus(HttpStatus.NO_CONTENT)
 public class DataNotFoundException extends RuntimeException {

 }

或者,您也可以定义一个异常处理程序。同样,这可以通过使用普通对象或ResponseEntity来完成,例如:

@ResponseStatus(HttpStatus.NOT_FOUND) // Or @ResponseStatus(HttpStatus.NO_CONTENT)
@ExceptionHandler(DataNotFoundException.class)
public Book handleNotFound(DataNotFoundException ex) {
    return null;
}

或者:

@ExceptionHandler(DataNotFoundException.class)
public ResponseEntity<Book> handleNotFound(DataNotFoundException ex) {
    return new ResponseEntity<>(null, HttpStatus.NOT_FOUND); // Or HttpStatus.NO_CONTENT
}

同样,两者都不比对方更好,并且您选择的内容主要基于个人偏好。但是,您可能应该始终使用一个。


现在,这意味着还有两个选择,可以选择HttpStatus.NOT_FOUND(404)或HttpStatus.NO_CONTENT(204)。从技术上来说,您可以使用任何一种状态,但它们具有不同的含义:

  • 204 =请求成功,但是什么都没有。
  • 404 =请求未成功,资源不存在

现在,如果您请求/book/123并且没有ID为123的书,则该书可能被视为不存在的资源,因此HttpStatus.NOT_FOUND很有道理。

答案 1 :(得分:0)

  1. 如果您的终结点通过ID获取书籍,但书籍不存在,则返回400。不返回404。404是协议错误:应为错误的URL保留。现在,URL是正确的,但是 id 是错误的。 Id通常不会被猜中,而是由先前的查询返回。它不会突然消失:如果id错误,则请求是错误的。
  2. 如果您的端点按书名获得书并且书不存在,则返回204。在这种情况下,书不存在是绝对正常的,客户应该准备处理204。

有人可能会说400和204之间的差异是模糊的,最好总是返回204。确实,差异可能是模糊的,但是从监视的角度来看,我想知道什么都可以(没有书的标题),什么时候可以闻起来(id找不到书)。

我知道我的答案不符合REST指令(或者可能不符合REST指令)。我不在乎。我只是认为404应该为应用程序服务器保留,而不应该由应用程序使用。原因已经在其他答案中得到了解释。

摘要:

  • 404:错误的网址
  • 400:错误的ID
  • 204:找不到,就可以了

答案 2 :(得分:-1)

每当找不到资源时,您都应该使用前面提到的HTTP状态代码404 Not Found向客户端表明这一点。

对于集合,只需在响应正文中返回一个空数组(以及响应代码200 OK,这是我的观点),请返回404 Not Found,因为资源实际上存在。< / p>

请注意,此处202 No Content是一个错误的选择,因为服务器成功完成了请求。而是使用此返回码,例如,用于成功的PUT请求(您已更改了内部数据,但在响应正文中未返回任何内容)。

在大多数API中,您会在响应正文中遇到其他信息:

{"messages":{"error":[{"code":404,"message":"Resource not found."}]}}

您将找到所有错误及其响应代码的列表,并提供丰富的说明。一件事很重要,很艰难:坚持 one 格式,否则对客户来说会很痛苦。大多数API也仅使用大约6-8个HTTP响应代码。

此外,Spring还提供了许多实用程序来帮助您:

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order")
public class OrderNotFoundException extends RuntimeException {
    // ...
}

或者,使用以下注释创建自定义响应格式:

@ExceptionHandler({ YourException.class })

答案 3 :(得分:-1)

首先,我认为您的方法参数是@PathVariable而不是@RequestParam(请参见difference between PathVariable and RequestParam here)。

第二,对于收到404找不到响应的客户端来说,这是不明确,因为这意味着:

  

服务器未找到与请求的地址(URI)匹配的任何内容   ( 未找到 )。这表示您输入的网址错误或已过时   并且与服务器上现有的任何文档都不匹配(您可以尝试   从右到左逐渐删除URL组件,以   最终检索到现有路径。

知道您的返回类型为ResponsEntity时,使用它是更合适的:

    @GetMapping(value="/book/{id}")
    public ResponseEntity getBook(@PathVariable String id){

        Optional<Book> book = bookService.getBook();

        if(book.isPresent()) {
            return ResponseEntity.status(HttpStatus.OK).body(book.get());
        }

        return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
    }

答案 4 :(得分:-2)

只需将404 HttpStatus返回给客户端,不要浪费时间。没有人会请求db中通常不存在的id。通常客户请求(例如model / {id})来自 针对您的收藏集[model1,model2,.....]