基础模板
spring:
cloud:
gateway:
routes:
-id: gulimall-search # 别重复就行
uri: lb://gulimall-search #对应微服务的applicationName
predicates:
- Path=/api/search/**
predicates的概念
每一个route对应一个--->RouteDefinition
而route对应的predicates对应---->RouteDefinition的List
如何生成对应的predicate?
由路由断言工厂实现(RoutePredicateFactory(接口)),总共有12个具体实现类
分别对应12种断言方式,至于用什么取决于 predicates:后的 每个element的内容例如- Path则是PathRoute....
类似Cookie的形式有所不同-->,前面是key,后面是value 要完全符合才可以使用
Cookie与Header在项目更新中灰度测试有用,可以给指定用户配上特定cookie或者header,来匹配上某个微服务中换上新代码的机器
- 最常用是:Host,Path,Header
分布式登录要注意的问题
- 登录功能在对应的微服务上,但是登录信息如token要统一在gateway解析
- 解析后,需要把用户信息记录到每个要发到其他微服务的request上(通常放header)
- 要预防openFeign发请求带没带原定要共享的数据
网关过滤器的执行流程
概念回想:
- dispatcherHandler-->根据predicatesmapping来转发给哪一个微服务
- 有一系列的过滤链--->(设计模式:责任链模式),每个过滤器有pre和post拦截,pre是在转发前,post是在转发后,和MVC一样,pre是按优先级正序,post是按优先级倒序
- 优先级最低的是负责转发的filter
- 在cloud里有一系列的内置的filter
- 如果要针对某个route在route ->> -id下弄一个filters(具体有哪些看官网)
- 如果是针对每一个route--->在gateway下,与routes同级,弄一个default-filters
- 要自定义filter/了解内置filter
- globalFilter:面向全部
- gateWayFilter:更加灵活,可以作用于任意指定的路由(yaml配置的route即是路由)
完整的概念过程:
- 关于StripPrefix:指定的=1就是删除path的几段前缀,然后这个path是/a/c/这样的(是url去掉协议和域名or地址的剩余部分)
- RewritePath,那里说明有误
自定义过滤器
gateWayFilter(必须在yaml中配置才会生效)
注意点
- 不是直接new,而是去弄一个factory(工厂模式(一个工厂只培养一个filter))
- 该工厂extends AbstractGatewayFilterFactory
- public class PrinthhGatewayFilterFactory,命名有规范,加粗为固定后缀,之后使用更方便
- 使用上直接在default-filters下当做一个ele来使用,---->使用固定后缀优势在于----> - Printhh就可以了
@Component
public class PrinthhGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("hhhh");
ServerHttpRequest request = exchange.getRequest();
return chain.filter(exchange);
}
};
}
}
疑问?像Mono这种类型,假如要拒绝该怎么办?
带上参数plus版
@Component
public class PrinthhGatewayFilterFactory extends AbstractGatewayFilterFactory<PrinthhGatewayFilterFactory.Config> {
@Override
public GatewayFilter apply(PrinthhGatewayFilterFactory.Config config) {
return new OrderedGatewayFilter(new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println(config.getA());
System.out.println(config.getB());
System.out.println(config.getC());
return chain.filter(exchange);
}
},1);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("a","b","c");
}
@Override
public Class<Config> getConfigClass() {
return Config.class;
}
@Data
public static class Config{
public String a;
public String b;
public String c;
}
}
使用上:直接在 - Printhh=1,2,3就可以了(可以不按顺序,但是需要拆成对象的形式(更复杂))
带上过滤器顺序
@Component
public class PrinthhGatewayFilterFactory extends AbstractGatewayFilterFactory<PrinthhGatewayFilterFactory.Config> {
@Override
public GatewayFilter apply(PrinthhGatewayFilterFactory.Config config) {
//重点!!!!!!
return new OrderedGatewayFilter(new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println(config.getA());
System.out.println(config.getB());
System.out.println(config.getC());
return chain.filter(exchange);
}
},1);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("a","b","c");
}
@Override
public Class<Config> getConfigClass() {
return Config.class;
}
@Data
public static class Config{
public String a;
public String b;
public String c;
}
}
GlobalFilter(及其容易)
- implements GlobalFilter, Ordered
- 添加@Component注解
不用在yaml里面去配置,默认生效,针对所有
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("全局过滤器");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 1;
}
}
非对称加密(公钥加密只能私钥解密,私钥加密只能公钥解密)
通常是公钥放到网关,而私钥放到内部服务器
网关登录校验
- 首先,回答Mono拒绝的问题---->抛异常或者直接return一个response(记得设置下code)
注意点
- 通常校验时要考虑哪些是要放行的(springsecurity在配置文件里面有auth:....配置下通行路径(如果需要用REST,要自己带上GET:等))
- 比较时,可以用spring的private AntPathMatcher antPathMatcher;
- 拦截器中需要网关校验后要修改request(例如往header添加user-Info)
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("全局过滤器");
//重点
ServerWebExchange exc = exchange.mutate().request(builder -> builder.header("user", "UserInfo")).build();
return chain.filter(exc);
}
-
在各个微服务中,需要添加Interceptor(同时要弄个MvcConfig implements WebMvcConfigurer ,在里面addInterceptor)来拦截request中header的user-Info,然后根据逻辑添加到ThreadLocal中(通常由于都要用到,所以放在common)
- 配置在common包通常扫描不到,需要配置spring.factories(新增目录META-INF,底下再放spring.factories)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.seamount3.common.config.GuliFeignConfig,\ //按上面的格式写多个,如果只有一个把,\去掉
- 或者弄一个注解类
@Import(GuliFeignConfig.class)//重点 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface EnableFeignConfig { }
@Configuration //@ConditionalOnClass(DispatcherServlet.class),直接弄一个enable的注解得了,这里要注意像gateway用webflux时,要记得打开这个,同时记得gateway不能导入MVC依赖 public class GuliFeignConfig
-
openFeign也要添加一个requestInterceptor来拦截所有请求添加user-Info到header中
@Bean
public RequestInterceptor requestInterceptor(){
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(requestAttributes!=null) {
String cookie = requestAttributes.getRequest().getHeader("Cookie");
if (StringUtils.hasText(cookie)) {
requestTemplate.header("Cookie", cookie);
}
}
}
};
}
标签:return,exchange,springcloud,class,public,filter,Override,gateWay
From: https://www.cnblogs.com/seamount3/p/17784188.html