我正在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);
}
。
处理此问题的最佳方法是什么?
答案 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)。从技术上来说,您可以使用任何一种状态,但它们具有不同的含义:
现在,如果您请求/book/123
并且没有ID为123的书,则该书可能被视为不存在的资源,因此HttpStatus.NOT_FOUND
很有道理。
答案 1 :(得分:0)
有人可能会说400和204之间的差异是模糊的,最好总是返回204。确实,差异可能是模糊的,但是从监视的角度来看,我想知道什么都可以(没有书的标题),什么时候可以闻起来(id找不到书)。
我知道我的答案不符合REST指令(或者可能不符合REST指令)。我不在乎。我只是认为404应该为应用程序服务器保留,而不应该由应用程序使用。原因已经在其他答案中得到了解释。
摘要:
答案 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,.....]