Springfox、Springdoc和Swagger

news2025/3/13 16:28:17

Springfox、Swagger 和 Springdoc

Springfox、Swagger 和 Springdoc 是用于在 Spring Boot 项目中生成API文档的工具,但它们之间有显著的区别和演进关系:

1.Swagger

简介
  • Swagger 是一个开源项目,旨在为 RESTful APIs 提供交互式文档。
  • 最早由 SmartBear 开发,后来演进为 OpenAPI 规范 的前身。
  • Swagger 的核心组件包括:
    • Swagger UI:提供交互式的 Web 界面,展示 API 端点并允许直接调用测试。
    • Swagger Editor:编写和查看 OpenAPI 描述文件的工具。
    • Swagger Codegen:基于 API 描述文件生成客户端和服务端代码。
与 Spring 的关系

Swagger 本身不依赖 Spring,但通过扩展工具(如 Springfox)使其在 Spring 框架中得到使用。

Swagger2是Swagger规范的一个实现

Swagger3是基于OpenAPI规范的新版本,它是Swagger规范的后续标准,
提供了更好的可扩展性和更丰富的功能。

Spring Boot从2.6.0版本开始不再原生支持Swagger2,因为Spring官方的更新导致了与Swagger2的不兼容。
开发者需要使用Springdoc OpenAPI库来替代Springfox,以在Spring Boot 2.6.0及以上版本中集成OpenAPI文档。
Springdoc OpenAPI提供了对OpenAPI 3.0规范的支持,并且与Spring Boot的新版本兼容。

2.Springfox

简介
  • Springfox 是一个专门为 Spring Boot 集成 Swagger 的库。
  • 核心功能:扫描 Spring 项目中的注解和配置,生成基于 Swagger 的 API 文档。
  • 特点:
    • 支持 Spring MVC 和 Spring WebFlux。
    • 使用 @ApiOperation@ApiModel 等注解来生成文档。
    • 支持 Swagger 2 和部分 OpenAPI 3 特性。
现状
  • 停止活跃维护:Springfox 项目在 2021 年后维护频率大幅降低,社区对它的支持逐渐减少。3.0.x版本以后没有再更新
  • 兼容性问题:
    • 与 Spring Boot 2.6.x 和更高版本存在兼容性问题,主要是因为 Springfox 使用的 RequestMappingHandlerMapping 被 Spring Framework 的 Web 模块改动影响。
何时使用
  • 如果项目是基于 Spring Boot 2.5.x 或更早版本,并且已经使用了 Springfox,可以暂时保留。
  • 对于新项目,不建议继续使用 Springfox。

3.Springdoc

简介
  • Springdoc 是一个现代化工具,基于 OpenAPI 3 规范设计,替代 Springfox。
  • 提供与 Spring Boot 的无缝集成:
    • 自动生成 OpenAPI 3 文档。
    • 提供嵌入式的 Swagger UI(无需单独配置)。
    • 兼容 Spring MVC 和 Spring WebFlux。
优点
  • 强大兼容性
    • 与 Spring Boot 2.x 和 3.x 完美兼容。
    • 支持 Spring Framework 的最新功能,例如响应式流和新注解模型。
  • 零配置:
    • 大部分功能开箱即用,减少了复杂的注解和配置需求。
  • 社区活跃:
    • 相比 Springfox,Springdoc 项目更活跃,持续发布新版本,解决社区反馈。
使用方式

1.添加 Maven 依赖:

<dependency>
 <groupId>org.springdoc</groupId>
 <artifactId>springdoc-openapi-ui</artifactId>
 <version>最新版本</version>
</dependency>

2.启用后,访问默认路径 http://localhost:8080/swagger-ui.html。

总结:它们的关系与选择
工具关系适用场景当前建议
Swagger基础规范和工具原始工具,用于标准化 API 文档用于 OpenAPI 标准支持
SpringfoxSwagger 的 Spring 集成实现传统项目(Spring Boot 2.5.x)不再推荐,已过时
Springdoc基于 OpenAPI 3 的现代化替代工具新项目,支持最新的 Spring Boot强烈推荐
迁移建议:从 Springfox 到 Springdoc

如果你当前使用 Springfox,但需要升级 Spring Boot 或改进文档支持,可以迁移到 Springdoc:

  1. 替换依赖:
    • 移除 springfox-swagger2springfox-swagger-ui
    • 添加 springdoc-openapi-ui
  2. 注解适配:
    • Springdoc 支持 OpenAPI 3 的注解,通常是标准的 JSR-303 和 Spring 注解。
    • 替换 @ApiOperation@Operation,替换 @ApiModel 为标准注解。
  3. 配置改动:
    • Springdoc 几乎不需要额外配置,大部分文档生成会自动完成。

结论:对于新项目,推荐使用 Springdoc;对于维护中的老项目,可以逐步迁移到 Springdoc,以便享受最新功能和更好的兼容性。

使用springboot2.6+版本和swagger2不兼容的解决方案

以下是一个springboot2.7.10集成swagger2和knife4j的例子

1、引入knife4j

 <dependency>
     <groupId>com.github.xiaoymin</groupId>
     <artifactId>knife4j-spring-boot-starter</artifactId>
     <version>3.0.3</version>
</dependency>

knife4j官方建议开发者不要使用

在这里插入图片描述

2、knife4j配置文件

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

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

@Configuration
@EnableSwagger2
@EnableKnife4j
public class Knife4jConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .enable(true)
                .apiInfo(apiInfo())
                .select()
                //.apis(RequestHandlerSelectors.basePackage("com.linear.visual.controller"))
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(Collections.singletonList(securityScheme()))
                .securityContexts(securityContexts());

    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .description("可视化接口")
                .contact(new Contact("Linear", "linear", "linear"))
                .version("v1.0.0")
                .title("API测试文档")
                .build();
    }

    @Bean
    SecurityScheme securityScheme() {
        return new ApiKey("Authorization", "Authorization", "header");
    }

    /**
     * 安全上下文
     */
    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .build());
        return securityContexts;
    }

    /**
     * 默认的安全上引用
     */
    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }
}

如果使用低版本的springboot比如2.6以下的,基本上都可以成功的。
但是使用2.6以上版本,这个时候可能会报启动失败

org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.26.jar:5.3.26]
	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.26.jar:5.3.26]
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.26.jar:5.3.26]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.26.jar:5.3.26]
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.26.jar:5.3.26]
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:937) ~[spring-context-5.3.26.jar:5.3.26]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.26.jar:5.3.26]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.10.jar:2.7.10]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.10.jar:2.7.10]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.10.jar:2.7.10]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.10.jar:2.7.10]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.10.jar:2.7.10]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.10.jar:2.7.10]
	at com.asr.hedu.fsp.service.oms.course.OmsCourseBootstrap.main(OmsCourseBootstrap.java:47) ~[classes/:na]
Caused by: java.lang.NullPointerException: null
	at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0]
	at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113) ~[springfox-core-3.0.0.jar:3.0.0]
	at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89) ~[springfox-spi-3.0.0.jar:3.0.0]
	at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) ~[na:na]
	at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:na]
	at java.base/java.util.TimSort.sort(TimSort.java:234) ~[na:na]
	at java.base/java.util.Arrays.sort(Arrays.java:1515) ~[na:na]
	at java.base/java.util.ArrayList.sort(ArrayList.java:1750) ~[na:na]
	at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392) ~[na:na]
	at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
	at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
	at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
	at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
	at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107) ~[springfox-spring-web-3.0.0.jar:3.0.0]
	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91) ~[springfox-spring-web-3.0.0.jar:3.0.0]
	at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82) ~[springfox-spring-web-3.0.0.jar:3.0.0]
	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100) ~[springfox-spring-web-3.0.0.jar:3.0.0]
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.26.jar:5.3.26]
	... 14 common frames omitted

这个问题经查询跟springboot的bean初始化有关系,后续的版本更改了相关的东西,具体是什么没有细究,反正参照stackoverflow中的修改方法,加入一下配置类就可以避免错误

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;

import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;

/**
 * swagger config
 *
 * @author zxl
 * @date 2023-05-16
 */
@Configuration
public class SwaggerConfig {

    @Bean
    public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
        return new BeanPostProcessor() {

            @Override
            public Object postProcessAfterInitialization(@NonNull  Object bean, @NonNull String beanName) throws BeansException {
                if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
                }
                return bean;
            }

            private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
                List<T> copy = mappings.stream()
                        .filter(mapping -> mapping.getPatternParser() == null)
                        .collect(Collectors.toList());
                mappings.clear();
                mappings.addAll(copy);
            }

            @SuppressWarnings("unchecked")
            private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
                try {
                    Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
                    assert field != null;
                    field.setAccessible(true);
                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
        };
    }
}

加入后启动正常,但是访问swagger的/v2/api-docs接口,发现没有获得数据,接口内容是空的。
这是通过搜索得到有几种解决方案
1、ShortVideoSwagger2的配置类需要集成WebMvcConfigurationSupport
2、ShortVideoSwagger2的配置类增加@EnableWebMvc注解
3、springboot的配置增加增加一下配置

spring:
  mvc:
    pathmatch:
      matching-strategy: ANT_PATH_MATCHE

通过试验得知,这三种接口都可以解决,但是前两种是有副总用的
@EnableWebMvc建议慎用,最后在非springboot项目中使用
前两种解决方案会破坏springboot对springwebmvc的自动装配,导致自定义的一些convertor或者ObjectMapper失效。
目前我的项目中是自定义的ObjectMapper失效。所以最后使用第三种方式,后期的springboot版本的matching-strategy默认的改为了PATH_PATTERN_PARSER,把它改为ANT_PATH_MATCHER就可以了。

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

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

相关文章

在Spring Boot项目中如何实现获取FTP远端目录结构

Java语言实现获取FTP远端目录结构的实现方式有多种,在Spring Boot 项目中,最简单和快速的方式就是使用Spring Integration 实现FTP相关的功能。 前言 本篇的示例和演示基于Windows 的FTP 服务,关于如何在Windows 开启FTP服务可以参考: Windows 如何开启和使用FTP服务 本…

Flutter_学习记录_device_info_plus 插件获取设备信息

引入三方库device_info_plus导入头文件 import package:device_info_plus/device_info_plus.dart;获取设备信息的主要代码 DeviceInfoPlugin deviceInfoPlugin DeviceInfoPlugin(); BaseDeviceInfo deviceInfo await deviceInfoPlugin.deviceInfo;完整案例 import package…

Java高频面试之集合-10

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;详解红黑树&#xff1f;HashMap为什么不用二叉树/平衡树呢&#xff1f; 一、红黑树&#xff08;Red-Black Tree&#xff…

never_give_up

一个很有意思的题&#xff1a; never_give_up - Bugku CTF平台 注意到注释里面有1p.html&#xff0c;我们直接在源代码界面看&#xff0c;这样就不会跳转到它那个链接的&#xff1a; 然后解码可得&#xff1a; ";if(!$_GET[id]) {header(Location: hello.php?id1);exi…

Python Selenium库入门使用,图文详细。附网页爬虫、web自动化操作等实战操作。

文章目录 前言1 创建conda环境安装Selenium库2 浏览器驱动下载&#xff08;以Chrome和Edge为例&#xff09;3 基础使用&#xff08;以Chrome为例演示&#xff09;3.1 与浏览器相关的操作3.1.1 打开/关闭浏览器3.1.2 访问指定域名的网页3.1.3 控制浏览器的窗口大小3.1.4 前进/后…

AI4CODE】3 Trae 锤一个贪吃蛇的小游戏

【AI4CODE】目录 【AI4CODE】1 Trae CN 锥安装配置与迁移 【AI4CODE】2 Trae 锤一个 To-Do-List 这次还是采用 HTML/CSS/JAVASCRIPT 技术栈 Trae 锤一个贪吃蛇的小游戏。 1 环境准备 创建一个 Snake 的子文件夹&#xff0c;清除以前的会话记录。 2 开始构建 2.1 输入会…

Linux 进程的一生(一):进程与线程的创建机制解析

在 Linux 操作系统中&#xff0c;每个任务都以「进程」的形式存在。但 Linux 下的「线程」又是什么&#xff1f;Linux 并没有单独定义一种全新数据结构来表示线程&#xff0c;而是将线程视为一种特殊的进程——一种共享资源的轻量级进程。然而&#xff0c;在具体实现和运行机制…

STM32之I2C硬件外设

注意&#xff1a;硬件I2C的引脚是固定的 SDA和SCL都是复用到外部引脚。 SDA发送时数据寄存器的数据在数据移位寄存器空闲的状态下进入数据移位寄存器&#xff0c;此时会置状态寄存器的TXE为1&#xff0c;表示发送寄存器为空&#xff0c;然后往数据控制寄存器中一位一位的移送数…

windows版本的时序数据库TDengine安装以及可视化工具

了解时序数据库TDengine&#xff0c;可以点击官方文档进行详细查阅 安装步骤 首先找到自己需要下载的版本&#xff0c;这边我暂时只写windows版本的安装 首先我们需要点开官网&#xff0c;找到发布历史&#xff0c;目前TDengine的windows版本只更新到3.0.7.1&#xff0c;我们…

【AI】单台10卡4090 openEuler服务器离线部署kasm workspace 提供简单的GPU云服务 虚拟化桌面

下载网址 Downloads | Kasm Workspaces 文件连接 wget https://kasm-static-content.s3.amazonaws.com/kasm_release_plugin_images_amd64_1.16.1.98d6fa.tar.gz wget https://kasm-static-content.s3.amazonaws.com/kasm_release_1.16.1.98d6fa.tar.gz wget https://kasm-st…

NetAssist 5.0.14网络助手基础使用及自动应答使用方案

以下是NetAssist v5.0.14自动应答功能的详细使用步骤&#xff1a; 一、基础准备&#xff1a; 工具下载网址页面&#xff1a;https://www.cmsoft.cn/resource/102.html 下载安装好后&#xff0c;根据需要可以创建多个server&#xff0c;双击程序图标运行即可&#xff0c;下面…

47.HarmonyOS NEXT 登录模块开发教程(二):一键登录页面实现

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 登录模块开发教程&#xff08;二&#xff09;&#xff1a;一键登录页面实现 文章目录 HarmonyOS NEXT 登录模块开发教程&#xff0…

5.1 程序调试

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 本节中为了演示方便&#xff0c;使用的代码如下&#xff1a; 【例 5.1】【项目&#xff1a;code5-001】程序的调试。 static void Ma…

Cursor初体验:excel转成CANoe的vsysvar文件

今天公司大佬先锋们给培训了cursor的使用&#xff0c;还给注册了官方账号&#xff01;跃跃欲试&#xff0c;但是测试任务好重&#xff0c;结合第三方工具开发也是没有头绪。 但巧的是&#xff0c;刚好下午有同事有个需求&#xff0c;想要把一个几千行的excel转成canoe的系统变…

vue3-element-admin 前后端本地启动联调

一、后端环境准备 1.1、下载地址 gitee 下载地址 1.2、环境要求 JDK 17 1.3、项目启动 克隆项目 git clone https://gitee.com/youlaiorg/youlai-boot.git数据库初始化 执行 youlai_boot.sql 脚本完成数据库创建、表结构和基础数据的初始化。 修改配置 application-dev.y…

《MySQL数据库从零搭建到高效管理|库的基本操作》

目录 一、数据库的操作 1.1 展示数据库 1.2 创建数据库 1.3 使用数据库 1.4 查看当前数据库 1.5 删除数据库 1.6 小结 二、常用数据类型 2.1 数值类型 2.2 字符串类型 2.3 日期类型 一、数据库的操作 打开MySQL命令行客户端&#xff0c;安装完MySQL后会有两个客户端…

mac使用Homebrew安装miniconda(mac搭建python环境),并在IDEA中集成miniconda环境

一、安装Homebrew mac安装brew 二、使用Homebrew安装miniconda brew search condabrew install miniconda安装完成后的截图&#xff1a; # 查看是否安装成功 brew list环境变量&#xff08;无需手动配置&#xff09; 先执行命令看能不能正常返回&#xff0c;如果不能正常…

Linux基础开发工具—vim

目录 1、vim的概念 2、vim的常见模式 2.1 演示切换vim模式 3、vim命令模式常用操作 3.1 移动光标 3.2 删除文字 3.3 复制 3.4 替换 4、vim底行模式常用命令 4.1 查找字符 5、vim的配置文件 1、vim的概念 Vim全称是Vi IMproved&#xff0c;即说明它是Vi编辑器的增强…

【C++】数据结构 队列的实现

本篇博客给大家带来的是用C语言来实现数据结构的队列的实现&#xff01; &#x1f41f;&#x1f41f;文章专栏&#xff1a;数据结构 &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢迎大家点赞、收藏、分享&#xff01; 今日思想&#xff1a;你…

macOS 终端优化

macOS 安装、优化、还原、升级 Oh My Zsh 完全指南 &#x1f680; Oh My Zsh 是 macOS 终端增强的利器&#xff0c;它能提供强大的自动补全、主题定制和插件支持&#xff0c;让你的终端更高效、更炫酷。本文将全面介绍 如何安装、优化、还原、重新安装和升级 Oh My Zsh&#x…