spring cloud网关zuul之filter注册

原文地址 https://my.oschina.net/u/3300636/blog/851984?nocache=1491877235421

zuul开启

首先由@EnableZuulProxy 注解是开启zuul的注解。

@EnableCircuitBreaker
@EnableDiscoveryClient
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
//引入zuul配置
@Import({ZuulProxyConfiguration.class})
public @interface EnableZuulProxy {
}

ZuulProxyConfiguration 继承了ZuulConfiguration

//该配置等同于xml中的beans
@Configuration
public class ZuulProxyConfiguration extends ZuulConfiguration {
@Configuration
@EnableConfigurationProperties({ZuulProperties.class})
//加载了ZuulServlet后才会加载该配置
@ConditionalOnClass({ZuulServlet.class})
@Import({ServerPropertiesAutoConfiguration.class})
public class ZuulConfiguration {

这两个类主要加载了四类东西:

1,注册zuulServlet,ZuulController 这是后面调用一些列zuulFilter的入口。

//ZuulController实现ServletWrappingController
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
    ModelAndView var3;
    try {
       //此处调用zuulServlet中的方法
        var3 = super.handleRequestInternal(request, response);
    } finally {
        RequestContext.getCurrentContext().unset();
    }

    return var3;
}

2,加载zuul各种自带的filter,比如preDecorationFilter、ribbonRoutingFilter等等

  我这个版本中(1.1.2.RELEASE),zuul默认加载的filter有: pre类型的filter5个,route的3个,post的2个,共10个filter。  每个filter的功能这里就不详述了。

一些场景下,我们想要禁用掉部分过滤器,此时该怎么办呢?在网上看到了这个方法:

只需设置zuul...disable=true ,即可禁用SimpleClassName所对应的过滤器。以过滤器org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter为例,只需设置zuul.SendResponseFilter.post.disable=true ,即可禁用该过滤器。

3,加载ZuulFilterConfiguration,这个是定义在ZuulConfiguration中的Configuration。这个配置是将所有filter由ZuulFilterInitializer收集到FilterRegistry中。调用时,filter都是从这当中取的。

@Configuration
protected static class ZuulFilterConfiguration {
//按类型将所有ZuulFilter注入到map中
    @Autowired
    private Map filters;

    protected ZuulFilterConfiguration() {
    }

    @Bean
    public ZuulFilterInitializer zuulFilterInitializer() {
        return new ZuulFilterInitializer(this.filters);
    }
}

4,加载ZuulRefreshListener、ZuulDiscoveryRefreshListener用于动态刷新zuul配置

p.s. 当应用启动时,加载顺序是:Configuration配置》ConditionalOnClass注解的bean》Configuration中的Configuration》自定义bean》Configuration中的bean》Configuration中的Configuration中的bean

zuul之filter调用

基本的调用顺序就不细说了,转载文章中介绍的比较详细。这里说一下zuul一个有点绕的地方。在ZuulServlet中

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    try {
        this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
        RequestContext e = RequestContext.getCurrentContext();
        e.setZuulEngineRan();

        try {
            this.preRoute();
        } catch (ZuulException var12) {
            this.error(var12);
            this.postRoute();
            return;
        }

        try {
            this.route();
        } catch (ZuulException var13) {
            this.error(var13);
            this.postRoute();
            return;
        }

        try {
            this.postRoute();
        } catch (ZuulException var11) {
            this.error(var11);
        }
    } catch (Throwable var14) {
        this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName()));
    } finally {
       //清空上下文
        RequestContext.getCurrentContext().unset();
    }
}


如果执行pre类型的filter抛出ZuulException则执行error类型的filter,再执行post类型的filter

如果执行route类型的filter抛出ZuulException则执行error类型的filter,再执行post类型的filter

如果执行post类型的filter抛出ZuulException则执行error类型的filter

如果在抛出其他异常,或者在catch ZuulException后执行发生异常,则执行error类型的filter

这里有点绕,如果使用的时候需要注意一下。另外zuul许多默认的filter,虽然是zuul开发人员考虑周到,但在我们自己定制功能中,也可能造成麻烦。

你可能感兴趣的:(spring,cloud,Spring,boot相关实战知识的专栏)