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;
    }

}
相关文章
|
4月前
|
算法 NoSQL API
SpringCloud&Gateway网关限流
SpringCloud&Gateway网关限流
218 7
|
4月前
|
负载均衡 Nacos 数据安全/隐私保护
SpringCloud GateWay 使用
SpringCloud GateWay 使用
54 0
|
8天前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
19天前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
72 6
|
2月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
290 15
|
2月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
61 3
|
2月前
|
Java 微服务 Spring
SpringCloud gateway自定义请求的 httpClient
SpringCloud gateway自定义请求的 httpClient
112 3
|
2月前
|
JSON 前端开发 Java
SpringCloud怎么搭建GateWay网关&统一登录模块
本文来分享一下,最近我在自己的项目中实现的认证服务,目前比较简单,就是可以提供一个公共的服务,专门来处理登录请求,然后我还在API网关处实现了登录拦截的效果,因为在一个博客系统中,有一些地址是可以不登录的,比方说首页;也有一些是必须登录的,比如发布文章、评论等。所以,在网关处可以支持自定义一些不需要登录的地址,一些需要登录的地址,也可以在网关处进行校验,如果未登录,可以返回JSON格式的出参,前端可以进行相关处理,比如跳转到登录页面等。
|
2月前
|
缓存 监控 Java
通用快照方案问题之Spring Boot Admin的定义如何解决
通用快照方案问题之Spring Boot Admin的定义如何解决
45 0
|
3月前
|
Java API 网络架构
Spring Cloud Gateway的高级配置与实践
Spring Cloud Gateway的高级配置与实践