Spring Cloud学习(四)Zuul过滤器详解

转载自:http://www.itmuch.com/spring-cloud/zuul/spring-cloud-zuul-filter/
    http://blog.didispace.com/spring-cloud-zuul-exception-2/
    http://blog.didispace.com/spring-cloud-zuul-exception-3/

  过滤器是Zuul的核心组件,本节来详细讨论Zuul的过滤器。

过滤器类型与请求生命周期

  Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
  (1) PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
  (2) ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
  (3) POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
  (4) ERROR:在其他阶段发生错误时执行该过滤器。

  除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
  Zuul请求的生命周期如图所示,该图详细描述了各种类型的过滤器的执行顺序。
Spring Cloud学习(四)Zuul过滤器详解_第1张图片
  com.netflix.zuul.http.ZuulServlet的service方法实现也可以看出,Zuul处理外部请求过程时,各个类型过滤器的执行逻辑:

try {
    preRoute();
} catch (ZuulException e) {
    error(e);
    postRoute();
    return;
}
try {
    route();
} catch (ZuulException e) {
    error(e);
    postRoute();
    return;
}
try {
    postRoute();
} catch (ZuulException e) {
    error(e);
    return;
}

  从代码中可以看到三个try-catch块,它们依次分别代表了pre、route、post三个阶段的过滤器调用,在catch的异常处理中都会被error类型的过滤器进行处理。error类型的过滤器处理完毕之后,除了来自post阶段的异常之外,都会再被post过滤器进行处理。

自定义Zuul过滤器

  理解过滤器类型和请求生命周期后,来编写一个Zuul过滤器。编写Zuul的过滤器非常简单,只需继承抽象类ZuulFilter,然后实现几个抽象方法就可以了。
  示例代码,定义一个简单的Zuul过滤器,它实现了在请求被路由之前检查HttpServletRequest中是否有accessToken参数,若有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误。

@Component
public class AccessFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

    @Override
    public String filterType() {
        return "pre";
    }

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

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());

        Object accessToken = request.getParameter("accessToken");
        if (accessToken == null) {
            log.warn("access token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("miss token");
            return null;
        }
        log.info("access token ok");
        return null;
    }
}

  在上面实现的过滤器代码中,通过继承ZuulFilter抽象类并重写了下面的四个方法来实现自定义的过滤器。这四个方法分别定义了:

  • filterType:过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。这里定义为pre,代表会在请求被路由之前执行。详细可以参考com.netflix.zuul.ZuulFilter.filterType() 中的注释。
  • filterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。
  • shouldFilter:判断该过滤器是否需要被执行。这里直接返回了true,因此该过滤器对所有请求都会生效。实际运用中可以利用该函数来指定过滤器的有效范围。
  • run:过滤器的具体逻辑。这里通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由。

Zuul默认过滤器

  Spring Cloud Zuul自带的核心过滤器,例如DebugFilterFormBodyWrapperFilterPreDecorationFilter等。这些过滤器都存放在spring-cloud-netflix-core这个Jar包的org.springframework.cloud.netflix.zuul.filters包中。具体的各类过滤器可以参看如下图:
Spring Cloud学习(四)Zuul过滤器详解_第2张图片

禁用Zuul过滤器

  Spring Cloud默认为Zuul编写并启用了一些过滤器,一些场景下,想要禁用掉部分过滤器,此时该怎么办呢?只需设置zuul...disable=true,即可禁用SimpleClassName所对应的过滤器。以过滤器org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter为例,只需设置zuul.SendResponseFilter.post.disable=true,即可禁用该过滤器。

你可能感兴趣的:(-------【Spring,Cloud】)