原文: https://howtodoinjava.com/spring-restful/exception-handling-example/
在使用 Spring REST 模块创建的 REST API 中学习处理异常(请求验证,错误数据或其他请求处理错误)。 我们将研究一种使用@ControllerAdvice
和@ExceptionHandler
的方法。
要使用@ControllerAdvice
全局处理 REST 异常,我们需要遵循以下步骤。
1. 使用@ControllerAdvice
和@ExceptionHandler
创建处理器
@ControllerAdvice
注解是@Component
注解的特化,其方法(以@ExceptionHandler
注解)在全球范围内跨多个@Controller
类共享。- 通过类路径扫描自动检测带有
@ControllerAdvice
的类。 - 使用选择器
annotations()
,basePackageClasses()
和basePackages()
定义目标控制器的更窄子集。 - 我们可以在选择器中应用 OR 运算符,即如果遇到给定异常中的任何一个,则将执行给定方法。
请注意,ResponseEntityExceptionHandler
是@ControllerAdvice
类的便捷基类,这些类希望通过@ExceptionHandler
方法跨所有@RequestMapping
方法提供集中的异常处理 。
CustomExceptionHandler.java
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler
{
private String INCORRECT_REQUEST = "INCORRECT_REQUEST";
private String BAD_REQUEST = "BAD_REQUEST";
@ExceptionHandler(RecordNotFoundException.class)
public final ResponseEntity<ErrorResponse> handleUserNotFoundException
(RecordNotFoundException ex, WebRequest request)
{
List<String> details = new ArrayList<>();
details.add(ex.getLocalizedMessage());
ErrorResponse error = new ErrorResponse(INCORRECT_REQUEST, details);
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(MissingHeaderInfoException.class)
public final ResponseEntity<ErrorResponse> handleInvalidTraceIdException
(MissingHeaderInfoException ex, WebRequest request) {
List<String> details = new ArrayList<>();
details.add(ex.getLocalizedMessage());
ErrorResponse error = new ErrorResponse(BAD_REQUEST, details);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
}
2. 创建异常模型类
我们需要识别业务异常用例,并用异常类来表示它们。 这些类将扩展RuntimeException
类。 也可以根据需要随意创建更多错误响应表示。
MissingHeaderInfoException.java
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class MissingHeaderInfoException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public MissingHeaderInfoException(String message) {
super(message);
}
}
RecordNotFoundException.java
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class RecordNotFoundException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public RecordNotFoundException(String message) {
super(message);
}
}
ErrorResponse.java
import java.util.List;
public class ErrorResponse
{
public ErrorResponse(String message, List<String> details) {
super();
this.message = message;
this.details = details;
}
private String message;
private List<String> details;
//getters and setters
}
3. 配置视图解析器
如果尚未完成,我们需要配置视图解析器以将异常消息转换为 XML 或 JSON 形式。
在 Spring Boot 中,此配置是自动完成的。 没有 SpringBoot,我们需要像下面这样。
重要说明:确保已启用
mvc: annotation-driven
配置,或已使用@EnableWebMvc
注解。
rest-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.howtodoinjava.demo" />
<mvc:view-resolvers>
<mvc:content-negotiation>
<mvc:default-views>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</mvc:default-views>
</mvc:content-negotiation>
</mvc:view-resolvers>
<!-- JPA Config -->
</beans>
4. REST 控制器更改
从 rest 控制器处理器方法中,我们需要抛出要转换并作为响应发送给 API 使用者的异常。 在这种情况下,如果id
搜索了一个雇员并且该雇员在数据库中不存在,我们将发送RecordNotFoundException
。
EmployeeRESTController.java
@GetMapping("/employees/{id}")
Employee getEmployeeById(@PathVariable Long id)
{
return repository.findById(id)
.orElseThrow(() -> new RecordNotFoundException("Employee id '" + id + "' does no exist"));
}
5. Spring REST 异常处理演示
尝试按 ID(在数据库中不存在 ID)获取员工。
API Request
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/101
API Response
{
"message": "INCORRECT_REQUEST",
"details": [
"Employee id '101' does no exist"
],
}
请把关于 Spring Rest API 中的异常处理的问题交给我。
学习愉快!