91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Springcloud中zuul的Zuul Filter是什么

發布時間:2021-10-19 18:22:14 來源:億速云 閱讀:105 作者:柒染 欄目:大數據

Springcloud中zuul的Zuul Filter是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

    Springcloud的版本是Greenwich.SR2,Springboot版本是2.1.6.release.

    最近使用到Springcloud的zuul,分析了下源碼,記錄下。

    如下List-1,我們自己定義的ZuulFilter繼承zuul的zuulFilter,之后定義為Bean,交給Spring容器:

    List-1

//將過濾器交給Spring管理
@Bean
public AuthFilter authFilter(){
    return new AuthFilter();
}

//xss過濾
@Bean
public XssFilter xssFilter(){
    return new XssFilter();
}

@Bean
public HelloZuulFilter firewallFilter(){
    return new HelloZuulFilter();
}

@Bean
public HelloInfoFilter helloInfoFilter(){
    return new HelloInfoFilter();
}

    之后看下ZuulServerAutoConfiguration,如下List-2,@Autowired private Map<String, ZuulFilter> filters會從Spring容器中獲取所有的ZuulFilter,之后實例化ZuulFilterInitializer時,將這個filters傳入。

    List-2

...
@Configuration
protected static class ZuulFilterConfiguration {

    @Autowired
    private Map<String, ZuulFilter> filters;

    @Bean
    public ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory,
            TracerFactory tracerFactory) {
        FilterLoader filterLoader = FilterLoader.getInstance();
        FilterRegistry filterRegistry = FilterRegistry.instance();
        return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory,
                filterLoader, filterRegistry);
    }
}
...

    如下List-3,

  1. FilterRegistry是屬性類型,contextInitialized方法上加了@PostConstruct,所以Spring創建這個Bean之后就會調用這個方法,遍歷filters之后,放入filterRegistry中,filterRegistry中有個ConcurrentHashMap類型的屬性,這些filter就是放入這個ConcurrentHashMap中。

  2. 方法contextDestroyed上加了@PreDestroy注解,之后遍歷filters,將其從filterRegistry中移除。

    List-3

public class ZuulFilterInitializer {
	private static final Log log = LogFactory.getLog(ZuulFilterInitializer.class);
	private final Map<String, ZuulFilter> filters;
	private final CounterFactory counterFactory;
	private final TracerFactory tracerFactory;
	private final FilterLoader filterLoader;
	private final FilterRegistry filterRegistry;

	public ZuulFilterInitializer(Map<String, ZuulFilter> filters,
			CounterFactory counterFactory, TracerFactory tracerFactory,
			FilterLoader filterLoader, FilterRegistry filterRegistry) {
		this.filters = filters;
		this.counterFactory = counterFactory;
		this.tracerFactory = tracerFactory;
		this.filterLoader = filterLoader;
		this.filterRegistry = filterRegistry;
	}

	@PostConstruct
	public void contextInitialized() {
		log.info("Starting filter initializer");

		TracerFactory.initialize(tracerFactory);
		CounterFactory.initialize(counterFactory);

		for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
			filterRegistry.put(entry.getKey(), entry.getValue());
		}
	}

	@PreDestroy
	public void contextDestroyed() {
		log.info("Stopping filter initializer");
		for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
			filterRegistry.remove(entry.getKey());
		}
		clearLoaderCache();

		TracerFactory.initialize(null);
		CounterFactory.initialize(null);
	}
...

    默認會將ZuulServlet或者ZuulServletFilter注入到Spring容器中,如下如果設置zuul.use-filter為true,那么使用的是ZuulServletFilter,默認沒有設置zuul.use-filter,所以使用的是ZuulServlet,如下List-4,ZuulServlet繼承了HttpServlet,是個Servlet,之后交給ServletRegistrationBean,將這個ZuulServlet放入到web容器中。

    List-4

...
@Bean
@ConditionalOnMissingBean(name = "zuulServlet")
@ConditionalOnProperty(name = "zuul.use-filter", havingValue = "false", matchIfMissing = true)
public ServletRegistrationBean zuulServlet() {
    ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean<>(
            new ZuulServlet(), this.zuulProperties.getServletPattern());
    // The whole point of exposing this servlet is to provide a route that doesn't
    // buffer requests.
    servlet.addInitParameter("buffer-requests", "false");
    return servlet;
}

@Bean
@ConditionalOnMissingBean(name = "zuulServletFilter")
@ConditionalOnProperty(name = "zuul.use-filter", havingValue = "true", matchIfMissing = false)
public FilterRegistrationBean zuulServletFilter() {
    final FilterRegistrationBean<ZuulServletFilter> filterRegistration = new FilterRegistrationBean<>();
    filterRegistration.setUrlPatterns(
            Collections.singleton(this.zuulProperties.getServletPattern()));
    filterRegistration.setFilter(new ZuulServletFilter());
    filterRegistration.setOrder(Ordered.LOWEST_PRECEDENCE);
    // The whole point of exposing this servlet is to provide a route that doesn't
    // buffer requests.
    filterRegistration.addInitParameter("buffer-requests", "false");
    return filterRegistration;
}
...

    ZuulServlet的service方法如下,首先會調用preRoute()方法,之后調用route(),最后是postRoute(),preRoute方法調用了zuulRunner.preRoute(),ZuulRunner的preRoute()方法里面調用了FilterProcessor.getInstance().preRoute(),再深入FilterProcessor的preRoute方法,

    List-5

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

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

        try {
            this.route();
        } catch (ZuulException var12) {
            this.error(var12);
            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();
    }
}

void postRoute() throws ZuulException {
    this.zuulRunner.postRoute();
}

void route() throws ZuulException {
    this.zuulRunner.route();
}

void preRoute() throws ZuulException {
    this.zuulRunner.preRoute();
}

    FilterProcessor的preRoute()里面的代碼如下List-6,調用runFilters方法,從FilterRegistry取出所有filterType是pre的所有ZuulFilter,之后進行排序,之后逐個調用ZuulFilter的runFilter方法——在方法processZuulFilter里面。ZuulFilter是個抽象類,runFilter方法里面調用了run方法,run方法是抽象方法,由我們自定義實現,如下List-7所示,

    List-6

...
public void preRoute() throws ZuulException {
    try {
        this.runFilters("pre");
    } catch (ZuulException var2) {
        throw var2;
    } catch (Throwable var3) {
        throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + var3.getClass().getName());
    }
}

public Object runFilters(String sType) throws Throwable {
    if (RequestContext.getCurrentContext().debugRouting()) {
        Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
    }

    boolean bResult = false;
    List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
    if (list != null) {
        for(int i = 0; i < list.size(); ++i) {
            ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
            Object result = this.processZuulFilter(zuulFilter);
            if (result != null && result instanceof Boolean) {
                bResult |= (Boolean)result;
            }
        }
    }

    return bResult;
}

public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    boolean bDebug = ctx.debugRouting();
    String metricPrefix = "zuul.filter-";
    long execTime = 0L;
    String filterName = "";

    try {
        long ltime = System.currentTimeMillis();
        filterName = filter.getClass().getSimpleName();
        RequestContext copy = null;
        Object o = null;
        Throwable t = null;
        if (bDebug) {
            Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);
            copy = ctx.copy();
        }

        ZuulFilterResult result = filter.runFilter();
        ExecutionStatus s = result.getStatus();
        execTime = System.currentTimeMillis() - ltime;
        switch(s) {
        case FAILED:
            t = result.getException();
            ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
            break;
        case SUCCESS:
            o = result.getResult();
            ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);
            if (bDebug) {
                Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms");
                Debug.compareContextState(filterName, copy);
            }
        }

        if (t != null) {
            throw t;
        } else {
            this.usageNotifier.notify(filter, s);
            return o;
        }
    } catch (Throwable var15) {
        if (bDebug) {
            Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + var15.getMessage());
        }

        this.usageNotifier.notify(filter, ExecutionStatus.FAILED);
        if (var15 instanceof ZuulException) {
            throw (ZuulException)var15;
        } else {
            ZuulException ex = new ZuulException(var15, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);
            ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
            throw ex;
        }
    }
}
...

    如下List-7所示,用try catch方式來調用run方法,如果run方法拋出異常,則視為失敗,將ZuulFilterResult的ExecutionStatus設置為FAILED,所以我們實現的run方法返回什么值并不重要,重要的是不拋出異常,如果拋出異常則視為處理失敗。

    List-7

public ZuulFilterResult runFilter() {
    ZuulFilterResult zr = new ZuulFilterResult();
    if (!this.isFilterDisabled()) {
        if (this.shouldFilter()) {
            Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());

            try {
                Object res = this.run();
                zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
            } catch (Throwable var7) {
                t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
                zr = new ZuulFilterResult(ExecutionStatus.FAILED);
                zr.setException(var7);
            } finally {
                t.stopAndLog();
            }
        } else {
            zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
        }
    }
    return zr;
}

    要注意的是,上面中涉及到的FilterRegistry引用的都是同一個靜態變量,所以各個調用關系見不顯示的傳遞,依然能確保線程安全。

private static final FilterRegistry INSTANCE = new FilterRegistry();

    需要注意的是,ZuulServlet和ZuulServletFilter處理的是url為/zuul/*的請求,可以看List-4的this.zuulProperties.getServletPattern(),它的值就是/zuul,之后用ServletRegistration.Dynamic的addMapping方法加上處理的url為/zuul/*的。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

博白县| 乐陵市| 保山市| 嘉祥县| 百色市| 棋牌| 嫩江县| 南澳县| 佛冈县| 乌苏市| 房产| 阿勒泰市| 桃园县| 万源市| 枣阳市| 闵行区| 屯留县| 乃东县| 永康市| 吉隆县| 虎林市| 雷山县| 呼和浩特市| 双牌县| 哈密市| 连云港市| 康乐县| 盱眙县| 麻城市| 渭源县| 静海县| 漳平市| 儋州市| 谷城县| 溆浦县| 新乡市| 梧州市| 永新县| 龙井市| 文登市| 洮南市|