文章目录
一、关于Gateway(面试)
1.Gateway和Zuul
SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
2.组成Gateway的三大件
1.路由
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
2.断言
开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
3.过滤
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
(类似于拦截器那一套,请求前、请求后来进行过滤)
3.Gateway的工作流程
- 客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。
- Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。 - Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,
在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
总之,路由转发+执行过滤器链
二、Gateway9527的搭建
1.Gateway9527的搭建的第一种方式
1.建Module
2.改pom
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--一般基础配置类-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3.写yml
写过的8001多了,下面这个是一开始咱们写的8001
4.主启动类
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527
{
public static void main(String[] args)
{
SpringApplication.run(GateWayMain9527.class,args);
}
}
5.业务类
无
6.测试
启动顺序是7001到8001到9527
7.说明
2.Gateway9527的搭建的第二种方式
- 之前就是在yml中配置,我们也可以写一个配置类来搭建网关。
- 需求:本次是通过9527网关访问到外网的百度新闻网址
1.改pom
和以前一样
2.写yml
yml和以前一样,以前yml是是通过9527网关访问到在8001;
现在是通过9527网关访问到百度国内新闻网址;
二者互不干扰,没必要修改yml
3.主启动类
不变
4.业务类
没有
5.配置类
@Configuration
public class GateWayConfig
{
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder)
{
RouteLocatorBuilder.Builder routes = builder.routes();
//这段代码含义是 “当访问地址 http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei。”
routes.route("path_route_atguigu", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
6.测试
三、Gateway实现动态路由
1.问题
2.解决方法
默认情况下Gateway会根据注册中心注册的服务列表,
以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
1.修改9527的yml
2.测试
四、Gateway常用的Predicate
1.After—Before—Between
2.cookie断言
3.Header请求头
4.Host Route Predicate
正确:curl http://localhost:9527/payment/lb -H “Host: www.atguigu.com”
正确:curl http://localhost:9527/payment/lb -H “Host: java.atguigu.com”
错误:curl http://localhost:9527/payment/lb -H “Host: java.atguigu.net”
5.Method Route Predicate
6.Query Route Predicate
http://localhost:9527/payment/lb?username=31
http://localhost:9527/payment/lb?username=-31
7.总结
说白了,Predicate就是为了实现一组匹配规则,
让请求过来找到对应的Route进行处理。
五、Gateway的Filter
1.过滤器的种类
见官网,它的什么31种的单一过滤器、11种的全局过滤器学不学无所谓,自定义过滤器更为常用,因为想怎么拦截怎么拦截
2.自定义过滤器
1.写自定义过滤器
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered //要实现GlobalFilter,Ordered
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
log.info("***********come in MyLogGateWayFilter: "+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");//得到请求参数里的uname
if(uname == null)
{
log.info("*******用户名为null,非法用户,o(╥﹏╥)o");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//设置状态码
return exchange.getResponse().setComplete();//返回告诉你错在了哪里
}
return chain.filter(exchange);//放行,让下一个过滤链去过滤
}
@Override
public int getOrder()
{
return 0;
}
}
3.测试