Zuul提供了一个框架,可以对过滤器进行动态的加载,编译,运行。
Zuul的过滤器之间没有直接的相互通信,他们之间通过一个RequestContext的静态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所需要传递的数据。
Zuul的过滤器是由Groovy写成,这些过滤器文件被放在Zuul Server上的特定目录下面,Zuul会定期轮询这些目录,修改过的过滤器会动态的加载到Zuul Server中以便过滤请求使用。
下面有几种标准的过滤器类型:
Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
(1) PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
(2) ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
(3) POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
(4) ERROR:在其他阶段发生错误时执行该过滤器。
内置的特殊过滤器
zuul还提供了一类特殊的过滤器,分别为:StaticResponseFilter和SurgicalDebugFilter
StaticResponseFilter:StaticResponseFilter允许从Zuul本身生成响应,而不是将请求转发到源。
SurgicalDebugFilter:SurgicalDebugFilter允许将特定请求路由到分隔的调试集群或主机。
自定义的过滤器
除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。
例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
2、过滤器的生命周期
Zuul请求的生命周期如图,该图详细描述了各种类型的过滤器的执行顺序。
使用:
1)导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
2)主函数开启注解
@EnableZuulProxy
3)配置文件
server:
port: 8084
spring:
application:
name: geteway
eureka:
client:
service-url:
defaultZone: #注册到Ereuka,拉去服务
zuul:
routes:
user-service:
path: /user/**
serviceId: user-service
strip-prefix: false # 去除路由前缀 localhost:8084/user/1
# prefix: api #加前缀
# user-service: /user/**
# user-service: /user-service/** #服务id,请求映射地址 默认为该配置 localhost:8084/user-service/user/1
ignored-services:
- consumer-service #仅供服务间相互调用,不给客户端直接使用。
5)访问浏览器
http://localhost:8084/user-service/user/5 //尽管去掉前缀,但是默认配置依然存在。
{"id":5,"username":"ty是","password":"ty"}
http://localhost:8084/user/5
{"id":5,"username":"ty是","password":"ty"}
添加过滤器:
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;//前置
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; //在处理请求头后进行过滤
}
@Override
public boolean shouldFilter() {//是否过滤
return true;
}
@Override
public Object run() throws ZuulException {//逻辑处理
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("access-token");
if (StringUtils.isBlank(token)) {
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
}
return null;
}
}