【深入解析spring cloud gateway】07 自定义异常返回报文

这篇具有很好参考价值的文章主要介绍了【深入解析spring cloud gateway】07 自定义异常返回报文。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Servlet的HttpResponse对象,返回响应报文,一般是这么写的,通过输出流直接就可以将返回报文输出。

OutputStream out = response.getOutputStream();
out.write("输出的内容");
out.flush();

在filter中如果发生异常(例如请求参数不合法),抛出异常信息的时候,调用方收到的返回码和body都是Spring Cloud Gateway框架处理来处理的。这一节我们分析一下,gateway的异常返回报文是怎么返回的,并定义一个自己的异常返回报文格式。

一、先定义一个Filter,直接抛出异常

定义一个直接抛出异常的filter

public class ExceptionFilter implements GlobalFilter, Ordered {

    @Override    
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        throw new IllegalArgumentException("参数不合法");    }

    @Override    
    public int getOrder() {
        return 0;    
    }
}

异常抛出如下图
【深入解析spring cloud gateway】07 自定义异常返回报文,深入解析析SpringCloud Gateway,spring cloud,gateway

json内容如下:

{
    "timestamp": "2023-08-28T03:55:02.380+00:00",
    "path": "/hello-service/hello",
    "status": 500,
    "error": "Internal Server Error",
    "requestId": "0204dca5-1"
}

二、源码分析

上节我们分析了核心流程。在整个核心流程中,我们并没有关注有异常的情况。
入口HttpWebHandlerAdapter调用的delegate实际上就是:DefaultErrorWebExceptionHandler
【深入解析spring cloud gateway】07 自定义异常返回报文,深入解析析SpringCloud Gateway,spring cloud,gateway

代码如下:

@Override
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
    //省略部分代码
    return getDelegate().handle(exchange)
            .doOnSuccess(aVoid -> logResponse(exchange))
            .onErrorResume(ex -> handleUnresolvedError(exchange, ex))
            .then(Mono.defer(response::setComplete));
}

进入DefaultErrorWebExceptionHandler的handle方法,分析见注释

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
    Mono<Void> completion;
    try {
 //正常的处理流程
        completion = super.handle(exchange);
    }
    catch (Throwable ex) {
        completion = Mono.error(ex);
    }
//产生异常的情况,由异常处理器来进行处理
    for (WebExceptionHandler handler : this.exceptionHandlers) {
        completion = completion.onErrorResume(ex -> handler.handle(exchange, ex));
    }
    return completion;
}

如果产生异常的情况,由异常处理器来进行处理,这个异常处理器是一个列表。
而异常处理器最核心的就是这个:DefaultErrorWebExceptionHandler
其handle方法如下

@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {
    if (exchange.getResponse().isCommitted() || isDisconnectedClientError(throwable)) {
        return Mono.error(throwable);
    }
    this.errorAttributes.storeErrorInformation(throwable, exchange);
    ServerRequest request = ServerRequest.create(exchange, this.messageReaders);
    return getRoutingFunction(this.errorAttributes).route(request)
        .switchIfEmpty(Mono.error(throwable))
        .flatMap((handler) -> handler.handle(request))
        .doOnNext((response) -> logError(request, response, throwable))
        .flatMap((response) -> write(exchange, response));
}

跟到getRoutingFunction里面看看

@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
    return route(acceptsTextHtml(), this::renderErrorView).andRoute(all(), this::renderErrorResponse);
}

最终跟到下面的这个方法:renderErrorResponse,从下面的截图可以看到,error Map这个对象,正是报文体的格式
【深入解析spring cloud gateway】07 自定义异常返回报文,深入解析析SpringCloud Gateway,spring cloud,gateway

如果我们想自定义一个异常响应的返回报文,如下,应该怎么弄呢?

{
    "returnCode": "ERROR",
    "errorMsg": "参数异常",
    "body": null
}

我们实际上可以继承DefaultErrorWebExceptionHandler,并且实现其renderErrorResponse方法就可以了。
可以看到DefaultErrorWebExceptionHandler,是通过下面的方式注入到容器的,如果我们也定义一个也注册到容器,那么就会覆盖原有的实现
【深入解析spring cloud gateway】07 自定义异常返回报文,深入解析析SpringCloud Gateway,spring cloud,gateway

整体流程图如下:

【深入解析spring cloud gateway】07 自定义异常返回报文,深入解析析SpringCloud Gateway,spring cloud,gateway

三、自定义异常处理器

1、定义一个产生异常的filter,模拟产生异常

@Slf4j
public class ExceptionFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("filter产生了异常");
        throw new IllegalArgumentException("参数不合法");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

2、自定义异常处理器

/**
 * 自定义异常处理器
 */
public class CustomErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    public CustomErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties.Resources resources, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resources, errorProperties, applicationContext);
    }

    @Override
    protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        // 最终是用responseBodyMap来生成响应body的
        Map<String, Object> responseBodyMap = new HashMap<>();

        // 这里和父类的做法一样,取得DefaultErrorAttributes整理出来的所有异常信息
        Map<String, Object> error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));

        // 原始的异常信息可以用getError方法取得
        Throwable throwable = getError(request);

        responseBodyMap.put("returnCode", "my error code");
        responseBodyMap.put("errorMsg", throwable.getMessage());
        responseBodyMap.put("body", null);
        return ServerResponse
                // http返回码
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                // 类型和以前一样
                .contentType(MediaType.APPLICATION_JSON)
                // 响应body的内容
                .body(BodyInserters.fromValue(responseBodyMap));
    }
}

3、注册异常处理器

@Configuration(proxyBeanMethods = false)
public class ExceptionHandlerConfig {
    private final ServerProperties serverProperties;

    public ExceptionHandlerConfig(ServerProperties serverProperties) {
        this.serverProperties = serverProperties;
    }

    @Bean
    public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes,
                                                             WebProperties webProperties, ObjectProvider<ViewResolver> viewResolvers,
                                                             ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) {
        CustomErrorWebExceptionHandler exceptionHandler = new CustomErrorWebExceptionHandler(errorAttributes,
                webProperties.getResources(), this.serverProperties.getError(), applicationContext);
        exceptionHandler.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));
        exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }
}

4、请求效果
【深入解析spring cloud gateway】07 自定义异常返回报文,深入解析析SpringCloud Gateway,spring cloud,gateway文章来源地址https://www.toymoban.com/news/detail-695683.html

到了这里,关于【深入解析spring cloud gateway】07 自定义异常返回报文的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【深入解析spring cloud gateway】04 Global Filters

    上一节学习了GatewayFilter。 回忆一下一个关键点: GateWayFilterFactory的本质就是:针对配置进行解析,为指定的路由,添加Filter,以便对请求报文进行处理。 GlobalFilter又是啥?先看一下接口定义 再看一下GatewayFilter 可以看到GatewayFilter和GlobalFilter方法签名是一模一样的,那为啥又

    2024年02月09日
    浏览(38)
  • 【深入解析spring cloud gateway】08 Reactor 知识扫盲

    1.1 背景知识 为了应对高并发服务器端开发场景,在2009 年,微软提出了一个更优雅地实现异步编程的方式——Reactive Programming,我们称之为响应式编程。随后,Netflix 和LightBend 公司提供了RxJava 和Akka Stream 等技术,使得Java 平台也有了能够实现响应式编程的框架。 在2017 年9 月

    2024年02月09日
    浏览(39)
  • Spring-Cloud-Gateway修改请求(json,form带文件请求)参数,返回值参数

    新项目需要在getway统一做入参、出参加解密,记录日志。记录一下form,x-www-form-urlencoded , json 这几种修改数据的方式。 gateway做拦截器是实现GlobalFilter接口,修改json方式网上有很多文章,后来又想研究研究能不能实现修改form-data参数,以及文件请求,后者文章不多大部分是怎

    2024年02月16日
    浏览(47)
  • Spring-Cloud-Gateway如何自定义断言工厂?

    遇到这么一个面试题:如何在网关做配置,实现只有在早晨9点到下午18点之间接口才允许访问,其他时间访问都是404。 我们知道网关的一个重要的作用就是路由转发,路由表的配置大概是这个样子: 上面的id是路由的名称,uri是要路由到的目的地,predicates就是断言过滤条件,

    2024年02月16日
    浏览(48)
  • 吃透Spring Cloud gateway自定义错误处理Handler

    我们来学习和了解下GatewayExceptionHandler有助于我们处理spring gateway和webFlux中的异常自定义处理。它继承自ErrorWebExceptionHandler,类关系图如下: 通过类上述关系图,我们可以看到,DefaultErrorWebExceptionHandler是ErrorWebExceptionHandler的实现类,如果我们不自定义类异常处理器,系统将自

    2024年02月12日
    浏览(35)
  • Spring Cloud - 手写 Gateway 源码,实现自定义局部 FilterFactory

    目录 一、FilterFactory 分析 1.1、前置知识 1.2、分析源码 1.2.1、整体分析 1.2.2、源码分析 1.3、手写源码 1.3.1、基础框架 1.3.2、实现自定义局部过滤器 1.3.3、加参数的自定义局部过滤器器 前面的学习我们知道,GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服

    2024年02月03日
    浏览(43)
  • Spring-Cloud-Gateway如何自定义路由过滤器?

    遇到这么一个面试题:自定义网关过滤器实现把url中的请求参数放到http的header中传递给微服务。 我们知道网关的一个重要的作用就是路由转发,路由表的配置大概是这个样子: 其中的filters就是配置的路由过滤器,Spring已经内置了31个路由的过滤器,这些过滤器都是 org.spring

    2024年02月16日
    浏览(40)
  • spring cloud gateway自定义负载均衡, 优先转发到指定IP

    示例为优先将请求分配到指定IP, 如果指定IP没有服务, 则随机分配. GatewayLoadBalancerConfiguration.java 挂载配置类, 可以通过 @org.springframework.boot.autoconfigure.condition.ConditionalOnXXX 或者 @Profile 注解或者@ComponentScan过滤等方式来配置是否启用 在任意一个@Configuration注解的类上配置均可 L

    2024年02月07日
    浏览(40)
  • 第九章 : Spring cloud 网关中心 Gateway (内置断言与自定义断言)

    第九章 : Spring cloud 网关中心 Gateway (内置断言与自定义断言) 前言 本章知识点:Spring cloud Gateway 内置断言(Predicate)类型的 yaml 和 json 数据格式;自定义路由Predicate 断言的案例。 Gateway 内置 Predicate 格式配置 概述 本文针对 Spring Cloud Gateway 框架中断言(Predicate)类型在 Yaml

    2024年01月17日
    浏览(37)
  • 【Spring Cloud】深入探索统一网关 Gateway 的搭建,断言工厂,过滤器工厂,全局过滤器以及跨域问题

    在微服务架构中,网关是至关重要的组件,具有多重职责,为整个系统提供了一系列关键功能。从下面的微服务结构图中,我们可以明确网关的几项主要作用: 微服务结构图: 请求过滤与安全: 用户的所有请求首先经过网关,这使得网关成为系统的第一道防线。通过对传入

    2024年02月07日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包