@ControllerAdvice 未捕获 Rest API 异常
Posted
技术标签:
【中文标题】@ControllerAdvice 未捕获 Rest API 异常【英文标题】:@ControllerAdvice not catching Rest API exceptions 【发布时间】:2020-08-04 07:36:56 【问题描述】:我正在尝试在我的 Rest API 中实现错误处理并使用 Postman 进行测试,当我给出不正确的路径时,邮递员返回 404 但它是 404 html。我将@ControllerAdvice 用于全局异常处理程序。
@ControllerAdvice 类是 RestResponseEntityExceptionHandler.java
@ControllerAdvice
public class RestResponseEntityExceptionHandler
extends ResponseEntityExceptionHandler
@ExceptionHandler(value = IllegalArgumentException.class, IllegalStateException.class )
protected ResponseEntity<Object> handleConflict(
RuntimeException ex, WebRequest request)
String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse,
new HttpHeaders(), HttpStatus.CONFLICT, request);
有人告诉我,默认情况下 spring boot 应该返回类似这样的东西
"timestamp": 1436442596410,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/item"
我给它的不存在的路径是
http://localhost:8080/Assignment2C/breweriessdfsdf
我得到的回应是
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 404 – Not Found</title>
<style type="text/css">
h1
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
font-size: 22px;
h2
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
font-size: 16px;
h3
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
font-size: 14px;
body
font-family: Tahoma, Arial, sans-serif;
color: black;
background-color: white;
b
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
p
font-family: Tahoma, Arial, sans-serif;
background: white;
color: black;
font-size: 12px;
a
color: black;
a.name
color: black;
.line
height: 1px;
background-color: #525D76;
border: none;
</style>
</head>
<body>
<h1>HTTP Status 404 – Not Found</h1>
<hr class="line" />
<p><b>Type</b> Status Report</p>
<p><b>Description</b> The origin server did not find a current representation for the target resource or is not
willing to disclose that one exists.</p>
<hr class="line" />
<h3>Apache Tomcat/9.0.26</h3>
</body>
</html>
我使用的spring boot依赖是
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
我的控制器类是 Breweries_Controller
@RestController
@RequestMapping("/breweries")
public class Breweries_Controller
@Autowired
Breweries_Service service;
@GetMapping(produces = MediaTypes.HAL_JSON_VALUE)
public Resources<Breweries> getAllBreweries(@RequestParam(name = "limit", required = false) Integer limit , @RequestParam(name = "offset", required = false) Integer offset)
List<Breweries> allBreweries = service.getAllBreweries();
if(limit == null && offset == null)
limit = 20;
offset = 0;
List<Breweries> paginatedList = allBreweries.subList(offset, offset + limit);
for (Breweries b : allBreweries)
int id = b.getResourceId();
Link self = linkTo(this.getClass()).slash(id).withSelfRel();
b.add(self);
linkTo(methodOn(this.getClass()).getBrewerie(id));
Link link = linkTo(this.getClass()).withSelfRel();
Resources<Breweries> result = new Resources<Breweries>(paginatedList, link);
return result;
@GetMapping(value = "/id", produces = MediaTypes.HAL_JSON_VALUE)
public Resource<Breweries> getBrewerie(@PathVariable("id") int id)
Resource<Breweries> brewerie = new Resource<Breweries>(service.getBrewerieById(id));
ControllerLinkBuilder linkTo = linkTo(methodOn(this.getClass()).getAllBreweries(5, 50));
brewerie.add(linkTo.withRel("all-breweries"));
return brewerie;
@DeleteMapping(value = "/id")
@ResponseStatus(HttpStatus.OK)
public void delete(@PathVariable("id") int id)
Breweries brewerie = service.getBrewerieById(id);
service.deleteBrewerie(brewerie);
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void create(@RequestBody Breweries b)
b.setResourceId(0);
b.setAddUser(0);
b.setLastMod(new Date());
service.addBrewerie(b);
@PutMapping(value = "/id")
@ResponseStatus(HttpStatus.OK)
public void update(@PathVariable("id") int id, @RequestBody Breweries b)
b.setResourceId(id);
b.setAddUser(0);
b.setLastMod(new Date());
service.editBrewerie(b);
【问题讨论】:
【参考方案1】:404
表示spring mvc未能找到合适的端点(控制器+方法)来运行你的请求。
@ControllerAdvice
仅在实际调用了该方法并且存在异常时才相关。但是在您的情况下,流程甚至没有到达控制器,这就是控制器建议不起作用的原因。
您可以通过创建一个实现 ErrorController 的控制器来自定义错误页面。
此信息并未严格回答问题,但我意识到这才是解决问题真正需要的,因此我将在相关教程中发布 link。
【讨论】:
感谢解答,不过这个项目的一个规范是不能使用JSP,需要使用postman来测试异常处理 JSP 与此有何关系? ErrorController 可以生成静态 Json - 不需要 JSP。重点是为根本不调用 Spring MVC 的情况提供一个特殊的钩子...... 谢谢,我终于弄明白了,明白你在说什么以上是关于@ControllerAdvice 未捕获 Rest API 异常的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot(十九)@ControllerAdvice+@ExceptionHandler全局捕获Controller异常
什么异常能被 @RestControllerAdvice 或 @ControllerAdvice 捕获,什么情况不能被捕获?
什么异常能被 @RestControllerAdvice 或 @ControllerAdvice 捕获,什么情况不能被捕获?