之前做过的项目都是从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>