「 從0到1學習微服務SpringCloud 」12 Zuul的綜合使用

上次講了Zuul的基本使用,這篇講的是綜合使用,好比過濾器,限流,鑑權等應用
這裏繼續使用api-getway這個項目html

過濾器

實現token驗證(前置過濾器)

1.新建一個類,繼承ZuulFilter,細節方面看下面代碼,還有別忘了在類上加@Component註解,不然不生效git

@Component
public class TokenFilter extends ZuulFilter {

    /**
     * 過濾器類型
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     *  優先級,數字越大,優先級越低
     *  只作通常過濾,沒有特殊要求的,能夠放在內置過濾器後面
     * @return
     */
    @Override
    public int filterOrder() {
        //最後一個內置PRE過濾器後面
        return PRE_DECORATION_FILTER_ORDER+1;
    }

    /**
     * 是否執行該過濾器,true表明須要過濾
     * 這裏能夠忽略掉一些不須要過濾請求
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String token = request.getParameter("token");
        //若是沒有token,則返回401
        //這裏就不作校驗了,只判斷有無
        if(StringUtils.isEmpty(token)){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            ctx.setResponseBody("未登錄!");
             //設置返回體的編碼爲UTF-8
            HttpServletResponse response = ctx.getResponse();
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
        }
        return null;
    }
}

2.開啓Eureka Server,api-getway,service-hi項目github

3.測試
不帶token http://localhost:8900/myHi/hi算法

image

帶token http://localhost:8900/myHi/hi?token=123spring

image

添加Response Header(後置過濾器)

1.新建一個類,繼承ZuulFilterapi

@Component
public class AddResponseHeaderFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return POST_TYPE;
    }

    @Override
    public int filterOrder() {
        //放在返回過濾器前
        return SEND_RESPONSE_FILTER_ORDER - 1;
    }

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

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletResponse  response = context.getResponse();
        response.setHeader("my-response","hello");
        return null;
    }
}

2.開啓Eureka Server,api-getway,service-hi項目跨域

3.測試
http://localhost:8900/myHi/hi?token=123瀏覽器

image

限流

限流的功能也是常常會在網關實現,咱們這裏使用令牌桶算法實現,這個算法已經有相關實現了,直接用就行緩存

令牌桶算法:一邊以一個固定的速率發令牌,另外一邊用一個固定大小的桶裝令牌,桶滿了則將令牌該令牌丟棄,不然放進桶裏。進來的請求嘗試從桶裏取令牌,取到令牌的請求放行,沒有令牌的請求則會被拒絕。以下圖cors

image

代碼實現

1.新建一個類,繼承ZuulFilter

@Component
public class RateFilter extends ZuulFilter {
    /**
     * 建立令牌桶 容量爲1(爲了方便測試,這裏設置小一點)
     */
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(1);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //設置順序 請求轉發過濾器 前
        return SERVLET_DETECTION_FILTER_ORDER - 1;
    }

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

    @Override
    public Object run() throws ZuulException {
        //獲取不到令牌
        if(!RATE_LIMITER.tryAcquire()){
            //TODO 跳轉到錯誤頁面或友好提示
            throw new RuntimeException("訪問人數過多,請稍後再試!");
        }
        return null;
    }
}

2.開啓Eureka Server,api-getway,service-hi項目

3.測試
在過濾器run方法中打個斷點,而後開3個瀏覽器tag訪問http://localhost:8900/myHi/hi?token=123,進入斷點後,點擊忽略斷點,再點擊釋放斷點運行程序

結果:
至少有一個請求會被拒絕,後臺拋出異常

image

image

跨域

瀏覽器是不容許跨域訪問,一般解決跨域,可在接口類或方法加上@CrossOrigin(allowCredentials = "true"),但這種方法是很繁瑣的,不可能有100個接口就加100次,因此咱們這裏可使用Zuul實現跨域

代碼實現

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter(){
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        //是否支持Cookie跨域
        config.setAllowCredentials(true);
        //支持的原始域 *表示全部
        config.setAllowedOrigins(Arrays.asList("*"));
        //容許的頭 *表示全部
        config.setAllowedHeaders(Arrays.asList("*"));
        //容許的請求方法 POST,GET等 *表示全部
        config.setAllowedMethods(Arrays.asList("*"));
        //緩存時間 表示300秒內對相同請求不須要再判斷
        config.setMaxAge(300L);

        //path參數爲對哪些域名進行設置 /**表示全部
        source.registerCorsConfiguration("/**",config);
        return  new CorsFilter(source);
    }
}

由於跨域是須要在不一樣域名下,這裏不太好演示,就不測試了。

以上3種是Zuul比較經常使用的一些使用方式,今天就到這裏,下期見~

代碼已更新至gitthub
https://github.com/zhangwenka...

若是以爲不錯,分享給你的朋友!

一個立志成大腿而天天努力奮鬥的年輕人

伴學習伴成長,成長之路你並不孤單!

掃描二維碼,關注公衆號

相關文章
相關標籤/搜索