原文: 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;@ControllerAdvicepublic 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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/mvchttp://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 中的异常处理的问题交给我。
学习愉快!
