Spring Cloud Gateway---自定義過濾器

前言


即便Spring Cloud Gateway自帶有許多實用的GatewayFilter Factory、Gateway Filter、Global Filter,可是在不少情景下咱們仍然但願能夠自定義本身的過濾器。實現一些騷操做。因此自定義過濾器就顯得很是有必要。本文主要介紹了自定義Gateway Filter、自定義Global Filter、自定義Gateway Filter Factoryspring

案例


實現本身的過濾器咱們其實能夠去查看Spring Cloud Gateway自帶過濾器源碼是如何實現的,api

自定義Gateway Filter


實現自定義的Gateway Filter咱們須要GatewayFilter、Ordered兩個接口bash

/**
 * 此過濾器功能爲計算請求完成時間
 */
public class MyFilter implements GatewayFilter, Ordered {

    private static final String ELAPSED_TIME_BEGIN = "elapsedTimeBegin";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(ELAPSED_TIME_BEGIN, System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long startTime = exchange.getAttribute(ELAPSED_TIME_BEGIN);
                    if (startTime != null) {
                        System.out.println(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
                    }
                })
        );
    }

    /*
    *過濾器存在優先級,order越大,優先級越低
    */
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

複製代碼

定義好MyFilter之後,其須要跟Route綁定使用,不能在application.yml文件中配置使用app

@Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes().route(r ->
                r.path("/aa")
                        //轉發路由
                        .uri("http://localhost:8003/provider/test")
                        //註冊自定義過濾器
                        .filters(new MyFilter())
                        //給定id
                        .id("user-service"))
                .build();
    }
複製代碼

測試結果:能夠在控制檯看到請求響應時間。ide

自定義Gateway Filter Factory


不少時候咱們更但願在配置文件中配置Gateway Filter,因此咱們能夠自定義過濾器工廠實現。
自定義過濾器工廠須要繼承AbstractGatewayFilterFactory測試

@Component
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {

    private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class);

    private static final String AUTHORIZE_TOKEN = "token";
    private static final String AUTHORIZE_UID = "uid";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public AuthorizeGatewayFilterFactory() {
        super(Config.class);
        logger.info("Loaded GatewayFilterFactory [Authorize]");
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }

    @Override
    public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) {
        return (exchange, chain) -> {
            if (!config.isEnabled()) {
                return chain.filter(exchange);
            }

            ServerHttpRequest request = exchange.getRequest();
            HttpHeaders headers = request.getHeaders();
            String token = headers.getFirst(AUTHORIZE_TOKEN);
            String uid = headers.getFirst(AUTHORIZE_UID);
            if (token == null) {
                token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
            }
            if (uid == null) {
                uid = request.getQueryParams().getFirst(AUTHORIZE_UID);
            }

            ServerHttpResponse response = exchange.getResponse();
            if (StringUtils.isEmpty(token) || StringUtils.isEmpty(uid)) {
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
            String authToken = stringRedisTemplate.opsForValue().get(uid);
            if (authToken == null || !authToken.equals(token)) {
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
            return chain.filter(exchange);
        };
    }

    public static class Config {
        // 控制是否開啓認證
        private boolean enabled;

        public Config() {}

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }
}
複製代碼

application.yml配置使用ui

# 網關路由配置
spring:
  cloud:
    gateway:
      routes:
      - id: user-service
        uri: http://localhost:8077/api/user/list
        predicates:
        - Path=/user/list
        filters:
        # 關鍵在下面一句,值爲true則開啓認證,false則不開啓
        # 這種配置方式和spring cloud gateway內置的GatewayFilterFactory一致
        - Authorize=true
複製代碼

自定義Global Filter


實現自定義全局過濾器須要繼承GlobalFilterOrderedthis

@Component
public class MyGloablFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("1111111111111111");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
複製代碼

使用它只須要加上@Component註解spa

相關文章
相關標籤/搜索