有人会疑问,之前的默认过滤器不也是针对所有路由请求的吗?为什么又要有一个全局过滤器?答案很简单,因为之前的默认过滤器我们只能在配置文件里面配置一些Spring规定好的参数,但是如果我们有一个复杂的业务逻辑想要加到拦截的请求内呢,那之前的默认过滤器不就没有办法了。
1.认识全局过滤器
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。 区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。
定义方式是实现GlobalFilter接口。
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息,甚至往里面存个东西,取个东西都行,从请求进入网关开始,一直到结束为止,整个流程中都可以共享exchange对象,第一个参数就是让我们编写整个过滤器的业务逻辑的,你需要的信息里面都有
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono<Void>} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
在filter中编写自定义逻辑,可以实现下列功能:
-
登录状态判断
-
权限校验
-
请求限流等
2.自定义全局过滤器
实例:定义全局过滤器,拦截请求,判断请求的参数是否有authorization且值为admin
实现:在gateway服务中定义一个过滤器
package cn.itcast.gateway.filters;
import com.sun.org.apache.bcel.internal.generic.RET;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author 温柔哥
* @create 2024-01-19 22:34
*/
// @Order() // 过滤器有很多,根据这个顺序来决定谁先执行谁后执行,值越小越先,默认,也可通过实现Ordered接口来实现
@Component // 注入到Spring容器中
public class Authorization 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();
}
/**
* 等同于@order(-1)注解的功能
* @return
*/
@Override
public int getOrder() {
return -1;
}
}
测试:
如果不加参数的话
@总结
全局过滤器的作用是什么?
- 对所有路由都生效的过滤器,并且可以自定义处理逻辑
实现全局过滤器的步骤?
- 实现GlobalFilter接口
- 添加@Order注解或实现Ordered接口
- 编写处理逻辑