API网关,能替换Zuul。比Zuul强大。
优点:
性能强劲:是第一代网关Zuul的1.6倍;
功能强大:内置了很多实用的功能,例如转发、监控、限流等;
设计优雅,容易扩展;
缺点:
其实现依赖Netty与WebFlux,不是传统的Servlet模型,学习成本高;
不能将其部署在Tomcat、Jetty等Servlet容器中,只能打成jar包运行;
需要SpringBoot2.0及以上版本;
使用:
引入依赖:
<!-- gateway 注意:此模块不能引入starter-web -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
启动类:
@SpringBootApplication
public class ShopGateWay {
public static void main(String[] args) {
SpringApplication.run(ShopGateWay.class,args);
}
}
配置文件:
server:
port: 7000
spring:
application:
name: api-gateway
cloud:
#网关配置
gateway:
routes: #路由数组,可配置多个 【路由就是指当请求满足什么样的条件的时候转发到哪个服务】
- id: product_route #当前路由的标识,唯一
uri: http://127.0.0.1:8081 #请求最终要被转发到的地址
order: 1 #路由的优先级,数字越小优先级越高
predicates: #断言(条件判断,返回值是boolean 转发请求要满足的条件)
- Path=/product-serv/** #当请求路径满足Path指定的规则时,此路由信息才会正常转发
filters: #过滤器(在请求传递过程中,对请求进行操作)
- StripPrefix=1 #在请求转发之前去掉一层前缀路径 /product-serv/** --》**
#metadata: #元数据
到此即可完成基本的gateway使用。
从Nacos中获取服务信息
上述配置中,配置文件以硬编码的方式将目标uri写死固定,非常不方便。
所以要从Nacos中获取服务信息。
步骤:
引入nacos依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
更新application.yml配置文件代码:
server:
port: 7000
spring:
application:
name: api-gateway
cloud:
#网关配置
gateway:
routes: #路由数组,可配置多个 【路由就是指当请求满足什么样的条件的时候转发到哪个服务】
- id: product_route #当前路由的标识,唯一
# uri: http://127.0.0.1:8081 #请求最终要被转发到的地址
uri: lb://shop-product # lb 指的是负载均衡,后面跟的是具体微服务在nacos中的服务名
order: 1 #路由的优先级,数字越小优先级越高
predicates: #断言(条件判断,返回值是boolean 转发请求要满足的条件)
- Path=/product-serv/** #当请求路径满足Path指定的规则时,此路由信息才会正常转发
filters: #过滤器(在请求传递过程中,对请求进行操作)
- StripPrefix=1 #在请求转发之前去掉一层前缀路径 /product-serv/** --》**
#metadata: #元数据
discovery:
locator:
enabled: true # 让gateway从Nacos中获取服务信息
nacos:
discovery:
server-addr: 127.0.0.1:8848
在配置类上开启服务发现:加上 @EnableDiscoveryClient 注解。
完成。
SpringCloud Gateway执行流程:
predicate断言详解:
内置断言:
自定义路由断言:
结构:
1、新建一个类,命名格式:XXX + RoutePredicateFactory;
2、继承抽象类 AbstractRoutePredicateFactory<XXXRoutePredicateFactory.Config>;
3、无参构造器
public XXXRoutePredicateFactory() {
super(XXXRoutePredicateFactory.Config.class);
}
4、
public List<String> shortcutFieldOrder() {
//返回的是参数,例如下面这个返回的是"datetime"
return Collections.singletonList("datetime");
}
5、
public Predicate<ServerWebExchange> apply(XXXRoutePredicateFactory.Config config) {
return new GatewayPredicate() {
public boolean test(ServerWebExchange serverWebExchange) {
//判断逻辑,返回boolean值。
}
};
}
public static class Config {
//config相应实体类
}
例如:自定义一个限制年龄的断言:
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
//无参构造器
public AgeRoutePredicateFactory() {
super(AgeRoutePredicateFactory.Config.class);
}
//读取配置文件中的参数值,然后赋值到配置实体类属性上
public List<String> shortcutFieldOrder() {
return Arrays.asList("minAge","maxAge");
}
//断言逻辑
public Predicate<ServerWebExchange> apply(Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
//获取参数
String age = serverWebExchange.getRequest().getQueryParams().getFirst("age");
if (StringUtils.isNotEmpty(age)){
int i = Integer.parseInt(age);
if (i<config.getMaxAge() && i>config.getMinAge()){
return true;
}
}
return false;
}
};
}
//配置类,用于接受配置文件中的对应参数
@Data
public static class Config{
private Integer minAge;
private Integer maxAge;
// public Integer getMinAge() {
// return minAge;
// }
//
// public void setMinAge(Integer minAge) {
// this.minAge = minAge;
// }
//
// public Integer getMaxAge() {
// return maxAge;
// }
//
// public void setMaxAge(Integer maxAge) {
// this.maxAge = maxAge;
// }
}
}
在配置文件中使用即可:
结果:
SpringCloud Gateway 过滤器:
1、作用:
对请求根据某些条件进行过滤。
2、生命周期:
Pre、Post
3、分类:
GatewayFilter局部过滤器:作用在特定的路由上;
GlobalFilter全局过滤器:作用在全部路由上
局部过滤器:
内置的局部过滤器:
有30种. 详情见官网. Spring Cloud Gateway
自定义局部过滤器:
与自定义断言套路结构差不多:
1. 命名要以 Sign+GatewayFilterFactory为格式.
2. 继承抽象类: AbstractGatewayFilterFactory<XXXGatewayFilterFactory.Config>
3.无参构造器
4.模板:
public class XXXGatewayFilterFactory extends AbstractGatewayFilterFactory<XXXGatewayFilterFactory.Config> {
//无参构造器
public XXXGatewayFilterFactory() {
super(XXXGatewayFilterFactory.Config.class);
}
//读取配置文件中参数,赋值到配置类中的相应参数
public List<String> shortcutFieldOrder() {
return Arrays.asList("要获取的参数名");//可获取多个
}
//逻辑
public GatewayFilter apply(XXXGatewayFilterFactory.Config config) {
}
//配置类
public static class Config {
}
}
全局过滤器:
内置全局过滤器:
见官网: 地址在上面...
自定义全局过滤器:
官方的一段代码:
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
由此可以看出,自定义的全局过滤器必须要实现两个接口:GlobalFilter和Ordered.
getOrder()方法用于设置返回过滤器执行的优先级, filter方法用于设置过滤的逻辑.