GateWay网关异常处理

使用网关异常处理类来返回给前端错误信息的json数据,可处理的类别如全局过滤器、局部过滤器中校验失败的信息。如token信息的校验,没有token时的错误信息的返回,供前端进行相应处理!
步骤:皆在网关模块操作

  1. 创建自定义的异常类
//自定义异常.传入对应异常信息即可
public class IllegalTokenException extends RuntimeException {
    public IllegalTokenException(String message) {
        super(message);
    }
}
  1. 创建网关异常处理器
    场景:在网关过滤器中,token信息未通过校验的时候
/**
 * 网关全局异常处理器
 *  :处理网关过滤器、request、response出现问题的情况
 *  不合法参数问题*/
@Configuration
public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {
    //日志对象
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionConfiguration.class);
    @Override //参数1: request response   ex:出现异常时异常对象
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        //存放响应到response的数据
        Map<String, String> result = new HashMap<>(1);
        //1.获取响应对象
        ServerHttpResponse response = exchange.getResponse();
        //2.response是否结束  用于多个异常处理时候
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        //2.设置响应头类型
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        //3.设置响应状态吗
        if (ex instanceof IllegalTokenException) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
        } else {
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        //4.设置响应内容
        return response
                .writeWith(Mono.fromSupplier(() -> {
                    DataBufferFactory bufferFactory = response.bufferFactory();
                    log.error("msg:",ex);
                    result.put("msg", ex.getMessage());
                    ObjectMapper objectMapper = new ObjectMapper();
                    try {
                        //设置响应到response的数据
                        return bufferFactory.wrap(objectMapper.writeValueAsBytes(result));
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                        return null;
                    }
                }));
    }
}
  1. 在局部、全局过滤器中对相关不合法或异常情况进行手动抛出即可
/**
 * GateWay网关的局部过滤器
 *      检验请求有无参数name
 *      */
@Component
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
    /**使用日志纪记录相关信息*/
    private final static Logger log = LoggerFactory.getLogger(MyParamGatewayFilterFactory.class);

    public MyParamGatewayFilterFactory() {
        super(Config.class);
    }
    /**
     * 绑定Config类的参数的值为yaml中配置的值*/
    @Override
    public List<String> shortcutFieldOrder() {
        //指定把yaml配置的过滤器的值赋值给配置类的param属性。 - MyParam=name即param=name
        //如果Config中定义了多个属性时候传入即可。例如声明了config中有name和age  配置文件中为- MyParam=name,age
        //return Arrays.asList("param","age");
        return Arrays.asList("param");
    }
    /**
     * 过滤相关操作,定义自己的过滤逻辑。Config为配置类传来的yaml配置类中配置的局部过滤器的的参数的值*/
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            log.info("进入过滤器");
            // http://localhost:9090/admins/demos?name=yh 相当于config.param ==> name
            //获取请求参数中param对应的参数名 的参数值
            ServerHttpRequest request = exchange.getRequest();
            if (request.getQueryParams().containsKey(config.param)){//此处循环遍历是因为可以为一个参数名称指定多个值。如name=yh&name=zq
                //一般一个属性只给传一个值
                //String value=request.getQueryParams().get(config.param).get(0);
                request.getQueryParams().get(config.param).forEach((v) -> {
                    log.info("获得请求的参数::"+config.param+"="+ v);
                    //做相应的业务处理
                });
            }
            else {
                throw new IllegalTokenException("no params name!");
            }
            return chain.filter(exchange);//执行请求
        };
    }
    /**
     * 自定义配置类
     *      用于接收yaml中过滤器配置的参数。 - MyParam=name  即param=name.在shortcutFieldOrder方法中进行绑定*/

    public static class Config{
        //对应配置在application.yml配置文件中的过滤器参数名
        private String param;

        public String getParam() {
            return param;
        }
        public void setParam(String param) {
            this.param = param;
        }
    }
}
  1. 配置局部过滤器
    在网关配置文件的filters下添加即可
server:
  port: 9090
spring:
#   application:
#     name: API-GATEWAY
  cloud:
    # nacos:
    #   server-addr: 8.142.68.138:8848
    gateway:
      routes: #配置路由规则
        # admins
        - id: admins_router
          # 配置路由到的地址ip:port
          uri: lb://API-ADMINS
          # 配置路径的映射
          predicates:
            - Path=/admins/**
          filters:
            # 去除断言前的路径.1代表去除一级
            - StripPrefix=1
            #局部过滤器名字的前部分
            - MyParam=name

  1. 使用网关访问配置了局部过滤器的请求,没有name参数会报错
    在这里插入图片描述

这样可以很好的向前端返回数据而不是404

完结撒花

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值