天天看點

Spring Boot中進行統一的異常處理spring-boot-demo-exception-handler

spring-boot-demo-exception-handler

此 demo 示範了如何在Spring Boot中進行統一的異常處理,包括了兩種方式的處理:第一種對常見API形式的接口進行異常處理,統一封裝傳回格式;第二種是對模闆頁面請求的異常處理,統一處理錯誤頁面。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<artifactId>spring-boot-demo-exception-handler</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-boot-demo-exception-handler</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>com.xkcoding</groupId>
		<artifactId>spring-boot-demo</artifactId>
		<version>1.0.0-SNAPSHOT</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
        <!--模闆引擎用來跳轉頁面使用,類似Freemarker 但操作不一樣>>SpringBoot官方是推薦使用thymeleaf作為優選的視圖解析器-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>

	<build>
		<finalName>spring-boot-demo-exception-handler</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
           

ApiResponse.java

統一的API格式傳回封裝,裡面涉及到的

BaseException

Status

這兩個類,具體代碼見 demo。
/**
 * <p>
 * 通用的 API 接口封裝
 * </p>
 *
 * @package: com.xkcoding.exception.handler.model
 * @description: 通用的 API 接口封裝
 * @author: yangkai.shen
 * @date: Created in 2018/10/2 8:57 PM
 * @copyright: Copyright (c) 2018
 * @version: V1.0
 * @modified: yangkai.shen
 */
@Data
public class ApiResponse {
	/**
	 * 狀态碼
	 */
	private Integer code;

	/**
	 * 傳回内容
	 */
	private String message;

	/**
	 * 傳回資料
	 */
	private Object data;

	/**
	 * 無參構造函數
	 */
	private ApiResponse() {

	}

	/**
	 * 全參構造函數
	 *
	 * @param code    狀态碼
	 * @param message 傳回内容
	 * @param data    傳回資料
	 */
	private ApiResponse(Integer code, String message, Object data) {
		this.code = code;
		this.message = message;
		this.data = data;
	}

	/**
	 * 構造一個自定義的API傳回
	 *
	 * @param code    狀态碼
	 * @param message 傳回内容
	 * @param data    傳回資料
	 * @return ApiResponse
	 */
	public static ApiResponse of(Integer code, String message, Object data) {
		return new ApiResponse(code, message, data);
	}

	/**
	 * 構造一個成功且帶資料的API傳回
	 *
	 * @param data 傳回資料
	 * @return ApiResponse
	 */
	public static ApiResponse ofSuccess(Object data) {
		return ofStatus(Status.OK, data);
	}

	/**
	 * 構造一個成功且自定義消息的API傳回
	 *
	 * @param message 傳回内容
	 * @return ApiResponse
	 */
	public static ApiResponse ofMessage(String message) {
		return of(Status.OK.getCode(), message, null);
	}

	/**
	 * 構造一個有狀态的API傳回
	 *
	 * @param status 狀态 {@link Status}
	 * @return ApiResponse
	 */
	public static ApiResponse ofStatus(Status status) {
		return ofStatus(status, null);
	}

	/**
	 * 構造一個有狀态且帶資料的API傳回
	 *
	 * @param status 狀态 {@link Status}
	 * @param data   傳回資料
	 * @return ApiResponse
	 */
	public static ApiResponse ofStatus(Status status, Object data) {
		return of(status.getCode(), status.getMessage(), data);
	}

	/**
	 * 構造一個異常且帶資料的API傳回
	 *
	 * @param t    異常
	 * @param data 傳回資料
	 * @param <T>  {@link BaseException} 的子類
	 * @return ApiResponse
	 */
	public static <T extends BaseException> ApiResponse ofException(T t, Object data) {
		return of(t.getCode(), t.getMessage(), data);
	}

	/**
	 * 構造一個異常且帶資料的API傳回
	 *
	 * @param t   異常
	 * @param <T> {@link BaseException} 的子類
	 * @return ApiResponse
	 */
	public static <T extends BaseException> ApiResponse ofException(T t) {
		return ofException(t, null);
	}
}
           

DemoExceptionHandler.java

/**
 * <p>
 * 統一異常處理
 * </p>
 *
 * @package: com.xkcoding.exception.handler.handler
 * @description: 統一異常處理
 * @author: yangkai.shen
 * @date: Created in 2018/10/2 9:26 PM
 * @copyright: Copyright (c) 2018
 * @version: V1.0
 * @modified: yangkai.shen
 */
@ControllerAdvice
@Slf4j
public class DemoExceptionHandler {
	private static final String DEFAULT_ERROR_VIEW = "error";

	/**
	 * 統一 json 異常處理
	 *
	 * @param exception JsonException
	 * @return 統一傳回 json 格式
	 */
	@ExceptionHandler(value = JsonException.class)
	@ResponseBody
	public ApiResponse jsonErrorHandler(JsonException exception) {
		log.error("【JsonException】:{}", exception.getMessage());
		return ApiResponse.ofException(exception);
	}

	/**
	 * 統一 頁面 異常處理
	 *
	 * @param exception PageException
	 * @return 統一跳轉到異常頁面
	 */
	@ExceptionHandler(value = PageException.class)
	public ModelAndView pageErrorHandler(PageException exception) {
		log.error("【DemoPageException】:{}", exception.getMessage());
		ModelAndView view = new ModelAndView();
		view.addObject("message", exception.getMessage());
		view.setViewName(DEFAULT_ERROR_VIEW);
		return view;
	}
}
           

error.html

位于

src/main/resources/template

目錄下
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
	<meta charset="UTF-8"/>
	<title>統一頁面異常處理</title>
</head>
<body>
<h1>統一頁面異常處理</h1>
<div th:text="${message}"></div>
</body>
</html>
           

項目代碼(連結):