Spring Cloud Gateway 的自定義Filter分為GatewayFilter局部過濾器和GlobalFilter全局過濾器
GatewayFilter : 需要通過spring.cloud.routes.filters 配置在具體路由下,只作用在當前路由上或通過spring.cloud.default-filters配置在全局,作用在所有路由上
GlobalFilter : 全局過濾器,不需要在配置文件中配置,作用在所有的路由上,最終通過GatewayFilterAdapter包裝成GatewayFilterChain可識別的過濾器
GatewayFilter局部過濾器
自定義局部過濾器需要實現GatewayFilter
和 Ordered
兩個接口
@Slf4j
public class CostomerGatewayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("自定義局部過濾器:{}====================", "CustomerGatewayFilter");
return chain.filter(exchange);
}
/**
* 值越小,優先級越高
*
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
在配置文件中使用自定義局部過濾器還需要使用自定義過濾器工廠來包裝
這里的后綴GatewayFilterFactory
不能寫錯,因為配置文件中配置的自定義過濾器名就是自定義過濾器工廠的類名去掉GatewayFilterFactory
后綴的名字
把后綴寫錯了項目啟動的時候就會報錯說找不到這個自定義過濾器
public class CustomerGatewayFilterFactory extends AbstractGatewayFilterFactory {
@Override
public GatewayFilter apply(Object config) {
return new CostomerGatewayFilter();
}
}
在配置類中將自定義過濾器工廠注冊到容器中,當然也可以在自定義過濾器工廠類上加@Component注解
@Configuration
public class GatewayConfig {
@Bean
public CustomerGatewayFilterFactory myGatewayFilterFactory() {
return new CustomerGatewayFilterFactory();
}
}
在配置文件中配置自定義過濾器,這里的Customer
就是自定義過濾器工廠類名去掉GatewayFilterFactory
后綴的名字
spring:
application:
name: service-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: service-provider
uri: lb://service-provider
predicates:
- Path=/provider/**
filters:
- Customer
GlobalFilter全局過濾器
自定義全局過濾器需要實現 GlobalFilter
和 Ordered
接口
@Slf4j
public class LoginFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
String token = request.getHeaders().getFirst("token");
log.info("訪問的路徑:{}", path);
log.info("token: {}==================", token);
if (token == null) {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
ResponseData responseData = new ResponseData(401, "請登錄");
String res = null;
try {
res = new ObjectMapper().writeValueAsString(responseData);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
DataBuffer wrap = response.bufferFactory().wrap(res.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(wrap));
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
在配置類中注冊全局過濾器,這樣這個全局過濾器就是全局過濾了
@Configuration
public class GatewayConfig {
@Bean
public GlobalFilter loginFilter() {
return new LoginFilter();
}
}