Loading

gateway笔记

自定义断言

  • 新增一个Bean 标记为@Component、
    • 继承AbstractRoutePredicateFactory类命名需要以 RoutePredicateFactory结尾
    • 声明一个静态内部类 来接受配置文件中的信息
    • 重写 shortcutFieldOrder 来映射 配置文件中的参数
    • 重写apply方法

下面是一个根据 请求头和时间 来决定是否放心请求的例子

yaml配置

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: user_router
          uri: lb://user-service
          predicates:
            - Path=/user-serv/**
   #当请求的为FirstHeader 值为 FirstValue 时间在2024-01-19 之前的请求放行到user-service服务
            - Custom=test, testValue,2024-01-19 
          filters:
            - StripPrefix=1

实现类

package com.cckeep.gateway.predicates;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.function.Predicate;

@Component
@Slf4j
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {
    //需要与前面配置文文件中第一个值名称一致 因为前面我业务上把第一个当做请求头head 
    private static final String HEAD_KEY = "test";
    
    public CustomRoutePredicateFactory() {
        super(Config.class);
    }
    //把前面配置文件的值通过set方法按顺序 映射到 Config
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("head", "value", "limitTime");
    }

    @Validated
    public static class Config {
        @Setter
        @Getter
        private String head;
        @Setter
        @Getter
        private String value;
        @Getter
        private Date limitTime;
        public Config() {
        }
      //  读取配置文件出来的是String 所以这里重写set方法
        public void setLimitTime(String limitTime) {
            try {
                this.limitTime = new SimpleDateFormat("yyyy-MM-dd").parse(limitTime);
            } catch (ParseException e) {
                log.error("格式化时间错误");
                throw new RuntimeException(e);
            }
        }
    }
    @Override
  //真正处理逻辑的地方  
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                List<String> heads = serverWebExchange.getRequest().getHeaders().getOrDefault(HEAD_KEY, Collections.emptyList());
                if (heads.isEmpty()) {
                    return false;
                }
                for (int i = 0; i < heads.size(); i++) {
                    if (config.getValue().equals(heads.get(i)) && new Date().before(config.getLimitTime())) {
                        return true;
                    }
                }
                return false;
            }
        };
    }

}

测试

这是我的controller

通过apiPost发请求测试


当请求头 和值 与配置一致时候请求成功

修改请求头不一致 请求失败

posted @ 2024-01-17 22:30  冰莫莫  阅读(2)  评论(0编辑  收藏  举报