【Spring Cloud总结】28.Zuul的Filter过滤器

接上篇《27.通过Zuul上传文件》  Spring Cloud版本为Finchley.SR2版

上一篇我们介绍了使用Zuul上传文件的相关知识。本篇我们来介绍有关Zuul的Filter过滤器禁用和Zuul回退的相关知识。
本部分官方文档:https://cloud.spring.io/spring-cloud-static/Finchley.SR4/single/spring-cloud.html#_disable_zuul_filters
注:好像Finchley.SR2的文档已经挂了,最新的是Finchley.SR4的文档。

一、Zuul的Filter过滤器

Zuul的大部分功能都是基于Filter过滤器的,这个Filter不是我们Web开发中Servlet的Filter,而是Zuul自己的Filter,但其功能类似于Servlet框架的Filter以及AOP功能。
Spring Cloud中默认已经为Zuul编写并启用了一些过滤器,这些过滤器都在spring-cloud-netflix-zuul这个Jar包的org.springframework.cloud.netflix.zuul.filters包中,我们可以打开编译器看一下:

可以看到,filters过滤器包下面有很多种类的过滤器,例如“discovery”包下的服务发现相关过滤器,“pre”包下的前置过滤器,“route”包下的路由过滤器。
我们打开pre包,可以看到下面有“DebugFilter”、“FormBodyWrapperFilter”、“PreDecorationFilter”等过滤器:

我们点开“DebugFilter”可以看到,该过滤器继承了ZuulFilter父类:

package org.springframework.cloud.netflix.zuul.filters.pre;

import javax.servlet.http.HttpServletRequest;
import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.RequestContext;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.DEBUG_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * Pre {@link ZuulFilter} that sets {@link RequestContext} debug attributes to true if
 * the "debug" request parameter is set.
 * @author Spencer Gibb
 */
public class DebugFilter extends ZuulFilter {

    private static final DynamicBooleanProperty ROUTING_DEBUG = DynamicPropertyFactory
            .getInstance().getBooleanProperty(ZuulConstants.ZUUL_DEBUG_REQUEST, false);
    private static final DynamicStringProperty DEBUG_PARAMETER = DynamicPropertyFactory
            .getInstance().getStringProperty(ZuulConstants.ZUUL_DEBUG_PARAMETER, "debug");

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return DEBUG_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        if ("true".equals(request.getParameter(DEBUG_PARAMETER.get()))) {
            return true;
        }
        return ROUTING_DEBUG.get();
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.setDebugRouting(true);
        ctx.setDebugRequest(true);
        return null;
    }
}

打开其他的过滤器也是如此,也就是说,需要实现Zuul的过滤器,就需要继承ZuulFilter的父类,通过上面的过滤器例子,可以知道继承ZuulFilter父类后,要实现filterType()、filterOrder()、shouldFilter()以及run()方法,其中:
(1)filterType()方法为获取该过滤器的类型。
通过“FilterConstants”类中的Type常量,我们可以知晓,Zuul的标准过滤器一共有“error”、“post”、“pre”和“route”的类型:

// Zuul Filter TYPE constants -----------------------------------

/**
 * {@link ZuulFilter#filterType()} error type.
 */
public static final String ERROR_TYPE = "error";

/**
 * {@link ZuulFilter#filterType()} post type.
 */
public static final String POST_TYPE = "post";

/**
 * {@link ZuulFilter#filterType()} pre type.
 */
public static final String PRE_TYPE = "pre";

/**
 * {@link ZuulFilter#filterType()} route type.
 */
public static final String ROUTE_TYPE = "route";

其中:
PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务,记录调试信息等。
ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache?HttpClient或Netflix?Ribbon请求微服务。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发送错误时执行该过滤器。
除了上面的标准过滤器以外,Zuul还允许我们自定义过滤器类型。比如我们可以自定义一个STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
Zuul请求的生命周期如下图:

该图详细描述了各种类型的过滤器的执行顺序。

(2)filterOrder()方法为获取过滤器在责任链中的顺序,其中数值越大,越后执行;
这里各个filter之间不直接进行交互,而是通过RequestContext来共享状态信息。
(3)shouldFilter()方法获取是否需要执行该过滤;
(4)run()方法就是该过滤器的具体过滤逻辑的执行。

上面的DebugFilter就是来设置RequestContext上下文对象的请求和路由是否进行Debug的设置。
如果我们要自定义Zuul的Filter过滤器,继承ZuulFilter父类,并实现以上四个方法即可。Zuul会动态的读取,编译,运行新添加的filter,

二、编写Zuul的自定义过滤器

这里我们来编写一个过滤器,并禁用它试一下。
首选我们在之前的“microserver-getaway-zuul”工程下的“”包下,新建一个“RiskCheckFilter”类,并继承自ZuulFilter父类:

package com.microserver.cloud;

import javax.servlet.http.HttpServletRequest;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.util.StringUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

public class RiskCheckFilter extends ZuulFilter{

    @Override
    public boolean shouldFilter() {
        return true;//执行该过滤器
    }

    @Override
    public Object run() throws ZuulException {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String URI = request.getRequestURI();
        if(URI.contains("/findById/")) {
            //获取RESTful风格请求URI"/user/findById/1" 中的“1"
            String userId = URI.split("/")[3];
            if(!StringUtils.isEmpty(userId)&&userId.equals("1")) {
                System.out.println("请求了UserId为1的用户,有风险!!!");
            }else {
                System.out.println("请求了UserId不为1的用户,无风险~~");
            }
        }
        return null;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;//类型为pre
    }

    @Override
    public int filterOrder() {
        return 1;//过滤器排序为1号
    }
}

该类完成的功能是,在用户访问微服务中,如果userId为1的话,认为是有风险的,会提示风险信息。这里我们的filterType()为“pre”,意味着让该过滤器在请求被路由之前调用。然后把RiskCheckFilter类在启动类“MircoserverGateWayZuulApplication”中注入Bean对象:

package com.microserver.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableZuulProxy
public class MircoserverGateWayZuulApplication {
    
    @Bean
    public RiskCheckFilter riskCheckFilter() {
        return new RiskCheckFilter();
    }

    public static void main(String[] args) {
        SpringApplication.run(MircoserverGateWayZuulApplication.class, args);
    }
}

此时启动我们的Zuul微服务、user微服务以及eureka微服务:

然后在eureka Server注册中心确认两个微服务都成功启动:

然后通过Zuul去访问user的服务,设置Id为1,可以看到控制台的打印:


然后我们再请求一个Id为2的user信息,控制台打印:

这里证明我们的过滤器设置成功!

三、禁用Zuul的Filter过滤器

在某些情况下,我们需要对Zuul的某些过滤器进行禁用,我们只需要在配置文件中,通过以下格式来禁用某个过滤器即可:
zuul.<SimpleClassName>.<filterType>.disable=true
例如禁用 org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter 过滤器,我们设置为zuul.SendResponseFilter.post.disable=true即可。


参考:《51CTO学院Spring Cloud高级视频》
https://blog.csdn.net/chengqiuming/article/details/80821023
https://my.oschina.net/voole/blog/886468

转载请注明出处:https://blog.csdn.net/acmman/article/details/103843803

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光仔December

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值