常用功能:路由转发、权限校验、限流控制等
5.1.1、新建网关模块
5.1.2、依赖
<!-- 公共模块-->
<dependency>
<groupId>com.example.mall</groupId>
<artifactId>mall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
5.1.3、@EnableDiscoveryClient
开启服务注册功能
5.1.4、新建bootstrap.yml 和 application.yml
bootstrap.yml
spring:
application:
name: mall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: 6d405b31-5f62-4105-b8a6-339cc0b8464e
application.yml
server:
port: 88
spring:
application:
name: mall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
5.1.5、新建gateway命名空间 和 配置
5.1.6、排除数据源相关配置
由于我们引入了公共模块,网关不需要配置数据源,不排除数据源配置会报错
5.2、路由转发(yml新增网关配置)
server:
port: 88
spring:
application:
name: mall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
#网关配置
gateway:
routes:
- id: coupon
uri: http://127.0.0.1:8881/ #要去的请求地址
# uri: lb://mall-coupon #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Query=url,coupon # url 带有/coupon就去上方uri地址 例:url=coupon
# - Path=/coupon/** # url 这个是按照路径匹配,只要以/coupon开头就符合要求
#- After=2037-01-20T17:42:47.789-07:00[Asia/Shanghai] # 这个时间之后可以访问
- id: member
uri: http://127.0.0.1:8882/ #要去的请求地址
# uri: lb://mall-member #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Query=url,member # url 带有/coupon就去上方uri地址 url=member
# - Path=/member/** # url 这个是按照路径匹配,只要以/member开头就符合要求
名称 | 说明 | 示例 |
---|---|---|
After | 是某个时间点后的请求 | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含某些cookie | - Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | - Header=X-Request-Id, \d+ |
Host | 请求必须是访问某个host(域名) | - Host=.somehost.org,.anotherhost.org |
Method | 请求方式必须是指定方式 | - Method=GET,POST |
Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
Query | 请求参数必须包含指定参数 | - Query=name或者 - Query=name(参数), Jack. (值,如Jacks,没有点就全匹配,两个.就是Jackss) |
RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
Weight | 权重处理 |
routes:
- id: coupon
# uri: http://127.0.0.1:8881/ #要去的请求地址
uri: lb://mall-coupon #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Query=url # 请求参数中带有 url的都将被匹配。
- Query=url,coupon. # url 带有/coupon就去上方uri地址 例:url=coupons,【① coupon全值匹配 ; ② coupon.后面需多随便一位,例coupons ; ③coupon..后面需多随便两位例,couponst】
- Path=/foo/{segment},/bar/** # ① /foo/1 或者 /foo/bar,②只要以/bar开头就符合要求
# URI模板变量 (如上例中的 segment )将以Map的方式保存于ServerWebExchange.getAttributes() key为ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE.
#这些值将在GatewayFilter Factories使用
# 可以用这个方法获取变量: Map uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
# String segment = uriVariables.get("segment");
- After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai] # 在该日期时间之后发生的请求都将被匹配
- Before=2017-01-20T17:42:47.789-07:00[Asia/Shanghai] # 在该日期时间之前发生的请求都将被匹配
- Between=2017-01-20T17:42:47.789-07:00[Asia/Shanghai], 2017-01-21T17:42:47.789-07:00[America/Denver] # 在两个时间之间的请求将被匹配
- Cookie=chocolate, ch.p # cookie名称和正则表达式。请求包含次cookie名称且正则表达式为真的将会被匹配。
- Header=X-Request-Id, \d+ # header名称和正则表达式。请求包含次header名称且正则表达式为真的将会被匹配。
- Host=**.somehost.org,**.anotherhost.org # host name列表。使用Ant路径匹配规则,.作为分隔符。
- Method=GET,POST # 请求方式必须是指定方式
- RemoteAddr=192.168.1.1/24 # 一个CIDR符号(IPv4或IPv6)字符串的列表,最小值为1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子网掩码)。
spring提供了31种不同的路由过滤器工厂。
名称 | 说明 |
---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除有一个响应头 |
RequestRateLimiter | 限制请求的流量 |
。。。 |
filters:
- AddRequestHeader=X-Request-Foo, Bar # 对于所有匹配的请求,这将向下游请求的头中添加 x-request-foo:bar header
- AddRequestParameter=foo, bar # 对于所有匹配的请求,这将向下游请求添加foo=bar查询字符串
- AddResponseHeader=X-Response-Foo, Bar # 对于所有匹配的请求,这会将x-response-foo:bar头添加到下游响应的header中
- RemoveRequestHeader=X-Request-Foo # 这将在X-Request-Foo header被发送到下游之前删除它。
- RemoveResponseHeader=X-Response-Foo # - RemoveResponseHeader=X-Response-Foo
- SetResponseHeader=X-Response-Foo, Bar # 替换所有header,而不是添加。因此,如果下游服务器响应为X-Response-Foo:1234,则会将其替换为X-Response-Foo:Bar,这是网关客户端将接收的内容。
- SetPath=/{segment} # 如果 - Path=/foo/{segment} 那么对于一个 /foo/bar请求,在做下游请求前,路径将被设置为/bar
- PrefixPath=/mypath #对于所有匹配的请求, 这将给所有匹配请求的路径加前缀/mypath。因此,向/hello发送的请求将发送到/mypath/hello。
- RewritePath=/foo/(?>.*), /$\{segment} # 对于请求路径/foo/bar,将在发出下游请求之前将路径设置为/bar。注意,由于YAML规范,请使用 $\替换 $。
- StripPrefix=1 # 表示在将请求发送到下游之前从请求中剥离的路径个数
- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
# 对于一个/42?user=ford&password=omg!what&flag=true的header值,在做下游请求时将被设置为/42?user=ford&password=***&flag=true,由于YAML规范,请使用 $\替换 $。
- SetStatus=401 #对于所有匹配的请求,HTTP返回码将设置为401.
- RedirectTo=302, http://acme.org # 对于所有匹配的请求,发送一个302状态码和一个Location:http://acme.org header来执行重定向。
- SaveSession # 对于所有匹配的请求,将调用转发到下游之前强制执行WebSession::save 操作
测试
1、添加配置
2、在接口中获取请求头
3、已添加到请求头里
4、对所有路由请求都生效
5、代码
server:
port: 88
spring:
application:
name: mall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
#网关配置
gateway:
routes:
- id: coupon
uri: http://127.0.0.1:8881/ #要去的请求地址
# uri: lb://coupon #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
#- Query=url,coupon # url 带有/coupon就去上方uri地址 例:url=coupon
- Path=/coupon/** # url 这个是按照路径匹配,只要以/coupon开头就符合要求
#- After=2037-01-20T17:42:47.789-07:00[Asia/Shanghai] # 这个时间之后可以访问
#filters: #过滤器
#- AddRequestHeader=Truth,niubi! #添加请求头
- id: member
uri: http://127.0.0.1:8882/ #要去的请求地址
# uri: lb://member #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
#- Query=url,member # url 带有/coupon就去上方uri地址 url=member
- Path=/member/** # url 这个是按照路径匹配,只要以/member开头就符合要求
default-filters: #默认过滤器,会对所有的路由请求都生效
- AddRequestHeader=Truth,niubi!
与GetewayFilter区别在于,GetewayFilter是通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。
定义方式是实现GlobalFilter接口。
案例:定义全局过滤器,拦截并判断用户身份
需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面的条件:
1、 参数中是否有authorization
2、authorization参数值是否为admin
如果同时满足则放行,否则拦截
@Order(-1) // 多个过滤器,这个值越小,优先级越高
@Component
public class AuthorizationFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1、获取请求头
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
// 2、获取参数中的authorization 参数
String auth = params.getFirst("authorization");
// 3、判断参数值是否等于admin
if ("admin".equals(auth)){
// 4、是,放行
return chain.filter(exchange);
} // 5、否,拦截
// 设置状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
每一个过滤器都必须指定order值,order值越小,优先级却高,执行顺序越前
.
GlobalFilter通过实现@Order注解来指定order值,有我们自己指定
.
路由过滤器和defaultFilter的order由Spring指定,默认是按声明顺序从1递增(就是yml配置,越上面的的越高)
.
当过滤器的order值一样时,会按照defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。
跨域:域名不一致就是跨域,主要包括
1、域名不同
:www.taobao.com 和 www.taobao.org 和 www.jd.com
2、域名相同,端口不同
:8080和8081
跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截问题
解决方案:CORS
#网关配置
gateway:
discovery:
locator:
enabled: true
globalcors:
cors-configurations:
'[/**]':
allowCredentials: true
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*" #允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
server:
port: 88
spring:
application:
name: mall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
#网关配置
gateway:
discovery:
locator:
enabled: true
globalcors:
cors-configurations:
'[/**]':
allowCredentials: true
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*" #允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
routes:
- id: coupon
uri: http://127.0.0.1:8881/ #要去的请求地址
# uri: lb://coupon #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
#- Query=url,coupon # url 带有/coupon就去上方uri地址 例:url=coupon
- Path=/coupon/** # url 这个是按照路径匹配,只要以/coupon开头就符合要求
#- After=2037-01-20T17:42:47.789-07:00[Asia/Shanghai] # 这个时间之后可以访问
#filters: #过滤器
#- AddRequestHeader=Truth,niubi! #添加请求头
- id: member
#uri: http://127.0.0.1:8882/ #要去的请求地址
uri: lb://mall-member #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
#- Query=url,member # url 带有/coupon就去上方uri地址 url=member
- Path=/member/** # url 这个是按照路径匹配,只要以/member开头就符合要求
- id: product
#uri: http://127.0.0.1:8884/ #要去的请求地址
uri: lb://mall-product #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
#- Query=url,member # url 带有/coupon就去上方uri地址 url=member
- Path=/product/**,/renren-fast/product/** # url 这个是按照路径匹配,只要以/member开头就符合要求
filters:
- RewritePath=/renren-fast/(?>.*),/$\{segment} #路径重写,去除/renren-fast
- id: renrenfast
uri: lb://renrenfast #要去的请求地址
#uri: http://127.0.0.1:8883/ #要去的请求地址
# uri: lb://member #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
#- Query=url,member # url 带有/coupon就去上方uri地址 url=member
- Path=/renren-fast/** # url 这个是按照路径匹配,只要以/member开头就符合要求
filters:
- RewritePath=/api/(?>.*), /renren-fast/$\{segment}
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
default-filters: #默认过滤器,会对所有的路由请求都生效
- AddRequestHeader=origin,gateway # 添加为origin的请求头,值为gateway
原文地址