Zuul网关统一入口
一、什么是Zuul
Zuul 包含了对请求的路由和过滤两个主要的功能:
路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础;
过滤功能负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
Zuul 和 Eureka 进行整合,将 Zuul 自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取其他微服务的信息,同时以后的访问微服务都是通过 Zuul 跳转后获得。
二、代码实现
这里的前提是:已经创建好了 parent父工程,common 工程,provider 工程、consumer 工程、Eureka 工程。
1、创建一个 Zuul 工程
pro07-spring-cloud-zuul
2、在 Zuul 工程 的 pom.xml 中加入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
3、创建 application.yml 配置文件
server:
port: 9000
spring:
application:
name: zuul-gateway
eureka:
client:
service-url:
defaultZone: http://localhost:5000/eureka/
4、创建主启动类 SpringCloudZuul
加上 @EnableZuulProxy 注解 启用 Zuul 网关代理功能
// 启用 Zuul 网关代理功能
@EnableZuulProxy
@SpringBootApplication
public class SpringCloudZuul {
public static void main(String[] args) {
SpringApplication.run(SpringCloudZuul.class, args);
}
}
5、依次启动 Eureka注册中心、provider、consumer、Zuul ,进行访问测试
① 初步访问
三、配置路由原则
① 使用指定地址代替微服务名称
zuul:
routes:
employee: # 自定义路由规则的名称,在底层的数据结构中是 Map 的键
service-id: com-feign-consumer # 目标微服务名称,ZuulRoute 类型的一个属性
path: /zuul-emp/** # 用来代替目标微服务名称的路径, ZuulRoute 类型的一个属性
# /**表示匹配多层路径
效果:使用微服务名称和新配置的地址都可以访问
使用微服务名称访问:
使用新配置的地址访问:
② 让用户不能通过微服务名称访问
zuul:
routes:
employee: # 自定义路由规则的名称,在底层的数据结构中是 Map 的键
service-id: com-feign-consumer # 目标微服务名称,ZuulRoute 类型的一个属性
path: /zuul-emp/** # 用来代替目标微服务名称的路径, ZuulRoute 类型的一个属性
# /**表示匹配多层路径
ignored-services: # 忽略指定微服务名称,让用户不能通过微服务名称访问
- com-feign-consumer
效果:只能通过新配置的地址访问
使用微服务名称访问:
使用新配置的地址访问:
③忽略所有微服务名称
zuul:
routes:
employee: # 自定义路由规则的名称,在底层的数据结构中是 Map 的键
service-id: com-feign-consumer # 目标微服务名称,ZuulRoute 类型的一个属性
path: /zuul-emp/** # 用来代替目标微服务名称的路径, ZuulRoute 类型的一个属性
# /**表示匹配多层路径
# ignored-services: # 忽略指定微服务名称,让用户不能通过微服务名称访问
# - com-feign-consumer
ignored-services: '*' # 忽略所有微服务名称
④给访问路径添加统一前缀
zuul:
routes:
employee: # 自定义路由规则的名称,在底层的数据结构中是 Map 的键
service-id: com-feign-consumer # 目标微服务名称,ZuulRoute 类型的一个属性
path: /zuul-emp/** # 用来代替目标微服务名称的路径, ZuulRoute 类型的一个属性
# /**表示匹配多层路径
ignored-services: '*' # 忽略所有微服务名称
# ignored-services: # 忽略指定微服务名称,让用户不能通过微服务名称访问
# - com-feign-consumer
prefix: /consumer # 给访问路径添加统一前缀
效果:只有在新配置的地址前加上前缀才能访问
没有加前缀访问:
加前缀后访问:
四、使用ZuulFilter拦截过滤请求
1、需要编写一个类继承 ZuulFilter 类,并实现里面的方法。
/**
*
* 使用 ZuulFilter 拦截过滤请求
*
* @author: Herz
* @date: 2021/7/26 21:17
*/
@Component
public class MyZuulFilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(MyZuulFilter.class);
@Override
public String filterType() {
// 返回当前过滤器类型
// 可选类型包括:pre、route、post、static
// 如果需要在目标微服务前面执行过滤操作,选用 pre 类型
String fileType = "pre";
return fileType;
}
@Override
public int filterOrder() {
return 0;
}
/**
* 判断当前请求会否要进行过滤
* @return true:表示要过滤,继续执行 run()方法
* false:表示不过滤,直接放行
*/
@Override
public boolean shouldFilter() {
// 获取 requestContext 对象
RequestContext requestContext = RequestContext.getCurrentContext();
// 获取 当前请求 对象
HttpServletRequest request = requestContext.getRequest();
// 判断当前请求参数是否为 signal=hello
String parameter = request.getParameter("signal");
return "hello".equals(parameter);
}
@Override
public Object run() throws ZuulException {
logger.info("当前请求要进行过滤,run()执行了");
// 官方文档说:当前实现会忽略这个返回值,所以返回 null 即可
return null;
}
}
2、发送请求访问
① 当请求参数 signal 不满足过滤条件时
控制台没有打印信息。
②当请求参数 signal 满足过滤条件时(即 signal=hello)
同时,控制台也打印了信息