Spring Cloud Gateway入门
- (1)网关是什么?
网关(Gateway) 就是一个网络连接到另一个网络的“关口”。就是网络关卡。
从一个房间走到另一个房间,必然要经过一扇门。同样,从一个网络向另一个网络发送信息,也必须经过一道“关口” - (2)SpringCloud的网关是什么?
Spring Cloud Gateway的核心就是一系列的过滤器,可以将客户端的请求转发到不同的微服务。主要作用:过滤和路由
。
Spring Cloud Gateway入门
- (1)GateWay如何使用
》依赖
》配置路由信息
id 路由id,可以任意
uri 代理的服务地址
predicates 路由断言: 可以匹配映射路径
》启用
》启动
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
application.properties
spring.application.name=demo04_gateway_1001
server.port=1001
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka
# route
spring.cloud.gateway.routes[0].id=demo04_gateway_1001
#spring.cloud.gateway.routes[0].uri.=http://127.0.0.1:8001
spring.cloud.gateway.routes[0].uri=lb://demo01-provider-user
spring.cloud.gateway.routes[0].predicates[0]=Path=/**
#spring.cloud.gateway.routes[0].predicates[0]=Path=/users/*
spring.cloud.gateway.routes[0].filters[0]=PrefixPath=/users
main
@SpringBootApplication
@EnableDiscoveryClient
public class Demo04Gateway1001Application
面向服务的路由 uri
- (1)面向服务的路由是什么?
配置路由信息时,使用服务的名称来代替 ip+port的配置方式
只需要在配置文件中指定路由路径类似:lb://user-service
- (2)代理的服务地址;lb表示从eureka中获取具体服务
- (3)注意事项
lb 之后编写的服务名必须要在eureka中注册才能使用 - (4)分析
路由配置中uri所用的协议为lb时(以uri: lb://user-service为例),gateway将使用 LoadBalancerClient把user-service通过eureka解析为实际的主机和端口,并进行ribbon负载均衡。
路由前缀处理 filter
- (1)路由的前缀
请求地址与微服务的服务地址如果不一致的时候,可以通过配置路径过滤器实现路径前缀的添加和去除。
提供服务的地址:http://127.0.0.1:8001/user/8
》 添加前缀:对请求地址添加前缀路径之后再作为代理的服务地址;
http://127.0.0.1:101/8 --> http://127.0.0.1:8001/user
/8 添加前缀路径/user
spring.cloud.gateway.routes[0].predicates[0]=Path=/**
spring.cloud.gateway.routes[0].filters[0]=PrefixPath=/users
》去除前缀:将请求地址中路径去除一些前缀路径之后再作为代理的服务地址;
http://127.0.0.1:101/api
/user/8 --> http://127.0.0.1:8001/user/8 去除前缀路径/api
spring.cloud.gateway.routes[0].predicates[0]=Path=/api/users/**
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
过滤器简介
- (1)过滤器
符合条件的请求放行,否则不放行 - (2)Gateway自带过滤器有几十个,常见自带过滤器有
在配置文件中指定要使用的过滤器名称 - (3)案例:添加响应头过滤器
spring.cloud.gateway.default-filters[0]=AddResponseHeader=name,rose
spring.cloud.gateway.default-filters[1]=AddResponseHeader=age,34
过滤器分类
- (1)过滤器的分类 两类
》局部过滤器
只对当前路由起作用
spring.cloud.gateway.routes.filters
》全局过滤器
作用在所有的路由上
》spring.cloud.gateway.default-filters + 实现GatewayFilterFactory接口的过滤器
》实现GlobalFilter接口,不需要配置
自定义全局过滤器
判断请求上的token值是否为空,不为空放行
- (1)实现GlobalFilter
- (2)实现Ordered接口
- (3)符合条件,放行
- (4)否则结束响应
//1:本类为全局网关过滤器 /*
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
//exchange = req + resp
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//拦截方法,拦截到请求后,自动执行
log.info("filter 拦截方法,拦截到请求后,自动执行 ");
//以后开发中,不会将 user对象存到session,只会在地址上带上token
//根据token是否有空可以判断是否登录
//http://localhost:8001/users/3?token=10001&pageSize=30
String token = exchange.getRequest().getQueryParams().getFirst("token");
if(token == null || "".equals(token)){
//未登录 跳转到登录页
log.info("----跳到登录页面");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
exchange.getResponse().setComplete();
}
return chain.filter(exchange);//2 全部放行
}
@Override
public int getOrder() {//3:系统调用该方法获得过滤器的优先级
return 1; //数字越小,越优先
}
}
自定义局部过滤器
- (1)使用场景:请求鉴权、异常处理、记录调用时长等。
- (2)步骤
》》配置
MyParam=name,address
》》定义Config
》》MyParamGatewayFilterFactory继承AbstractGatewayFilterFactory
》》实现shortcutFieldOrder
》》实现apply
application.properties
spring.cloud.gateway.routes[0].filters[0]=MyParam=name,address
MyParamGatewayFilterFactory
//1:本类为局部过滤器类
@Component
@Slf4j
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
//5:将config交给父类的构造方法
public MyParamGatewayFilterFactory() {
super(Config.class);
}
@Override //4:过滤器
public GatewayFilter apply(Config config) {
GatewayFilter gatewayFilter = new GatewayFilter(){
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//http://127.0.0.1:1001/users/3?token=333&name=jack&address=bj
String name = exchange.getRequest().getQueryParams().getFirst(config.name);
String address = exchange.getRequest().getQueryParams().getFirst(config.address);
log.info("filter ....name"+name);
log.info("filter ....address"+address);
log.info("filter ....拦截了请求");
return chain.filter(exchange);//全部放行
}
};
return gatewayFilter;//返回一个自己定义的过滤器
}
//3:定义顺序
@Override
public List<String> shortcutFieldOrder() {//定义变量的顺序
List<String> order = new ArrayList<>();
order.add("name");
order.add("address");
return order;
}
//name,address
//http://127.0.0.1:8001/users/1?name=jack&address=bj
@Data //2:定义config
public static class Config{
private String name;
private String address;
}
}