@ExceptionHandler与@Aspect对异常的全局处理

之前做过的项目都是从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>
发布了43 篇原创文章 · 获赞 2 · 访问量 3499
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览