@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>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,您想了解关于使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理的内容,这是一个常用的方案,可以实现全局异常的捕获和处理,让程序更加健壮和稳定。 @ExceptionHandler注解用于标记一个方法,该方法用于处理指定的异常类型。@ControllerAdvice注解用于标记一个类,该类用于处理全局异常。枚举则可以用于定义异常类型,方便异常处理时的统一管理。 在实现全局异常处理时,我们可以通过 @ExceptionHandler 注解来捕获指定的异常类型,并在方法中进行相应的处理。@ControllerAdvice注解可以让我们在一个类中定义多个 @ExceptionHandler方法,用于处理不同类型的异常。同时,我们也可以使用枚举来定义不同的异常类型,方便管理和调用。 下面是一个简单的示例,演示如何使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = BusinessException.class) @ResponseBody public ResultVO handleBusinessException(BusinessException e) { return ResultVO.error(e.getCode(), e.getMessage()); } } public enum ExceptionEnum { PARAMETER_ERROR(1001, "参数错误"), DATA_NOT_FOUND(1002, "数据不存在"), SYSTEM_ERROR(5000, "系统错误"); private final int code; private final String message; ExceptionEnum(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } } public class BusinessException extends RuntimeException { private final int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(ExceptionEnum exceptionEnum) { super(exceptionEnum.getMessage()); this.code = exceptionEnum.getCode(); } public int getCode() { return code; } } ``` 在上面的示例中,GlobalExceptionHandler类标记了@ControllerAdvice注解,用于全局异常处理。其中,handleBusinessException方法用于处理BusinessException异常,返回一个ResultVO对象,其中包含错误码和错误信息。 BusinessException则是一个自定义的异常类,它包含一个code属性和一个message属性,用于表示异常的错误码和错误信息。同时,它还提供了一个构造方法,可以根据ExceptionEnum来构造一个BusinessException对象。 ExceptionEnum则是一个枚举类,包含了不同的异常类型,每个异常类型都有一个对应的错误码和错误信息。 在实际开发中,我们可以根据实际需求来定义不同的异常类型和错误码,以便更好地管理和调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值