遇到这么一个面试题:如何在网关做配置,实现只有在早晨9点到下午18点之间接口才允许访问,其他时间访问都是404。
我们知道网关的一个重要的作用就是路由转发,路由表的配置大概是这个样子:
java
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/*
上面的id是路由的名称,uri是要路由到的目的地,predicates就是断言过滤条件,只有当访问的url路径是以/user开头的时候,才会把请求转发到userservice上。
gateway中内置了很多断言规则,每一种断言规则背后都是实现了AbstractRoutePredicateFactory
的一个实现类,比如Path断言org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory
。但是gateway并没有提供一个根据时间做过滤条件的断言工厂,因此,我们可以自定义一个断言工厂实现这个功能。
那如何来自定义一个断言工厂呢?
首先,写一个AbstractRoutePredicateFactory
的实现类
java
/**
* 自定义的断言工厂<br>
* 1.名称必须是配置+RoutePredicateFactory<br>
* 2.必须继承AbstractRoutePredicateFactory<配置类>
*/
@Component
public class HourRoutePredicateFactory extends AbstractRoutePredicateFactory<HourRoutePredicateFactory.Config> {
public HourRoutePredicateFactory() {
super(HourRoutePredicateFactory.Config.class);
}
//读取配置文件的参数值,赋值到配置类中的属性上
public List<String> shortcutFieldOrder() {
//顺序必须与yml文件中的配置顺序对应
return Arrays.asList("startHour", "endHour");
}
public Predicate<ServerWebExchange> apply(HourRoutePredicateFactory.Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
//获取当前时间
LocalDateTime now = LocalDateTime.now();
int hour = now.getHour();
if(hour >= config.getStartHour() && hour <= config.getEndHour()){
return true;
}
return false;
}
};
}
//用于接收参数
@Data
@NoArgsConstructor
public static class Config {
private int startHour;
private int endHour;
}
}
然后在配置文件中使用就可以了,比如:
yml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/*
- Hour=9,18
打开浏览器,测试一下,如果当前时间是在9-18点之间可以正常访问,否则返回404。
源码下载:https://github.com/xjs1919/enumdemo/tree/master/gateway-predicate-demo