前言
简单回顾下异常分类:
- 非受检异常:运行时异常
- 受检异常:编译时异常
异常的处理通常有两种方式:
- 第一种就是在当前类使用try-catch捕获异常并直接处理
- 另一种就是不在当前类处理,使用throws抛给上一级处理
如果在每个异常处都进行try-catch处理的话,无疑会造成代码的臃肿,且不够美观。
所以,一般来说除非的必须在在当前类处理的异常,否则都会向上抛出,直到抛到controller层为止,在controller层进行统一的异常处理(不处理的话,再往上抛就抛到前端去了)。
统一进行异常处理的常见方式有两种:1. 使用注解 或者 2. 使用(AOP)拦截器
统一返回结果
既然要统一进行异常处理了,自然需要统一下数据结果的返回格式,这里建议使用一个实体类进行处理,更加的可控易于管理修改。
在实体类中对数据的返回格式进行下规范:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| import io.swagger.annotations.ApiModelProperty; import lombok.Data;
import java.util.Collection; import java.util.HashMap;
@Data public 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类示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @RestController public class ErrorTestController { @Autowired ErrorService 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类中模拟异常:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Service public 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切面类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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 @Component public 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类型的)数据。
创建一个统一的异常处理类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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
public 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); }
}
|


