dubbo全局统一异常处理

背景:对于dubbo服务,我们在调用provider提供的服务时,因为要考虑到provider服务的异常,所以往往会在consumer代码中大量使用 try{}catch(){},对于consumer,大量的捕获会显的项目臃肿、代码不够优雅,所以我们可以在provider构建一个全局异常捕获,将异常信息包装成统一的RESTful风格的返回值。dubbo全局捕获的实现方式有很多种,这次采用切面的方式进行处理,直接上代码:

/*
 * bq.com
 * Copyright (C) 2018-2020 All Rights Reserved.
 */
package com.alijk.bqhospital.common.aspect;

import com.alijk.bqhospital.client.exception.BusinessException;
import com.alijk.bqhospital.client.exception.ExceptionEnum;
import com.alijk.bqhospital.client.vto.response.base.Response;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 自定义dubbo异常处理
 *
 * @author liuyuan
 * @version DubboExceptionAspect.java, v 0.1 2020-09-28 20:35
 */
@Component
@Aspect
@Slf4j
public class DubboExceptionAspect {

    /**
     * 返回值类型为Response的Service
     */
    @Pointcut(value = "execution(public com.alijk.bqhospital.client.vto.response.base.* com.alijk.bqhospital.client.facade..*Facade*.*(..))")
    private void servicePointcut() {
    }

    /**
     * 任何持有@Transactional注解的方法
     */
    @Pointcut(value = "@annotation(org.springframework.transaction.annotation.Transactional)")
    private void transactionalPointcut() {
    }

    /**
     * 异常处理切面
     * 将异常包装为Response,避免dubbo进行包装
     *
     * @param pjp 处理点
     * @return Object
     */
    @Around("servicePointcut() && !transactionalPointcut()")
    public Object doAround(ProceedingJoinPoint pjp) {
        return this.processException(pjp);
    }

    /**
     * 任何持有@Transactional注解的方法异常处理切面
     * 将自定义的业务异常转为RuntimeException:
     * 1.规避dubbo的包装,让customer可以正常获取message
     * 2.抛出RuntimeException使事务可以正确回滚
     * 其他异常不处理
     *
     * @param pjp 处理点
     * @return Object
     */
    @Around("servicePointcut() && transactionalPointcut()")
    public Object doTransactionalAround(ProceedingJoinPoint pjp) {
        return this.processException(pjp);
    }

    /**
     * 处理异常
     *
     * @param pjp 切点
     * @return
     */
    private Object processException(ProceedingJoinPoint pjp) {
        Object[] args = pjp.getArgs();
        try {
            return pjp.proceed();
        } catch (BusinessException e) { // 自定义异常
            printlnException(pjp, args, e);
            return Response.error(e.getCode(), e.getMsg());
        } catch (Throwable e) {
            printlnException(pjp, args, e);
            return Response.error(ExceptionEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 异常信息打印
     *
     * @param joinPoint 切点
     * @param args      参数
     * @param throwable 异常
     */
    private void printlnException(final ProceedingJoinPoint joinPoint, final Object[] args, Throwable throwable) {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        String[] classNameArray = method.getDeclaringClass().getName().split("\\.");
        String methodName = classNameArray[classNameArray.length - 1] + "  >>> " + method.getName();

        String inputParam = "";
        if (args != null && args.length > 0) {
            StringBuilder sb = new StringBuilder();
            for (Object arg : args) {
                sb.append(",");
                sb.append(arg);
            }
            inputParam = sb.toString().substring(1);
        }
        log.warn("\n 方法: {}\n 入参: {} \n 异常: {}", methodName, inputParam, throwable.getMessage());
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值