🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Spring REST 异常处理示例 > 原文: [https://howtodoinjava.com/spring-restful/exception-handling-example/](https://howtodoinjava.com/spring-restful/exception-handling-example/) 在使用 **Spring REST** 模块创建的 [REST API](https://restfulapi.net) 中学习处理异常(请求验证,错误数据或其他请求处理错误)。 我们将研究一种使用`@ControllerAdvice`和`@ExceptionHandler`的方法。 要使用`@ControllerAdvice`全局处理 REST 异常,我们需要遵循以下步骤。 ## 1\. 使用`@ControllerAdvice`和`@ExceptionHandler`创建处理器 * [`@ControllerAdvice`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html)注解是`@Component`注解的特化,其方法(以[`@ExceptionHandler`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html)注解)在全球范围内跨多个`@Controller`类共享。 * 通过类路径扫描自动检测带有`@ControllerAdvice`的类。 * 使用选择器`annotations()`,`basePackageClasses()`和`basePackages()`定义目标控制器的更窄子集。 * 我们可以在选择器中应用 OR 运算符,即如果遇到给定异常中的任何一个,则将执行给定方法。 请注意,[`ResponseEntityExceptionHandler`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html)是`@ControllerAdvice`类的便捷基类,这些类希望通过`@ExceptionHandler`方法跨所有`@RequestMapping`方法提供集中的[异常处理](https://howtodoinjava.com/best-practices/java-exception-handling-best-practices/) 。 `CustomExceptionHandler.java` ```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` ```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` ```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` ```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` ```java <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` ```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` ```java HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/101 ``` `API Response` ```java { "message": "INCORRECT_REQUEST", "details": [ "Employee id '101' does no exist" ], } ``` 请把关于 Spring Rest API 中的**异常处理**的问题交给我。 学习愉快! [下载源码](https://howtodoinjava.com/wp-content/downloads/SpringRestExample.zip)