在Spring Cloud Gateway中,DefaultFilter和GlobalFilter都是用于执行请求过滤逻辑的接口,但它们的作用有些不同。
DefaultFilter是一种内置的过滤器类型,用于实现GatewayFilter接口的默认实现,提供了一些通用的过滤逻辑,例如请求/响应日志记录、路由信息记录等。可以通过配置来自定义和覆盖DefaultFilter的行为。
GlobalFilter则是一种自定义的过滤器类型,它可以被应用于全局的请求过滤链中,无需显式地将其添加到路由规则中。GlobalFilter在请求被路由之前和之后都会被执行,并且可以对请求和响应进行修改。通常情况下,GlobalFilter用于实现一些通用的逻辑,例如身份认证、请求限流、请求日志记录等。
因此,可以认为DefaultFilter是Spring Cloud Gateway中内置的一些通用过滤器的实现,而GlobalFilter则是用户可以自定义的全局过滤器,用于实现一些通用的业务逻辑。在实际使用中,可以根据具体的需求选择合适的过滤器类型来实现请求过滤逻辑。‘
以下是一些示例,说明在不同场景下,如何使用DefaultFilter和GlobalFilter来实现请求过滤逻辑:
1、日志记录
使用DefaultFilter实现:在application.yml配置文件中,可以使用以下配置来启用请求日志记录:
spring:
cloud:
gateway:
httpclient:
wiretap: true
default-filters:
- name: RequestTimeFilter
args:
baseMessageData: true
inClass: java.lang.Object
outClass: java.lang.Object
这里配置了一个名为RequestTimeFilter的DefaultFilter,它将记录请求的时间信息,并在请求完成时将其输出到日志中。
使用GlobalFilter实现:定义一个实现了GlobalFilter接口的过滤器类,重写filter方法,在该方法中实现请求日志记录的逻辑,例如:
@Component
public class RequestLoggingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
return chain.filter(exchange).doFinally(signalType -> {
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
String path = exchange.getRequest().getPath().toString();
String method = exchange.getRequest().getMethodValue();
int status = exchange.getResponse().getStatusCode().value();
// 日志输出逻辑
log.info("Request [{} {}] finished with status [{}] in [{}] ms", method, path, status, executeTime);
});
}
@Override
public int getOrder() {
return -1;
}
}
这里定义了一个RequestLoggingFilter类,它实现了GlobalFilter接口,并重写了filter方法,在该方法中实现了请求日志记录的逻辑。通过实现GlobalFilter接口,并将过滤器添加到Spring容器中,就可以实现全局的请求日志记录。
2、身份认证
使用GlobalFilter实现:定义一个实现了GlobalFilter接口的过滤器类,重写filter方法,在该方法中实现身份认证的逻辑,例如:
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (StringUtils.isEmpty(token)) {
return unauthorized(exchange);
}
// 调用身份认证服务进行认证
boolean isValidToken = authenticate(token);
if (!isValidToken) {
return unauthorized(exchange);
}
return chain.filter(exchange);
}
private Mono<Void> unauthorized(ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
private boolean authenticate(String token) {
// 调用身份认证服务进行认证,返回认证结果
return true;
}
@Override
public int getOrder() {
return 0;
}
}
这里定义了一个AuthFilter类,它实现了GlobalFilter接口,并重写了filter方法,在该方法中实现了身份认证的逻辑。在该方法中,我们从请求头中获取认证令牌,然后调用身份认证服务进行认证,最后根
据认证结果决定是否允许请求通过。如果认证失败,就返回HTTP状态码为401(未授权)的响应,否则将请求转发给下一个过滤器或者目标服务。
可以将AuthFilter添加到Spring容器中,以便全局使用。
3、请求限流
使用GlobalFilter实现:定义一个实现了GlobalFilter接口的过滤器类,重写filter方法,在该方法中实现请求限流的逻辑,例如:
@Component
public class RateLimitFilter implements GlobalFilter, Ordered {
private final RateLimiter rateLimiter;
public RateLimitFilter(RateLimiter rateLimiter) {
this.rateLimiter = rateLimiter;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String key = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
RateLimiter.Response response = rateLimiter.isAllowed(key);
if (response.isAllowed()) {
return chain.filter(exchange);
} else {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
}
@Override
public int getOrder() {
return -2;
}
}
这里定义了一个RateLimitFilter类,它实现了GlobalFilter接口,并重写了filter方法,在该方法中实现了请求限流的逻辑。在该方法中,我们从请求中获取客户端的IP地址,并使用一个名为RateLimiter的限流工具对请求进行限流。如果请求被允许通过,就将请求转发给下一个过滤器或者目标服务,否则返回HTTP状态码为429(太多请求)的响应。
在实际使用中,可以将RateLimitFilter添加到Spring容器中,以便全局使用。同时,也可以根据具体的需求,将不同的限流规则应用于不同的路由规则或服务实例。