1、是什么
路由过滤器可用于修改进入HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用
SpringCloud GateWay 内置了多种路由过滤器,他们都由GateWayFilter的工厂类来产生
官网:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories
2、Spring Cloud GateWay的Filter
1、生命周期 Only Two
1、pre
2、post
2、种类 Only Two
1、GateWayFilter(网关过滤器)
2、GlobalFilter(全局过滤器)
3、常用的GateWayFilter
1、两个主要接口介绍
public class MyLogGateWayFilter implements GlobalFilter, Ordered
2、能干嘛
4、自定义过滤器
@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("*****************come in MyLogGateWayFilter"+new Date());String uname = exchange.getRequest().getQueryParams().getFirst("uname");if (uname==null){log.info("*******用户名为null, 非法用户 ,o(╥﹏╥)o");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0; //这个是优先级}
网关过滤器
Path路径过滤器
Path路径过滤器可以实现URL重写,通过重写URL可以实现隐藏实际路径提高安全性,易于用户记忆和键入,易于被搜索引擎收录等优点,实现方式如下:
1、RewritePathGateWayFilterFactory
ReWritePath网关过滤器工厂采用路径正则表达式参数和替换参数,使用Java正则表达式来灵活地重写请求路径
2、PrefixPathGateWayFilterFactory
PrefixPath网关过滤器工厂为匹配的URI添加指定前缀
请求
发现可以正常请求,那是因为在filter添加了/product
3、StripPrefixGateWayFilterFactory
StripPrefix网关过滤器工厂采用了一个参数StripPrefix,该参数表示在将请求发送到下游之前从请求中剥离的路径个数。
4、SetpathGateWayFilterFactory
SetPath网关过滤器工厂采用路径模板参数,它提供了一种通过允许模板化路径段来操作请求路径的简单方法,使用了SpringFramework中的URI模板,允许多个匹配段
参数过滤器
AddRequestParameter网关过滤器工厂会将指定参数添加至匹配的下游请求中
Status状态过滤器
SetStatus网关过滤器工厂采用单个状态参数,它必须是有效的Spring HttpStatus,它可以是整数404 或枚举NoT_FOUND 的字符串表示

即使请求成功,也可以更改状态
全局过滤器
全局过滤器不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GateWayFilterChain可识别的过滤器,它是请求业务以及路由的URI转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,并作用在每个路由上。
自定义过滤器
自定义网关过滤器
自定义网关过滤器需要实现以下两个接口: GateWayFilter,Ordered。
(1)创建过滤器
/*** 此过滤器功能为计算请求完成时间*/public class MyFilter implements GatewayFilter, Ordered {private static final String ELAPSED_TIME_BEGIN = "elapsedTimeBegin";@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {exchange.getAttributes().put(ELAPSED_TIME_BEGIN, System.currentTimeMillis());return chain.filter(exchange).then(Mono.fromRunnable(() -> {Long startTime = exchange.getAttribute(ELAPSED_TIME_BEGIN);if (startTime != null) {System.out.println(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");}}));}/**过滤器存在优先级,order越大,优先级越低*/@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}}
(2)注册过滤器
定义好MyFilter以后其需要跟Route绑定使用,不能在application.yml文件中配置使用
@Beanpublic RouteLocator routeLocator(RouteLocatorBuilder builder) {return builder.routes().route(r ->r.path("/abc/**")//去掉前缀1节.filters(p->p.stripPrefix(1))//转发路由.uri("lb://eureka-client")//注册自定义过滤器.filters(new MyFilter())//给定id.id("user-service")).build();}
自定义全局过滤器
会在所有的路由上
自定义过滤器, 假设对请求头的token进行认证。
/*** @Author: zhihao* @Date: 2020/3/31 17:38* @Description: 自定义过滤器* @Versions 1.0**/@Component //交给框架管理public class MyGatewayFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取请求对象ServerHttpRequest request = exchange.getRequest();//2.获取请求头AuthenticateList<String> authenticate = request.getHeaders().get("Authenticate");if (null == authenticate || authenticate.isEmpty()) {//说明Authenticate为空,返回错误码,阻止通过网关路由ServerHttpResponse response = exchange.getResponse();Map<String,String> resultMap = new LinkedHashMap<>();resultMap.put("code", "401");resultMap.put("message", "没有token");String jsonStr = JSONUtil.toJsonStr(resultMap);//将错误信息输出页面DataBuffer dataBuffer = response.bufferFactory().wrap(jsonStr.getBytes());response.setStatusCode(HttpStatus.UNAUTHORIZED); //状态码response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");Mono<Void> mono = response.writeWith(Mono.just(dataBuffer));return mono;//return response.setComplete();}//......可以通过String[] strings = authenticate.toArray(new String[authenticate.size()]);String str = strings[0];return chain.filter(exchange);}@Overridepublic int getOrder() {//值越大则优先级越低。return -1;}}
使用全局过滤器实现鉴权


