Gateway的介绍: 1. 为什么需要Gateway? 在微服务架构中,微服务系统的开发存在如下问题: 1. 每一个微服务都有各自的端口,导致端口太多,不易维护; 2. 跨域问题的解决; 3. 权限的问题解决; 2. Gateway的作用: Gateway其实就是一个微服务系统,接收所有的请求,根据URL进行路由,转发到相应的微服务系统进行处理; 3. 实现网关的技术: ngnix; spring cloud gateway spring cloud zuul ... 4. spring cloud gateway中的概念: 路由:可以理解为转发请求; 断言:可以理解为符合某种条件才进行路由; 过滤:转发请求的时候需要对请求本身进行处理; 5. spring cloud gateway的使用: 1. 创建工程it-spring-cloud-gateway,添加依赖,因为父工程已经添加了公共的依赖,所以子工程只需添加自身需要的依赖即可: <dependencies> <!--网关依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> 2. 创建配置文件application.yml,配置端口及应用名称,并将网关微服务注册给Eureka: # 注释版本 server: port: 18084 spring: application: name: api-gateway # 应用名 # Eureka服务中心配置 eureka: client: service-url: # 注册Eureka Server集群 defaultZone: http://127.0.0.1:7001/eureka 3. 创建启动类,并在启动类开启Eureka客户端 package com.it; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * ToDo * * @author Lyle * @date 2020/4/4 */ @SpringBootApplication @EnableEurekaClient public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class,args); } } 4. 路由规则配置: 在application.yml中进行如下配置: # 注释版本 server: port: 18084 spring: application: name: api-gateway # 应用名 cloud: gateway: routes: #id唯一标识,可自定义,可以配置多个,这里只配置一个为例 - id: user-service-route #路由的服务地址,即:符合条件就转发请求到这个地址 # uri: http://localhost:18082 uri: lb//user-consumer # 若配置了集群,有多个微服务,可以使用名称配置,此处18082对应的微服务名为user-consumer # 路由拦截的地址配置(断言):判断条件是否满足 # 例如:请求为:http://localhost:18084/feign/123,满足断言要求,转发到http://localhost:18081/feign/123 predicates: - Path=/feign/** #- id: user-service-route2 5. 过滤器: 1.自带的过滤器: 全局过滤器; 局部过滤器; 配置文件: # 注释版本 server: port: 18084 spring: application: name: api-gateway # 应用名 cloud: gateway: # 配置全局默认过滤器,所有请求都要经过该过滤器进行处理 default-filters: # 往响应过滤器中加入信息:X-Response-Default-MyName,值为lyle - AddResponseHeader=X-Response-Default-MyName,lyle routes: #id唯一标识,可自定义,可以配置多个,这里只配置一个为例 - id: user-service-route #路由的服务地址,即:符合条件就转发请求到这个地址 # uri: http://localhost:18082 uri: lb://user-consumer # 若配置了集群,有多个微服务,可以使用名称配置,此处18082对应的微服务名为user-consumer # 路由拦截的地址配置(断言):判断条件是否满足 # 例如:请求为:http://localhost:18084/feign/123,满足断言要求,转发到http://localhost:18081/feign/123 predicates: #- Path=/feign/** - Path=/** filters: # 请求地址添加路径前缀过滤器 # 请求为:http://localhost:18084/test,添加前缀并转发:转发到http://localhost:18081/feign/test # - PrefixPath=/feign # 去除路径前缀过滤器,1表示去除1个 # http://localhost:18084/api/test,去除前缀并转发:转发到http://localhost:18081/test - StripPrefix=1 #- id: user-service-route2 # Eureka服务中心配置 eureka: client: service-url: # 注册Eureka Server集群 defaultZone: http://127.0.0.1:7001/eureka 2.自定义过滤器: 全局过滤器; 局部过滤器; 自定义全局过滤器的实现: 在微服务it-spring-cloud-gateway中定义类交给spring管理,这个类实现接口GlobalFilter和Ordered接口,重写方法处理业务: package com.it.filter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * ToDo * * @author Lyle * @date 2020/4/4 */ @Component public class MyGlobalFilter implements GlobalFilter, Ordered { //该方法用于接收所有的请求进行业务处理 @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //模拟权限判断,只要请求中携带了token,并且值为1234就放行 //1.获取请求对象 request ServerHttpRequest request = exchange.getRequest(); //2.获取响应对象 response ServerHttpResponse response = exchange.getResponse(); //获取请求参数中token的值,判断并处理 String token = request.getQueryParams().getFirst("token"); if (!StringUtils.isEmpty(token)&&token.equals("1234")){ //有权限,放行 return chain.filter(exchange); }else { //没有权限 response.setStatusCode(HttpStatus.UNAUTHORIZED); //完成请求 return response.setComplete(); } } //用于执行过滤器的顺序的判断:过滤器链 @Override public int getOrder() { return 0; } }