Spring Cloud Gateway①入门以及自定义过滤器开发

本文开发环境介绍

开发依赖版本
Spring Boot2.7.0
Spring Cloud2021.0.1
Spring Cloud Alibaba2021.0.1.0

转发示例演示

启动Spring Cloud Gateway的最小依赖配置

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--引⼊webflux-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>

转发配置示例

以下是一个简单的转发的配置,把/baidu的请求转发到https://www.baidu.com

server:
  port: 8081
spring:
  application:
    name: demo-gateway
  cloud:
    gateway:
      #路由配置
      routes:
        - id: baidu
          uri: https://www.baidu.com
          predicates:
            - Path=/baidu
          filters:
            - StripPrefix=1

Spring Boot启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoGatewayApplication.class, args);
    }
}

程序启动

程序启动后输出以下日志,说明程序启动成功

Started DemoGatewayApplication in 16.408 seconds (JVM running for 19.345)

浏览器访问

在浏览器地址栏输入http://localhost:8081/baidu
在这里插入图片描述

演示总结

Spring Cloud Gateway内置了多种过滤器,我们示例中演示了StripPrefix过滤器的使用,把原始请求/baidu截断了,这样转发到http://localhost:8081/baidu时才不会出现404错误

自定义过滤器

Spring Cloud Gateway虽然自带有许多实用的GatewayFilter FactoryGateway FilterGlobal Filter,但是在很多业务情景下仍然需要自定义过滤器,实现一些自定义操作,满足业务需求。所以自定义过滤器就显得非常有必要。本文分表介绍自定义Gateway Filter、自定义Global Filter、自定义Gateway Filter Factory

自定义Gateway Filter

实现自定义的Gateway Filter,需要实现GatewayFilterOrdered两个接口

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
@Slf4j
public class DemoGatewayFilter implements GatewayFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.debug("this is GatewayFilter!");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 数值越小,越先执行
        return 0;
    }
}

定义好DemoGatewayFilter以后,需要跟Route绑定使用,不能在application.yml文件中配置使用

@Configuration
public class FilterAutoConfiguration {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes().route(r ->
                        r.path("/**")
                                .filters(gfs -> gfs.filters(new DemoGatewayFilter()))
                                .uri("https://www.baidu.com"))
                .build();
    }
}

测试结果: 可以在控制台看到输出this is GatewayFilter!,但会报404,因为/baidu的请求转发后最终请求的是https://www.baidu.com/baidu

自定义Gateway Filter Factory

很多时候更希望在配置文件中配置Gateway Filter, 像使用gateway内置的过滤器那样,所以可以自定义过滤器工厂实现。稍微改造下上面的DemoGatewayFilter

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
@Slf4j
public class DemoGatewayFilter implements GatewayFilter, Ordered {

    private final Config config;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (!config.isEnabled()) {
            return chain.filter(exchange);
        }

        log.debug("this is DemoGatewayFilterFactory!");
        log.debug("args: {}, {}, {}", config.isEnabled(), config.getArg1(), config.getArg2());

        exchange.getAttributes().put("begin_time", System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long beginTime = exchange.getAttribute("begin_time");
                    log.info("begin:{}, end:{}", beginTime, System.currentTimeMillis());
                })
        );
    }

    @Override
    public int getOrder() {
        // 数值越小,越先执行
        return 0;
    }

    @Data
    public static class Config {
        private boolean enabled;
        private String arg1;
        private String arg2;
    }
}

注释掉上面测试时绑定的Route

@Configuration
public class FilterAutoConfiguration {

//    @Bean
//    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
//        return builder.routes().route(r ->
//                        r.path("/**")
//                                .filters(gfs -> gfs.filters(new DemoGatewayFilter1()))
//                                .uri("https://www.baidu.com"))
//                .build();
//    }
}

自定义过滤器工厂需要继承AbstractGatewayFilterFactory

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

@Slf4j
@Component
public class DemoGatewayFilterFactory extends AbstractGatewayFilterFactory<DemoGatewayFilter.Config> {

    public DemoGatewayFilterFactory() {
        super(DemoGatewayFilter.Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        // yml配置文件中参数的赋值顺序
        return Arrays.asList("enabled", "arg1", "arg2");
    }

    @Override
    public GatewayFilter apply(DemoGatewayFilter.Config config) {
        return new DemoGatewayFilter(config);
    }
}

在application.yml配置使用

server:
  port: 8081
spring:
  application:
    name: demo-gateway
  cloud:
    gateway:
      #路由配置
      routes:
        - id: baidu
          uri: https://www.baidu.com
          predicates:
            - Path=/baidu
          filters:
            - StripPrefix=1
            - Demo=true,hello,world

测试结果: 控制台可以看到输出

this is DemoGatewayFilterFactory!
args: true, hello, world

自定义Global Filter

实现自定义全局过滤器需要实现GlobalFilterOrdered

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class DemoGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.debug("this is DemoGlobalFilter");
        return chain.filter(exchange);
    }

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

测试结果: 控制台可以看到输出
在这里插入图片描述

filter多种配置方式

同一种filter可以配置多次,配置方式也有多种,以下是不同方式的示例

server:
  port: 8081
spring:
  application:
    name: demo-gateway
  cloud:
    gateway:
      #路由配置
      routes:
        - id: baidu
          uri: https://www.baidu.com
          predicates:
            - Path=/baidu
          filters:
            - StripPrefix=1
            - Demo=true,hello,world
            - name: Demo
              args:
                enabled: true
                arg1: hello2
                arg2: world2

测试结果: 控制台可以看到输出
在这里插入图片描述

总结

示例演示了启动一个Spring Cloud Gateway需要的最小依赖,以及程序配置。通过自定义Filter可以满足我们个性化的业务需求,希望可以帮助大家快速基于Gateway做二次开发。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太空眼睛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值