快速搭建对象存储服务 - Minio,并解决临时地址暴露ip、短链接请求改变浏览器地址等问题

其他文章

服务容错治理框架resilience4j&sentinel基础应用---微服务的限流/熔断/降级解决方案-CSDN博客

conda管理python环境-CSDN博客

快速搭建对象存储服务 - Minio,并解决临时地址暴露ip、短链接请求改变浏览器地址等问题-CSDN博客

大模型LLMs的MCP入门-CSDN博客 

使用LangGraph构建多代理Agent、RAG-CSDN博客 

大模型LLMs框架Langchain之链详解_langchain.llms.base.llm详解-CSDN博客 

大模型LLMs基于Langchain+FAISS+Ollama/Deepseek/Qwen/OpenAI的RAG检索方法以及优化_faiss ollamaembeddings-CSDN博客

大模型LLM基于PEFT的LoRA微调详细步骤---第二篇:环境及其详细流程篇-CSDN博客 

大模型LLM基于PEFT的LoRA微调详细步骤---第一篇:模型下载篇_vocab.json merges.txt资源文件下载-CSDN博客 使用docker-compose安装Redis的主从+哨兵模式_使用docker部署redis 一主一从一哨兵模式 csdn-CSDN博客

docker-compose安装canal并利用rabbitmq同步多个mysql数据_docker-compose canal-CSDN博客

目录

本文要解决的问题

基于Docker-compose的Minio安装

配置文件docker-compose.yml

启动

启动成功后登录webUI

上传资源-web操作 

Java使用 --- 基础版

Step1、引入pom依赖

 Step2、创建一个新key,并下载

 Step3、创建一个application.yml文件

Step4、创建配置实体MinioProperties.java

Step5、创建文件类型枚举类FileType.java 

Step6、创建工具类MinioUtils.java

Step7、启动类MinioApplication.java

Step8、测试类---按需

关于Minio真实IP解决方法:

Step1、前提准备

step2、修改application.yml文件

Step3、添加nginx.conf配置,并启动nginx

Step4、生成短链接以及访问短链接

使用重定向访问短链接

服务端代理请求形式 --- 直接由服务器端发起请求


本文要解决的问题

基础的Minio下载安装、java操作方法、完整的工具类。

使用minio时需要注意的地方:

      使用Minio的时候,生成资源的临时访问链接时,生成的地址IP是真实的IP和端口,不安全,怎么办?

      生成的Minio的临时访问链接过长怎么办?

从而引导出:

1、如何生成短链接:

2、重定向和转发的区别?

3、重定向的实现方式:

4、如何保证浏览器地址不变的情况下请求资源?

基于Docker-compose的Minio安装

配置文件docker-compose.yml

创建docker-compose.yml,并在docker-compose.yml文件夹下面创建文件夹data

mkdir data

version: "3"
services:minio:image: minio/miniocontainer_name: minioprivileged: true  #是否要获取宿主机的特权volumes:- /root/common/data/minio/data:/data #目录映射ports:- "9001:9001"    #端口映射 ---- 不能采用:9001:9000之类的- "9000:9000"    #端口映射environment:MINIO_ACCESS_KEY: xxxxxA1    #账号MINIO_SECRET_KEY: xxxxxA2 #密码command: server --console-address ':9001' /data  #启动命令healthcheck: #健康检测test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]interval: 30stimeout: 20sretries: 3

启动

docker-compose up -d  # 后台启动

启动成功后登录webUI

URL:ip:9001

Access Key:xxxxxA1

Secret_key:xxxxxA2

上传资源-web操作 

创建bucket

上传资源

 

 上传成功后的样式

Java使用 --- 基础版

Step1、引入pom依赖


<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.17</version>
</dependency>

 Step2、创建一个新key,并下载

此时系统会下载:credentials.json

{"url":"http://ip:9001/api/v1/service-account-credentials","accessKey":"xxxxx","secretKey":"xxxxxxx","api":"s3v4","path":"auto"} 

 Step3、创建一个application.yml文件

minio:url: "http://ip:9000"  # 如果是http://ip:9001 会报错“S3 API Requests must be made to API port.”
#  url: "http://www.abcxxxx域名.com"  # 需要配置 指向MinIO真实地址:http://ip:9000; --- 可以使用Nginx反向代理 --- 解决暴露真实IP的方法accessKey: "xxxxxA1"secretKey: "xxxxxA2"api: "s3v4"

Step4、创建配置实体MinioProperties.java

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties {private String url;private String accessKey;private String secretKey;private String api;
}

Step5、创建文件类型枚举类FileType.java 

package com.lting.minio.model;import lombok.Getter;
/**
* 枚举类,按需定义
*/
public enum FileType {// 修正后的枚举定义(包含扩展名和MIME类型)MP4("mp4", "video/mp4"),TXT("txt", "text/plain"),JSON("json", "application/json"),PNG("png", "image/png"),      // 修正PNG类型JPG("jpg", "image/jpeg"),PDF("pdf", "application/pdf"),DOC("doc", "application/msword"),DOCX("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),CSV("csv", "text/csv"),EXCEL("xls", "application/vnd.ms-excel");private final String extension;@Getterprivate final String mimeType;// 枚举构造函数FileType(String extension, String mimeType) {this.extension = extension;this.mimeType = mimeType;}// 根据文件名获取MIME类型public static String getMimeTypeForFile(String fileName) {String extension = getFileExtension(fileName);for (FileType type : values()) {if (type.extension.equalsIgnoreCase(extension)) {return type.mimeType;}}return "application/octet-stream"; // 默认类型}// 根据扩展名获取枚举实例public static FileType fromExtension(String extension) {for (FileType type : values()) {if (type.extension.equalsIgnoreCase(extension)) {return type;}}throw new IllegalArgumentException("Unsupported file extension: " + extension);}// 获取文件扩展名辅助方法private static String getFileExtension(String fileName) {int lastDotIndex = fileName.lastIndexOf('.');if (lastDotIndex == -1 || lastDotIndex == fileName.length() - 1) {return "";}return fileName.substring(lastDotIndex + 1).toLowerCase();}
}

Step6、创建工具类MinioUtils.java

package com.lting.minio;import com.lting.minio.model.FileType;
import com.lting.minio.model.MinioProperties;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;/*** 0、桶列表* 1、CRUD桶Buckets* 2、Upload(指定路径)* 3、查看桶下面的list列表* 4、Delete* 5、Download*/
@Component
@Log4j2
public class MinioUtils {@Getterprivate final MinioProperties minioProperties;private MinioClient minioClient;@Autowiredpublic MinioUtils(MinioProperties minioProperties) {this.minioProperties = minioProperties;}@PostConstructpublic void init() {try {this.minioClient = MinioClient.builder().endpoint(minioProperties.getUrl()) // 使用代理域名---不然生成的临时地址为真实ip地址.credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()).build();} catch (Exception e) {log.error("初始化minio配置异常", e.fillInStackTrace());}}/*** 已经存在的bucket集合列表*/public List<Bucket> listBucket() throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {return minioClient.listBuckets();}/*** 创建buckets*/public void createBuckets(final String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}/*** 某一个bucket是否存在*/public boolean bucketExists(final String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {return this.minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());}/*** 删除buckets*/public void removeBucket(final String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}/*** 上传文件* 通用上传方法*/public ObjectWriteResponse uploadFile(final String bucketName, final String fileName, final InputStream inputStream, final long fileSize, String contentType) throws Exception {return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, fileSize, -1).contentType(contentType).build());}/*** 上传文件(如图片/PDF等)*/public ObjectWriteResponse uploadFile(File file, String bucketName, final String fileName) throws Exception {String contentType = Files.probeContentType(file.toPath());if (contentType == null) {contentType = "application/octet-stream"; // 默认类型}try (InputStream inputStream = new FileInputStream(file)) {return uploadFile(bucketName, fileName, inputStream, file.length(), contentType);}}/*** 上传本地文件*/public ObjectWriteResponse uploadLocalFile(final String bucketName, final String filePath, final String fileType) throws Exception {this.isMakeBuckets(bucketName);File file = new File(filePath);try (InputStream inputStream = new FileInputStream(file)) {return uploadFile(bucketName, file.getName(), inputStream, file.length(), fileType);}}/*** 上传MultipartFile(适用于HTTP文件上传)*/public ObjectWriteResponse uploadMultipartFile(final String bucketName, MultipartFile file, String fileName) throws Exception {this.isMakeBuckets(bucketName);final String contentType = file.getContentType();try (InputStream inputStream = file.getInputStream()) {return uploadFile(bucketName, fileName, inputStream, file.getSize(), contentType);}}/*** 上传二进制数据(如图片/PDF等) --- 会自动生成文件*/public ObjectWriteResponse uploadBytes(String bucketName, String fileName, byte[] data, final String fileType) throws Exception {this.isMakeBuckets(bucketName);try (InputStream inputStream = new ByteArrayInputStream(data)) {return uploadFile(bucketName, fileName, inputStream, data.length, fileType);}}/*** 上传文本内容 --- 会自动生成文件*/public ObjectWriteResponse uploadText(String bucketName, String fileName, String text) throws Exception {this.isMakeBuckets(bucketName);byte[] bytes = text.getBytes(StandardCharsets.UTF_8);try (InputStream inputStream = new ByteArrayInputStream(bytes)) {return uploadFile(bucketName, fileName, inputStream, bytes.length, FileType.TXT.getMimeType());}}/*** 上传JSON内容 --- 会自动生成文件*/public ObjectWriteResponse uploadJson(final String bucketName, final String fileName, final String json) throws Exception {this.isMakeBuckets(bucketName);byte[] bytes = json.getBytes(StandardCharsets.UTF_8);try (InputStream inputStream = new ByteArrayInputStream(bytes)) {return uploadFile(bucketName, fileName, inputStream, bytes.length, FileType.JSON.name());}}private void isMakeBuckets(String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {boolean found = this.bucketExists(bucketName);if (!found) {this.createBuckets(bucketName);}}/*** 查看已经存在的buckets下面的文件*/public List<Result<Item>> listObject(final String bucketName) throws Exception {return listObject(bucketName, "", 1000);}public List<Result<Item>> listObject(final String bucketName, final String prefix, final int size) throws Exception {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix) // 开始名称.maxKeys(size) // 最大数量.includeVersions(true).recursive(true) // 是否递归遍历子目录.build());return StreamSupport.stream(results.spliterator(), false).collect(Collectors.toList());}/*** 下载到流*/public InputStream downloadToStream(String bucketName, String fileName) throws Exception {try {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());} catch (MinioException e) {throw new Exception("下载失败: " + e.getMessage());}}/*** 下载到本地*/public void downloadToLocal(String bucketName, String fileName, String localFilePath) throws Exception {try (InputStream inputStream = downloadToStream(bucketName, fileName)) {Path path = Path.of(localFilePath);Files.copy(inputStream, path);} catch (Exception e) {throw new Exception("文件保存失败: " + e.getMessage());}}/*** 单个文件删除*/public void deleteObject(String bucketName, String fileName) throws Exception {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());} catch (MinioException e) {throw new Exception("删除失败: " + e.getMessage());}}/*** 批量删除(需自行遍历)*/public void batchDelete(String bucketName, List<String> objectNames) {objectNames.forEach(name -> {try {deleteObject(bucketName, name);} catch (Exception e) {// 记录日志或处理异常System.err.println("删除失败: " + name + " | 原因: " + e.getMessage());}});}/*** 获取预览地址* 有效时间默认1H** @return*/public String getPreviewFileUrl(String bucketName, String fileName) throws Exception {return getPreviewFileUrl(bucketName, fileName, 10, TimeUnit.MINUTES);}public String getPreviewFileUrl(String bucketName, String fileName, final int expiryTime, final TimeUnit timeUnit) throws Exception {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(fileName).expiry(expiryTime, timeUnit).build());}
}

Step7、启动类MinioApplication.java

@SpringBootApplication
@EnableConfigurationProperties(MinioProperties.class) // 显式启用
public class MinioApplication {public static void main(String[] args) {SpringApplication.run(MinioApplication.class, args);}
}

Step8、测试类---按需

import com.lting.MinioApplication;
import io.minio.ObjectWriteResponse;
import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.File;
import java.util.List;@SpringBootTest(classes = MinioApplication.class)
public class MinioTest {@Autowiredprivate MinioUtils minioUtils;@Test@DisplayName("MinioUtils")public void properties() {System.out.println(minioUtils.getMinioProperties());}@Test@DisplayName("listBuckets")public void listBuckets() {try {List<Bucket> buckets = minioUtils.listBucket();buckets.forEach(x -> System.out.println(x.creationDate() + ", " + x.name()));} catch (Exception e) {throw new RuntimeException(e);}}@Test@DisplayName("makeBuckets")public void createBuckets() {try {minioUtils.createBuckets("test_code_create");listBuckets();} catch (Exception e) {throw new RuntimeException(e);}}@Test@DisplayName("deleteBuckets")public void deleteBuckets() {try {minioUtils.removeBucket("test_code_create");listBuckets();} catch (Exception e) {throw new RuntimeException(e);}}@Test@DisplayName("uploadLocalFile")public void uploadLocalFile() throws Exception {final String bucketName = "test_code_create";final String filePath = "C:\\Users\\xxxxx.png";final File file = new File(filePath);ObjectWriteResponse owr = minioUtils.uploadFile(file, bucketName,"2025/04/25/pig.png");  // 当在webui中创建的路径:V1/V2/V3一样的效果System.out.println(owr.etag());}@Test@DisplayName("listBuckets")public void uploadText() throws Exception {String content = "{\"url\":\"http://ip:9001/api/v1/service-account-credentials\",\"accessKey\":\"xxxx\",\"secretKey\":\"xxxxxx\",\"api\":\"s3v4\",\"path\":\"auto\"}";ObjectWriteResponse owr= minioUtils.uploadText("test_code_create", "/2025/04/25/测试.txt", content);System.out.println(owr.etag());}@Test@DisplayName("listObject")public void listObject() throws Exception {List<Result<Item>> items= minioUtils.listObject("test_code_create");items.forEach(x -> {try {Item item = x.get();System.out.println(item.etag() + "\t" + item.objectName() + "\t" + item.size() + "\t" + item.lastModified().toLocalDateTime() + "\t" + item.versionId());} catch (Exception e) {throw new RuntimeException(e);}});}@Test@DisplayName("getPreviewFileUrl")public void getPreviewFileUrl() throws Exception {System.out.println(minioUtils.getPreviewFileUrl("test_code_create", "2025/04/25/ltingzx.png"));;}@Test@DisplayName("downloadToLocal")public void downloadToLocal() throws Exception {minioUtils.downloadToLocal("test_code_create", "requirements.txt", "C:\\Users\\YiYang\\Desktop\\LLama-Factory\\req.txt");}}

关于Minio真实IP解决方法:

使用Minio的时候,生成资源的临时访问链接时,生成的地址IP是真实的IP和端口,不安全,怎么办?

minio通过“minioUtils.getPreviewFileUrl”方法生成临时链接为一般为比较长的链接,比如:“http://127.0.0.1:9001/test/xxxx_47109.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=gKK5g5pdjV6LWdW8XtoO%2F20250428%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250428T100736Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=bd9560f5655e341263a8944545142449b1a7a393e8952eb20f9be9be9cc1391b”

---- 注意:解决方案有很多种,但是本文使用的是,短链接+Nginx代理+代理请求方案解决

Step1、前提准备

准备一个域名 比如 minio.ltingzx.com

如果没有域名,可以在本地修改hosts文件 添加: 127.0.0.1 minio.ltingzx.com

step2、修改application.yml文件

将url修改为step1中的域名;

minio:url: "http://minio.ltingzx.com"  # 需要配置 指向MinIO真实地址:http://ip:9000; --- 可以使用Nginx反向代理

Step3、添加nginx.conf配置,并启动nginx

关于优化,因为我们使用的是minio存储图片等资源,所以我们可以在Nginx上面开启缓存,用以优化...;

server {listen       80;server_name  minio.ltingzx.com;# 指定前端项目所在的位置location / {proxy_pass http://ip:9000; # 指向MinIO真实地址proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}

Step4、生成短链接以及访问短链接

长链接请求接口A ,接口A 生成短链接并返回;

用户拿到短链接后,请求服务的接口,服务接口拿到短链接以后,在映射关系中找到对应的长链接,直接重定向/转发/代理请求即可。

重定向:重定向是需要服务器端返回url地址,由浏览器端再次请求---此时依然会暴露真实ip和端口,且浏览器会改变地址;

转发:之所以不使用转发,核心原因是因为,转发的话需要资源和服务在同一网络---此时我们的minio在云端服务器,服务在本地,所以不适用。

代理请求:拿到短链接后,直接由服务器进行请求;然后服务器拿到的资源返回给response的outputstream流即可。

本文使用UUID临时处理,并且直接使用map方法存储:
真实开发中,我们的映射关系可以存储在数据库(比如Redis/MySQL)中,并且要设置过期时间;

使用重定向访问短链接

    private final static Map<String, String> URL_MAP = new HashMap<>();
@PostMapping("/generate")public R<String> generate(@RequestParam("longUrl") String longUrl) {String shortUrl = UUID.randomUUID().toString().replace("-", "");URL_MAP.put(shortUrl, longUrl);return R.ok(shortUrl);}/*** 短链接点击跳转*重定向方法: ---- 要改变浏览器地址* 设置sendRedirect,比如response.sendRedirect(URL_MAP.get(shortURL))* 或者设置状态302,*      response.setStatus(302);*      response.setHeader("Location", URL_MAP.get(shortURL));* @param shortURL*/
@GetMapping("/{shortURL}")public void redirect(@PathVariable("shortURL") String shortURL, HttpServletResponse response) throws IOException, NotFoundException {System.out.println("短链接 redirect to :" + shortURL);if (URL_MAP.containsKey(shortURL)) {
//            response.sendRedirect(URL_MAP.get(shortURL));response.setStatus(302);response.setHeader("Location", URL_MAP.get(shortURL));
//            response.sendRedirect(URL_MAP.get(shortURL));} else {throw new NotFoundException("短链已过期");}}

服务端代理请求形式 --- 直接由服务器端发起请求

实现步骤

  1. 生成短链接:将长URL映射为短码(如Base62编码),并存储映射关系。

  2. 处理短链接请求:当访问短链接时,服务器通过短码获取长URL。

  3. 代理请求:服务器端发起HTTP请求到长URL,将响应内容返回客户端,保持地址栏不变。

    @GetMapping("/{shortURL}")public void proxyRequest(@PathVariable("shortURL") String targetUrl, HttpServletResponse resp) throws IOException, NotFoundException {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpGet httpGet = new HttpGet(URL_MAP.get(targetUrl));try (CloseableHttpResponse response = httpClient.execute(httpGet)) {// 复制状态码resp.setStatus(response.getStatusLine().getStatusCode());// 复制响应头org.apache.http.Header[] headers = response.getAllHeaders();for (org.apache.http.Header header : headers) {resp.setHeader(header.getName(), header.getValue());}// 复制响应内容HttpEntity entity = response.getEntity();if (entity != null) {try (InputStream inputStream = entity.getContent();OutputStream outputStream = resp.getOutputStream()) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}}}}}

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

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

相关文章

朴素贝叶斯分类器

朴素贝叶斯分类器 朴素贝叶斯是一种基于密度估计的分类算法&#xff0c;它利用贝叶斯定理进行预测。该算法的核心假设是在给定类别的情况下&#xff0c;各个特征之间是条件独立的&#xff0c;尽管这一假设在现实中通常不成立&#xff0c;但朴素贝叶斯分类器依然能够生成对有偏…

在 Trae CN IDE 中配置 Python 3.11的指南

在 Trae CN IDE 中配置 Python 3.11的指南 下载 python 3.11 安装 Python 3.11 首先&#xff0c;我们需要确保安装了 Python 3.11。可以从Python 官方网站下载适合你操作系统的版本。 链接 如果你已经安装了 Python 3.11&#xff0c;可以通过以下命令确认&#xff1a; 文…

MQTT 协议与 HTTP 协议的区别

在现代的网络通信中&#xff0c;MQTT 协议和 HTTP 协议都扮演着重要的角色&#xff0c;但它们有着不同的特点和适用场景。下面我们就从多个方面来详细探讨它们之间的区别。 一.协议设计理念 1. MQTT 协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;即…

Postgresql源码(145)优化器nestloop参数化路径评估不准问题分析

相关 《Postgresql源码&#xff08;133&#xff09;优化器动态规划生成连接路径的实例分析》 1 问题 最近遇到一个问题&#xff0c;评估行数和真实行数存在较大差距&#xff0c;导致计划不准的问题。 nestloop内表评估是根据外表的参数来的。因为外表驱动表每取一条&#xff…

HTML与CSS实现风车旋转图形的代码技术详解

在前端开发中&#xff0c;HTML和CSS是构建网页的基础技术。通过巧妙运用HTML的结构搭建和CSS的样式控制&#xff0c;我们能够实现各种精美的视觉效果。本文将对一段实现旋转图形效果的HTML和CSS代码进行详细解读&#xff0c;剖析其中的技术要点。 一、运行效果 HTML与CSS实现风…

linux下,ollama会把模型文件保存在哪里?

文章目录 运行ollama,有两种形式,估计得分开讨论首先是使用自动启动的ollama:先跑个“小一点的大模型”但是现在模型文件存在哪儿呢?运行ollama,有两种形式,估计得分开讨论 我们用两种方式,来运行ollama。 首先是使用自动启动的ollama: ps -aux | grep ollama系统自…

鼎讯信通 智能通信干扰设备:多频段多模态信号压制解决方案

在万物互联时代&#xff0c;通信安全已成为现代社会的核心基础设施防护重点。面对日益复杂的电磁环境挑战&#xff0c;新一代智能通信干扰设备通过技术创新实现了信号压制能力的革命性突破。本文将深入解析该设备的八大核心功能与技术特性&#xff0c;展现其在商业通信保障、工…

【2025软考高级架构师】——案例分析总结(13)

摘要 本文对2025年软考高级架构师的考纲及案例分析进行了总结。内容涵盖系统规划、架构设计、系统建模、安全架构、可靠性分析、大数据架构等多方面知识点&#xff0c;还涉及软件质量特性、系统流程图与数据流图、嵌入式系统架构、分布式系统设计等考查内容&#xff0c;详细列…

js单调栈解题模板

模板 function solve(arr) {const stack [];const result new Array(arr.length).fill(默认值);for (let i 0; i < arr.length; i) {while (stack.length && 比较条件(arr[i], arr[栈顶])) {const top stack.pop();result[top] 计算结果(i, top); }stack.push…

[蓝桥杯真题题目及解析]2025年C++b组

移动距离&#xff08;填空&#xff09;** 小明初始在二维平面的原点&#xff0c;他想前往坐标 (233,666)。在移动过程中&#xff0c;他只能采用以下两种移动方式&#xff0c;并且这两种移动方式可以交替、不限次数地使用&#xff1a; 水平向右移动&#xff0c;即沿着 x 轴正方…

【ICMP协议深度解析】从网络诊断到安全实践

目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键报文类型说明协议版本对比 二、实战演示环境配置要求核心实验实现实验1&#xff1a;标准ping流程实验2&#xff1a;traceroute路径发现实验3&#xff1a;自定义ICMP…

安卓基础(悬浮窗分级菜单和弹窗)

initializeViews() 初始化 把全部的按钮都弄出来 // 主菜单按钮ImageButton mainButton floatingMenuView.findViewById(R.id.main_button);// 二级菜单按钮subButtons new ImageButton[3];subButtons[0] floatingMenuView.findViewById(R.id.sub_button_1);subButtons[1]…

冯·诺依曼体系:现代计算机的底层逻辑与百年传承

在智能手机流畅运行复杂游戏、超级计算机模拟气候变化的今天&#xff0c;很少有人会想到&#xff0c;驱动这些神奇机器运转的核心架构&#xff0c;依然遵循着70多年前提出的设计理念。这就是由匈牙利裔美国科学家约翰冯诺依曼&#xff08;John von Neumann&#xff09;奠定的冯…

【云备份】服务端工具类实现

1.文件实用工具类设计 不管是客户端还是服务端&#xff0c;文件的传输备份都涉及到文件的读写&#xff0c;包括数据管理信息的持久化也是如此&#xff0c;因此首先设 计封装文件操作类&#xff0c;这个类封装完毕之后&#xff0c;则在任意模块中对文件进行操作时都将变的简单化…

CGI 协议是否会具体到通讯报文?

CGI&#xff08;Common Gateway Interface&#xff09;不涉及具体的网络通讯报文格式&#xff0c;它定义的是 Web服务器与外部程序之间的数据交互方式&#xff0c;而不是像HTTP或FastCGI那样的二进制协议。下面分几个方面详细说明&#xff1a; 1. CGI 的交互方式&#xff08;非…

【Mytais系列】Type模块:类型转换

MyBatis 的 类型系统&#xff08;Type System&#xff09; 是框架处理 Java 类型与数据库类型之间映射的核心模块&#xff0c;它通过 类型处理器&#xff08;TypeHandler&#xff09;、类型别名&#xff08;TypeAlias&#xff09; 和 类型转换器 等机制&#xff0c;实现了数据库…

新华三H3CNE网络工程师认证—动态NAT

静态NAT严格地一对一进行地址映射&#xff0c;这就导致即便内网主机长时间离线或者不发送数据时&#xff0c;与之对应的共有地址也处于使用状态。为了避免地址浪费&#xff0c;动态NAT提出了地址池的概念&#xff1a;所有可用的共用地址组成地址池。 当内部主机访问外部网络时临…

华为OD机试真题 Java 实现【水库蓄水问题】

前言 博主刷的华为机考题&#xff0c;代码仅供参考&#xff0c;因为没有后台数据&#xff0c;可能有没考虑到的情况 如果感觉对你有帮助&#xff0c;请点点关注点点赞吧&#xff0c;谢谢你&#xff01; 题目描述 思路 1. 其实就是找一个最大的水坑&#xff0c;两个…

【Linux】Petalinux驱动开发基础

基于Petalinux做Linux驱动开发。 部分图片和经验来源于网络,若有侵权麻烦联系我删除,主要是做笔记的时候忘记写来源了,做完笔记很久才写博客。 专栏目录:记录自己的嵌入式学习之路-CSDN博客 目录 1 一个完整的Linux系统(针对Zynq) 1.1 PS部分 1.2 PL部分(若…

JAVA刷题记录: 递归,搜索与回溯

专题一 递归 面试题 08.06. 汉诺塔问题 - 力扣&#xff08;LeetCode&#xff09; class Solution {public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {dfs(A, B, C, A.size());}public void dfs(List<Integer> a, List<In…