SpringBoot实现本地对象存储【minio、阿里云、七牛云】
引入依赖
<!-- minio -->
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.12</version>
</dependency><!-- 阿里云oss -->
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.1</version>
</dependency><!-- 七牛云 -->
<dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>7.12.1</version>
</dependency>
代码实现
package com.meteor.blog.common.file.config;import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** 文件配置属性类** @author meteor* @date 2024-05-13*/
@Data
@ConfigurationProperties(prefix = "meteor.file")
public class FileStoreProperties {/*** 存储类型:local/minio/aliyun*/private FileStoreTypeEnum type = FileStoreTypeEnum.LOCAL;/*** 基础路径【type为local时生效】*/private String baseDir;/*** 服务地址*/private String endpoint;/*** 认证账户*/private String accessKey;/*** 认证密码*/private String secretKey;/*** 默认桶*/private String bucket;/*** nginx代理*/private String nginxHost;}
package com.meteor.blog.common.file;import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import com.meteor.blog.common.file.service.FileTemplate;
import com.meteor.blog.common.file.service.FileTemplateImpl;
import com.meteor.blog.common.file.strategy.*;
import com.meteor.blog.common.file.config.FileStoreProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 验证码自动配置** @author meteor* @date 2024-07-03*/
@Configuration
@EnableConfigurationProperties(FileStoreProperties.class)
public class FileAutoConfiguration {@Beanpublic FileStrategy fileStrategy(FileStoreProperties fileStoreProperties) {FileStoreTypeEnum type = fileStoreProperties.getType();switch (type) {case MINIO -> {return new MinioStrategyImpl(fileStoreProperties);}case ALIYUN -> {return new AliyunStrategyImpl(fileStoreProperties);}case QINIU -> {return new QiniuStrategyImpl(fileStoreProperties);}default -> {return new LocalStrategyImpl(fileStoreProperties);}}}@Beanpublic FileTemplate fileService(FileStrategy fileStrategy) {return new FileTemplateImpl(fileStrategy);}}
package com.meteor.blog.common.file.config;import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import com.meteor.blog.common.file.strategy.FileStrategy;
import org.springframework.util.ObjectUtils;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 策略工厂** @author meteor* @date 2024-05-13*/
public final class StrategyFactory {private static final Map<FileStoreTypeEnum, FileStrategy> STRATEGY_MAP = new ConcurrentHashMap<>();/*** 通过类型获取策略** @param type* @return*/public static FileStrategy getStrategy(FileStoreTypeEnum type) {return STRATEGY_MAP.get(type);}/*** 注册策略** @param type* @param strategy*/public static void register(FileStoreTypeEnum type, FileStrategy strategy) {if (ObjectUtils.isEmpty(type)) {return;}STRATEGY_MAP.put(type, strategy);}}
package com.meteor.blog.common.file.strategy;import org.springframework.beans.factory.InitializingBean;import java.io.InputStream;
import java.util.List;/*** 文件存储策略** @author meteor* @date 2023-04-21*/
public interface FileStrategy extends InitializingBean {/*** 目录是否存在** @param directory* @return* @throws Exception*/boolean directoryExists(String directory) throws Exception;/*** 获取目录** @return* @throws Exception*/List<String> listDirectories() throws Exception;/*** 创建目录** @param directory* @throws Exception*/void createDirectory(String directory) throws Exception;/*** 删除目录** @param directory* @throws Exception*/void removeDirectory(String directory) throws Exception;/*** 获取目录文件** @return*/List<String> listFiles() throws Exception;/*** 获取目录文件** @param directory* @return* @throws Exception*/List<String> listFiles(String directory) throws Exception;/*** 上传文件** @param fileName* @param inputStream* @throws Exception*/void uploadFile(String fileName, InputStream inputStream) throws Exception;/*** 上传文件** @param directory* @param fileName* @param inputStream* @return* @throws Exception*/void uploadFile(String directory, String fileName, InputStream inputStream) throws Exception;/*** 删除文件** @param directory* @param fileName* @throws Exception*/void removeFile(String directory, String fileName) throws Exception;/*** 删除文件** @param directory* @param fileNames* @throws Exception*/void removeFiles(String directory, List<String> fileNames) throws Exception;/*** 下载文件** @param directory* @param fileName* @return* @throws Exception*/InputStream downloadFile(String directory, String fileName) throws Exception;}
package com.meteor.blog.common.file.strategy;import cn.hutool.core.util.StrUtil;
import com.meteor.blog.common.base.util.SymbolUtil;
import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import com.meteor.blog.common.file.config.FileStoreProperties;
import com.meteor.blog.common.file.config.StrategyFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;/*** 本地策略实现** @author meteor* @date 2024-05-13*/
@Slf4j
@RequiredArgsConstructor
public class LocalStrategyImpl implements FileStrategy {private String baseDir;public LocalStrategyImpl(FileStoreProperties fileStoreProperties) {this.baseDir = fileStoreProperties.getBaseDir();}@Overridepublic boolean directoryExists(String directory) throws Exception {return new File(this.baseDir + File.separator + directory).exists();}@Overridepublic List<String> listDirectories() throws Exception {File file = new File(this.baseDir);List<String> list = new ArrayList<>();for (File subFile : Objects.requireNonNull(file.listFiles())) {if (subFile.isDirectory()) {list.add(subFile.getName());}}return list;}@Overridepublic void createDirectory(String directory) throws Exception {File file = new File(this.baseDir + File.separator + directory);if (!file.exists()) {file.mkdirs();}}@Overridepublic void removeDirectory(String directory) throws Exception {File file = new File(this.baseDir + File.separator + directory);if (file.exists()) {file.delete();}}@Overridepublic List<String> listFiles() throws Exception {return this.listFiles(null);}@Overridepublic List<String> listFiles(String directory) throws Exception {File file = new File(this.baseDir + (StrUtil.isBlank(directory) ? "" : File.separator + directory));List<String> list = new ArrayList<>();for (File subFile : Objects.requireNonNull(file.listFiles())) {if (subFile.isFile()) {list.add(subFile.getName());}}return list;}@Overridepublic void uploadFile(String fileName, InputStream inputStream) throws Exception {this.uploadFile(this.baseDir, fileName, inputStream);}@Overridepublic void uploadFile(String directory, String fileName, InputStream inputStream) throws Exception {try (FileOutputStream outputStream = new FileOutputStream(directory + SymbolUtil.SLASH + fileName)) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}} catch (IOException e) {throw new RuntimeException("Failed to upload file to local storage", e);}}@Overridepublic void removeFile(String directory, String fileName) throws Exception {File file = new File(directory + File.separator + fileName);if (file.exists()) {file.delete();}}@Overridepublic void removeFiles(String directory, List<String> fileNames) throws Exception {for (String fileName : fileNames) {this.removeFile(directory, fileName);}}@Overridepublic InputStream downloadFile(String directory, String fileName) throws Exception {try {return new FileInputStream(this.baseDir + (StrUtil.isBlank(directory) ? "" : File.separator + directory) + File.separator + fileName);} catch (IOException e) {throw new RuntimeException("Failed to download file from local storage", e);}}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register(FileStoreTypeEnum.LOCAL, this);}}
package com.meteor.blog.common.file.strategy;import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.meteor.blog.common.base.util.SymbolUtil;
import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import com.meteor.blog.common.file.config.FileStoreProperties;
import com.meteor.blog.common.file.config.StrategyFactory;
import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/*** minio策略实现** @author meteor* @date 2024-05-13*/
@Slf4j
@RequiredArgsConstructor
public class MinioStrategyImpl implements FileStrategy {private MinioClient minioClient;private String bucket;public MinioStrategyImpl(FileStoreProperties fileStoreProperties) {this.minioClient = MinioClient.builder().credentials(fileStoreProperties.getAccessKey(), fileStoreProperties.getSecretKey()).endpoint(fileStoreProperties.getEndpoint()).build();this.bucket = fileStoreProperties.getBucket();}@Overridepublic boolean directoryExists(String directory) throws Exception {return minioClient.bucketExists(BucketExistsArgs.builder().bucket(directory).build());}@Overridepublic List<String> listDirectories() throws Exception {return minioClient.listBuckets().stream().map(Bucket::name).collect(Collectors.toList());}@Overridepublic void createDirectory(String directory) throws Exception {if (!this.directoryExists(directory)) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(directory).build());}}@Overridepublic void removeDirectory(String directory) throws Exception {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(directory).build());}@Overridepublic List<String> listFiles() throws Exception {return this.listFiles(this.bucket);}@Overridepublic List<String> listFiles(String directory) throws Exception {List<String> list = new ArrayList<>();Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(directory).build());for (Result<Item> result : results) {list.add(result.get().objectName());}return list;}@Overridepublic void uploadFile(String fileName, InputStream inputStream) throws Exception {this.uploadFile(this.bucket, fileName, inputStream);}@Overridepublic void uploadFile(String directory, String fileName, InputStream inputStream) throws Exception {this.createDirectory(directory);minioClient.putObject(PutObjectArgs.builder().bucket(directory).object(fileName).stream(inputStream, inputStream.available(), -1).contentType("").build());}@Overridepublic void removeFile(String directory, String fileName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().bucket(directory).object(fileName).build());}@Overridepublic void removeFiles(String directory, List<String> fileNames) throws Exception {List<DeleteObject> deleteObjectList = new ArrayList<>();for (String fileName : fileNames) {DeleteObject deleteObject = new DeleteObject(fileName);deleteObjectList.add(deleteObject);}Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(directory).objects(deleteObjectList).build());for (Result<DeleteError> result : results) {DeleteError error = result.get();log.error("Error in deleting object {}, reason: {}", error.objectName(), error.message());}}@Overridepublic InputStream downloadFile(String directory, String fileName) throws Exception {GetObjectResponse object = minioClient.getObject(GetObjectArgs.builder().bucket(directory).object(fileName).build());String object1 = object.object();return null;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register(FileStoreTypeEnum.MINIO, this);}}
package com.meteor.blog.common.file.strategy;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import com.meteor.blog.common.file.config.FileStoreProperties;
import com.meteor.blog.common.file.config.StrategyFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;/*** 阿里云策略实现** @author meteor* @date 2024-05-13*/
@Slf4j
@RequiredArgsConstructor
public class AliyunStrategyImpl implements FileStrategy {private OSS ossClient;private String bucket;public AliyunStrategyImpl(FileStoreProperties fileStoreProperties) {this.ossClient = new OSSClientBuilder().build(fileStoreProperties.getEndpoint(),fileStoreProperties.getAccessKey(),fileStoreProperties.getSecretKey());this.bucket = fileStoreProperties.getBucket();}@Overridepublic boolean directoryExists(String directory) throws Exception {return ossClient.doesBucketExist(directory);}@Overridepublic List<String> listDirectories() throws Exception {return ossClient.listBuckets().stream().map(Bucket::getName).collect(Collectors.toList());}@Overridepublic void createDirectory(String directory) throws Exception {if (!this.directoryExists(directory)) {ossClient.createBucket(directory);}}@Overridepublic void removeDirectory(String directory) throws Exception {ossClient.deleteBucket(directory);}@Overridepublic List<String> listFiles() throws Exception {return this.listFiles(this.bucket);}@Overridepublic List<String> listFiles(String directory) throws Exception {ObjectListing objectListing = ossClient.listObjects(directory);return objectListing.getObjectSummaries().stream().map(e -> e.getKey()).collect(Collectors.toList());}@Overridepublic void uploadFile(String directory, InputStream inputStream) throws Exception {this.uploadFile(directory, this.bucket, inputStream);}@Overridepublic void uploadFile(String directory, String fileName, InputStream inputStream) throws Exception {this.createDirectory(directory);ossClient.putObject(directory, fileName, inputStream);}@Overridepublic void removeFile(String directory, String fileName) throws Exception {ossClient.deleteObject(directory, fileName);}@Overridepublic void removeFiles(String directory, List<String> fileNames) throws Exception {ossClient.deleteObjects(new DeleteObjectsRequest(directory).withKeys(fileNames));}@Overridepublic InputStream downloadFile(String directory, String fileName) throws Exception {OSSObject object = ossClient.getObject(new GetObjectRequest(directory, fileName));return object.getObjectContent();}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register(FileStoreTypeEnum.ALIYUN, this);}}
package com.meteor.blog.common.file.strategy;import com.meteor.blog.common.file.constant.FileStoreTypeEnum;
import com.meteor.blog.common.file.config.FileStoreProperties;
import com.meteor.blog.common.file.config.StrategyFactory;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.storage.model.FileListing;
import com.qiniu.util.Auth;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 七牛云策略实现** @author meteor* @date 2024-05-13*/
@Slf4j
@RequiredArgsConstructor
public class QiniuStrategyImpl implements FileStrategy {private Auth auth;private String bucket;private BucketManager bucketManager;private UploadManager uploadManager;public QiniuStrategyImpl(FileStoreProperties fileStoreProperties) {Configuration cfg = new Configuration(Region.autoRegion());this.auth = Auth.create(fileStoreProperties.getAccessKey(), fileStoreProperties.getSecretKey());this.bucket = fileStoreProperties.getBucket();this.bucketManager = new BucketManager(this.auth, cfg);this.uploadManager = new UploadManager(cfg);}@Overridepublic boolean directoryExists(String directory) throws Exception {return this.listDirectories().contains(directory);}@Overridepublic List<String> listDirectories() throws Exception {return Arrays.asList(bucketManager.buckets());}@Overridepublic void createDirectory(String directory) throws Exception {if (!this.directoryExists(directory)) {bucketManager.createBucket(directory, null);}}@Overridepublic void removeDirectory(String directory) throws Exception {bucketManager.delete(directory, null);}@Overridepublic List<String> listFiles() throws Exception {return this.listFiles(this.bucket);}@Overridepublic List<String> listFiles(String directory) throws Exception {FileListing fileListing = bucketManager.listFiles(directory, null, null, -1, null);List<String> list = new ArrayList<>();for (FileInfo fileInfo : fileListing.items) {list.add(fileInfo.key);}return list;}@Overridepublic void uploadFile(String fileName, InputStream inputStream) throws Exception {this.uploadFile(this.bucket, fileName, inputStream);}@Overridepublic void uploadFile(String directory, String fileName, InputStream inputStream) throws Exception {String token = auth.uploadToken(directory);uploadManager.put(inputStream, fileName, token, null, null);}@Overridepublic void removeFile(String directory, String fileName) throws Exception {bucketManager.delete(directory, fileName);}@Overridepublic void removeFiles(String directory, List<String> fileNames) throws Exception {BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();batchOperations.addDeleteOp(directory, fileNames.toArray(new String[0]));bucketManager.batch(batchOperations);}@Overridepublic InputStream downloadFile(String directory, String fileName) throws Exception {auth.privateDownloadUrl(fileName);return null;}@Overridepublic void afterPropertiesSet() throws Exception {StrategyFactory.register(FileStoreTypeEnum.QINIU, this);}}
package com.meteor.blog.common.file.constant;import com.meteor.blog.common.base.constant.BaseEnum;
import lombok.Getter;
import lombok.RequiredArgsConstructor;/*** 文件存储类型** @author meteor* @date 2024-05-13*/
@Getter
@RequiredArgsConstructor
public enum FileStoreTypeEnum implements BaseEnum<String> {ALIYUN("aliyun", "阿里云"),QINIU("qiniu", "七牛云"),MINIO("minio", "minio"),LOCAL("local", "本地");/*** 编码*/private final String code;/*** 描述*/private final String message;}
package com.meteor.blog.common.file.service;import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;
import java.util.List;/*** 文件服务接口** @author meteor* @date 2024-05-13*/
public interface FileTemplate {/*** 目录是否存在** @param directory* @return* @throws Exception*/boolean directoryExists(String directory) throws Exception;/*** 获取目录** @return* @throws Exception*/List<String> listDirectories() throws Exception;/*** 创建目录** @param directory* @throws Exception*/void createDirectory(String directory) throws Exception;/*** 删除目录** @param directory* @throws Exception*/void removeDirectory(String directory) throws Exception;/*** 获取目录文件** @return*/List<String> listFiles() throws Exception;/*** 上传文件** @param fileName* @param inputStream* @return* @throws Exception*/String uploadFile(String fileName, InputStream inputStream) throws Exception;/*** 上传文件** @param directory* @param inputStream* @param fileName* @return* @throws Exception*/String uploadFile(String directory, String fileName, InputStream inputStream) throws Exception;/*** 删除文件** @param directory* @param fileName* @throws Exception*/void removeFile(String directory, String fileName) throws Exception;/*** 删除文件** @param directory* @param fileNames* @throws Exception*/void removeFiles(String directory, List<String> fileNames) throws Exception;/*** 下载文件** @param directory* @param fileName* @return* @throws Exception*/InputStream downloadFile(String directory, String fileName) throws Exception;}
package com.meteor.blog.common.file.service;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.meteor.blog.common.file.strategy.FileStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.util.Assert;import java.io.InputStream;
import java.util.List;/*** 文件服务实现类** @author meteor* @date 2024-05-13*/
@RequiredArgsConstructor
public class FileTemplateImpl implements FileTemplate {private final FileStrategy fileStrategy;@Overridepublic boolean directoryExists(String directory) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(directory), "The directory cannot be blank");return fileStrategy.directoryExists(directory);}@Overridepublic List<String> listDirectories() throws Exception {return fileStrategy.listDirectories();}@Overridepublic void createDirectory(String directory) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(directory), "The directory cannot be blank");fileStrategy.createDirectory(directory);}@Overridepublic void removeDirectory(String directory) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(directory), "The directory cannot be blank");fileStrategy.removeDirectory(directory);}@Overridepublic List<String> listFiles() throws Exception {return fileStrategy.listFiles();}@Overridepublic String uploadFile(String fileName, InputStream inputStream) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(fileName), "The fileName cannot be blank");Assert.notNull(inputStream, "The inputStream cannot be null");fileStrategy.uploadFile(fileName, inputStream);return null;}@Overridepublic String uploadFile(String directory, String fileName, InputStream inputStream) throws Exception {fileStrategy.uploadFile(directory, fileName, inputStream);return "";}@Overridepublic void removeFile(String directory, String fileName) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(directory), "The directory cannot be blank");Assert.isTrue(StrUtil.isNotBlank(fileName), "The fileName cannot be blank");fileStrategy.removeFile(directory, fileName);}@Overridepublic void removeFiles(String directory, List<String> fileNames) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(directory), "The directory cannot be blank");Assert.isTrue(CollUtil.isNotEmpty(fileNames), "The fileNames cannot be empty");fileStrategy.removeFiles(directory, fileNames);}@Overridepublic InputStream downloadFile(String directory, String fileName) throws Exception {// 参数校验Assert.isTrue(StrUtil.isNotBlank(directory), "The directory cannot be blank");Assert.isTrue(StrUtil.isNotBlank(fileName), "The fileName cannot be blank");return fileStrategy.downloadFile(directory, fileName);}}
相关文章:
SpringBoot实现本地对象存储【minio、阿里云、七牛云】
引入依赖 <!-- minio --> <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.12</version> </dependency><!-- 阿里云oss --> <dependency><groupId>com.aliyun.…...
阿里云百炼(1) : 阿里云百炼应用问答_回答图片问题_方案1_提问时上传图片文件
直接用于拍照答题不大理想, 可能适用其他用途, 更好的方案: 阿里云百炼(1) : 阿里云百炼应用问答_回答图片问题_方案2_提取题目再提问-CSDN博客 1.实现代码 package cn.nordrassil.ly.test.拍照答题;import com.alibaba.dashscope.app.Application; import com.alibaba.dashsc…...
理解阿里云的MQTT
一、阿里云的mqtt分几种 阿里云提供的MQTT服务主要分为标准MQTT协议和P2P模式MQTT两种类型,二者在通信模式及适用场景上有显著差异: 1、标准MQTT与P2P MQTT的区别 特性标准MQTTP2P模式MQTT通信模式发布/订阅(Pub/S…...
HarmonyOS5云服务技术分享--云缓存快速上手指南
大家好,今天我们来聊聊如何快速上手华为AppGallery Connect(AGC)的云缓存服务。作为一款基于Serverless架构的Key-Value型缓存服务,它不仅能自动弹性伸缩,还能免去运维烦恼,非常适合高并发场景下的数据快速…...
FreeSWITCH rtcp-mux 测试
rtcp 跟 rtp 占用同一个端口,这就是 rtcp 复用 Fs 呼出是这样的: originate [rtcp_muxtrue][rtcp_audio_interval_msec5000]user/1001 &echo 需要同时指定 rtcp_audio_interval_msec,否则 rtcp_mux 不能生效 Fs 呼入不需要配置…...
浏览器播放 WebRTC 视频流
源码(vue) <template><video ref"videoElement" class"video" autoplay muted playsinline></video> </template><script setup lang"ts">import { onBeforeUnmount, onMounted, ref } fr…...
SpringBoot3+Vue3(1)-后端 请求头校验,jwt退出登录,mybaits实现数据库用户校验
1.后端:jwt请求头校验 解析 工具类jwtUtils 解析token 令牌是否过期,验证 正常、异常、运行时错误 倒入工具类是resource 工具类中添加解析用户的方法: 在 在工具类添加id解析 此处调用 添加controller做测试 测试&…...
Oracle RAC 中的 RBAL 进程
Oracle RAC 中的 RBAL 进程 RBAL 进程概述 RBAL(ReBalancer)是 Oracle RAC 和 ASM(Automatic Storage Management)环境中的一个关键后台进程,主要负责 ASM 磁盘组的重新平衡操作。 主要功能 磁盘组监控:…...
mac上将 Excel 文件的扩展名从 .xls 改为 .xlsx 后,打开时报错:“文件格式或文件扩展名无效”。
方法一:使用 Excel for Mac 打开并另存为 打开 Excel 应用程序。 打开你的 .xls 文件: 如果 Excel 能正常打开它,说明文件没问题。 在菜单栏点击:文件 → 另存为。 在文件格式中选择:Excel 工作簿 (.xlsx)。 点击保存…...
【算法-栈】深入栈模拟题:从题型特征到实现技巧
算法相关知识点可以通过点击以下链接进行学习一起加油!双指针滑动窗口二分查找前缀和位运算模拟链表哈希表字符串模拟 在算法学习中,栈是最基础也是最容易上手的数据结构之一。然而,当它被用于模拟复杂操作流程时,却常常成为区分“…...
OK536N-C测评:开箱体验以及在Linux下如何管理开发板
前言 OK536N-C终于到我手上了,因为我的主要领域是做嵌入式音视频。例如相机类产品,录像类产品,直播类产品都是我所涉及到的。本片文章一起来开箱见证下OK536N-C有哪些魅力,据说很强。 对于一个嵌入式领域的开发者来说࿰…...
【强化学习】深度强化学习 - Deep Q-Network(DQN)算法
文章目录 摘要一、DQN核心原理1. Q-learning回顾2. 用深度网络逼近Q函数3. 经验回放(Experience Replay)4. 目标网络(Target Network)5. 损失函数6. ε-贪心策略(ε-greedy) 二、算法流程与伪代码三、典型实…...
Python实例题:PyOt实现简易浏览器
目录 Python实例题 题目 代码实现 功能说明 基本浏览功能: 标签页支持: 用户界面: 使用方法 注意事项 Python实例题 题目 PyOt实现简易浏览器 代码实现 import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QT…...
MinerU可视化界面程序部署(Windows环境)
前提是要安装好MinerU,才能部署可视化程序(这个可视化程序的源码是MinerU自带的),安装MinerU的步骤参考: MinerU安装(pdf转markdown、json)-CSDN博客 下面进行可视化界面的部署操作(在Windows环境部署&…...
STM32之定时器(TIMER)与脉冲宽度调制(PWM)
一、STM32定时器的原理与应用 基本概念 定时器的作用一般是为了使用定时功能和中断功能(洗衣机、微波炉、电风扇、智能空调......),当然在STM32中也可以利用定时器产生周期性的脉冲信号来控制不同的外设(电机的转速、舵机的角度…...
Linux jq 命令使用详解
简介 jq 是一个命令行 JSON 处理器,允许解析、过滤、转换和格式化 JSON 数据,提取特定字段或重构 JSON,高效使用 JSON 中的 API 或配置文件。 安装 Debian/Ubuntu sudo apt install jqCentOS/RHEL sudo yum install jq或sudo dnf insta…...
【25软考网工】第七章 (2)UOS Linux文件和目录管理、用户和组管理
博客主页:christine-rr-CSDN博客 专栏主页:软考中级网络工程师笔记 大家好,我是christine-rr !目前《软考中级网络工程师》专栏已经更新三十多篇文章了,每篇笔记都包含详细的知识点,希望能帮助到你&#x…...
1.3 C++之变量与数据类型
变量与数据类型教程 目标 理解变量是存储数据的“容器”,数据类型决定容器中能放什么。掌握 int, float, char, bool 的使用。学会声明变量、赋值,定义常量 const。 一、什么是变量? 生活比喻:变量就像“贴了标签的盒子” 盒子…...
SAR ADC 比较器寄生电容对性能的影响
比较器的输入端直接连接CDAC的输出,那比较器的输入端的寄生电容对SAR ADC的性能是否有影响,我们来分析一下。 这是一个单端传统的SAR ADC,SAR ADC 转换只需要采样阶段和转换两个阶段,其中采样阶段一般包含比较器的offset的校正。 采样阶段:接Vin的开关闭合,接Vcom的开关…...
20250520在全志H3平台的Nano Pi NEO CORE开发板上运行Ubuntu Core16.04.3时跑通4G模块EC20
1、h3-sd-friendlycore-xenial-4.14-armhf-20210618.img.gz 在WIN10下使用7-ZIP解压缩/ubuntu20.04下使用tar 2、Win32DiskImager.exe 写如32GB的TF卡。【以管理员身份运行】 3、TF卡如果已经做过会有3个磁盘分区,可以使用SD Card Formatter/SDCardFormatterv5_WinE…...
探秘汽车门槛梁内板右后段成型工艺
引言:汽车制造的关键环节 在汽车制造的复杂体系中,每一个零部件都扮演着不可或缺的角色,其中汽车门槛梁内板右后段虽看似平凡,却对汽车的整体性能和安全起着关键作用。它是车身结构的重要组成部分,犹如建筑的基石&…...
阅读笔记---城市计算中用于预测学习的时空图神经网络研究综述
摘要 随着近年来传感技术的进步,智能城市产生并记录了无数的时空数据。预测时空数据的演变模式是城市计算的一个重要而又苛刻的方面,它可以增强各个领域的智能管理决策,包括交通、环境、气候、公共安全、医疗保健等。传统的统计和深度学习方…...
SpringBootDay1|面试题
目录 一、springboot框架 1、什么是springboot 2、Spring Boot的主要优点 3、springboot核心注解 4、定义banner(springboot的logo) 5、springboot配置文件 6、springboot 整合 jdbc 二、面试题 1)springmvc的作用 编辑 2&#x…...
PyCharm2025的字体的设置
前言 Pycharm中的字体调节,看起来似乎无足轻重。但是,能从容的调节,也是蛮好的,特别是做程序演示的时候。 当前PyCharm采用的是最新的2025.1.1版本(Community),当前的操作系统是Windows。 一、初始状态 …...
【Linux】进程间通信(三):命名管道
📝前言: 这篇文章我们来讲讲Linux 进程间通信(三)——命名管道 🎬个人简介:努力学习ing 📋个人专栏:Linux 🎀CSDN主页 愚润求学 🌄其他专栏:C学习…...
人工智能+:职业技能培训的元命题与能力重构
当“人工智能”成为各行各业的热门命题时,我们似乎跳过了一个更根本的思考:人类究竟需要怎样的AI能力?这个问题不解决,任何技术赋能都可能沦为无本之木。真正的挑战不在于如何应用AI,而在于如何定义人与AI的能力边界—…...
HarmonyOS5云服务技术分享--云存储SDK文章整理
在HarmonyOS ArkTS应用中集成华为云存储SDK指南 大家好呀!今天咱们来聊聊如何将华为云存储SDK集成到基于ArkTS(API 9-11)的HarmonyOS应用中。这篇指南会手把手带你完成从环境准备到代码实现的完整流程,过程中遇到的常见问题也会贴…...
《财务自由之路Ⅱ》理论篇
欢迎来到啾啾的博客🐱。 记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。 欢迎评论交流,感谢您的阅读😄。 目录 引言认知赚钱方式收入与负债都很重要整天工作的人,没有时间赚钱 一些建议做法…...
AI筑基,新质跃升|英码科技亮相华为广东新质生产力创新峰会,发布大模型一体机新品,助力产业智能化转型
5月15日,以“AI筑基,新质跃升”为主题的华为中国行2025广东新质生产力创新峰会在惠州圆满召开。本次峰会聚焦人工智能、算力基础设施等新ICT技术如何驱动“新质生产力”,共探广东高质量发展新路径。英码科技受邀出席本次峰会,并携…...
【C++】C++的拷贝构造函数介绍使用
拷贝构造函数 1.作用示例代码1:拷贝构造函数的调用示例代码2:系统默认的拷贝构造做的事情示例代码3:写法1-4示例代码4:写法5示例代码5:C编译器默认给类提供了4中隐含的方法 2.语法规则示例代码: 3.深拷贝和…...
能管理MySQL、Oracle、达梦数据库的桌面管理软件开源了
能管理MySQL、Oracle、达梦数据库的桌面管理软件开源了 能管理MySQL、Oracle、达梦数据库的桌面管理软件开源了1.项目介绍2. 项目源码开发2.1克隆项目2.2 配置并运行 3.使用3.1添加数据库连接3.2新增表3.3操作表3.4 运行sql 4.总结 能管理MySQL、Oracle、达梦数据库的桌面管理…...
5.20打卡
浙大疏锦行 DAY 31 文件的规范拆分和写法 知识点回顾 1. 规范的文件命名 2. 规范的文件夹管理 3. 机器学习项目的拆分 4. 编码格式和类型注解 作业:尝试针对之前的心脏病项目,准备拆分的项目文件,思考下哪些部分可以未来复用。 预处理&am…...
unity XCharts插件生成曲线图在UICanvas中
【推荐100个unity插件之22】基于UGUI的功能强大的简单易用的Unity数据可视化图表插件——XCharts3.0插件的使用_unity xcharts-CSDN博客...
创建thinkphp项目并配置数据库
配置环境并引入UI ssr模式 使用 composer 命令在指定的目录安装 Thinkphp6.x composer create-project topthink/think tp6demo出现Fatal error: Directive ‘track_errors’ is no longer available in PHP in Unknown on line 0说明你的php版本较高,在php.ini中…...
头歌实践平台:动态NAT配置
第一:打开GNS3,创建名为nat的项目文件 第二:创建网络拓扑结构如下: note:s端口线需要在关闭路由器的情况下双击进入,选配4T端口(不要忘记点击OK) 第三:打开所有设备(所…...
贝叶斯优化+CNN+LSTM=小论文创新点
2周速成小论文可能吗?有点悬,但有可能。今天我就给论文er推荐一个高潜力、易创新、适合速发的小论文选题:贝叶斯优化CNNLSTM! 这种“三结合”的优势在于技术成熟度高(经典CNN和LSTM)、创新点灵活性强&…...
软考中级软件设计师——计算机网络 IP地址与子网掩码相关题型
一、常见题型分类 题型考查重点解题关键子网划分根据需求划分子网,计算网络地址、广播地址、可用主机范围等二进制与十进制转换,子网掩码计算,网络位与主机位划分子网掩码转换CIDR表示法(如/24)与点分十进制ÿ…...
bi报表是什么意思?如何制作一张bi报表?
目录 一、BI 报表是什么意思? 1. BI 报表的基本概念 2. BI 报表的特点 3. BI 报表的作用 二、制作 BI 报表的前期准备 1. 明确报表的目标和需求 2. 确定数据来源 3. 选择合适的 BI 工具 三、制作 BI 报表的具体步骤 1. 数据收集与整理 2. 数据分析 3. 可…...
vivado fpga程序固化
一般下载到fpga上的程序在掉电之后就会丢失,如果想要掉电之后程序不丢失,就需要将比特流文件固化到板载的flash上。 以下以我的7a100t开发板为例,介绍程序固化的流程 点击OK就可以下载了。...
人生的真谛杂谈
文章目录 自我的哲学奠基自我存在的真实性身体与思想的决定关系自由意志自我的当代解构 三观的意义系统构建世界观:认知世界的根基人生观:生命意义的探索价值观:行为选择的准则三观构建的终极目标 价值的哲学解构价值的本体论价值客观性的形而…...
【Java】继承和多态在 Java 中是怎样实现的?
extends 关键字 class 子类 extends 父类 {... } // 类继承是单继承父类的哪些成员被继承 ? 访问修饰符 public 和 protected 修饰的父类成员字段和成员方法可以被继承 , 父类的默认方法只能在同包下继承 , 父类的 private 成员和构造方法不可继承 . super 关键字 表示父类…...
输出字母在字符串中位置索引
输入一个字符串,再输入两个字符,求这两个字符在字符串中的索引。 输入格式: 第一行输入字符串 第二行输入两个字符,用空格分开。 输出格式: 从右向左输出字符和索引,即下标最大的字符最先输出。每行一个。 输入样例: 在这里…...
Oracle中如何解决LATCH:CACHE BUFFERS LRU CHAIN
简单来讲,Oracle为了高效管理BUFFER CACHE主要使用以下2种LRU列: LRU列,又叫替换列(replacement list),其中又分为主列和辅助列。 主列:已使用的缓冲区列,分为HOT和COLD区域。HOT区…...
FPGA:基于Vivado的仿真流程与波形调试实践
在FPGA开发过程中,仿真是验证设计逻辑正确性的关键环节。尤其在复杂系统中,单靠硬件板级调试远远不够,往往需要依赖仿真工具提前发现潜在问题,提升开发效率。本文将结合Xilinx Vivado设计套件,系统梳理从仿真环境构建到…...
前端流行框架Vue3教程:20. 插槽slot(2)
插槽slot(2) 渲染作用域 插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的 SlotsTow.vue <script> export default {data() {return {};} } </script><template><h3>Slots续集</…...
CodeBuddy全新升级:体验Craft智能体的对话式编程革命
本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 腾讯云AI编程助手官网:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 目录 引言:软件开发的新范式 一、Craft智能体核心功能解析 1.1 自然语…...
基于SpringBoot+Vue的学籍管理系统的设计与实现
获取源码:SpringBootVue的学籍管理系统: 学籍管理系统:登录、个人中心、学生管理、教师管理、学院管理、专业管理、班级信息管理、课程信息管理、学生成绩管理、学生学籍管理、招生信息录入等功能 系统演示视频地址:SpringBootVue的学籍管理…...
【动态规划】P10988 [蓝桥杯 2023 国 Python A] 走方格|普及+
本文涉及知识点 C动态规划 P10988 [蓝桥杯 2023 国 Python A] 走方格 题目描述 给定一个 N N N 行 N N N 列的方格,第 i i i 行第 j j j 列的方格坐标为 ( i , j ) (i, j) (i,j),高度为 H i , j H_{i,j} Hi,j。小蓝从左上角坐标 ( 0 , 0 ) …...
pycharm无法正常调试问题
pycharm无法正常调试问题 1.错误代码 已连接到 pydev 调试器(内部版本号 231.8109.197)Traceback (most recent call last):File "E:\Python\pycharm\PyCharm 2023.1\plugins\python\helpers\pydev\_pydevd_bundle\pydevd_comm.py", line 304, in _on_runr r.deco…...
自学嵌入式 day21 - 数据结构 双向链表
1.双向链表 2.基础操作 (1)头部插入 int InsertHeadDouLinkList(DouLinkList *dl,DATATYPE *data) { DouLinkNode *newnode (DouLinkNode *)malloc(sizeof(DouLinkNode));//定义新节点来存储需插入的数据 if(NULL newnode)//判断结点空间…...