GatewayFilter是網關中提供的一種過濾器,可以對進入網關的請求和微服務返回的響應做處理
Spring提供了31種不同的路由過濾器工廠
名稱 |
說明 |
AddRequestHeader |
給當前請求添加一個請求頭 |
RemoveRequestHeader |
移除請求中的一個請求頭 |
AddResponseHeader |
給響應結果中添加一個響應頭 |
RemoveResponseHeader |
從響應結果中移除有一個響應頭 |
RequestRateLimiter |
限制請求的流量 |
... |
路由過濾器
給所有進入userservice的請求添加一個請求頭:- AddRequestHeader=info, AddRequestHeader!
實現方式:在gateway項目中修改application.yml文件,給userservice的路由添加過濾器:
spring: cloud: gateway: routes: # 網關路由配置 - id: user-service uri: lb://userservice predicates: - Path=/user/** filters: # 過濾器 - AddRequestHeader=info, AddRequestHeader! # 添加請求頭
userservice項目中controller中的請求方法上獲取Info的內容
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/{id}") public User queryByid(@PathVariable("id") Long id, @RequestHeader(value = "Info",required = false) String info) { System.out.println(info); return userService.queryById(id); } }
默認過濾器
如果要對所有的路由都生效,則可以將過濾器工廠寫到default下。格式如下
spring: gateway: routes: # 網關路由配置 - id: user-service # 路由id,自定義,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目標地址 http就是固定地址 uri: lb://userservice # 路由的目標地址 lb就是負載均衡,后面跟服務名稱 predicates: # 路由斷言,也就是判斷請求是否符合路由規則的條件 - Path=/user/** # 這個是按照路徑匹配,只要以/user/開頭就符合要求 #filters: # 過濾器 # - AddRequestHeader=info, AddRequestHeader! # 添加請求頭 - id: feign-order-service uri: lb://feignorderservice predicates: - Path=/order/** default-filters: # 默認過濾器,會對所有的路由請求都生效 - AddRequestHeader=Info,'default filers request header!' # 添加請求頭
全局過濾器GlobalFilter
全局過濾器的作用也是處理一切進入網關的請求和微服務響應,和默認過濾器處理一樣,那為什么還要全局過濾器呢?
默認過濾器通過配置設定過濾器,過濾器的邏輯時固定的,無法根據項目需求隨意調整。
GlobalFilter的邏輯需要自己寫代碼實現
定義方式是實現GlobalFilter接口
public interface GlobalFilter { /** * Process the Web request and (optionally) delegate to the next {@code WebFilter} * through the given {@link GatewayFilterChain}. * @param exchange 請求上下文,可以獲取request、response等信息 * @param chain 過濾器鏈,下一個過濾器 * @return {@code Mono<Void>} to indicate when request processing is complete */ Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain); }
需求:定義全局過濾器,攔截請求,判斷請求的參數是否滿足下面條件:
- 參數中是否有authorization,
- authorization參數值是否為admin
- 如果同時滿足則放行,否則攔截
//@Order(-1) //過濾器執行順序 @Component //spring容器管理 public class AuthorizationFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1.獲取請求參數 ServerHttpRequest request = exchange.getRequest(); MultiValueMap<String, String> params = request.getQueryParams(); // 2.獲取參數中的 authorization 參數 String auth = params.getFirst("authorization"); // 3.判斷參數值是否等於 admin if ("admin".equals(auth)) { // 4.是,放行 return chain.filter(exchange); } // 5.否,攔截 // 5.1.設置狀態碼 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); // 5.2.攔截請求 return exchange.getResponse().setComplete(); } @Override public int getOrder() { return -1; } }
注意:Order注解和implements Ordered作用是完全一樣的,二選一即可。
gateway項目結構
訪問:http://localhost:10018/user/1
訪問:http://localhost:10018/user/1?authorization=admin
過濾器執行順序
過濾器鏈那就會有過濾器執行順序
過濾器都必須指定一個int類型的order值,order值越小,優先級越高,執行順序越靠前。
GlobalFilter通過實現Ordered接口,或者添加@Order注解來指定order值
路由過濾器和defaultFilter的order由Spring指定,默認是按照聲明順序從1遞增
當過濾器的order值一樣時,會按照 defaultFilter 、 路由過濾器、 GlobalFilter的順序執行
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加載defaultFilters,然后再加載某個route的filters,然后合並。
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法會加載全局過濾器,與前面的過濾器合並后根據order排序,組織過濾器鏈