dubbo~全局异常拦截器的使用与设计缺陷~续

dubbo · 浏览次数 : 9

小编点评

本文将介绍如何使用Dubbo框架统一捕获异常并添加自定义异常处理器。首先,我们需要了解异常处理的流程。当Dubbo的_provider端抛出异常时,会经过ExceptionFilter拦截器,然后执行onResponse方法。在这个过程中,我们可以自定义filter来包裹自定义异常,以便在Mapper中进行统一的捕获。 步骤如下: 1. 创建自定义异常处理器(如CustomExceptionFilter)。 2. 在资源的META-INF/services目录下创建dubbo/provider过滤器配置文件,注册自定义过滤器(如com.xxx.register.exception.filter.CustomExceptionFilter)。 3. 在dubbo.protocols.http.extension配置中指定自定义异常处理器(如com.xxx.register_exception.mapper.CustomExceptionMapper)。 4. 在Mapper中实现统一的异常捕获。 示例代码如下: 1. 自定义异常处理器(CustomExceptionFilter.java): ```java public class CustomExceptionFilter implements Filter, BaseFilter.Listener { public void onResponse(Result appResponse, Invoker invoker, Invocation invocation) { Exception exception = appResponse.getException(); String className = exception.getClass().getName(); // 本项目的异常也直接抛出 if (className.startsWith("com.myself.")) { appResponse.setException(new RuntimeException(exception)); return; } // 其它原来ExceptionFilter中的代码 } } ``` 2. 注册自定义过滤器: 在`src/main/resources/META-INF/dubbo`目录下创建`org.apache.dubbo.rpcFilter` 文件夹,然后在文件夹内创建一个名为`customExceptionFilter`的文件,内容如下: ``` com.xxx.register.exception.filter.CustomExceptionFilter ``` 3. 配置dubbo提供商端的过滤器: 在`src/main/resources/application.properties`文件中添加以下配置: ``` dubbo.provider.filter=customExceptionFilter,-exception ``` 其中,`-exception`表示去除默认的异常处理器,只使用自定义异常处理器。 4. 实现自定义异常处理器: 创建一个名为`CustomExceptionMapper`的接口: ```java import com Xxx.Register.ExceptionMapper; public interface CustomExceptionMapper extends ExceptionMapper { Response toResponse(RuntimeException exception); } ``` 然后在实现类中添加自定义异常处理逻辑: ```java import com Xxx.Register.ExceptionMapper; import com Xxx.Register.ExceptionMapper.DefaultExceptionMapper; import com Xxx.RequestContext; import com Xxx.Response; import com Xxx.RpcContext; import com Xxx.model.User; import org.springframework.stereotype.Component; @Component public class CustomExceptionMapper implements ExceptionMapper { @Override public Response toResponse(RuntimeException ex) { // 自定义异常处理逻辑 // 本项目中可以根据实际情况处理异常,例如记录日志、通知服务等 return new Response<>(); } @Override public boolean isDefault(Exception ex) { return false; } } ``` 根据以上步骤,我们可以在Dubbo框架中统一捕获并处理自定义异常。

正文

上一次的介绍,主要围绕如何统一去捕获异常,以及为每一种异常添加自己的Mapper实现,并且我们知道,当在ExceptionMapper中返回非200的Response,不支持application/json的响应类型,而是写死的text/plain类型。

Filter为二方包异常手动捕获

参考:https://blog.csdn.net/2401_84048290/article/details/138105184

我们来看看dubbo的源码进行分析,如果Dubbo的provider端 抛出异常(Throwable),则会被 provider端 的ExceptionFilter拦截到,执行以下invoke方法,里面有个实现Listener类,重写了onResponse,我们可以自定义filter来覆盖原来的ExceptionFilter,把自定义的异常通过RuntimeException进行包裹,然后在Mapper中进行统一的捕获。

  • 添加CustomExceptionFilter类型,实现Filter和BaseFilter.Listener,重写onResponse方法,添加自定义代码,如下:
public class CustomExceptionFilter implements Filter, BaseFilter.Listener {
    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
        	exception = appResponse.getException();
				String className = exception.getClass().getName();

				// 本项目的异常也直接抛出
				if (className.startsWith("com.myself.")) {
					appResponse.setException(new RuntimeException(exception));
					return;
				}
				// 其它原来ExceptionFilter中的代码
    }
}
  • META-INF中注册这个过滤器resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter
customExceptionFilter=com.xxx.register.exception.filter.CustomExceptionFilter
  • 配置中文中注册,并移除默认的resources/application.properties
# 自定义过滤器,上面-exception就是dubbo默认的处理异常的filter,前面-号就代表去除,注意:不需要加双引号
dubbo.provider.filter=customExceptionFilter,-exception

一个Mapper处理所有自定义异常

  • 配置文件中指定mapper,resources/application.properties
dubbo.protocols.http.extension=com.xxx.register.exception.mapper.CustomExceptionMapper
  • mapper源码如下
@Provider
public class DbViolationExceptionMapper implements ExceptionMapper<RuntimeException> {

	@Override
	public Response toResponse(RuntimeException exception) {
		Map<String, String> map = MapUtil.<String, String>builder().put("error", exception.getMessage()).build();
		if (exception.getCause() instanceof ForbiddenException) {
			return Response.status(Response.Status.FORBIDDEN).entity(map).type(MediaType.APPLICATION_JSON).build();
		}
		if (exception.getCause() instanceof CustomException) {
			return Response.status(Response.Status.BAD_REQUEST).entity(map).type(MediaType.APPLICATION_JSON).build();
		}
		if (exception.getCause() instanceof IdentityBrokerException) {
			return Response.status(Response.Status.UNAUTHORIZED).entity(map).type(MediaType.APPLICATION_JSON).build();
		}
		if (exception.getCause() instanceof UniqueException) {
			return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(map).type(MediaType.APPLICATION_JSON)
					.build();
		}
		return Response.status(Response.Status.SERVICE_UNAVAILABLE)
				.entity(MapUtil.builder().put("error", exception.getMessage()).build()).type(MediaType.APPLICATION_JSON)
				.encoding("utf-8").build();// 非200的请求,这个type无效,一直是text/plain

	}

}

未解决的问题

  • 目前非200的请求,toResponse时,响应类型还是text/plain

与dubbo~全局异常拦截器的使用与设计缺陷~续相似的内容:

dubbo~全局异常拦截器的使用与设计缺陷~续

上一次的介绍,主要围绕如何统一去捕获异常,以及为每一种异常添加自己的Mapper实现,并且我们知道,当在ExceptionMapper中返回非200的Response,不支持application/json的响应类型,而是写死的text/plain类型。 Filter为二方包异常手动捕获 参考:ht

dubbo~全局异常拦截器的使用与设计缺陷

异常拦截器ExceptionMapper 在JAX-RS(Java API for RESTful Web Services)中,ExceptionMapper接口用于将Java异常映射到HTTP响应。通过实现ExceptionMapper接口,你可以自定义如何处理特定类型的异常,并生成相应的HTT

深入理解java和dubbo的SPI机制

1 SPI简介 1.1 SPI(Service Provider Interface) 本质:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。 java SPI:用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我

Spring Cloud微服务核心架构分析

Spring Cloud是一个相对比较成熟的微服务框架。虽然,Spring Cloud于2016年才推出1.0的release版本, 时间最短, 但是相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案。 Spring Cloud是一系列框架的有序集合。它利用Spri

面试官:Dubbo一次RPC请求经历哪些环节?

大家好,我是三友~~ 今天继续探秘系列,扒一扒一次RPC请求在Dubbo中经历的核心流程。 本文是基于Dubbo3.x版本进行讲解 一个简单的Demo 这里还是老样子,为了保证文章的完整性和连贯性,方便那些没有使用过的小伙伴更加容易接受文章的内容,这里快速讲一讲Dubbo一个简单的Demo 如果你已

哈啰面试:说说Dubbo运行原理?

Dubbo 是一款高性能、轻量级的开源 RPC(远程过程调用)框架,主要用于构建分布式服务和微服务架构。那 Dubbo 又是如何运行的呢?让我们一起来看。 1.核心组件 要说 Dubbo 运行流程就不得不先来了解一下 Dubbo 的核心组件了,因为 Dubbo 的交互流程是和核心组件息息相关的。 D

dubbo~javax.validation和jakarta.validation的介绍与排雷

javax.validation和jakarta.validation都是用于Java中进行数据验证(validation)的相关API,它们提供了一套标准的验证框架,用于验证Java对象的属性是否符合指定的约束条件。这两个API的作用类似,只是在Java EE平台的演进过程中发生了一些变化。 ja

Dubbo 中 Zookeeper 注册中心原理分析

本文通过分析Dubbo中ZooKeeper注册中心的实现ZooKeeperResitry的继承体系结构,详细介绍了Dubbo中ZooKeeper注册中心的实现原理。

Dubbo架构设计与源码解析(一) 架构设计

作者:黄金 一、架构演变 单应用架构 > 垂直架构 > 分布式架构 > 微服务架构 > 云原生架构   二、Dubbo总体架构   1、角色职能 • Container:服务容器 (tomcat、jetty、weblogic) • Provider:服务提供者 •Consumer:服务消

Dubbo架构设计与源码解析(三)责任链模式

作者:周可强 一、责任链模式简介 1、责任链模式定义 责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。