Spring Cloud Gateway 使用 Redis 限流使用教程

news2025/1/24 2:13:15

从本文开始,笔者将总结 spring cloud 相关内容的教程

版本选择

为了适应 java8,笔者选择了下面的版本,后续会出 java17的以SpringBoot3.0.X为主的教程

SpringBoot 版本 2.6.5

SpringCloud 版本 2021.0.1

SpringCloudAlibaba 版本 2021.0.1.0

SpringCloudAlibaba github 版本说明截图

SpringCloud 官网:https://spring.io/projects/spring-cloud

Spring Cloud Alibaba 官网:https://sca.aliyun.com/zh-cn/

目录

1、环境准备

2、项目创建

3、测试限流

4、改进限流返回

5、项目代码


1、环境准备

本文讲解Spring Cloud Gateway 使用 Redis 限流,注册中心使用 Nacos

Macos 官网:https://nacos.io/zh-cn/index.html

Nacos 安装这里不做过多介绍,不了解的朋友可以参考

Nacos 单机安装:https://blog.csdn.net/wsjzzcbq/article/details/123916233

Nacos 集群安装:https://blog.csdn.net/wsjzzcbq/article/details/123956116

笔者使用 docker 开启 nacos 和 redis

Spring Cloud Alibaba  2021.0.1.0 版本对应的nacos版本是 1.4.2

笔者使用的 Naocs 版本是 2.0.0-bugfix,redis 版本是 7.0.6

2、项目创建

新建 maven 聚合项目 cloud-learn

最外层父工程 cloud-learn 的 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wsjzzcbq</groupId>
    <artifactId>cloud-learn</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>gateway-learn</module>
        <module>consumer-learn</module>
    </modules>
    <packaging>pom</packaging>

    <repositories>
        <repository>
            <id>naxus-aliyun</id>
            <name>naxus-aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/>
    </parent>

    <properties>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
        <alibaba-nacos-discovery.veriosn>2021.1</alibaba-nacos-discovery.veriosn>
        <alibaba-nacos-config.version>2021.1</alibaba-nacos-config.version>
        <spring-cloud-starter-bootstrap.version>3.1.1</spring-cloud-starter-bootstrap.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <version>${alibaba-nacos-discovery.veriosn}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
                <version>${alibaba-nacos-config.version}</version>
            </dependency>

            <!--spring-cloud-dependencies 2020.0.0 版本不在默认加载bootstrap文件,如果需要加载bootstrap文件需要手动添加依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bootstrap</artifactId>
                <version>${spring-cloud-starter-bootstrap.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>2.0.40</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>


</project>

然后创建2个子工程 consumer-learn 和 gateway-learn

gateway-learn 中配置路由转发到 consumer-learn

consumer-learn 工程 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-learn</artifactId>
        <groupId>com.wsjzzcbq</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumer-learn</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!--feign负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

consumer-learn 工程 启动类

package com.wsjzzcbq;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * ConsumerApplication
 *
 * @author wsjz
 * @date 2023/09/17
 */
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {

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

consumer-learn 工程 配置文件

spring.application.name=consumer-learn
server.port=8081
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
spring.cloud.nacos.discovery.server-addr=192.168.31.152:8848
spring.cloud.nacos.discovery.namespace=public
logging.level.com.alibaba.cloudlearnconsumer.feign.ProducerService=DEBUG

consumer-learn 工程 controller

package com.wsjzzcbq.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * ConsumerController
 *
 * @author wsjz
 * @date 2023/09/17
 */
@RestController
public class ConsumerController {

    @RequestMapping("/name")
    public String user() {
        return "宝剑锋从磨砺出,梅花香自苦寒来";
    }
}

gateway-learn

gateway-learn 工程 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-learn</artifactId>
        <groupId>com.wsjzzcbq</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway-learn</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- gateway负载均衡需要下面依赖,不添加会报错503-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

        <!--redis使用较高版本,5以上版本,不要使用windows版redis,低版本redis不支持lua中的命令-->
        <!--https://blog.csdn.net/wxxiangge/article/details/95024214/-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

gateway-learn 工程 启动类

package com.wsjzzcbq;

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

/**
 * GatewayApplication
 *
 * @author wsjz
 * @date 2023/09/17
 */
@SpringBootApplication
public class GatewayApplication {

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

限流需要实现 KeyResolver 接口的 resolve 方法

在 resolve 方法中返回限流的维度,如请求路径、ip地址、请求参数等

笔者这里限流维度是请求路径

package com.wsjzzcbq.limit;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * ApiKeyResolver
 *
 * @author wsjz
 * @date 2023/09/17
 */
@Component
public class ApiKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        System.out.println("API限流: " + exchange.getRequest().getPath().value());
        return Mono.just(exchange.getRequest().getPath().value());
    }
}

gateway-learn 工程 配置文件

server:
  port: 9000
spring:
  application:
    name: gateway-learn

  redis:
    host: 192.168.31.152
    password: 123456
    timeout: 5000
    database: 0
  cloud:
    nacos:
      discovery:
        server-addr: http://192.168.31.152:8848
    gateway:
      routes:
        - id: consumer-learn
          uri:  lb://consumer-learn
          predicates:
            - Path=/cloudlearn/consumer/**
          filters:
            - name: RequestRateLimiter
              args:
                key-resolver: "#{@apiKeyResolver}"
                redis-rate-limiter.replenishRate: 1 #生成令牌速率:个/秒
                redis-rate-limiter.burstCapacity: 2 #令牌桶容量
                redis-rate-limiter.requestedTokens: 1 #每次消费的Token数量,默认是 1
            - StripPrefix=2



配置说明:

RequestRateLimiter 是 gateway 提供的限流过滤器

#{@apiKeyResolver} 是笔者实现的 ApiKeyResolver

redis-rate-limiter.replenishRate 生成令牌的速率每秒几个

redis-rate-limiter.burstCapacity 令牌桶容量

redis-rate-limiter.requestedTokens 每次消费的令牌数量

当请求到网关以 /cloudlearn/consumer/  为开头前缀时,会路由到 consumer-learn 服务上

创建完成的项目结构

3、测试限流

分别启动 consumer-learn 和 gateway-learn

登录 Nacos 控制台查看

启动成功后,可在Naocs 控制台查看注册服务信息

浏览器访问测试限流:http://localhost:9000/cloudlearn/consumer/name

运行效果

可以看到当1秒钟内请求超过2次时会被限流

4、改进限流返回

上面代码实现了限流,但限流触发后返回的是429,不利于前端处理,这里我们可以在默认的限流过滤器基础上进行改进,自定义限流时的返回

新建 NewRequestRateLimiterGatewayFilterFactory 类

继承默认的 RequestRateLimiterGatewayFilterFactory

package com.wsjzzcbq.filter;

import com.alibaba.fastjson2.JSONObject;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.HttpStatusHolder;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;

/**
 * NewRequestRateLimiterGatewayFilterFactory
 *
 * @author wsjz
 * @date 2023/09/17
 */
@Component
public class NewRequestRateLimiterGatewayFilterFactory extends RequestRateLimiterGatewayFilterFactory {

    private final RateLimiter defaultRateLimiter;

    private final KeyResolver defaultKeyResolver;

    private boolean denyEmptyKey = true;

    private String emptyKeyStatusCode = HttpStatus.FORBIDDEN.name();

    public NewRequestRateLimiterGatewayFilterFactory(RateLimiter defaultRateLimiter, KeyResolver defaultKeyResolver) {
        super(defaultRateLimiter, defaultKeyResolver);
        this.defaultRateLimiter = defaultRateLimiter;
        this.defaultKeyResolver = defaultKeyResolver;
    }

    @Override
    public GatewayFilter apply(Config config) {
        System.out.println("过滤限流");
        KeyResolver resolver = (KeyResolver)this.getOrDefault(config.getKeyResolver(), this.defaultKeyResolver);
        RateLimiter<Object> limiter = (RateLimiter)this.getOrDefault(config.getRateLimiter(), this.defaultRateLimiter);
        boolean denyEmpty = (Boolean)this.getOrDefault(config.getDenyEmptyKey(), this.denyEmptyKey);
        HttpStatusHolder emptyKeyStatus = HttpStatusHolder.parse((String)this.getOrDefault(config.getEmptyKeyStatus(), this.emptyKeyStatusCode));
        return (exchange, chain) -> {
            return resolver.resolve(exchange).defaultIfEmpty("____EMPTY_KEY__").flatMap((key) -> {
                if ("____EMPTY_KEY__".equals(key)) {
                    if (denyEmpty) {
                        ServerWebExchangeUtils.setResponseStatus(exchange, emptyKeyStatus);
                        return exchange.getResponse().setComplete();
                    } else {
                        return chain.filter(exchange);
                    }
                } else {
                    String routeId = config.getRouteId();
                    if (routeId == null) {
                        Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
                        routeId = route.getId();
                    }

                    return limiter.isAllowed(routeId, key).flatMap((response) -> {
                        Iterator var4 = response.getHeaders().entrySet().iterator();

                        while(var4.hasNext()) {
                            Map.Entry<String, String> header = (Map.Entry)var4.next();
                            exchange.getResponse().getHeaders().add((String)header.getKey(), (String)header.getValue());
                        }

                        if (response.isAllowed()) {
                            return chain.filter(exchange);
                        } else {
                            ServerHttpResponse httpResponse = exchange.getResponse();
                            httpResponse.getHeaders().set("Content-Type", "application/json");
                            JSONObject json = new JSONObject();
                            json.put("code", 0);
                            json.put("msg", "当前请求人数较多,请稍后再访问");
                            DataBuffer dataBuffer = httpResponse.bufferFactory().wrap(json.toJSONString().getBytes(StandardCharsets.UTF_8));
                            return httpResponse.writeWith(Mono.just(dataBuffer));
                        }
                    });
                }
            });
        };
    }

    private <T> T getOrDefault(T configValue, T defaultValue) {
        return configValue != null ? configValue : defaultValue;
    }
}

修改配置文件

配置我们自定义的限流过滤器

server:
  port: 9000
spring:
  application:
    name: gateway-learn

  redis:
    host: 192.168.31.152
    password: 123456
    timeout: 5000
    database: 0
  cloud:
    nacos:
      discovery:
        server-addr: http://192.168.31.152:8848
    gateway:
      routes:
        - id: consumer-learn
          uri:  lb://consumer-learn
          predicates:
            - Path=/cloudlearn/consumer/**
          filters:
            - name: NewRequestRateLimiter
              args:
                key-resolver: "#{@apiKeyResolver}"
                redis-rate-limiter.replenishRate: 1 #生成令牌速率:个/秒
                redis-rate-limiter.burstCapacity: 2 #令牌桶容量
                redis-rate-limiter.requestedTokens: 1 #每次消费的Token数量
            - StripPrefix=2



重新启动 gateway-learn

请求测试

5、项目代码

码云地址:https://gitee.com/wsjzzcbq/csdn-blog/tree/master/cloud-learn

至此完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1094646.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单目3D目标检测——MonoCon 模型训练 | 模型推理

本文分享 MonoCon 的模型训练、模型推理、可视化3D检测结果、以及可视化BEV效果。 模型原理&#xff0c;参考我这篇博客&#xff1a;【论文解读】单目3D目标检测 MonoCon&#xff08;AAAI2022&#xff09;_一颗小树x的博客-CSDN博客 源码地址&#xff1a;https://github.com/2…

在vs code中创建一个名为 “django_env“ 的虚拟环境报错?!以下或许方法可以解决

# vs code 终端窗口中运行&#xff1a; mkvirtualenv django_env # 拓展&#xff1a; mkvirtualenv django_env 是一个命令&#xff0c;用于创建一个名为 "django_env" 的虚拟环境。虚拟环境是一种用于隔离不同Python项目所需依赖的工具。通过创建虚拟环境&#x…

【分布式计算】九、容错性 Fault Tolerance

分布式系统应当有一定的容错性&#xff0c;发生故障时仍能运行 一些概念&#xff1a; 可用性Availability&#xff1a;系统是否准备好立即使用 可靠性Reliability&#xff1a;系统连续运行不发生故障 安全性&#xff1a;衡量安全故障的指标&#xff0c;没有严重事件发生 可维护…

zabbix内置宏、自动发现与注册

一、zabbix内置宏 1、概念&#xff1a; 在Zabbix中&#xff0c;内置宏是一种特殊的变量&#xff0c;通常用在 Trigger 名称和表达式中&#xff0c;引用有关监控对象的信息。 2、种类&#xff1a; {HOST.NAME} 主机名 {HOST.IP} 主机 IP 地址 {TRIGGER.DESCRIPTION} 触…

Unity中Shader的深度缓冲区

文章目录 前言一、什么是深度缓冲区深度缓冲区是和颜色缓冲区、模板缓冲区平行的一个缓冲区在这里插入图片描述 二、什么是深度信息三、深度缓冲区的作用 前言 Unity中的深度缓冲区 一、什么是深度缓冲区 深度缓冲区是和颜色缓冲区、模板缓冲区平行的一个缓冲区 深度缓冲区&a…

勒索软件组织声称它“损害了所有索尼系统”

新晋勒索软件组织 RansomedVC 声称已成功入侵娱乐巨头索尼的计算机系统。正如勒索软件团伙所做的那样&#xff0c;它在其暗网网站上发布了这一消息&#xff0c;并在那里出售从受害者计算机网络中窃取的数据。 该公告称索尼的数据正在出售&#xff1a; 索尼集团公司&#xff08…

数据结构与算法--并查集结构

数据结构与算法--并查集结构 1 岛问题 2 并查集结构 1 岛问题 一个矩阵中只有0和1两种值&#xff0c;每个位置都可以和自己的上、下、左、右 四个位置相连&#xff0c;如果有一片1连在一起&#xff0c;这个部分叫做一个岛&#xff0c;求一个矩阵中有多少个岛? 【举例】 001…

FutureTask的测试使用和方法执行分析

FutureTask类图如下 java.util.concurrent.FutureTask#run run方法执行逻辑如下 public void run() {if (state ! NEW ||!RUNNER.compareAndSet(this, null, Thread.currentThread()))return;try {Callable<V> c callable;if (c ! null && state NEW) {V res…

【软考】9.4 图的概念/存储/遍历/最小生成树/拓扑/查找

《图》 图的存储&#xff08;顶点和边&#xff09; 邻接矩阵&#xff1a;适合边数较多的图&#xff0c;不易造成浪费无向图&#xff1a;不分方向&#xff1b;对称矩阵 邻接链表&#xff1a;顶点&#xff0c;边——>&#xff08;编号&#xff0c;权值&#xff09;&#xff1b…

二维数组的行指针与列指针

二维数组的行指针与列指针 笔记来源&#xff1a;懒猫老师-C语言-用指针访问二维数组&#xff08;指针与二维数组&#xff09; 声明&#xff1a;本文笔记来自bili懒猫老师&#xff0c;仅供学习参考 回顾一维数组 int a[3];//其中a或a[0]是数组首地址 //a1指向第二个元素的地址…

The SDK location is inside Studio install location 解决

The SDK location is inside Studio install location 解决 安装 Android Studio SDK 时提示&#xff1a;The SDK location is inside Studio install location 解决 问题&#xff1a; 由于 SDK 与 编辑器(Android Studio)的安装在同一目录下所以报错。 解决 你需要在 Andro…

五、RocketMQ发送顺序消息

顺序消息的应用场景 在有序事件处理、撮合交易、数据实时增量同步等场景下&#xff0c;异构系统间需要维持强一致的状态同步&#xff0c;上游的事件变更需要按照顺序传递到下游进行处理。 例如需要保证一个订单的生成、付款和发货&#xff0c;这三件事情是被顺序执行的。 如…

C# OpenVINO Det 物体检测

效果 耗时 elephant:89% Preprocess: 0.00ms Infer: 47.21ms Postprocess: 11.63ms Total: 58.84ms 项目 代码 using OpenCvSharp; using Sdcb.OpenVINO; using Sdcb.OpenVINO.Natives; using System; using System.Diagnostics; using System.Drawing; using System.Text; …

淘宝店铺订单详情接口,淘宝店铺订单列表数据,淘宝店铺订单物流接口,淘宝店铺订单线下发货接口-

淘宝店铺订单详情接口可以理解为淘宝开放平台&#xff08;Taobao Open Platform&#xff09;提供的API接口1。 该接口可以获取淘宝店铺的订单详情&#xff0c;包括订单号、买家昵称、收货人姓名、收货地址、邮编、电话、商品描述、价格等信息。开发者可以在淘宝开放平台注册一…

使用winUSB进行USB开发

什么是winUSB WinUSB是Windows操作系统提供的一种通用USB驱动程序&#xff0c;用于简化USB设备的开发和使用。它是一个用户模式驱动程序&#xff0c;可以在Windows XP及更高版本的操作系统上使用。WinUSB提供了一组API和工具&#xff0c;使开发人员能够与USB设备进行通信&…

C++11可变参数模板

文章目录 1.可变参数模板的介绍1.1C语言中的可变参数1.2C98/C11的类模板和函数模板1.3可变参数的函数模板1.4展开参数包递归展开初始化列表展开 2.可变参数模板的应用 1.可变参数模板的介绍 1.1C语言中的可变参数 1.2C98/C11的类模板和函数模板 C98/03&#xff0c;类模版和函…

Numpy(一)简介与基本使用

Numpy&#xff08;一&#xff09;简介与基本使用 一、Numpy简介 1.Numpy是一个运行速度非常快的数学库&#xff0c;主要用于数组计算 2.包含&#xff1a;N维数组对象ndarray、广播功能函数、整合C/C/Fortran代码工具、包含线性代数/傅里叶变换/随机数生成等功能 3.优点&…

ChatGPT快速入门

ChatGPT快速入门 一、什么是ChatGPT二、ChatGPT底层逻辑2.1 实现原理2.2 IO流程 三、ChatGPT应用场景3.1 知心好友3.2 文案助理3.3 创意助理3.4 角色扮演 一、什么是ChatGPT ChatGPT指的是基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型的对话生成系…

python字典、列表排序,从简单到复杂

因工作原因&#xff0c;需要频繁对python字典(dict)、列表(list)等进行各种各样的排序&#xff0c;发现网上这块的资料又多又杂&#xff0c;尤其涉及到lambda的&#xff0c;让人觉得难以理解看不下去&#xff0c;因此写了这篇文章&#xff0c;从简单到复杂&#xff0c;配合例子…

【Eclipse】安装教程

首先打开官网&#xff1a;Eclipse Downloads | The Eclipse Foundation 这里我选择了下载最新版本 下载好后&#xff0c;双击下载的文件 &#xff0c;即可进入到安装页面 点击第一个进行安装&#xff1a; 最后安装成功&#xff01; 补充&#xff1a; 【Eclipse】安装JAVA EE插…