Spring Cloud(2020.0.3) | 从入门到入土 - 21. Gateway 配置全局异常

一、前言

之前我们说断言规则的时候,在进行调用的过程中出现了 trace 报错。

但是默认的话是返回的一个 HTML 页面,这对于我们前后端分离式开发是没有用的,我们需要的是返回给前段一段错误 JSON 信息。

有的人可能会问了,SpringBoot 中不是给我们带了一个 @ControllerAdvice 的注解进行配置异常信息返回吗,为啥还要在 Gateway 中进行全局异常配置?

来看这个图,如果我们在服务层进行逻辑处理,或者是和数据库进行操作的时候报错了,我们是可以通过 @ControllerAdvice 注解所配置的异常处理进行返回。但是!!!

如果我们的服务是在 Gateway 进行请求的时候发生了错误呢?好比之前我们的 404 没有找到服务,那么我们的 @ControllerAdvice 是没有办法捕获到错误进行处理的,所以我们可以在所有微服务上层也就是 Gateway 中进行统一配置。

二、Gateway 全局异常配置

首先去创建一个 GatewayExceptionHandler 类,这个类需要实现 ErrorWebExceptionHandler 接口。ErrorWebExceptionHandler 接口是 Gateway 最核心接口,所以我们实现这个接口即可。

@Order(-1)
@Configuration
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {

	public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
		ServerHttpResponse response = exchange.getResponse();
		
		if(response.isCommitted()) {
			return Mono.error(ex);
		}
		
		String msg;
		
		if (ex instanceof NotFoundException) {
            msg = "服务未找到";
        } else if (ex instanceof ResponseStatusException) {
            ResponseStatusException responseStatusException = (ResponseStatusException) ex;
            msg = responseStatusException.getMessage();
        } else {
            msg = "内部服务器错误";
        }
		
		return ServletUtil.webFluxResponseWriter(response, msg);
	}
	
}

简单解释一下代码~~~

首先是第一个判断,如果是 response 已经提交响应了,那么我们是直接返回 Mono 的错误信息。如果没有提交,我们就去看这个错误信息是什么,将错误信息赋值给 msg 对象,并且使用 webFluxResponseWriter 写回客户端即可。

接着再来一个工具类。

public class ServletUtil {

	/**
     * 设置webflux模型响应
     *
     * @param response ServerHttpResponse
     * @param value 响应内容
     * @return Mono<Void>
     */
    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String value) {
        return webFluxResponseWriter(response, HttpStatus.OK, value, 500);
    }

    /**
     * 设置webflux模型响应
     *
     * @param response ServerHttpResponse
     * @param code 响应状态码
     * @param value 响应内容
     * @return Mono<Void>
     */
    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String value, int code) {
        return webFluxResponseWriter(response, HttpStatus.OK, value, code);
    }

    /**
     * 设置webflux模型响应
     *
     * @param response ServerHttpResponse
     * @param status http状态码
     * @param code 响应状态码
     * @param value 响应内容
     * @return Mono<Void>
     */
    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, String value, int code) {
        return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
    }

    /**
     * 设置webflux模型响应
     *
     * @param response ServerHttpResponse
     * @param contentType content-type
     * @param status http状态码
     * @param code 响应状态码
     * @param value 响应内容
     * @return Mono<Void>
     */
    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, String value, int code) {
        response.setStatusCode(status);
        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
        String result = ResultUtil.resultToString(Result.error(value));
        DataBuffer dataBuffer = response.bufferFactory().wrap(result.getBytes());
        return response.writeWith(Mono.just(dataBuffer));
    }

工具类比较简单,就是将错误信息写出去。(Result 这个类,自己去弄,实在不行就自己弄个 Map 对象去用)。

写好之后其实我们可以测试一下。

我这里测试是使用 Weight 权重断言模式下进行测试的,可以使用 After、Before、Between 模式测试 404 之类的。

三、WebFlux 响应式编程

上面工具类中我们配置了一个东西:Webflux 模型响应。这里我们来简单介绍一下这是什么玩意。

1. Webflux

Webflux,它是 Spring 5.0 中发布的一个重量级组件,并拉起了响应式编程的规模使用序幕。

我们最开始使用的是 Spring MVC 这种同步阻塞式的调用,但是这种请求模式是有着很大的弊端,就是没有太大的吞吐量,而这也就意味着用户需要等待~~~

而 Webflux 的推出,使得这个问题有了很大的改善。

该组件是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统吞吐量。

注意!Webflux 的出现,并不是替代之前的 Spring MVC,而是各有各的作用,相互不影响。

2. 响应式编程

我们通过一个简单的 Java 代码来讲述什么是响应式编程。

public static void main(String[] args) {
		int a = 1;
		int b = 2;
		int c = a + b;
		System.out.println(c);
	}

代码很简单,声明变量 a、b、c,最后输出 c 的值,c 是 3。当然这个没有啥可以说的,好比我们在定义 c 之后,操作 b 的值,那么 c 还会变吗?

答案是:不会变。

上面的这个案例其实就是我们经常写的命令式编程,但如果上面的代码是响应式编程的,那么最后输出的 c 不是 3,而是 4。

在计算机中,响应式编程或反应式编程(英语:Reactive programming)是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。

响应式编程是基于异步和事件驱动的非阻塞程序,只需要在程序内启动少量线程扩展,而不是水平通过集群扩展。

用大白话讲,我们以前编写的大部分都是阻塞类的程序,当一个请求过来时任务会被阻塞,直到这个任务完成后再返回给前端;响应式编程接到请求后只是提交了一个请求给后端,后端会再安排另外的线程去执行任务,当任务执行完成后再异步通知到前端。

3. Reactor

说到响应式编程,就必须要提一个东西,Reactor!

Reactor 是一个基于 JVM 之上的异步应用基础库,为 Java 、Groovy 和其他 JVM 语言提供了构建基于事件和数据驱动应用的抽象库。而且正如它的名称一样,它在最新的硬件平台上,使用无堵塞分发器每秒钟可处理 1500 万个事件。

Reactor 中有两个非常重要的东西,Flux 和 Mono。

4. Flux 和 Mono

Reactor 中的发布者(Publisher)由 Flux 和 Mono 两个类定义,它们都提供了丰富的操作符(operator)。

一个 Flux 对象代表一个包含 0…N 个元素的响应式序列,而一个 Mono 对象代表一个包含零/一个(0…1)元素的结果。

既然是“数据流”的发布者,Flux和Mono都可以发出三种“数据信号”:元素值、错误信号、完成信号。

错误信号和完成信号都是终止信号,完成信号用于告知下游订阅者该数据流正常结束,错误信号终止数据流的同时将错误传递给下游订阅者。

当然,这个东西比较复杂,能理解就理解,理解不了就慢慢去理解好了,推荐是找几本书看。


这一讲就讲到这里,有问题可以联系我:QQ 2100363119,欢迎大家访问我的个人网站:https://www.lemon1234.com

Gateway 全局配置是参考的若依代码,感谢若依开源~

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

他 他 = new 他()

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值