Dubbo consumer catches custom exceptions thrown by service provider provider

Keywords: Dubbo Java Redis xml

Define an exception class in a common package that inherits from RuntimeException.

public class BusinessException extends RuntimeException {
	/**
     * Abnormal 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;
	}
}

Add the following to the service provider's Dubbo configuration file, which is mainly about customizing exceptionFilter, and then discharging the exceptionFilter that comes with dubbo.

<?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 is configured to have this persistent error and changed to http://code.alibabatech.com/schema/dubbo/dubbo.xsd->

    <! - Used to configure current application information, whether the application is a provider or a consumer - >
    <dubbo:application  name="dubbo-web-provide"/>
    <! - Used to configure connection registry related information - >
    <dubbo:registry address="zookeeper://localhost:2181" timeout="30000">
        <! - Configure redis connection parameters - >
        <! -- See 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>

    <!--
    The most important thing is the following configuration: customize exceptionFilter, and then exclude the exceptionFilter that comes with dubbo
    payload sets the maximum value of transmission
    -->
    <dubbo:provider filter="dubboExceptionFilter,-exception" payload="123886080" ></dubbo:provider>

    <! - Protocol information used to configure service delivery, which is designated by the provider and passively accepted by the consumer - >.
    <dubbo:protocol name="dubbo" port="20880" accesslog="true" serialization="hessian2" />

    <! - Implementation Class - >
    <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" />

    <! - Define the interface of exposed service, which can be used to expose a service and define the meta-information of the service. A service can be exposed by multiple protocols, and a service can also be registered with multiple registries - >.
    <! - Each interface should define a version number to make it possible for subsequent incompatible upgrades - >
    <! - ref: The Real Implementation Class of Services
    <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>

    Monitor Center Configuration Monitor Center Protocol, if it is protocol="registry", means to find the address of the Monitor Center from the Registry, otherwise directly connect to the Monitor Center. >
    <!--<dubbo:monitor protocol="registry"></dubbo:monitor>-->
    <! - Direct connection to the server address of the monitoring center - >
    <!-- <dubbo:monitor address="localhost:6379"></dubbo:monitor> --> 
</beans>

The most important inheritance is ExceptionFilter, and then rewrite the invoke method

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;

/**
 * Functional description: <br/>
 *
 * @Java_supermanNO1[2019]
 * @2019/9/25 
 */

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();

                    // Customized exceptions
                    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;
        }
    }

}

The exception can then be thrown directly by the provider and captured directly by the consumer. The consumer service consumer can create a new controller for global exception handling, which can be formatted and output to the front end.

Java_supermanNO1: Focus on Java development technology research and knowledge sharing!

--END--

-Like (hard to edit, thank you for your support)
- ...
- Forwarding (Sharing Knowledge, Spreading Happiness)
- ...
- Focus on (updating Java development technology every day)
- ...

Posted by echo64 on Wed, 25 Sep 2019 00:58:17 -0700