之前做過的項目都是從service一路拋到controller,然後定義一個controller層的統一異常處理類,最近做的項目卻是使用AOP進行全局的異常攔截處理,很好奇兩種方式有何不同,如果同時定義又會怎樣,經過驗證,
1、如果定義了AOP處理異常,正常請求後在controller層發生異常後@ExceptionHandler就捕獲不到了,因爲他是對於controller層拋出去的異常進行處理,而在切面處異常已經被處理,所以不會執行。
2、如果定義的請求方式是GET,用了POST方式進行請求時報的異常,由於此時未進入AOP,因此@ExceptionHandler會處理該異常而不是由AOP處理了
以下是代碼。
自定義異常
/**
* 自定義異常
*/
@Getter
@Setter
public class MyException extends RuntimeException {
private String code ;
private String msg ;
public MyException(String code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
}
controller層
/**
* controller demo
*/
@RestController
@Slf4j
public class DemoController {
@GetMapping("demo")
public BaseResponse demo(String str){
log.info("str:{}",str);
if (StringUtils.isEmpty(str)){
throw new NullPointerException();
}
if ("123".equals(str)){
throw new MyException(Constant.ResultCode.MY_EXCEPTION_CODE,Constant.ResultMsg.MY_EXCEPTION_MESSAGE);
}
return ResponseUtils.buildSuccess();
}
}
controller層異常攔截
/**
* 異常攔截接口
*/
public interface GlobalExceptionHandler<T extends Throwable> {
@ExceptionHandler/*({MyException.class,NullPointerException.class})*/ //可以直接寫@ExceptionHandler,不指明異常類,會自動映射
BaseResponse exceptionHandler(T t); //還可以聲明接收其他任意參數
}
/**
* 異常攔截實現,可以定義不同異常不同處理邏輯
*/
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandlerImpl implements GlobalExceptionHandler {
@ExceptionHandler
public BaseResponse myExceptionHandler(MyException e){
log.error("捕獲到MyException:{}",e.getMsg(),e);
return ResponseUtils.buildFail(e.getCode(),e.getMsg());
}
@Override
public BaseResponse exceptionHandler(Throwable t) {
log.error("捕獲到異常:{}",t.getMessage(),t);
return ResponseUtils.buildFail();
}
}
返回值基類
/**
* 返回基類
*/
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class BaseResponse<T> {
private String code;
private String msg;
private T data;
private boolean success;
private String traceId;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"code\":\"")
.append(code).append('\"');
sb.append(",\"msg\":\"")
.append(msg).append('\"');
sb.append(",\"data\":")
.append(data);
sb.append(",\"success\":")
.append(success);
sb.append(",\"traceId\":\"")
.append(traceId).append('\"');
sb.append("}");
return sb.toString();
}
}
返回值操作工具類
/**
* 返回值操作工具
*/
public class ResponseUtils<T> {
public static BaseResponse buildSuccess(){
return buildSuccess(null);
}
public static BaseResponse buildSuccess(Object data){
return BaseResponse.builder()
.code(Constant.ResultCode.SUCCESS_CODE)
.msg(Constant.ResultMsg.SUCCESS_MESSAGE)
.success(true)
.data(data)
.build();
}
public static BaseResponse buildFail(){
return buildFail(Constant.ResultCode.ERROR_CODE,Constant.ResultMsg.ERROR_MESSAGE);
}
public static BaseResponse buildFail(String code,String msg){
return buildResult(code, msg, null);
}
public static BaseResponse buildResult(String code,String msg,Object data){
return BaseResponse.builder()
.code(StringUtils.isEmpty(code) ? Constant.ResultCode.SUCCESS_CODE : code)
.msg(StringUtils.isEmpty(msg) ? (Constant.ResultCode.SUCCESS_CODE.equals(code) ? Constant.ResultMsg.SUCCESS_MESSAGE : Constant.ResultMsg.ERROR_MESSAGE) : msg)
.success(Constant.ResultCode.SUCCESS_CODE.equals(code))
.data(data)
.build();
}
}
常數類
/**
* 常數類
*/
public class Constant {
public final class ResultCode{
public static final String SUCCESS_CODE = "0000";
public static final String ERROR_CODE = "1001";
public static final String MY_EXCEPTION_CODE = "1002";
}
public final class ResultMsg{
public static final String SUCCESS_MESSAGE = "請求成功";
public static final String ERROR_MESSAGE = "未知錯誤";
public static final String MY_EXCEPTION_MESSAGE = "請求出錯";
}
}
AOP切面
/**
* AOP
*/
@Aspect
@Slf4j
@Component
public class AopAspect {
@Pointcut("execution(* com.star.dream.project.controller..*(..))")
private void traceLogAspect() {
}
@Around("traceLogAspect()")
public Object around(ProceedingJoinPoint joinPoint) {
String interfaceName = String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
Object result;
try {
result = joinPoint.proceed();
} catch (Throwable ex) {
if (ex instanceof MyException) {
MyException e = (MyException) ex;
result = ResponseUtils.buildFail(e.getCode(),e.getMsg());
log.error(String.format("調用接口%s異常,錯誤信息:%s", interfaceName, e.getMsg()), e);
} else {
result = ResponseUtils.buildFail();
log.error(String.format("調用接口%s異常,錯誤信息:%s", interfaceName, ex.toString()), ex);
}
}
return result;
}
}
使用到的全部依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>${cglib.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>