一.网关概念
1.网关作为系统的唯一流量入口,封装内部系统的架构,所有请求都先经过网关,由网关将请求路由到合适的微服务
2.各个组件的对比
二.网关的搭建
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2.在启动类上加上注解
@EnableDiscoveryClient
3.在配置文件中填写信息
server:
port: 8888
spring:
application:
name: gateway-service
cloud:
nacos:
server-addr: localhost:8848
gateway:
routes:
- id: path
predicates:
- Path=/gateway/**
uri: lb://user-service
- id: query
predicates:
- Query=name,jjh
uri: lb://user-service
- id: tobaidu
uri: http://www.baidu.com
predicates:
- Path=/to/**
default-filters:
- AddRequestHeader=JJH,is NB!
discovery:
locator:
enabled: true
lower-case-service-id: true
id: 每个路由的唯一值,不重复即可
predicates: 断言,一共有十一种断言,例如path,montheds,query等,具体可以到官网查询
uri: 要转发的具体地址, lb 代表负载均衡 ,后面跟上服务名称,也可以是具体的ip地址
三.断言
1.断言的类型
Path: 路径断言,
- Path=/gateway/** ,则只要是gateway开头的请求都将被转发,
Query: 查询参数断言,
-Query=name,jjh ,只要在请求路径上包含参数name=jjh时,进行匹配,
可以支持正则表达式,如jjh.表示最后一个字母是任意的
Method: 请求方法断言,
-Method=GET ,当请求是GET时,进行匹配
Header: 请求头断言,
-Header=header-name,jjh, 当携带请求头时,进行匹配
2.自定义断言
自定义断言需要继承AbstractRoutePredicateFactory类,重写apply()方法,通过serverWebExchange.getRequest()获取请求信息
(1)自定义查询参数断言
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<
MyRoutePredicateFactory.MyConfig> {
public MyRoutePredicateFactory() {
super(MyConfig.class);
}
/**
* 将配置文件中的值按返回集合的顺序,赋值给配置类
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(new String[]{"name"});
}
@Override
public Predicate<ServerWebExchange> apply(MyConfig config) {
return (ServerWebExchange exchange) ->{
System.out.println("自定义路由断言");
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(name.equals(config.getName())){
return true;
}else {
return false;
}
};
}
public static class MyConfig{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
这里定义了一个静态内部类,用来提供获取配置文件的参数,表示查询参数为name,
主要是重写了shortcutFieldOrder()方法,它将配置文件中的参数赋值给配置类,返回一个String的集合,
然后在断言里配置上该类的前面部分名称My
- id: nameQuery
uri: lb://user-service
predicates:
- My=JJh
这样在请求时加上?name=JJh,就会转发,否则不转发
(2)自定义年龄范围断言
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<
AgeRoutePredicateFactory.MyConfig> {
public AgeRoutePredicateFactory() {
super(MyConfig.class);
}
@Override
public Predicate<ServerWebExchange> apply(MyConfig config) {
return (ServerWebExchange exchange) ->{
String age = exchange.getRequest().getQueryParams().getFirst("age");
assert age != null;
if(!age.matches("[0-9]+")){
return false;
}
int Age = Integer.parseInt(age);
if(Age >= config.getMaxAge() && Age < config.getMinAge()){
return true;
}else {
return false;
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return super.shortcutFieldOrder();
}
public static class MyConfig{
private int minAge;
private int maxAge;
public int getMinAge() {
return minAge;
}
public void setMinAge(int minAge) {
this.minAge = minAge;
}
public int getMaxAge() {
return maxAge;
}
public void setMaxAge(int maxAge) {
this.maxAge = maxAge;
}
}
}
在配置文件里写上:
- id: ageQuery
predicates:
- Age=1,9
uri: lb://user-service
这样就会对年龄的范围做校验,在这个范围内,符合将被转发,否则不会转发
四.过滤器
1.请求头过滤器
- id: path
predicates:
- Path=/gateway/**
uri: lb://user-service
default-filters:
- AddRequestHeader=JJH,is NB!
添加该配置,将对该路径添加头信息
2.移除请求头过滤器
filters:
- RemoveRequestHeader=X-header-age
会移除该X-header-age请求头
3.状态码设置
filters:
- SetStatus=401
4.重定向设置
filters:
- RedirectTo=302,http://www.baidu.com
该请求将重定向到百度去
5.全局过滤器
网关需要做一些全局性的限制,例如限流,IP黑名单等,可以设置一个全局过滤器
@Configuration
public class GlobalCustomFilter {
@Bean
@Order(-1)
public GlobalFilter zero(){
return ((exchange, chain) -> {
return chain.filter(exchange)
.then(Mono.fromRunnable(()->{ System.out.println("-1号过滤器");
}));
});
}
@Bean
@Order(0)
public GlobalFilter second(){
return ((exchange, chain) -> {
return chain.filter(exchange)
.then(Mono.fromRunnable(()->{ System.out.println("0号过滤器");
}));
});
}
@Bean
@Order(1)
public GlobalFilter first(){
return ((exchange, chain) -> {
return chain.filter(exchange)
.then(Mono.fromRunnable(()->{ System.out.println("1号过滤器");
}));
});
}
}
这样就可以实现一个全局过滤的效果,order的数字越小,越先执行