全局异常处理的任何框架都需要解决的问题,通过 @RestControllerAdvice 可以实现对抛出的异常进行处理,并返回一个REST风格的对象到前端。

全局异常处理GlobalExceptionAdvice

GlobalExceptionAdvice可以用来监听所有主动和被动抛出的异常,并可以指定异常的类型。例如可以监听未知的Exception并记录系统日志,HttpException是一个继承自RuntimeException的自定义异常,通常是开发者主动抛出,通过在此监听后返回一个RESTf风格的视图。

@RestControllerAdvice
@Slf4j
public class GlobalExceptionAdvice {
	/**
	 * Exception异常处理
	 */
	@ExceptionHandler(Exception.class)
	public ResponseVO<Object> handleException(Exception e) {
		log.error("全局异常捕获: ", e);
		return new ResponseVO<>(ResultCode.INTERNAL_SERVER_ERROR);
	}

	/**
	 * HttpException异常处理
	 */
	@ExceptionHandler(HttpException.class)
	public ResponseVO<Object> handleHttpException(HttpException e) {
		return new ResponseVO<>(e.getCode(), e.getStatusCode(), e.getMsg());
	}

	/**
	 * ServletException异常处理
	 */
	@ExceptionHandler(ServletException.class)
	public ResponseVO<Object> handleServletException(ServletException e) {
		return new ResponseVO<>(ResultCode.FAILED.getCode(), ResultCode.FAILED.getStatusCode(), e.getMessage());
	}
}

业务异常HttpException

public class HttpException extends RuntimeException {
	private final Integer code;
	private final Integer statusCode;
	private final String msg;

	public HttpException(ResultCode resultCode) {
		this.code = resultCode.getCode();
		this.statusCode = resultCode.getStatusCode();
		this.msg = resultCode.getMsg();
	}
}

ResultCode配合异常处理

上一节返回统一响应时使用ResultCode来规范格式,当然它也可以用来规范异常信息,code码是开发者自定义的用于和前端交互使用的码,statusCode则是HTTP状态码,在返回时携带不同的状态码。

@Getter
@AllArgsConstructor
public enum ResultCode {
	// 成功 0~9998
	SUCCESS(0, 200, "成功"),
	CREATED(1, 201, "创建成功"),
	UPDATED(2, 200, "更新成功"),
	DELETED(3, 200, "删除成功"),

	// 基础错误 9999~10099
	INTERNAL_SERVER_ERROR(9999, 500, "服务器未知错误"),
	FAILED(10000, 400, "失败"),
	PARAMETER_ERROR(10001, 400, "参数错误"),
	DUPLICATED(10010, 400, "资源已存在"),
	NOT_FOUND(10011, 404, "资源不存在"),

	// 权限相关 10100~10199
	UN_AUTHENTICATION(10100, 401, "未授权访问"),
	UN_AUTHORIZATION(10102, 401, "认证失败"),

	// 文件相关 10200~10299
	FILE_EXTENSION_ERROR(10200, 401, "文件后缀名不合法"),
	FILE_TOO_LARGE(10201, 413, "文件大小超限"),
	FILE_TOO_MANY(10202, 413, "文件数量超限");

	private final Integer code;
	private final Integer statusCode;
	private final String msg;
}

定义异常时,只需要在父类构造函数中传入对应的ResultCode即可。

public class NotFoundException extends HttpException {
	public NotFoundException() {
		super(ResultCode.NOT_FOUND);
	}
}

标题:Spring Boot构建Web API Wheel(三)—— 全局异常处理
作者:Jeffrey