Spring Cloud之Gateway网关应⽤

该文章介绍了如何使用SpringCloudGateway作为微服务的代理,隐藏具体服务信息,以及配置Eureka服务发现。同时,文章展示了如何创建一个新的Maven模块,添加必要的依赖,并设置应用配置。此外,文中还讲解了自定义全局过滤器BlackListGlobalFilter来限制特定IP的访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使⽤⽹关对静态化微服务进⾏代理(添加在它的上游,相当于隐藏了具体微服务的信息,对外暴露的是⽹关)。
1. 右键⽗⼯程【 yx-parent 】选择【 New - Module 】选项,然后选择创建【 Maven 】类型项⽬(不勾选模 板),将项⽬名称设置为 注意这⾥不选择⽗⼯程

项⽬的pom.xml⽂件引⼊以下依赖。注意,Gateway不需要使⽤Web模块,使⽤的是 WebFlux(类似于Spring MVC)模块,因此不要引⼊starter-web模块,⽽引⼊的是starter-webflux模块。

    <!-- Spring Boot父启动器依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath />
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- Gateway网关 -->
        <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>
        <!-- 日志依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Lombok工具 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <!-- 引入Jaxb开始 -->
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.2.10-b140310.1920</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- 引入Jaxb结束 -->
        <!-- Actuator可以帮助你监控和管理Spring Boot应用 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 链路追踪 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <!-- Spring Cloud依赖版本管理 -->
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!-- 编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <!-- 打包插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
3. 如果导⼊ Maven 依赖后,提示 'parent.relativePath' of POM com.yx:yx-cloud-gateway:1.0-SNAPSHOT 问题,则 解决⽅案是在 <parent> 标签中加上 <relativePath /> 标签,然后重新编译,解决问题

 

错误原因:
1.xxx parent ⾥写的并不是 xxx 的上⼀级,⽽是继承了 Spring Boot
2.Maven 构建 jar 包的时候查找顺序: relativePath 元素中的地址 -> 本地仓库 -> 远程仓库。
3. <relativePath /> 设定⼀个空值将始终从仓库中获取,不从本地路径获取。

.在项⽬的com.yx.gateway包下创建GatewayApplication启动类。

package com.qf.product;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient  //将当前的项目标记为注册中心的客户端,然后向注册信息
public class ProductApplication9001 {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication9001.class,args);
    }
}

在项⽬的resources⽬录下创建application.yml配置⽂件并添加以下内容。

server:
  port: 9300
eureka:
  client:
    serviceUrl: # Eureka Server的路径
      defaultZone: http://YXCloudEurekaServerC:9200/eureka,http://YXCloudEurekaServerD:9201/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
spring:
  application:
   name: yx-cloud-gateway
  # gateway⽹关配置
  cloud:
    gateway:   # gateway⽹关配置
      routes: # 配置路由
        - id: service-page-router
           # 动态路由:从(消费)注册中⼼获取对应服务的实例
          #lb://表示从注册中心获取服务信息(//后更的是具体服务实例的具体名称)
          uri:  lb://yx-service-page
          predicates: # 当断⾔匹配成功后,则将请求转发给某个微服务
            - Path=/page/**
        - id: service-product-router
          uri: lb://yx-service-product
          predicates:
    # http://127.0.0.1:9300/product/query/1 - /query/1 - 商品微服务
            - Path=/product/**
          filters:
    # 访问uri时,会过滤掉uri中Path取值匹配上的前⼀部分,uri中第⼆部分才是⽬标访问路径
            - StripPrefix=1

 

⾃定义全局过滤器实现 IP 访问限制
y.filter 包下创建 BlackListGlobalFilter 全局过滤器
package com.qf.product.fifter;

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.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 定义全局过滤器,会对所有路由⽣效
 */
@Slf4j
@Component
public class BlackListGlobalFilter implements GlobalFilter, Ordered {
    // 模拟⿊名单(实际可以去数据库或者Redis中查询)
    private static List<String> blackList = new ArrayList<>();

    static {
        // 模拟本机地址
        blackList.add("127.0.0.1");
        blackList.add("10.48.185.11");
    }

    /**
     * 过滤器核⼼⽅法
     *
     * @param exchange 封装了request和response对象的上下⽂
     * @param chain    ⽹关过滤器链(包含全局过滤器和单路由过滤器)
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        /* 实现思路:获取客户端IP,判断是否在⿊名单中,在的话就拒绝访问,不在的话就放⾏ */
        // 从上下⽂中取出request和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 从request对象中获取客户端IP
        String clientIP = request.getRemoteAddress().getHostString();
        log.info("=====>IP: " + clientIP);
        // 获取到客户端IP后去⿊名单中查询,存在的话就决绝访问
        if (blackList.contains(clientIP)) {
            // 状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            String data = "Request be denied!";
            //响应的字符串转化成字节数组,将来输出返回客户端
            DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
            // 决绝访问,直接返回指定结果数据
            return response.writeWith(Mono.just(wrap));
        }
        // 合法请求,放⾏,执⾏后续的过滤器
        return chain.filter(exchange);
    }

    /**
     * 返回值表示当前过滤器的顺序(优先级),数值越⼩,优先级越⾼
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值