【第13章】Spring Cloud之Gateway全局异常处理


前言

网关作为我们对外服务的入口起着至关重要的作用,我们必须保证网关服务的稳定性,下面来为网关服务增加异常处理机制。


一、异常处理

1. 响应实体类

package org.example.common.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//统一响应结果
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
    private Integer code;//业务状态码  0-成功  1-失败
    private String title;//标题
    private String message;//提示信息
    private T data;//响应数据

    public Result(Integer code, String title, String message) {
        this.code = code;
        this.title = title;
        this.message = message;
    }

    public Result(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    //快速返回操作成功响应结果(带响应数据)
    public static <E> Result<E> success(E data) {
        return new Result<>(0, "操作成功", data);
    }

    public static <E> Result<E> success(String message,E data) {
        return new Result<>(0, message, data);
    }

    public static Result success(String message) {
        return new Result<>(0, message, null);
    }

    //快速返回操作成功响应结果
    public static Result success() {
        return new Result(0, "操作成功", null);
    }

    public static Result error(String message) {
        return new Result(1, message, null);
    }
    public static Result error(int code,String message) {
        return new Result(code, message, null);
    }
    public static Result error(int code,String title,String message) {
        return new Result(code,title , message);
    }
}

2. 异常处理类

这里针对性地处理了无可用路由和无可用服务两种场景异常,和一种铺地异常的处理,大家有自定义异常或其他异常可自行添加处理逻辑

package org.example.gateway.config;

import org.example.common.model.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.reactive.resource.NoResourceFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * Create by zjg on 2024/7/27
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    @ExceptionHandler(NoResourceFoundException.class)//无可用路由
    public Result exception(ServerHttpResponse response,NoResourceFoundException ex){
        String detail = ex.getBody().getDetail();
        String mark="resource ";
        String message = detail.substring(detail.indexOf(mark) + mark.length());
        setStatusCode(response,ex.getStatusCode());
        return  Result.error(ex.getStatusCode().value(),"无可用路由",String.format("没有可用的路由[%s]",message));
    }
    @ExceptionHandler(NotFoundException.class)//无可用服务
    public Result exception(ServerHttpResponse response,NotFoundException ex){
        logger.error(ex.getMessage());
        String detail = ex.getBody().getDetail();
        String mark="for ";
        String message = detail.substring(detail.indexOf(mark) + mark.length());
        setStatusCode(response,ex.getStatusCode());
        return  Result.error(ex.getStatusCode().value(),"服务不可用",String.format("没有可用的服务实例[%s]",message));
    }
    @ExceptionHandler(Exception.class)//异常保底
    public Result exception(ServerHttpResponse response,Exception exception){
        StringWriter stringWriter = new StringWriter();
        PrintWriter writer=new PrintWriter(stringWriter);
        exception.printStackTrace(writer);
        logger.error(stringWriter.toString());
        setStatusCode(response,HttpStatus.INTERNAL_SERVER_ERROR);
        return  Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(),exception.getMessage());
    }
    private void setStatusCode(ServerHttpResponse response,HttpStatusCode httpStatusCode){
        response.setStatusCode(httpStatusCode);
    }
}

二、单元测试

1. 无可用路由

curl 192.168.0.104:8888/provider/hello -H "Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9LCJpc3MiOiJhdXRoMCIsImV4cCI6MTcyMjE0NjE0MX0.IRlUZ5H_-PbPSbklqFGB1lOYquj0iifV2mhT-z68fhM"

在这里插入图片描述

2. 服务不可用

在这里插入图片描述


总结

回到顶部

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Gateway 提供了一种全局异常处理机制,它允许你在整个网关链路中统一管理和捕获错误。通过使用 `GlobalExceptionHandler` 或自定义拦截器,你可以配置如何处理来自下游服务的响应失败、路由错误或其他非预期的状况。 通常,全局异常处理的过程包括以下几个步骤: 1. **创建全局异常处理器**:在 Spring Boot 应用中,你可以创建一个实现了 `GlobalExceptionHandler` 接口的类,并覆盖其 `handle` 方法。这个方法接收 `WebExchange` 和 `Throwable` 参数,你可以在这里定制错误处理逻辑,如记录日志、返回统一的错误响应等。 ```java @Component public class GlobalExceptionHandler implements GlobalExceptionHandler { @Override public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { // 捕获异常并返回适当的响应 return handleException(exchange, new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage())); } } ``` 2. **应用配置**:在 Gateway 的配置中启用全局异常处理,并指定你的全局处理器类。例如,在 YAML 配置中添加如下内容: ```yaml spring: cloud: gateway: global-error-handler: com.example.GlobalExceptionHandler ``` 3. **错误响应处理**:`handleException` 方法可以根据需要决定返回何种状态码和错误信息给客户端。常见的做法是返回一个统一的 JSON 格式,比如包含错误码和描述的消息。 当你设置好全局异常处理后,无论内部服务出现何种类型的异常,Spring Cloud Gateway 都会按照你设定的方式进行处理,提供一个一致的服务响应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值