前言
简单回顾下异常分类:
- 非受检异常:运行时异常
- 受检异常:编译时异常
异常的处理通常有两种方式:
- 第一种就是在当前类使用try-catch捕获异常并直接处理
- 另一种就是不在当前类处理,使用throws抛给上一级处理
如果在每个异常处都进行try-catch处理的话,无疑会造成代码的臃肿,且不够美观。
所以,一般来说除非的必须在在当前类处理的异常,否则都会向上抛出,直到抛到controller层为止,在controller层进行统一的异常处理(不处理的话,再往上抛就抛到前端去了)。
统一进行异常处理的常见方式有两种:1. 使用注解 或者 2. 使用(AOP)拦截器
统一返回结果
既然要统一进行异常处理了,自然需要统一下数据结果的返回格式,这里建议使用一个实体类进行处理,更加的可控易于管理修改。
在实体类中对数据的返回格式进行下规范:
import io.swagger.annotations.ApiModelProperty;import lombok.Data;import java.util.Collection;import java.util.HashMap;@Datapublic class ReturnResult {@ApiModelProperty(value = "操作结果")private Boolean result;@ApiModelProperty(value = "返回消息")private String message;@ApiModelProperty(value = "返回数据")private HashMap<String, String> data;private ReturnResult() {}public static ReturnResult error() {ReturnResult returnResult = new ReturnResult();returnResult.setResult(false);returnResult.setMessage("操作出错");return returnResult;}public static ReturnResult error(HashMap<String, String> data) {ReturnResult returnResult = new ReturnResult();returnResult.setResult(false);returnResult.setMessage("操作出错");returnResult.setData(data);return returnResult;}public static ReturnResult success() {ReturnResult returnResult = new ReturnResult();returnResult.setResult(true);returnResult.setMessage("操作成功");return returnResult;}public static ReturnResult success(HashMap<String, String> data) {ReturnResult returnResult = new ReturnResult();returnResult.setResult(true);returnResult.setMessage("操作成功");returnResult.setData(data);return returnResult;}public ReturnResult result(Boolean success) {this.setResult(success);return this;}public ReturnResult message(String message) {this.setMessage(message);return this;}}
统一异常处理
controller类示例:
@RestControllerpublic class ErrorTestController {@AutowiredErrorService errorService;@GetMapping("/test")public ReturnResult toTest(){HashMap<String, String> map = new HashMap<>();map.put("data", "这里是返回的数据");return ReturnResult.success(map);}@GetMapping("/test1")public ReturnResult toTest1(){errorService.error1();return ReturnResult.success();}@GetMapping("/test2")public ReturnResult toTest2(){errorService.error2();return ReturnResult.success();}}
同时在service类中模拟异常:
@Servicepublic class ErrorService {public void error1() throws NullPointerException {String[] str = null;String s = str[0];}public void error2() throws ArithmeticException {int i = 9 / 0;}}
AOP处理异常
使用AOP切controller类,进行统一的异常处理。
AOP切面类:
import email.entity.ReturnResult;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import java.util.HashMap;@Aspect@Componentpublic class AOPCatch {private final Logger logger = LoggerFactory.getLogger(AOPCatch.class);@Around("execution(public * email.controller.*.*(..))")public ReturnResult catchException(ProceedingJoinPoint joinPoint) {try {Object result = joinPoint.proceed();// 没有异常,直接将接收到的被切方法的返回值原样返回return (ReturnResult) result;} catch (Throwable e) {HashMap<String, String> map = new HashMap<>();String className = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();logger.error(className + ":" + methodName + ":" + e);map.put("data", className + ":" + methodName + ":" + e);ReturnResult error = ReturnResult.error(map);// 有异常,则返回错误信息return error;}}}
注解处理异常
使用@ControllerAdvice或者@RestControllerAdvice配合@ExceptionHandler注解使用
@RestControllerAdvice注解就相当于@ControllerAdvice+@ResponseBody注解,标识该类中接收的返回信息的(json类型的)数据。
创建一个统一的异常处理类:
package email.servive;import email.entity.ReturnResult;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;@RestControllerAdvice//@ControllerAdvice//@ResponseBodypublic class GlobalExceptionHandler {private final Logger logger = LoggerFactory.getLogger(AOPCatch.class);// 全局异常处理@ExceptionHandler(Exception.class)public ReturnResult error(Exception e){e.printStackTrace();logger.error(e.getMessage());return ReturnResult.error();}// 指定异常处理@ExceptionHandler(NullPointerException.class)public ReturnResult error(NullPointerException e){e.printStackTrace();logger.error(e.getMessage());HashMap<String, String> map = new HashMap<>();map.put("data", "空指针异常");return ReturnResult.error(map);}// 自定义异常处理,针对于业务需求自定义的/*@ExceptionHandler(MyException.class)public ReturnResult error(MyException e){e.printStackTrace();return ReturnResult.error();}*/}




