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

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的麻章網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
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,
FilterRegistry是屬性類型,contextInitialized方法上加了@PostConstruct,所以Spring創(chuàng)建這個Bean之后就會調(diào)用這個方法,遍歷filters之后,放入filterRegistry中,filterRegistry中有個ConcurrentHashMap類型的屬性,這些filter就是放入這個ConcurrentHashMap中。
方法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容器中,如下如果設(shè)置zuul.use-filter為true,那么使用的是ZuulServletFilter,默認沒有設(shè)置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方法如下,首先會調(diào)用preRoute()方法,之后調(diào)用route(),最后是postRoute(),preRoute方法調(diào)用了zuulRunner.preRoute(),ZuulRunner的preRoute()方法里面調(diào)用了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,調(diào)用runFilters方法,從FilterRegistry取出所有filterType是pre的所有ZuulFilter,之后進行排序,之后逐個調(diào)用ZuulFilter的runFilter方法——在方法processZuulFilter里面。ZuulFilter是個抽象類,runFilter方法里面調(diào)用了run方法,run方法是抽象方法,由我們自定義實現(xiàn),如下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方式來調(diào)用run方法,如果run方法拋出異常,則視為失敗,將ZuulFilterResult的ExecutionStatus設(shè)置為FAILED,所以我們實現(xiàn)的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引用的都是同一個靜態(tài)變量,所以各個調(diào)用關(guān)系見不顯示的傳遞,依然能確保線程安全。
private static final FilterRegistry INSTANCE = new FilterRegistry();
需要注意的是,ZuulServlet和ZuulServletFilter處理的是url為/zuul/*的請求,可以看List-4的this.zuulProperties.getServletPattern(),它的值就是/zuul,之后用ServletRegistration.Dynamic的addMapping方法加上處理的url為/zuul/*的。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。
文章題目:Springcloud中zuul的ZuulFilter是什么
本文地址:http://www.chinadenli.net/article14/ispsge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、網(wǎng)站營銷、軟件開發(fā)、網(wǎng)站建設(shè)、品牌網(wǎng)站建設(shè)、域名注冊
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)