SpringCloud 微服務 (十四) 服務網關 Zuul 過濾器(Pre&Post)

上篇學習了zuul路由,這邊繼續學習,粗糙的記錄zuul過濾器的用法java

 

如今對請求url作個約定,在請求url上沒有帶參數key=123的url所有過濾掉redis

①localhost:7000/product/list?key=1234         ---不過濾算法

②localhost:7000/product/list                        ---過濾,不執行spring

完成以上功能,在gateway服務中,代碼以下 : docker

package com.cloud.gateway.filters;

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 static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * 常量類
 * 過濾器狀態 FilterConstants
 * 請求狀態 HttpStatus
 * 引用其中的屬性值便可,無需本身寫
 */
@Component
public class PreFilter extends ZuulFilter {
    /**
     * filter類型
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * filter執行順序,值越小優先級越高
     * 官方推薦使用x-1方式優先排序
     * @return
     */
    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER - 1;
    }

    /**
     * filter 開啓關閉
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 實現filter邏輯
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request =requestContext.getRequest();
        String key=request.getParameter("key");

        //若是不存在,則設置沒有權限不經過,狀態爲401
        if (StringUtils.isEmpty(key)){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}

瀏覽器訪問成功則返回list列表,失敗則返回錯誤頁面,錯誤碼:401瀏覽器

 

再來實現一個post過濾器,在獲得結果以後,實如今post filter階段,返回response的,給header頭部加點信息,代碼以下: dom

package com.cloud.gateway.filters;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER;

/**
 * 常量類
 * 過濾器狀態 FilterConstants
 * 請求狀態 HttpStatus
 * 引用其中的屬性值便可,無需本身寫
 */
@Component
public class PostFilter extends ZuulFilter {
    /**
     * filter類型
     *
     * @return
     */
    @Override
    public String filterType() {
        return POST_TYPE;
    }

    /**
     * filter執行順序,值越小優先級越高
     * 官方推薦使用x-1方式優先排序
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return SEND_RESPONSE_FILTER_ORDER - 1;
    }

    /**
     * filter 開啓關閉
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 實現filter邏輯
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response = requestContext.getResponse();
        response.setHeader("POST-UUID", UUID.randomUUID().toString());
        return null;
    }
}

 

瀏覽器控制檯 請求信息 : ide

 

寫了兩次, 套路也都摸清了,能寫的地方也就這麼幾個點,後面再作 限流 操做,結合上面學的,限流作在請求filter最靠前的地方,比鑑權pre前執行,否則流量都進去了,這裏須要一個算法---令牌桶算法,這個算法不少地方已經實現了,拿來用便可,意思是以必定速率將令牌放入桶中,桶中的令牌滿了,就不會再放進去了,外部的請求進入,請求將得到桶中的令牌,得令牌者可通行,沒有令牌請求將被拒絕post

下面代碼實現 : 學習

package com.cloud.gateway.filters;

import com.cloud.gateway.exceptions.RateLimiterException;
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;

/**
 * 限流
 */
@Component
public class RateLimiterFilter extends ZuulFilter {

    //create 每秒放入100個令牌
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);

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

    /**
     * filter執行順序,值越小優先級越高
     * 官方推薦使用x-1方式優先排序
     * 選擇最高優先級SERVLET_DETECTION_FILTER_ORDER,並-1
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return SERVLET_DETECTION_FILTER_ORDER - 1;
    }

    /**
     * filter 開啓關閉
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 實現filter邏輯
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        //判斷--獲取通行令牌-->若是沒有令牌不等於以前的沒有權限401,能夠拋出自定義異常或者其餘處理
        if (!RATE_LIMITER.tryAcquire()) {
            throw new RateLimiterException();
        }

        return null;
    }
}

自定義異常: 

package com.cloud.gateway.exceptions;

public class RateLimiterException extends RuntimeException {
}

 

以上是過濾器的簡單示例

還有一個Zuul關於鑑權的使用,涉及新建user服務,也會用到docker、redis,剛剛入手mac,上面什麼都沒有,裝好了再繼續下面的學習實踐

 

---------------------------------------------------------

相關文章
相關標籤/搜索