什么是过滤器?
过滤器有什么用?
过滤器的作用范围是什么?
怎么样自定义过滤器?
官网地址:https://spring.io/projects/spring-cloud-gateway#overview
本章代码已分享至Gitee: https://gitee.com/lengcz/springcloudalibaba01.git
Gateway中,Filter的生命周期只有两个,pre和post,
(1) PRE :这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等
(2) POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header,收集统计信息和指标、将响应从微服务发送到客户端。
Gateway的Filter从作用范围可分为GatewayFilter与GlobalFliter
官网地址文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
官方文档介绍了各种内置的局部过滤器,包含了案例。
以 AddResponseHeader为例子,使用这个过滤器
AddResponseHeader=X-Response-Red, Blue
重启网关,测试
需求配置Log,第一个参数控制台是否打印,第二个参数缓存日志是否打印
Log=true,false #开启缓存日志和控制台日志,第一个参数控制台日志,第二个参数缓存日志
2. 编写内部过滤器
package com.lcz.filters;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
/**
* 自定义的局部过滤器
* 1. 类名必须是配置+GatewayFilterFactory
* 2. 必须继承AbstractGatewayFilterFactory
*/
@Component
public class LogGatewayFilterFactory extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> {
public LogGatewayFilterFactory() {
super(LogGatewayFilterFactory.Config.class);
}
//过滤器的逻辑
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (config.isCacheLog()) {
System.out.println("cacheLog开启了-------");
}
if (config.isConsoleLog()) {
System.out.println("consoleLog开启了-------");
}
Mono<Void> mono = chain.filter(exchange);
return mono;
}
};
}
//用于接收参数,需要和配置文件里的参数对应
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("consoleLog", "cacheLog");
}
@Data
@NoArgsConstructor
public static class Config {
private boolean consoleLog;
private boolean cacheLog;
}
}
自定义的局部过滤器
顾名思义,全局过滤器不和具体的路由关联,作用在所有路由上,不需要配置。通过全局过滤器可以实现对权限的统一校验,安全性校验等。
SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理。
内置的过滤器已经实现了大部分的功能,但是对应企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的。
开发中的鉴权逻辑
package com.lcz.filters;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 自定义鉴权全局过滤器
* 必须实现GlobalFilter和Ordered两个接口,并实现接口的方法
*/
@Slf4j
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
//过滤器逻辑
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if(!StringUtils.equals("admin",token)){
log.warn("认证失败----");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//401表示未认证
return exchange.getResponse().setComplete();
}
//chain.filter继续传递向下
return chain.filter(exchange);
}
//返回值越小,优先级越高
@Override
public int getOrder() {
return 0;
}
}
自定义全局过滤器,只需要实现GlobalFilter, Ordered即可。
demo里面将token放在参数里面传递只是一个演示,正常的业务逻辑当然不是这样做,这里只是为了演示。