Spring REST 异常处理示例

Spring REST 异常处理示例

原文: 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 中的异常处理的问题交给我。

学习愉快!

下载源码