SpringBoot整合minio
SpringBoot整合minio
- 1. 下载及安装
- 1.1 windows版本
- 1.2 Linux版本
- 2. SpringBoot整合minio
- 2.1 依赖
- 2.2 配置文件
- 2.3 配置类
- 2.4 工具类
- 2.5 测试
- 1. 业务层
- 2. 控制层
1. 下载及安装
1.1 windows版本
目录结构
启动文件
标红的地方按实际安装地更改
@echo off
REM 声明采用UTF-8编码
chcp 65001
echo.
echo [信息] 运行MinIO文服务器。
echo.
:: 设置窗口标题
title Minio文件服务:: 设置用户名为myname
setx MINIO_ROOT_USER minio
:: 设置密码为mypassword
setx MINIO_ROOT_PASSWORD minio123cd %~dp0
:: 切换到minio.exe文件所在目录
cd D:\dev\minio\bin
:: 启动minio服务
minio.exe server D:\dev\minio\data --console-address ":9001" --address ":9000" > D:\dev\minio\logs\minio.log
pause
1.2 Linux版本
待更新
2. SpringBoot整合minio
2.1 依赖
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.1</version><exclusions><exclusion><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></exclusion><exclusion><groupId>org.jetbrains.kotlin</groupId><artifactId>kotlin-stdlib</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.0</version></dependency>
2.2 配置文件
minio:url: http://127.0.0.1:9000 #Minio服务所在地址bucketName: zld #存储桶名称accessKey: minio #访问的keysecretKey: minio123 #访问的秘钥
2.3 配置类
package com.ruoyi.minio.config;import io.minio.MinioClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {/*** minio服务器地址*/private String url;/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;/*** 密码*/private String bucketName;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getSecretKey() {return secretKey;}public void setSecretKey(String secretKey) {this.secretKey = secretKey;}public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();}
}
2.4 工具类
package com.ruoyi.minio.util;import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.minio.config.MinioConfig;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.Item;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Component
public class MinioUtil {@Autowiredprivate MinioConfig prop;@Resourceprivate MinioClient minioClient;/*** 查看存储bucket是否存在** @return boolean*/public Boolean bucketExists(String bucketName) {Boolean found;try {found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return found;}/*** 创建存储bucket** @return Boolean*/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 删除存储bucket** @return Boolean*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 获取全部bucket*/public List<Bucket> getAllBuckets() {try {List<Bucket> buckets = minioClient.listBuckets();return buckets;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件上传** @param file 文件* @return Boolean*/public String upload(MultipartFile file) {String originalFilename = file.getOriginalFilename();if (StringUtils.isBlank(originalFilename)) {throw new RuntimeException();}String fileName = IdUtils.simpleUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));String objectName = DateUtils.datePath() + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();//文件名称相同会覆盖minioClient.putObject(objectArgs);} catch (Exception e) {e.printStackTrace();return null;}return objectName;}/*** 文件上传** @param bucketName* @param fileName* @param multipartFile* @return* @throws IOException*/public String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException {String url = "";MinioClient minioClient = SpringUtils.getBean(MinioClient.class);try (InputStream inputStream = multipartFile.getInputStream()) {boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (!found) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());/*** bucket权限-读写*/String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}";minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(READ_WRITE).build());}minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());//路径获取url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build());url = url.substring(0, url.indexOf('?'));//常规访问路径获取return url;} catch (Exception e) {throw new IOException(e.getMessage(), e);}}/*** 预览图片** @param fileName* @return*/public String preview(String fileName) {// 查看文件地址GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();try {String url = minioClient.getPresignedObjectUrl(build);return url;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件下载** @param fileName 文件名称* @param res response* @return Boolean*/public void download(String fileName, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build();try (GetObjectResponse response = minioClient.getObject(objectArgs)) {byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {while ((len = response.read(buf)) != -1) {os.write(buf, 0, len);}os.flush();byte[] bytes = os.toByteArray();res.setCharacterEncoding("utf-8");// 设置强制下载不打开// res.setContentType("application/force-download");res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);try (ServletOutputStream stream = res.getOutputStream()) {stream.write(bytes);stream.flush();}}} catch (Exception e) {e.printStackTrace();}}/*** 查看文件对象** @return 存储bucket内文件对象信息*/public List<Item> listObjects() {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(prop.getBucketName()).build());List<Item> items = new ArrayList<>();try {for (Result<Item> result : results) {items.add(result.get());}} catch (Exception e) {e.printStackTrace();return null;}return items;}/*** 删除** @param fileName* @return* @throws Exception*/public boolean remove(String fileName) {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());} catch (Exception e) {return false;}return true;}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称:以.结尾为文件,以/结尾为文件夹* @since tarzan LIU*/public boolean deleteObjects(String bucketName, String objectName) {if (StringUtils.isNotBlank(objectName)) {if (objectName.endsWith(".") || objectName.endsWith("/")) {Iterable<Result<Item>> list = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(true).build());ExecutorService executorService = Executors.newFixedThreadPool(10);list.forEach(e -> {executorService.execute(new Runnable() {@Overridepublic void run() {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(e.get().objectName()).build());} catch (ErrorResponseException ex) {throw new RuntimeException(ex);} catch (InsufficientDataException ex) {throw new RuntimeException(ex);} catch (InternalException ex) {throw new RuntimeException(ex);} catch (InvalidKeyException ex) {throw new RuntimeException(ex);} catch (InvalidResponseException ex) {throw new RuntimeException(ex);} catch (IOException ex) {throw new RuntimeException(ex);} catch (NoSuchAlgorithmException ex) {throw new RuntimeException(ex);} catch (ServerException ex) {throw new RuntimeException(ex);} catch (XmlParserException ex) {throw new RuntimeException(ex);}}});});executorService.shutdown();return true;}}return true;}
}
2.5 测试
1. 业务层
package com.ruoyi.minio.service;import org.springframework.web.multipart.MultipartFile;/*** minio服务*/
public interface MinioService {/*** 文件上传** @param file* @return*/public String upload(MultipartFile file);/*** 文件上传** @param file* @return*/public String uploadFile(String bucketName, String fileName, MultipartFile multipartFile);/*** 预览图片* @param fileName* @return*/public String preview(String fileName);/*** 文件删除** @param fileName* @return*/public boolean remove(String fileName);/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/public boolean deleteObjects(String bucketName, String objectName);/*** 删除前几天文件夹* @param bucketName* @param day* @return*/boolean deleteObjectsByDay(String bucketName, int day);
}
package com.ruoyi.minio.service.impl;import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.minio.service.MinioService;
import com.ruoyi.minio.util.MinioUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.IOException;@Service
public class MinioServiceImpl implements MinioService {@Resourceprivate MinioUtil minioUtil;/*** 文件上传** @param file* @return*/@Overridepublic String upload(MultipartFile file) {return minioUtil.upload(file);}/*** 文件上传** @param bucketName* @param fileName* @param multipartFile* @return*/@Overridepublic String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) {try {return minioUtil.uploadFile(bucketName, fileName, multipartFile);} catch (IOException e) {throw new ServiceException("上传失败,请联系管理员");}}/*** 预览图片** @param fileName* @return*/@Overridepublic String preview(String fileName) {return minioUtil.preview(fileName);}/*** 文件删除** @param fileName* @return*/@Overridepublic boolean remove(String fileName) {return minioUtil.remove(fileName);}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/@Overridepublic boolean deleteObjects(String bucketName, String objectName) {return minioUtil.deleteObjects(bucketName, objectName);}/*** 删除前几天文件夹** @param bucketName* @param day* @return*/@Overridepublic boolean deleteObjectsByDay(String bucketName, int day) {String objectName = DateUtils.getDayAgoOrAfterString(day)+"/";return minioUtil.deleteObjects(bucketName, objectName);}
}
2. 控制层
package com.ruoyi.web.controller.minio;import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.minio.service.MinioService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;/*** minio文件管理*/
@RestController
@RequestMapping("/minio")
public class MinioController {@Resourcepublic MinioService minioService;@PostMapping("/upload")public AjaxResult upload(MultipartFile file) {String upload = minioService.upload(file);return AjaxResult.success(upload);}/*** 预览图片** @param fileName* @return*/@GetMapping("/preview")public AjaxResult preview(String fileName) {String preview = minioService.preview(fileName);return AjaxResult.success(preview);}/*** 删除文件** @param fileName* @return*/@GetMapping("/remove")public AjaxResult remove(String fileName) {return AjaxResult.success(minioService.remove(fileName));}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/@GetMapping("/deleteObjects")public AjaxResult deleteObjects(String bucketName, String objectName) {return AjaxResult.success(minioService.deleteObjects(bucketName, objectName));}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/@GetMapping("/deleteObjectsByDay")public AjaxResult deleteObjectsByDay(String bucketName, int day) {return AjaxResult.success(minioService.deleteObjectsByDay(bucketName, day));}
}
相关文章:

SpringBoot整合minio
SpringBoot整合minio 1. 下载及安装1.1 windows版本1.2 Linux版本 2. SpringBoot整合minio2.1 依赖2.2 配置文件2.3 配置类2.4 工具类2.5 测试1. 业务层2. 控制层 1. 下载及安装 1.1 windows版本 目录结构 启动文件 标红的地方按实际安装地更改 echo off REM 声明采用UT…...
3090. 每个字符最多出现两次的最长子字符串
说在前面 🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。 题目描述 给你一个字符串 s ,请找出满足每个字符最多出现两次的最长子字符串,…...
26.活锁、饥饿锁
两个线程,相互改变了对方结束条件,导致两个线程不能结束。执行时间也都是一样,导致两个线程永远不会结束。 Slf4j public class LiveLockDemo {static volatile int count 10;public static void main(String[] args) {new Thread(() ->…...

docker 安装nginx
一、先查看有没有nginx镜像 docker images 二、发现没有nginx镜像,下载最新镜像 docker pull nginx 三、运行镜像 为了先复制出部分文件,先启动一个临时容器 docker run --name nginx -p 9001:80 -d nginx docker cp nginx:/etc/nginx/conf.d /home/…...

2024年阿里云新用户便宜购买云服务器攻略:5大细节助你降低购买成本
随着互联网的蓬勃发展,无论是个人还是企业,拥有一个稳定且高效的网站或APP已成为提升竞争力的关键。为了将这些项目部署并运行起来,购买一台实用又便宜的云服务器是必不可少的。阿里云作为国内首屈一指的云服务提供商,自然成为了众…...

SSTI模板注入(jinja2)
前面学习了SSTI中的smarty类型,今天学习了Jinja2,两种类型都是flask框架的,但是在注入的语法上还是有不同 SSTI:服务器端模板注入,也属于一种注入类型。与sql注入类似,也是通过凭借进行命令的执行ÿ…...

ESP32学习---ESP-NOW(一)
ESP32学习---ESP-NOW(一) 官网简介arduino 官网简介 首先看官网的介绍:https://www.espressif.com.cn/zh-hans/solutions/low-power-solutions/esp-now ESP-NOW 是乐鑫定义的一种无线通信协议,能够在无路由器的情况下直接、快速…...
C++核心高级编程 --- 3、函数提高
文章目录 第三章:3.函数提高3.1 函数默认参数3.2 函数占位参数3.3 函数重载3.3.1 函数重载概述3.3.2 注意事项 第三章: 3.函数提高 3.1 函数默认参数 语法结构:返回值类型 函数名 (参数 默认值){} #include <iostream> using name…...
【微服务篇】深入理解分布式消息队列系统
分布式消息队列是一种在多个服务器、应用或服务之间进行消息传递的技术。它使得各个独立的组件可以通过异步消息进行通信,提高了系统的可扩展性、解耦性和可靠性。 典型应用场景 1. 异步处理 在许多系统中,某些任务的处理可能需要较长时间,…...

基于k8s的web服务器构建
文章目录 k8s综合项目1、项目规划图2、项目描述3、项目环境4、前期准备4.1、环境准备4.2、ip划分4.3、静态配置ip地址4.4、修改主机名4.5、部署k8s集群4.5.1、关闭防火墙和selinux4.5.2、升级系统4.5.3、每台主机都配置hosts文件,相互之间通过主机名互相访问4.5.4、…...
【名词解释】ImageCaption任务中的CIDEr、n-gram、TF-IDF、BLEU、METEOR、ROUGE 分别是什么?它们是怎样计算的?
CIDEr CIDEr(Consensus-based Image Description Evaluation)是一种用于自动评估图像描述(image captioning)任务性能的指标。它主要通过计算生成的描述与一组参考描述之间的相似性来评估图像描述的质量。CIDEr的独特之处在于它考…...

C++其他语法..
1.运算符重载 之前有一个案例如下所示 其中我们可以通过add方法将两个点组成一个新的点 class Point {friend Point add(Point, Point);int m_x;int m_y; public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x <<…...

【Vue3源码学习】— CH2.6 effect.ts:详解
effect.ts:详解 1. 理解activeEffect1.1 定义1.2 通过一个例子来说明这个过程a. 副作用函数的初始化b. 执行副作用函数前c. 访问state.countd. get拦截器中的track调用e. 修改state.count时的set拦截器f. trigger函数中的依赖重新执行 1.3 实战应用1.4 activeEffect…...

C语言:文件操作(一)
目录 前言 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 结(一) 前言 本篇文章将介绍C语言的文件操作,在后面的内容讲到:为什么使用文…...
集中进行一系列处理——函数
需要多次执行相同的处理,除了编写循环语句之外,还可以集中起来对它进行定义。 对一系列处理进行定义的做法被称为函数,步骤,子程序。 对函数进行定一后,只需要调用该函数就可以了。如果需要对处理的内容进行修正&…...
git diff
1. 如何将库文件的变化生成到patch中 git diff --binary commit1 commit2 > test.patch 打patch: git apply test.patch 2. 如何消除trailing whitespace 问题 git diff --ignore-space-at-eol commit1 commit2 > test.patch 打patch: git ap…...

新手使用GIT上传本地项目到Github(个人笔记)
亲测下面的文章很有用处。 1. 初次使用git上传代码到github远程仓库 - 知乎 (zhihu.com) 2. 使用Git时出现refusing to merge unrelated histories的解决办法 - 知乎...
结合《人力资源管理系统》的Java基础题
1.编写一个Java方法,接受一个整数数组作为参数,返回该数组中工资高于平均工资的员工数量。假设数组中的每个元素都代表一个员工的工资。 2.设计一个Java方法,接受一个字符串数组和一个关键字作为参数,返回包含该关键字的姓名的员…...
PostgreSQL备份还原数据库
1.切换PostgreSQL bin目录 配置Postgresql环境变量后可以不用切换 pg_dump 、psql都在postgresql bin目录下,所以需要切换到bin目录执行命令 2.备份数据库 方式一 语法 pg_dump -h <ip> -U <pg_username> -p <port> -d <databaseName>…...
实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用
实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用 在数据库管理中,读写分离是一种常见的性能优化方法,它通过将读操作和写操作分发到不同的服务器或数据库实例上,来减轻单个数据库的负载&#x…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...