SpringCloud Alibaba(三) - GateWay网关
1、基本环境搭建
1.1 依赖
<!-- Gatway 网关会和springMvc冲突,不能添加web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- gateway 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
1.2 配置
# 端口
server:
port: 9606
# 服务名
spring:
application:
name: kgcmall-gatway
cloud:
#nacos 配置
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 网关配置
gateway:
routes: # 路由,是list集合,可以配置多个路由
#product模块
- id: kh96_route_first # 当前route路由的唯一标识,不能重复
#uri: http://localhost:9602 # 路由转发的目标资源地址,不支持多负载调用,不利于扩展,不推荐
uri: lb://kgcmall96-prod # lb 从nacos注册中心的服务列表中,根据指定的服务名,调用服务,推荐用法
predicates: # 指定路由断言配置,支持多个断言,只要断言成功(满足路由转发条件),才会执行转发到目标资源地址访问
- Path=/prod-gateway/** # 指定path路径断言,必须满足请求地址是/prod-gateway开始,才会执行路由转发
filters: # 指定路由过滤配置,支持多个过滤器,在断言成功,执行路由转发时,对请求和响应数据进行过滤处理
- StripPrefix=1 # 在请求断言成功后,执行路由转发时,自动去除第一层的访问路径/prod-gateway
#user模块
- id: kh96_route_second
uri: lb://kgcmall96-user
predicates:
- Path=/user-gateway/**
filters:
- StripPrefix=1
1.3 测试
1.3.1 nacos
1.3.2 请求测试
1.3.2.1 通过gateway网关调用prod模块
1.3.2.1 通过gateway网关调用user模块
2、路由Route
Route 主要由 路由id、目标uri、断言集合和过滤器集合组成,那我们简单看看这些属性到底有什么作用。
(1)id:路由标识,要求唯一,名称任意(默认值 uuid,一般不用,需要自定义);
(2)uri:请求最终被转发到的目标地址;
(3)order: 路由优先级,数字越小,优先级越高;
(4)predicates:断言数组,即判断条件,如果返回值是boolean,则转发请求到 uri 属性指定的服务中;
(5)filters:过滤器数组,在请求传递过程中,对请求做一些修改;
3、断言 Predicate
Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。
断言就是说: 在什么条件下 才能进行路由转发;
3.1 内置路由断言工厂
基于Datetime类型的断言工厂
AfterRoutePredicateFactory
: 接收一个日期参数,判断请求日期是否晚于指定日期;- -After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
BeforeRoutePredicateFactory
: 接收一个日期参数,判断请求日期是否早于指定日期;BetweenRoutePredicateFactory
: 接收两个日期参数,判断请求日期是否在指定时间段内;
基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory
- -RemoteAddr=192.168.1.1/24
基于Cookie的断言工厂
CookieRoutePredicateFactory
(接收两个参数,cookie 名字和一个正则表达式)- -Cookie=chocolate, ch
基于Header的断言工厂
HeaderRoutePredicateFactory
- -Header=X-Request-Id, \d+
基于Host的断言工厂
HostRoutePredicateFactory
- -Host=**.testhost.org
基于Method请求方法的断言工厂
MethodRoutePredicateFactory
- -Method=GET
基于Path求路径的断言工厂
PathRoutePredicateFactory
(接收一个参数,判断请求的URI部分是否满足路径规则)- -Path=/foo/{segment}
- `QueryRoutePredicateFactory·
- -Query=baz, ba.
基于路由权重的断言工厂
WeightRoutePredicateFactory
(接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发)routes:
-id: weight_route1 uri: host1 predicates:
-Path=/product/**
-Weight=group3, 1
-id: weight_route2 uri: host2 predicates:
-Path=/product/**
-Weight= group3, 9
3.2 自定义路由断言工厂
3.2.1 自定义网关断言工厂 - 权限断言
/**
* Created On : 28/11/2022.
* <p>
* Author : huayu
* <p>
* Description: 自定义网关断言工厂-权限断言
*/
@Component //自定义断言工厂,必须是一个组件放入容器才可以生效
public class MyAuthRoutePredicateFactory
extends AbstractRoutePredicateFactory<MyAuthRoutePredicateFactory.Config> {
/*
配置项名MyAuth的配置参数值,映射到断言工厂内部类的属性名
*/
public static final String MYAUTH_KEY = "myAuth";
/*
通过空参构造方法,指定静态内部类,用于接收配置文件中的配置项的内容,即断言(- myAuth=xxx)
*/
public MyAuthRoutePredicateFactory() {
super(MyAuthRoutePredicateFactory.Config.class);
}
/*
价格核心配置文件中的自定义配置项的内容,映射到当前配置类的属性中,即Collections.singletonList(DATETIME_KEY);指定的内部属性
*/
public List<String> shortcutFieldOrder() {
return Collections.singletonList(MYAUTH_KEY);
}
@Override
public Predicate<ServerWebExchange> apply(MyAuthRoutePredicateFactory.Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
//自定义权限断言业务逻辑
if (StringUtils.isNotBlank(config.getMyAuth())) {
//判断自定义权限配置参数值,是否和当前指定的值一直,如果一致则断言成功,否则失败
return config.getMyAuth().equals("KH96");
}
//断言失败
return false;
}
};
}
@Data
public static class Config {
private String myAuth;
}
}
可以配置多个参数,案例:https://blog.csdn.net/qq_31155349/article/details/108557969
3.2.2 配置
3.2.2.1 正确配置成功效果
predicates:
- MyAuth=KH96 # 自定义 权限断言 配置 (注意首字母要大写)
测试效果:
3.2.2.1 正确配置失败效果
predicates:
- MyAuth=KHxx # 配置错误信息
测试效果 :
4、过滤器 Filter
1 作用: 过滤器就是在请求的传递过程中,对请求和响应做一些手脚
2 生命周期: Pre Post
3 分类: 局部过滤器(作用在某一个路由上) 全局过滤器(作用全部路由上)
在Gateway中, Filter的生命周期只有两个:“pre” 和 “post”。
PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
Gateway 的Filter从作用范围可分为两种: GatewayFilter与GlobalFilter。
- GatewayFilter:应用到单个路由或者一个分组的路由上。
- GlobalFilter:应用到所有的路由上。
4.1 内置的过滤器工厂
过滤器工厂 | 作用 | 参数 |
---|---|---|
AddRequestHeader | 为原始请求添加Header | Header的名称及值 |
AddRequestParameter | 为原始请求添加请求参数 | 参数名称及值 |
AddResponseHeader | 为原始响应添加Header | Header的名称及值 |
DedupeResponseHeader | 剔除响应头中重复的值 | 需要去重的Header名称及去重策略 |
Hystrix | 为路由引入Hystrix的断路器保护 HystrixCommand的名称 | |
FallbackHeaders | 为fallbackUri的请求头中添加具体的异常信息 | Header的名称 |
PrefixPath | 为原始请求路径添加前缀 | 前缀路径 |
PreserveHostHeader | 为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host | 无 |
RequestRateLimiter | 用于对请求限流,限流算法为令牌桶 | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
RedirectTo | 将原始请求重定向到指定的URL | http状态码及重定向的url |
RemoveHopByHopHeadersFilter | 为原始请求删除IETF组织规定的一系列Header | 默认就会启用,可以通过配置指定仅删除哪些Header |
RemoveRequestHeader | 为原始请求删除某个Header | Header名称 |
RemoveResponseHeader | 为原始响应删除某个Header | Header名称 |
RewritePath | 重写原始的请求路径 | 原始路径正则表达式以及重写后路径的正则表达式 |
RewriteResponseHeader | 重写原始响应中的某个Header | Header名称,值的正则表达式,重写后的值 |
SaveSession | 在转发请求之前,强制执行WebSession::save操作 | 无 |
secureHeaders | 为原始响应添加一系列起安全作用的响应头 | 无,支持修改这些安全响应头的值 |
SetPath | 修改原始的请求路径 | 修改后的路径 |
SetResponseHeader | 修改原始响应中某个Header的值 | Header名称,修改后的值 |
SetStatus | 修改原始响应的状态码 | HTTP 状态码,可以是数字,也可以是字符串 |
StripPrefix | 用于截断原始请求的路径 | 使用数字表示要截断的路径的数量 |
Retry | 针对不同的响应进行重试 | retries、statuses、methods、series |
RequestSize | 设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large | 请求包大小,单位为字节,默认值为5M |
ModifyRequestBody | 在转发请求之前修改原始请求体内容 | 修改后的请求体内容 |
ModifyResponseBody | 修改原始响应体的内容 | 修改后的响应体内容 |
Default | 为所有路由添加过滤器 | 过滤器工厂名称及值 |
4.2 测试
简单测试几个;
4.2.1 AddRequestHeader
4.2.1.1 添加配置
filters:
- AddRequestHeader=X-Request-token,token_kh96 # 添加请求头参数,两个参数,第一个是添加请求头参数名,第二个参数值
4.2.1.2 通过路由调用的方法
@GetMapping("/mallProduct")
public KgcMallProduct mallProduct(@RequestParam Integer pid,
@RequestHeader(value = "X-Request-token", required = false) String gateWayFilterToken) {
log.info("------ 根据商品编号:{}, 查询商品详情 ------", pid);
//通过GateWay网关滤器,增加请求头参数
log.info("------ 通过GateWay网关滤器,增加请求头参数 X-Request-token:{} ------", gateWayFilterToken);
// 调用业务接口,查询商品详情
return kgcMallProductService.getMallProductById(pid);
}
4.2.1.3 测试
4.2.2 AddRequestParameter
4.2.2.1 添加配置
filters:
- AddRequestParameter=queryName,param_kh96 # 添加普通 请求参数 ,两个参数,第一个是添加请求头参数名,第二个参数值
4.2.2.2 通过路由调用的方法
@GetMapping("/mallProduct")
public KgcMallProduct mallProduct(@RequestParam Integer pid
@RequestParam(value = "queryName", required = false) String gateWayFilterParamQueryName) {
log.info("------ 根据商品编号:{}, 查询商品详情 ------", pid);
//通过GateWay网关滤器,增加请求参数
log.info("------ 通过GateWay网关滤器,增加请求头参数 queryName:{} ------", gateWayFilterParamQueryName);
// 调用业务接口,查询商品详情
return kgcMallProductService.getMallProductById(pid);
}
4.2.2.3 测试
4.3 自定义网关过滤器
如果带checkParam参数进行参数校验,如果没有携带直接放行;
4.3.1 自定义网关过滤器
/**
* Created On : 28/11/2022.
* <p>
* Author : huayu
* <p>
* Description: 自定义网关过滤工厂 -校验过滤器
*/
@Component //自定义网关过滤工厂,必须是一个组件放入容器才可以生效
public class MyCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<MyCheckGatewayFilterFactory.Config> {
/*
配置项名MyAuth的配置参数值,映射到断言工厂内部类的属性名
*/
public static final String MYCHECK_KEY = "myCheck";
public MyCheckGatewayFilterFactory() {
super(MyCheckGatewayFilterFactory.Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList(MYCHECK_KEY);
}
public GatewayFilter apply(MyCheckGatewayFilterFactory.Config config) {
return new GatewayFilter() {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//自定义网关过滤器实现过滤业务逻辑
//模拟发送到网关的请求,如果请求携带参数和网关过滤器配置参数一致,放行,如果不一致,直接404
String checkParam = exchange.getRequest().getQueryParams().getFirst("checkParam");
//如果携带了checkParam参数 判断获取的请求参数是否和网关过滤器中配置的参数一致
if (StringUtils.isNotBlank(checkParam)) {
//判断是否一致
if (checkParam.equals(config.getMyCheck())) {
//过滤器放行到目标请求
return chain.filter(exchange);
}
//返回404
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
//没有携带参数,直接放行
return chain.filter(exchange);
}
};
}
@Data
public static class Config {
private String myCheck;
}
}
4.3.2 带正确的参数
4.3.3 带错误的参数
4.3.4 不带参数
4.4 自定义网关全局过滤(token)
4.4.1 自定义网关全局过滤(token)
携带token放行,不携带,跳转到登录页面(通过跳转到百度模拟)
/**
* Created On : 28/11/2022.
* <p>
* Author : huayu
* <p>
* Description: 自定义网关全局过滤,实现token鉴权,实现GlobalFilter 和 Ordered接口
*/
@Component //必须是spring组件
public class MyTokenGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//自定义全局过滤逻辑,判断请求头中们是否携带了token参数,如果带了就放行,非欧洲就就拒绝
if (StringUtils.isBlank(exchange.getRequest().getHeaders().getFirst("token"))) {
//没有携带token,直接重定向到登录页
//模拟重定向到单点登录网址,临时用百度
String redirectUrl = "https://www.baidu.com";
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.SEE_OTHER); //303 错误,重定向
response.getHeaders().set(HttpHeaders.LOCATION, redirectUrl);
//结束响应
return response.setComplete();
}
//代了token,
//TODO token校验
return chain.filter(exchange);
}
@Override
public int getOrder() {
//指定全局过滤器的优先级,值越小,优先级越高
return 0;
}
}
4.4.2 携带token
4.4.2 不携带token
SpringCloud Alibaba(三) - GateWay网关的更多相关文章
- 0.9.0.RELEASE版本的spring cloud alibaba sentinel+gateway网关实例
sentinel除了让服务提供方.消费方用之外,网关也能用它来限流.我们基于上次整的网关(参见0.9.0.RELEASE版本的spring cloud alibaba nacos+gateway网关实 ...
- SpringCloud Alibaba (三):Sentinel 流量控制组件
SpringCloud Alibaba (三):Sentinel 流量控制组件 Sentinel 是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel 是面向分布式服务架构 ...
- 0.9.0.RELEASE版本的spring cloud alibaba nacos+gateway网关实例
gateway就是用来替换zuul的,功能都差不多,我们看下它怎么来跟nacos一起玩.老套路,三板斧: 1.pom: <?xml version="1.0" encodin ...
- SpringCloud:学习Gateway网关拦截器的ServerWebExchange
1.Gateway的拦截器 我们要在项目中实现一个拦截器,需要继承两个类:GlobalFilter, Ordered GlobalFilter:全局过滤拦截器,在gateway中已经有部分实现,具体参 ...
- SpringCloud Alibaba实战(11:引入服务网关Gateway)
源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 大家好,我是三分恶. 在前面的章节中,我们已经完成了服务间的调用.统一配置等等,在这 ...
- SpringCloud + Consul服务注册中心 + gateway网关
1 启动Consul 2 创建springcloud-consul项目及三个子模块 2.1 数据模块consul-producer 2.2 数据消费模块consul-consumer 2.3 ga ...
- SpringCloud初体验:七、gateway 网关服务如何做token验证
说说背景:假如有一个用户服在用户登录后,生成一个token给到客户端,用户每次请求时都需要这个token,于是每次都会在网关 gateway 校验,校验通过后网关从token中解析出userId,然后 ...
- SpringCloud Alibaba微服务实战三 - 服务调用
导读:通过前面两篇文章我们准备好了微服务的基础环境并让accout-service 和 product-service对外提供了增删改查的能力,本篇我们的内容是让order-service作为消费者远 ...
- SpringCloud(四)GateWay网关
GateWay网关 概述简介 Gateway是在 Spring生态系统之上构建的AP网关服务,基于 Spring5, Spring Boot2和 Project Reactor等技术. Gateway ...
- 微服务入门三:SpringCloud Alibaba
一.什么是SpringCloud Alibaba 1.简介 1)简介 阿里云未分布式应用开发提供了一站式解决方案.它包含了开发分布式应用程序所需的所有组件,使您可以轻松地使用springcloud开发 ...
随机推荐
- java~springboot(2022之后)~目录索引
回到占占推荐博客索引 最近写了不过关于java,spring,微服务的相关文章,今天把它整理一下,方便大家学习与参考. java~springboot(2022之前)~目录索引 java~spring ...
- 100个Linux Shell脚本经典案例(附PDF)
转载自:https://mp.weixin.qq.com/s/tCKAM67_7K7q2vJthaIsDQ 原文链接:https://wenku.baidu.com/view/4f089430a116 ...
- ES重要配置解析
path.data和path.logs 如果您使用.zip或.tar.gz存档,则data和logs 目录是子文件夹$ES_HOME.如果这些重要文件夹保留在其默认位置,则在将Elasticsearc ...
- cAdvisor容器监控规则
其他说明参考host主机监控规则:https://www.cnblogs.com/sanduzxcvbnm/p/13589848.html 在prometheus主程序目录下的rules目录下新建do ...
- CentOS8本地安装Redash中文版,并且配置为生产环境
Centos8内置的Python为3.6.8版本,以下是在内置Python3.6.8基础上的安装步骤.由于安装多版本Python会导致系统底层库需要下载源码重新编译,比较麻烦,不建议在多版本Pytho ...
- 3_MyBatis
一. 引言 1.1 什么是框架? 软件的半成品, 解决了软件开发过程中的普适性问题, 从而简化了开发步骤, 提升了开发效率 1.2 什么是ORM框架? ORM(Object Relational Ma ...
- Pjax 下动态加载插件方案
在纯静态网站里,有时候会动态更新某个区域往会选择 Pjax(swup.barba.js)去处理,他们都是使用 ajax 和 pushState 通过真正的永久链接,页面标题和后退按钮提供快速浏览体验. ...
- IOC常用的创建对象方式
通过无参构造方法来创建 1.User.java public class User { private String name; public User() { System.out.println( ...
- Scanner的用法 从键盘输入
先导入包 import java.util.Scanner; 后输入 Scanner Sc=new Scanner(System.in); //(Sc可以自定义,无实质意义) int i; i=Sc. ...
- 彻底学会Selenium元素定位
转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/63099961.html 你好,我是测试蔡坨坨. 最近收到不少初学UI自动化测试的小伙伴私信,对于元素的定位还是有些头疼,总 ...