Gateway处理全局异常

简介: satoken 提供的示例,适用于单体项目的全局异常捕获。我选择了微服务架构,则就要变为通过网关来进行全局异常的处理,当权限发生异常的时候,可以统一做 401 的返回,前端进行跳转登录。

一. 建立网关全局异常处理器

package com.ac.club.gateway.auth;

import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.exception.SaTokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jingdianjichi.club.gateway.entity.Result;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
   

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
   
        ServerHttpRequest request = serverWebExchange.getRequest();
        ServerHttpResponse response = serverWebExchange.getResponse();
        Integer code = 200;
        String message = "";
        if(throwable instanceof SaTokenException){
   
            code = 401;
            message = "用户无权限";
        }else {
   
            code = 500;
            message = "服务器繁忙";
            throwable.printStackTrace();
        }
        Result result = Result.fail(code, message);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return response.writeWith(Mono.fromSupplier(()->{
   
            DataBufferFactory dataBufferFactory = response.bufferFactory();
            byte[] bytes = null;
            try {
   
                bytes = objectMapper.writeValueAsBytes(result);
            } catch (JsonProcessingException e) {
   
                e.printStackTrace();
            }
            return dataBufferFactory.wrap(bytes);
        }));
    }

}

二. 封装公共 Result

package com.ac.club.gateway.entity;

import lombok.Data;

@Data
public class Result<T> {
   

    private Boolean success;

    private Integer code;

    private String message;

    private T data;

    public static Result ok(){
   
        Result result = new Result();
        result.setSuccess(true);
        result.setCode(ResultCodeEnum.SUCCESS.getCode());
        result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
        return result;
    }

    public static <T> Result ok(T data){
   
        Result result = new Result();
        result.setSuccess(true);
        result.setCode(ResultCodeEnum.SUCCESS.getCode());
        result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
        result.setData(data);
        return result;
    }

    public static Result fail(){
   
        Result result = new Result();
        result.setSuccess(false);
        result.setCode(ResultCodeEnum.FAIL.getCode());
        result.setMessage(ResultCodeEnum.FAIL.getDesc());
        return result;
    }

    public static <T> Result fail(T data){
   
        Result result = new Result();
        result.setSuccess(false);
        result.setCode(ResultCodeEnum.FAIL.getCode());
        result.setMessage(ResultCodeEnum.FAIL.getDesc());
        result.setData(data);
        return result;
    }

    public static <T> Result fail(Integer code,String message){
   
        Result result = new Result();
        result.setSuccess(false);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

}

三. 封装状态码枚举类

package com.ac.club.gateway.entity;

import lombok.Getter;

@Getter
public enum ResultCodeEnum {
   

    SUCCESS(200,"成功"),
    FAIL(500,"失败");

    public int code;

    public String desc;

    ResultCodeEnum(int code,String desc){
   
        this.code = code;
        this.desc = desc;
    }

    public static ResultCodeEnum getByCode(int codeVal){
   
        for(ResultCodeEnum resultCodeEnum : ResultCodeEnum.values()){
   
            if(resultCodeEnum.code == codeVal){
   
                return resultCodeEnum;
            }
        }
        return null;
    }

}
相关文章
|
2月前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
157 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
2月前
|
JavaScript Java Kotlin
深入 Spring Cloud Gateway 过滤器
Spring Cloud Gateway 是新一代微服务网关框架,支持多种过滤器实现。本文详解了 `GlobalFilter`、`GatewayFilter` 和 `AbstractGatewayFilterFactory` 三种过滤器的实现方式及其应用场景,帮助开发者高效利用这些工具进行网关开发。
299 1
|
3月前
|
负载均衡 Java API
项目中用的网关Gateway及SpringCloud
Spring Cloud Gateway 是一个功能强大、灵活易用的API网关解决方案。通过配置路由、过滤器、熔断器和限流等功能,可以有效地管理和保护微服务。本文详细介绍了Spring Cloud Gateway的基本概念、配置方法和实际应用,希望能帮助开发者更好地理解和使用这一工具。通过合理使用Spring Cloud Gateway,可以显著提升微服务架构的健壮性和可维护性。
78 0
|
5月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
5月前
|
负载均衡 Java 网络架构
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
227 5
|
5月前
|
Java 开发者 Spring
Spring Cloud Gateway 中,过滤器的分类有哪些?
Spring Cloud Gateway 中,过滤器的分类有哪些?
116 3
|
4月前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
75 0
|
5月前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
322 6
|
7月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
728 15
|
7月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
151 3