1. 程式人生 > 實用技巧 >Spring-Cloud-Gateway Predicate謂詞(斷言)使用與自定義

Spring-Cloud-Gateway Predicate謂詞(斷言)使用與自定義

自定義路由謂詞需要繼承 AbstractRoutePredicateFactory 工廠類,重寫 apply() 方法的邏輯和shortcutFieldOrder方法。

在 apply() 方法中可以通過 serverWebExchange.getRequest() 拿到 ServerHttpRequest 物件,從而可以獲取到請求的引數、請求方式、請求頭等資訊。

apply() 方法的引數是自定義的配置類,在使用的時候配置引數,在 apply 方法中直接獲取使用。

命名需要以 RoutePredicateFactory 結尾,比如 UserNameCheckRoutePredicateFactory,那麼在使用的時候 UserNameCheck 就是這個路由謂詞工廠的名稱。程式碼如下所示。

自定義路由謂詞可以根據業務重寫路徑匹配規則或請求路徑日誌跟蹤。

本類例子:檢查請求引數中的userName是否與配置的資料相同,如果相同則允許訪問,否則不允許訪問

package com.lynch.gateway.predicate;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated; import org.springframework.web.server.ServerWebExchange; import javax.validation.constraints.NotEmpty; import java.util.function.Predicate; /** * 自定義謂詞工廠類 * * 1、繼承AbstractRoutePredicateFactory類 * 2、重寫apply方法 * 3、apply方法的引數是自定義的配置類,可以在apply方法中直接獲取使用配置引數。 * 4、類的命名需要以RoutePredicateFactory結尾 * * 本類例子:檢查請求引數中的userName是否與配置的資料相同,如果相同則允許訪問,否則不允許訪問
*/ @Component public class UserNameCheckRoutePredicateFactory extends AbstractRoutePredicateFactory<UserNameCheckRoutePredicateFactory.Config> { public UserNameCheckRoutePredicateFactory() { super(Config.class); } @Override public Predicate<ServerWebExchange> apply(UserNameCheckRoutePredicateFactory.Config config) { // 寫法1 return new Predicate<ServerWebExchange>() { @Override public boolean test(ServerWebExchange serverWebExchange) { String userName = serverWebExchange.getRequest().getQueryParams().getFirst("userName"); if(StringUtils.isBlank(userName)){ return false; } //檢查請求引數中的userName是否與配置的資料相同,如果相同則允許訪問,否則不允許訪問 if(userName.equals(config.getName())){ return true; } return false; } }; // 寫法2 /* return serverWebExchange -> { String userName = serverWebExchange.getRequest().getQueryParams().getFirst("userName"); if(StringUtils.isBlank(userName)){ return false; } //檢查請求引數中的userName是否與配置的資料相同,如果相同則允許訪問,否則不允許訪問 if(userName.equals(config.getName())){ return true; } return false; }; */ } @Validated public static class Config{ @NotEmpty private String name; public String getName(){ return name; } public void setName(String name){ this.name=name; } } }


在application.yml中新增路由配置,如下:

spring:
  application:
    name: mima-cloud-gateway
  cloud:
    gateway:
      routes:
        #自定義謂詞UserNameCheckRoutePredicateFactory的配置使用
        #謂詞用來匹配路徑
        -  id: Auth_route
           uri: lb://mima-cloud-producer
           order: 1
           predicates:
             - Path=/**
             # name配置為UserNameCheckRoutePredicateFactory類字首UserNameCheck
             # 只有訪問http://localhost:8801/getheader?userName=lynch 才可以訪問,否則為404
             # 必須攜帶userName請求引數,並且值為lynch
             - name: UserNameCheck
               args:
                 name: lynch
server:
  port: 8801
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${server.port}
debug: true
management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: always
    shutdown: true