Spring cloud gateway 自定义全局过滤器不起作用

发布于 2022-03-05 20:17:01 字数 3849 浏览 765 评论 11

我在网关中打算写一个自定义全局过滤器,按照官方的文档写出来,但是在运行时根本不进入这个过滤器

application.yml:

spring:
  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
  ## 综合
  profiles: route_all
  redis:
    host: localhost
    port: 6379
    database: 0
  application:
    # 应用名称
    name: bobfintech-gateway
  cloud:
    gateway:
      discovery:
        locator:
          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
          enabled: true
      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
      routes:
      # 路由标识(id:标识,具有唯一性)   综合
      - id: route_all
        # 目标服务地址(uri:地址,请求转发后的地址)
        uri: lb://gateway-service
        # 路由条件(predicates:断言,匹配 HTTP 请求内容)
        predicates:
        ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
        - Path=/all/routeAll
        ## 匹配 GET 请求
        - Method=GET
        # 过滤器(filters:过滤器,过滤规则)
        filters:
        ## 截取路径位数
        - StripPrefix=1
        ## 添加指定参数
        - AddRequestParameter=pass, yes
        ## 熔断
        - name: Hystrix
          args:
            name: fallbackcmd
            ### fallback 时调用的方法 http://localhost:8000/fallback
            fallbackUri: forward:/fallback
        ## 限流
        - name: RequestRateLimiter
          args:
            ### 限流过滤器的 Bean 名称
            key-resolver: '#{@pathKeyResolver}'
            ### 希望允许用户每秒处理多少个请求
            redis-rate-limiter.replenishRate: 1
            ### 用户允许在一秒钟内完成的最大请求数
            redis-rate-limiter.burstCapacity: 3
 
eureka:
  instance:
    # 使用 ip 代替实例名
    prefer-ip-address: true
    # 实例的主机名
    hostname: ${spring.cloud.client.ip-address}
    # 实例的 ID 规则
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
  client:
    serviceUrl:
      # 注册中心地址
      defaultZone: http://${eureka.instance.hostname}:8761/eureka/
 

我创建的自定义过滤器如下:

package cn.com.bobfintechgateway.filter;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import reactor.core.publisher.Mono;
 

@Configuration
public class GlobalCustomerFilter
{
    
    private Logger log = LoggerFactory.getLogger(GlobalCustomerFilter.class);
    
    @Bean
    @Order(-1)
    public GlobalFilter firstFilter()
    {
        return (exchange, chain) -> {
            log.info("The first filter !");
            
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("first pass filter");
            }));
        };
    }
    
    @Bean
    @Order(0)
    public GlobalFilter secondFilter()
    {
        return (exchange, chain) -> {
            log.info("The second filter !");
            
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("second pass filter");
            }));
        };
    }
 
}

使用另一种写法仍旧不行:

package cn.com.bobfintechgateway.filter;
 
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;
 
/**
 * @ClassName TokenFilter
 * @Desc TODO   请求认证过滤器
 * @Version 1.0
 */
@Component
public class TokenFilter implements GlobalFilter{
 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("测试过滤器内容================================================");
        // 如果不为空,就通过
        return chain.filter(exchange);
    }
 
}

请问这是什么原因?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

女中豪杰 2022-03-11 06:01:21

我把

spring.cloud.gateway.discovery.locator.enabled=false

就可以访问到那个过滤器了

樱花落人离去 2022-03-11 06:01:21

spring.cloud.gateway.discovery.locator.enabled=false

就可以访问到那个过滤器了

酷到爆炸 2022-03-11 06:01:19

需要实现Ordered接口,不能用@Order注解

拥有 2022-03-11 06:01:05

zb50471449 就是他说的,要先触发GlobalFilter 路由配置,才会触发GlobalFilter过滤器

悸初 2022-03-11 06:00:46

楼主解决了吗

长安忆 2022-03-11 05:42:16

我和你写的一样啊,没用啊,就很奇怪。

终止放荡 2022-03-11 02:49:29

正常来说,全局过滤器是不需要配置,只要实现GlobalFilter接口就行,在过滤器里加一个static块看看有没有注入bean初始化过,我怕你这是没有扫描到; 这是我的,有效,给你参考下;

/**
 * @Description 日志全局过滤器
 */
@Slf4j
@Component
public class LogGlobalFilter implements GlobalFilter, Ordered {

    private final String  PLACEHOLDER = "-";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Date requestTime = new Date();
        Mono<Void> completeMono = chain.filter(exchange);
        /**
         * doFinally(),执行后置过滤方法,只有响应返回后才执行
         */
        return completeMono.doFinally(signal -> {
            ServerHttpRequest request = exchange.getRequest();
            Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
            String routeId = route.getId();
            ServerHttpResponse response = exchange.getResponse();
            HttpHeaders headers = exchange.getRequest().getHeaders();
            String remoteAddr = NetworkIpUtils.getIpAddress(request);
            String method = request.getMethod().name();
            HttpStatus httpStatus = response.getStatusCode();
            int status = httpStatus == null ? 500 : httpStatus.value();
            long length = headers.getContentLength();
            URI uri = request.getURI();
            String host = uri.getHost();
            String path = uri.getPath();
            String uriStr = uri.toString();
            String userInfo = uri.getUserInfo();
            userInfo = (userInfo == null) ? PLACEHOLDER : userInfo;
            List<String> userAgentList = headers.get("User-Agent");
            String userAgent = userAgentList == null ? PLACEHOLDER : userAgentList.toString();
            MediaType mediaType = headers.getContentType();
            String contentType = (mediaType == null) ? PLACEHOLDER : mediaType.toString();
            long useOfTime = System.currentTimeMillis() - requestTime.getTime();

            //创建自定义请求监控日志
            //189.16.1.100 - - [03/Dec/2019:23:53:06 +0800] "GET /index.php HTTP/1.1" 200 0 189.16.1.100 "http://189.16.1.100:80/index.php" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)" "0.000"
            log.trace("{} {} {} [{}] "{} {} HTTP/1.1" {} {} {} "{}" "{}" "{}" {}", remoteAddr, userInfo, routeId, requestTime, method, path, host, status, length, uriStr, userAgent, contentType, useOfTime);
        });
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

 

孤檠 2022-03-11 02:22:00

不太了解,但是你可以去github上下载一个别人的demo 导入看看,应该就明白了

天涯离梦残月幽梦 2022-03-10 18:11:17

我将自定义过滤器实现GatewayFilter并添加到路由的过滤器上,方问接口还是无效

孤独患者 2022-03-10 17:43:05

今天也碰到了这个问题,说说我的- -。项目除了GlobalFilter以外,剩下的全都是GatewayFilterFactory,这些GatewayFilterFactory都没有显式配置order,但GlobalFilter配置了order在ribbon(10100)之后。个别鉴权类GatewayFilterFactory,会导致重定向,压根进不到GlobalFilter- -.分享一下,防踩坑

猫烠⑼条掵仅有一顆心 2022-03-10 17:28:07

我之前也是碰到过这种情况,自定义了一个GlobalFilter用来验签,看日志这个Bean已经注册进容器了,但是请求就是不进这个全局过滤器。折腾了一天,各种排除依赖,各种DEBUG,
后面发现,GlobalFilter居然是基于GatewayFilter起作用的,大概逻辑是,一个请求进来后先碰GatewayFilter的规则,如果碰到了才执行下面的过滤器逻辑,如果一个GatewayFilter规则都没碰到或者
项目里根本就没定义GatewayFilter的话,就会报404。如果你是这种情况的话,建议看看你所请求的路径是不是能被已有的GatewayFilter所收纳

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文