1、zuul的大部分功能都是通過過濾器進行。zuul定義四種標準的過濾器類型,這四種過濾器應用在請求生命週期的不同時期。
pre過濾器,它在請求被zuul路由之前調用。一般用來實現身份驗證、在集羣中的選擇請求的微服務、記錄調試信息等
routing過濾器,它將請求路由到微服務。一般用於構建發送請求到微服務,並使用apache的httpclient或者ribbon進行請求微服務。
post過濾器,這種過濾器是路由到微服務之後執行,相當於後置過濾器。這種過濾器可爲請求響應的時候添加標準的http header,收集統計信息、將響應從微服務發給客戶端等,簡單地說,就是請求處理後,響應給客戶端的時候,會調用這個過濾器。
error過濾器,在其他過濾器階段,發生錯誤的時候,會執行該過濾器,相當於在執行其他過濾器的時候,出現error會被error過濾器捕獲。
當然也可以自定義過濾器,後續再寫個自定義過濾器進行學習。
查看源碼,zuul過濾器定義在org.springframework.cloud.netflix.zuul.filters包下,這些過濾器默認包含了三種不同的生命週期,pre、routing、post。
自定義過濾器,需要繼承ZuulFilter,重寫filterType、filterOrder、shouldFilter、run方法
filterType:代表自定義過濾器的類型,值有pre、route、post、error
pre:可以在請求被路由之前調用
route:在路由請求時候被調用
post:在route和error過濾器之後被調用
error:處理請求時發生錯誤時被調用
filterOrder:用來代表過濾器的執行順序,越小越先被執行,int值
shouldFilter:返回boolean值來判斷該過濾器是否被執行,true表示該過濾器生效,false反之
run:過濾器的具體處理邏輯,根據shouldFilter的返回值判斷是否執行,true則會執行run方法,false則不會
這裏自定義RouteFilter
package com.etc.zuul.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.Map; /** * 過濾器 */ @Component public class RouteFilter extends ZuulFilter { /** * 設置過濾器類型爲前置過濾器 * @return */ @Override public String filterType() { return "pre"; } /** * 設置過濾器順序,越小越先執行 * @return */ @Override public int filterOrder() { return 0; } /** * 設置過濾器是否生效,返回true則需要權限校驗, * 返回false則不需要權限校驗 * @return */ @Override public boolean shouldFilter() { //獲取上下文對象 RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); Map<String, String[]> map = request.getParameterMap(); String contentType = request.getContentType(); int contentLength = request.getContentLength(); //獲取請求uri,對uri進行訪問判斷 String uri = request.getRequestURI(); if("/webreq/error/htp".equalsIgnoreCase(uri)){ return true; } return false; } /** * 業務邏輯,只有shouldFilter返回true, * 纔會進入該方法 * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); //jwt的token,可以用請求頭傳過來,也可以用參數傳過來,一般是用請求頭傳遞 String token = request.getHeader("token"); System.out.println("=================請求頭信息================="); //請求頭信息 Enumeration<String> headersMap = request.getHeaderNames(); while (headersMap.hasMoreElements()){ String headerName = (String)headersMap.nextElement(); String headerVal =request.getHeader(headerName); System.out.println(headerName+":"+headerVal); } if(StringUtils.isEmpty(token)){ //過濾掉該路由,不對它進行路由 requestContext.setSendZuulResponse(false); //返回錯誤代碼 requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null; } }