ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
* Spring Cloud Zuul 是整合Netflix公司的 Zuul开源项目(官方:https://github.com/Netflix/zuul); * Zuul 包含了对请求路由和校验过滤两个最主要的功能: 1.其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础, 客户端请求网关/api/product,通过路由转发到 product 服务 客户端请求网关/api/order,通过路由转发到 order 服务 2.而过滤功能则负责对请求的处理过程进行干预,是实现请求校验等功能的基础. * Zuul 和 Eureka 进行整合,将 **Zuul 自身注册为 Eureka 服务治理中的服务**,同时从 Eureka 中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。 ## **1. Zuul路由转发功能实战** ### 1.1 新建一个zuul路由模块 ![](https://img.kancloud.cn/80/51/8051a9198bb8621e0a76c837a58912f0_332x289.png) ### 1.2 修改pom文件 springboot web依赖、Eureka client启动器依赖、zuul启动器依赖 ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--zuul路由网关依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> ``` ### 1.3 修改yml,配置Eureka client 因为zuul需要向Eureka server注册和zuul配置 ~~~ zuul: routes: provider-product: # 路由名称,名称任意,路由名称唯一 path: /product/** # 访问路径 serviceId: microservice-product # 指定服务ID,会自动从Eureka中找到此服务的ip和端口 stripPrefix: false # 代理转发时去掉前缀,false:代理转发时不去掉前缀 例如:为true时请求 /product/get/1,代理转发到/get/1 ~~~ 完整配置 ~~~ server: port: 7001 spring: application: name: microservice-zuul-gateway eureka: client: registerWithEureka: true # 服务注册开关 fetchRegistry: true # 服务发现开关 serviceUrl: # 客户端(服务提供者)注册到哪一个Eureka Server服务注册中心,多个用逗号分隔 # 单机版 Eureka 服务注册中心 #defaultZone: http://localhost:6001/eureka # 集群版 Eureka 服务注册中心 defaultZone: http://eureka6001.com:6001/eureka,http://eureka6002.com:6002/eureka instance: instanceId: ${spring.application.name}:${server.port} # 指定实例ID,就不会显示主机名了 preferIpAddress: true #访问路径可以显示IP地址 zuul: routes: provider-product: # 路由名称,名称任意,路由名称唯一 path: /product/** # 访问路径 serviceId: microservice-product # 指定服务ID,会自动从Eureka中找到此服务的ip和端口 stripPrefix: false # 代理转发时去掉前缀,false:代理转发时不去掉前缀 例如:为true时请求 /product/get/1,代理转发到/get/1 ~~~ ### 1.4 @EnableZuulProxy 注解标注启动类,开启zuul的功能 ~~~ @EnableZuulProxy //开启zuul的功能 @SpringBootApplication public class ZuulServer_7001 { public static void main(String[] args) { SpringApplication.run(ZuulServer_7001.class, args); } } ~~~ 启动Eureka server,服务提供端和消费端,zuul server 观看Eureka server注册情况,如下图Eureka server处于集群模式,一共有三个服务端进行了注册,其中包括zuul路由 ![](https://img.kancloud.cn/9c/72/9c720e70fd1454aa406a161d47343033_1253x330.png) ### 1.5 路由测试 **1. 不用路由直接访问** 访问: http://localhost:8001/product/get/1 ![](https://img.kancloud.cn/bb/74/bb740a41ea1345f62ff1e475d45261d1_564x115.png) **2. 使用路由访问 (注意是 7001 端口), 当前要加上服务名** 访问:http://localhost:7001/microservice-product/product/get/1 ![](https://img.kancloud.cn/01/04/0104ab3d03aa1c18cc38b6c676793177_572x104.png) **3.不加服务名,直接通过路由访问** 因为zuul路由服务已经配置了 /product/** 形式的请求URL,都会转发到serviceId: microservice-product 微服务实例 ~~~ zuul: routes: provider-product: # 路由名称,名称任意,路由名称唯一 path: /product/** # 访问路径 serviceId: microservice-product # 指定服务ID,会自动从Eureka中找到此服务的ip和端口 stripPrefix: false # ~~~ ![](https://img.kancloud.cn/6b/0c/6b0cd0f19d41bc3fe83ab0131438696e_503x119.png) ## **2. 路由过滤实战** ### **2.1 自定义过滤器** > Zuul核心就是过虑器,通过过虑器实现**请求过虑**,**身份校验**等。 **自定义过虑器需要继承 ZuulFilter**,ZuulFilter是一个抽象类,需要覆盖它的4个方法,如下: **1. filterType**:返回字符串代表过滤器的类型,返回值有: * pre:在请求路由之前执行 * route:在请求路由时调用 * post:请求路由之后调用, 也就是在route和errror过滤器之后调用 * error:处理请求发生错误时调用 **2. filterOrder**:此方法返回整型数值,通过此数值来定义过滤器的执行顺序,数字越小优先级越高。 **3. shouldFilter**:返回Boolean值,判断该过滤器是否执行。返回true表示要执行此过虑器,false不执行。 **4. run**:过滤器的业务逻辑。 ### **2.2 自定义LoginFilter** 自定义一个zuul过滤器 LoginFilter ,大致需要以下几个操作步骤 1. 继承 ZuulFilter 2. 在类上添加 @Component 注解 (一定不要少了) 3. 实现抽象方法 ~~~ package com.tuna.springcloud.zuul.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @Component //一定不要少了 public class LoginFilter extends ZuulFilter { Logger logger = LoggerFactory.getLogger(getClass()); @Override public String filterType() { return "pre"; // } @Override public int filterOrder() { return 1; //返回值是int,会根据返回值进行定义过滤器的执行顺序,值越小优先级越大 } @Override public boolean shouldFilter() { return true; //当前过滤器是否被执行,true则执行,false不执行 } //定义 过滤功能 @Override public Object run() throws ZuulException { //1.获取请求上下文(zuul封装) RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); String token = request.getParameter("token"); //如果说请求带了token值,则表示已经登录过 if(token == null) { logger.warn("此操作需要先登录系统"); //没有登录 过,则不进行路由转发 context.setSendZuulResponse(false);//拒绝访问 context.setResponseStatusCode(200); //响应状态码 try { context.getResponse().getWriter().write("token is empty..."); } catch (IOException e) { e.printStackTrace(); } return null; } //通过,会进行路由转发 logger.info("通过,会进行路由转发"); return null; } } ~~~ ### **2.2 测试** 1. 直接访问,没有任何token信息,zuul过滤直接拒绝访问 ![](https://img.kancloud.cn/04/77/04776891275862d5267719a1502276b2_401x122.png) 2. 带token信息,可以访问 ![](https://img.kancloud.cn/31/a7/31a769b1735ea578124c0a06d4b68417_578x206.png)