Dubbo消费者consumer捕捉服务提供者provider抛出的自定义异常

栏目: Java · 发布时间: 6年前

内容简介:在一个公共包里定义一个异常类,继承自RuntimeException。在服务提供者的Dubbo配置文件中添加下面的内容,主要就是自定义exceptionFilter,然后排出dubbo自带的exceptionFilter最重要的继承ExceptionFilter,然后重写invoke方法

在一个公共包里定义一个异常类,继承自RuntimeException。

public class BusinessException extends RuntimeException {

    /**
     * 异常code
     */
    private String code;

    public BusinessException() {
        super();
    }

    public BusinessException(String message) {
        super(message);
    }

    public BusinessException(String code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }

    public BusinessException(String code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    public BusinessException(Throwable cause) {
        super(cause);
    }


    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

在服务提供者的Dubbo配置文件中添加下面的内容,主要就是自定义exceptionFilter,然后排出dubbo自带的exceptionFilter

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
     http://code.alibabatech.com/schema/dubbo
     http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- http://dubbo.apache.org/schema/dubbo/dubbo.xsd 上面配置为这个一直报错,改为 http://code.alibabatech.com/schema/dubbo/dubbo.xsd -->

    <!--用于配置当前应用信息,不管该应用是提供者还是消费者 -->
    <dubbo:application  name="dubbo-web-provide"/>
    <!-- 用于配置连接注册中心相关信息 -->
    <dubbo:registry address="zookeeper://localhost:2181" timeout="30000">
        <!--配置 redis 连接参数 -->
        <!--具体参数配置见com.alibaba.dubbo.registry.redis.RedisRegistry.class -->
        <dubbo:parameter key="max.idle" value="10" />
        <dubbo:parameter key="min.idle" value="5" />
        <dubbo:parameter key="max.active" value="20" />
        <dubbo:parameter key="max.total" value="100" />
    </dubbo:registry>

    <!--
    最重要的就是下面的配置:自定义exceptionFilter,然后排出dubbo自带的exceptionFilter
    payload 设置传输的最大值
    -->
    <dubbo:provider filter="dubboExceptionFilter,-exception" payload="123886080" ></dubbo:provider>

    <!-- 用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受 -->
    <dubbo:protocol name="dubbo" port="20880" accesslog="true" serialization="hessian2" />

    <!-- 实现类 -->
    <bean id="helloService" class="cn.ydstudio.dubbo.web.provide.serviceimpl.HelloServiceImpl" />
    <bean id="goodsService" class="cn.ydstudio.dubbo.web.provide.serviceimpl.GoodsServiceImpl" />
    <bean id="goodsService2" class="cn.ydstudio.dubbo.web.provide.serviceimpl.GoodsServiceImpl2" />
    <bean id="goodsOrderServiceRemoteImpl" class="cn.ydstudio.dubbo.web.provide.serviceimpl.GoodsOrderServiceRemoteImpl" />

    <!--定义暴露服务的接口,用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心 -->
    <!--每个接口都应定义版本号,为后续不兼容升级提供可能 -->
    <!--ref:服务的真正实现类 -->
    <dubbo:service interface="cn.ydstudio.dubbo.rpc.service.HelloService" ref="helloService" version="1.0.0" retries="1"/>
    <dubbo:service interface="cn.ydstudio.dubbo.rpc.service.GoodsService" ref="goodsService" version="1.0.0" retries="1"/>
    <dubbo:service interface="cn.ydstudio.dubbo.rpc.service.GoodsService" ref="goodsService2" version="2.0.0" retries="1"/>
    <dubbo:service interface="cn.ydstudio.dubbo.rpc.service.GoodsOrderServiceRemote" ref="goodsOrderServiceRemoteImpl" version="1.0.0" retries="0" >
        <dubbo:method name="querGoodsOrderList" timeout="1000000"/>
    </dubbo:service>

    <!--监控中心配置 监控中心协议,如果为protocol="registry",表示从注册中心发现监控中心地址,否则直连监控中心。 -->
    <!--<dubbo:monitor protocol="registry"></dubbo:monitor>-->
    <!-- 直连监控中心服务器地址 -->
    <!-- <dubbo:monitor address="localhost:6379"></dubbo:monitor> --> 
</beans>

最重要的继承ExceptionFilter,然后重写invoke方法

package cn.ydstudio.dubbo.web.provide.filter;

import cn.ydstudio.common.tools.exception.BizException;
import cn.ydstudio.common.tools.exception.BusinessException;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.rpc.*;
import com.alibaba.dubbo.rpc.filter.ExceptionFilter;
import com.alibaba.dubbo.rpc.service.GenericService;

import java.lang.reflect.Method;

/**
 * 功能描述:<br/>
 *
 * @Author 刘洋【19037900】
 * @Date 2019/4/30 18:02
 */

public class DubboExceptionFilter extends ExceptionFilter {

    private final Logger logger;

    public DubboExceptionFilter() {
        this(LoggerFactory.getLogger(com.alibaba.dubbo.rpc.filter.ExceptionFilter.class));
    }

    public DubboExceptionFilter(Logger logger) {
        this.logger = logger;
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        try {
            Result result = invoker.invoke(invocation);
            if (result.hasException() && GenericService.class != invoker.getInterface()) {

                try {
                    Throwable exception = result.getException();

                    // 自定义的异常
                    if (exception instanceof BizException || exception instanceof BusinessException){
                        return result;
                    }

                    if (!(exception instanceof RuntimeException) && exception instanceof Exception) {
                        return result;
                    } else {
                        try {
                            Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());
                            Class<?>[] exceptionClassses = method.getExceptionTypes();
                            Class[] arr$ = exceptionClassses;
                            int len$ = exceptionClassses.length;

                            for (int i$ = 0; i$ < len$; ++i$) {
                                Class<?> exceptionClass = arr$[i$];
                                if (exception.getClass().equals(exceptionClass)) {
                                    return result;
                                }
                            }
                        } catch (NoSuchMethodException var11) {
                            return result;
                        }

                        this.logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);
                        String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
                        String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
                        if (serviceFile != null && exceptionFile != null && !serviceFile.equals(exceptionFile)) {

                            String className = exception.getClass().getName();
                            if (!className.startsWith("java.") && !className.startsWith("javax.")) {
                                return (Result) (exception instanceof RpcException ? result : new RpcResult(new RuntimeException(StringUtils.toString(exception))));
                            } else {
                                return result;
                            }
                        } else {
                            return result;
                        }
                    }
                } catch (Throwable var12) {
                    this.logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + var12.getClass().getName() + ": " + var12.getMessage(), var12);
                    return result;
                }
            } else {
                return result;
            }
        } catch (RuntimeException var13) {
            this.logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + var13.getClass().getName() + ": " + var13.getMessage(), var13);
            throw var13;
        }
    }

}

然后在provider可以直接抛出异常,在consumer可以直接捕捉到。consumer服务消费端可以新建一个全局异常处理的控制器,可以格式化后输出给前端。

最后更新于 2019-05-20 20:12:02 并被添加「dubbo 自定义异常」标签,已有 1 位童鞋阅读过。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Distributed Systems

Distributed Systems

Sukumar Ghosh / Chapman and Hall/CRC / 2014-7-14 / USD 119.95

Distributed Systems: An Algorithmic Approach, Second Edition provides a balanced and straightforward treatment of the underlying theory and practical applications of distributed computing. As in the p......一起来看看 《Distributed Systems》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换