当前位置: 首页 > 知识库问答 >
问题:

用Spring云网关处理全局异常

闾丘晨
2023-03-14

我正在使用Spring Cloud Gateway Greenwich.sr1和Spring Boot 2.1.5。我正试图为我的下游服务创建一个网关。网关的部分工作是为下游请求提供全局错误页。当下游服务返回HTTP 403响应时,我希望网关提供一个合适的错误页面。

public class ForbiddenFilterFactory extends AbstractGatewayFilterFactory<Object> {

    @Override
    public String name() {
        return "Forbidden";
    }

    @Override
    public GatewayFilter apply(Object o) {
        return (exchange, chain) -> chain.filter(exchange).then(
                Mono.defer(() -> {
                    if (!exchange.getResponse().isCommitted() &&
                            HttpStatus.FORBIDDEN.equals(exchange.getResponse().getStatusCode())) {
                        return Mono.error(new ResponseStatusException(HttpStatus.FORBIDDEN));
                    }
                    return Mono.empty();
                }));
    }
}

有没有不同的方法让它起作用?

共有1个答案

燕钟展
2023-03-14

我通过使用自定义的ServerHttpResponseDecorator解决了这个问题。代码的关键部分是覆盖WriteWith方法以提供自定义正文:

ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
    @Override
    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
        if (shouldServeErrorPage(exchange)) {
            exchange.getResponse().getHeaders().setContentLength(-1);
            return errorWebExceptionHandler.handle(exchange, new ResponseStatusException(getHttpStatus(exchange)));
        } else {
            return getDelegate().writeWith(body);
        }
    }

    @Override
    public Mono<Void> writeAndFlushWith(
            Publisher<? extends Publisher<? extends DataBuffer>> body) {
        if (shouldServeErrorPage(exchange)) {
            return writeWith(Flux.from(body).flatMapSequential(p -> p));
        } else {
            return getDelegate().writeAndFlushWith(body);
        }
    }

    private boolean shouldServeErrorPage(ServerWebExchange exchange) {
        HttpStatus statusCode = getHttpStatus(exchange);
        return statusCode.is5xxServerError() || statusCode.is4xxClientError();
    }
};

return chain.filter(exchange.mutate().response(responseDecorator).build());

我在https://github.com/tine2k/scg-global-error-page上推送了一个工作示例

 类似资料:
  • 我有一个SpringCloudGateway应用程序,它充当我的数据服务的网关。我的应用程序使用SSE在UI中推送通知。当我看到网关日志时,我的日志中充满了异常,如: 我有一个错误处理程序类: 但它仍在记录错误。如何使我的网关不写入日志。 我的pom文件是: 我的依赖关系树:

  • 我对spring mvc非常陌生抱歉,如果我问的是一个基本问题,我需要在我的spring 4 MVC,Jersey项目中维护全局异常处理,并向IOS移动应用程序返回JSON响应。现在,通过使用@ControllerAdvice和@ExceptionHandler,我创建了一个如下所示的类 请建议,如果上述方法是正确的,或有任何替代方法来处理所有发生在控制器,服务和DAO层的异常。

  • 统一错误处理 文档:https://eggjs.org/zh-cn/tutorials/restful.html 自定义一个异常基类 // app / exceptions / http_exceptions.js class HttpExceptions extends Error { constructor(msg='服务器异常', code=1, httpCode=400) {

  • Middleware: 全局异常处理 我们在岩浆的实例其实已经注意到了,compose 的连接方式,让我们有能力精确控制异常。 Koa中间件最终行为强依赖注册顺序,比如我们这里要引入的异常处理,必须在业务逻辑中间件前注册,才能捕获后续中间件中未捕获异常,回想一下我们的调度器实现的异常传递流程。 <?php class ExceptionHandler implements Middleware

  • 我想要一些关于如何实现以下目标的建议。我不提供代码,因为我的问题是理论上的,但应要求我可以。所以情况是这样的: 我有多个控制器,每个控制器都可以抛出XYException 我有一个@ControllerAdvice类,其中有一个@ExceptionHandler监视XYExceptions。当它发生时,它打印出“xy”。 在一个(且仅有一个)控制器中,当抛出XYException时,我希望执行一些

  • 使用Spring Boot有几种方法可以解决这个问题。并且我选择将@ControllerAdvice与@ExceptionHandler方法一起使用。 因此,当抛出异常时,新的处理程序会捕获异常并返回一个包含消息的漂亮的json,如: 实施-没那么难。最难的部分是测试。 欢迎有任何想法。谢谢你!