OSS业务存储适配器模式

流程

当我们配置了阿里云,腾讯云,minio等多个云存储厂商的业务代码时,如果我们要修改具体使用哪一种厂商的云存储,那么我们的controller层和service层就会需要改变业务代码;此时我们可以使用适配器模式来进行松耦合——>**1.**我们首先会定义一个关于文件存储的接口(非常丰富),然后定义minio,阿里云等厂商的文件存储实现类,去实现文件存储的具体细节——>**2.**那么如何确定具体使用哪一个文件存储?——>**3.**我们利用nacos动态路由,得到storage.type——>**4.**然后再在我们的StorageConfig配置类中进行判断,如果是minio的,就返回minio的业务实现类,将其注入容器中,这样就实现了我们的动态路由,我们只需修改nacos上的配置文件进行发布即可

package com.wyh.oss.adapter;import com.wyh.oss.entity.FileInfo;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;
import java.util.List;/*** 文件存储适配器** @create: 2023/12/1 0:32*/
public interface StorageAdapter {/*** 创建存储桶** @param bucket 存储桶名称*/void createBucket(String bucket);/*** 上传文件** @param multipartFile 文件流* @param bucket      存储桶名称* @param objectName  对象名称*/void uploadFile(MultipartFile multipartFile, String bucket, String objectName);/*** 获取所有存储桶** @return 存储桶名称集合*/List<String> getAllBuckets();/*** 获取存储桶下所有文件** @param bucket 存储桶名称* @return 文件信息集合*/List<FileInfo> getAllFiles(String bucket);/*** 下载文件** @param bucket     存储桶名称* @param objectName 对象名称* @return 文件流*/InputStream download(String bucket, String objectName);/*** 删除存储桶** @param bucket 存储桶名称*/void deleteBucket(String bucket);/*** 删除文件** @param bucket     存储桶名称* @param objectName 对象名称*/void deleteObject(String bucket, String objectName);String getUrl(String bucketName, String objectName);
}

minio的业务实现类:

package com.wyh.oss.adapter;import com.wyh.oss.entity.FileInfo;
import com.wyh.oss.util.MinioUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.InputStream;
import java.util.List;/*** minioIO存储适配器** @create: 2023/12/1 0:38*/public class MinioStorageAdapter implements StorageAdapter {@Resourceprivate MinioUtil minioUtil;/*** minioUrl*/@Value("${minio.url}")private String url;// 创建存储桶@Override@SneakyThrowspublic void createBucket(String bucket) {minioUtil.createBucket(bucket);}// 文件上传@Override@SneakyThrowspublic void uploadFile(MultipartFile multipartFile, String bucket, String objectName) {// 使用 minioUtil 对象创建存储桶minioUtil.createBucket(bucket);// 如果 objectName 不为空,则将文件名设置为 objectName + "/" + multipartFile.getName()if (objectName != null) {// 使用 minioUtil 对象将文件上传到 MinIO 存储服务中,并将其保存到指定的 bucket 以及 objectName + "/" + multipartFile.getName()minioUtil.uploadFile(multipartFile.getInputStream(), bucket, objectName + "/" + multipartFile.getName());} else {// 使用 minioUtil 对象将文件上传到 MinIO 存储服务中,并将其保存到指定的 bucket 以及 multipartFile.getName()minioUtil.uploadFile(multipartFile.getInputStream(), bucket, multipartFile.getName());}}// 获取所有存储桶@Override@SneakyThrowspublic List<String> getAllBuckets() {return minioUtil.getAllBucket();}// 获取所有文件@Override@SneakyThrowspublic List<FileInfo> getAllFiles(String bucket) {return minioUtil.getAllFile(bucket);}// 文件下载@Override@SneakyThrowspublic InputStream download(String bucket, String objectName) {return minioUtil.downLoad(bucket, objectName);}// 桶删除@Override@SneakyThrowspublic void deleteBucket(String bucket) {minioUtil.deleteBucket(bucket);}// 文件删除@Override@SneakyThrowspublic void deleteObject(String bucket, String objectName) {minioUtil.deleteObject(bucket, objectName);}@Override@SneakyThrowspublic String getUrl(String bucket, String objectName) {return url + "/" + bucket + "/" + objectName;}}

Util中封装了所有存储的具体细节:

package com.wyh.oss.util;import com.wyh.oss.entity.FileInfo;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;/*** minio文件操作工具** @author: ChickenWing* @date: 2023/10/11*/
@Component
public class MinioUtil {@Resourceprivate MinioClient minioClient;/*** 创建bucket桶*/public void createBucket(String bucket) throws Exception {boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());if (!exists) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());}}/*** 上传文件*/public void uploadFile(InputStream inputStream, String bucket, String objectName) throws Exception {minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName).stream(inputStream, -1, 5242889L).build());}/*** 列出所有桶*/public List<String> getAllBucket() throws Exception {List<Bucket> buckets = minioClient.listBuckets();return buckets.stream().map(Bucket::name).collect(Collectors.toList());}/*** 列出当前桶及文件*/public List<FileInfo> getAllFile(String bucket) throws Exception {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucket).build());List<FileInfo> fileInfoList = new LinkedList<>();for (Result<Item> result : results) {FileInfo fileInfo = new FileInfo();Item item = result.get();fileInfo.setFileName(item.objectName());fileInfo.setDirectoryFlag(item.isDir());fileInfo.setEtag(item.etag());fileInfoList.add(fileInfo);}return fileInfoList;}/*** 下载文件*/public InputStream downLoad(String bucket, String objectName) throws Exception {return minioClient.getObject(GetObjectArgs.builder().bucket(bucket).object(objectName).build());}/*** 删除桶*/public void deleteBucket(String bucket) throws Exception {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());}/*** 删除文件*/public void deleteObject(String bucket, String objectName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());}/*** 获取文件url*/public String getPreviewFileUrl(String bucketName, String objectName) throws Exception{GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).build();return minioClient.getPresignedObjectUrl(args);}}

config的配置:

package com.wyh.oss.config;import com.wyh.oss.adapter.AliStorageAdapter;
import com.wyh.oss.adapter.MinioStorageAdapter;
import com.wyh.oss.adapter.StorageAdapter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 文件存储config** @create: 2023/12/1 10:35*/
@Configuration
@RefreshScope
public class StorageConfig {@Value("${storage.service.type}")private String storageType;/*@Resourceprivate StorageAdapter aliStorageAdapterImpl;@Resourceprivate StorageAdapter minioStorageServiceImpl;*/@Bean@RefreshScopepublic StorageAdapter storageService() {if ("minio".equals(storageType)){return new MinioStorageAdapter();} else if("aliyun".equals(storageType)) {return new AliStorageAdapter();} else {throw new IllegalArgumentException("未配置存储服务类型");}}}

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

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

相关文章

WebSocket 详细教程

WebSocket 是一种网络通信协议&#xff0c;它实现了客户端与服务器之间的全双工通信。与传统的 HTTP 协议不同&#xff0c;WebSocket 允许服务器主动向客户端发送消息&#xff0c;这对于实时应用&#xff08;如在线聊天、股票交易、游戏等&#xff09;来说非常重要。 1. 工作原…

Leetcode 11-15题

盛最多雨水的容器 数组的第 i i i个数字表示这个位置隔板的高度&#xff0c;选择哪两块板子可以装最多的水&#xff0c;返回可以存储的最大水量。 有一种双指针的贪心策略&#xff1a;如果左边的指针所在的挡板低&#xff0c;就将左边的指针右移&#xff0c;否则将右边的指针左…

MATLAB知识点:nchoosek函数(★★★☆☆)用来计算组合数,也能返回从向量v中抽取k个元素的所有组合

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章&#xff1a;课后习题讲解中拓展的函数 在讲解第三…

算法训练营day28(补), 贪心算法2

//122. 买卖股票的最佳时机 II func maxProfit(prices []int) int { result : 0 //利润总和 for i : 1; i < len(prices); i { if prices[i]-prices[i-1] > 0 { result result (prices[i] - prices[i-1]) } } return result } //55. 跳跃游戏 func canJump(nums []…

模型 4E(交换、体验、随处、传教)理论

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。聚焦体验营销。 1 模型 4E(交换、体验、随处、传教)理论的应用 1.1 4E 理论在软件产品营销中的应用 某软件公司利用 4E 理论提升软件产品的市场占有率。具体如下&#xff1a; Exchange&a…

人工智能学习与实训笔记(四):神经网络之NLP基础—词向量

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 本篇目录 四、自然语言处理 4.1 词向量 (Word Embedding) 4.1.1 词向量的生成过程 4.1.2 word2vec介绍 4.1.3 word2vec&#xff1a;skip-gram算法的实现 4.2 句向量 - 情感分析 4.2.1 LSTM (Long S…

C语言之日历问题

一、代码展示 #include<stdio.h> int leapyear(int year)//判断是不是闰年函数 {if (year % 4 0 && year % 100 ! 0 || year % 400 0)return 1;elsereturn 0; } int days(int year, int month, int* day)//判断一个月有几天 {if (month ! 2)return day[month…

7.JS里表达式,if条件判断,三元运算符,switch语句,断点调试

表达式和语句的区别 表达式就是可以被求值的代码比如什么a 1 语句就是一段可以执行的代码比如什么if else 直接给B站的黑马程序员的老师引流一波总结的真好 分支语句 就是基本上所有的语言都会有的if else 语句就是满足不同的条件执行不同的代码&#xff0c;让计算机有条件…

【Java程序员面试专栏 Java领域】Java虚拟机 核心面试指引

关于Java 虚拟机部分的核心知识进行一网打尽,主要包括Java虚拟机的内存分区,执行流程等,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 JVM 程序执行流程 包括Java程序的完整执行流程,以及Javac编译,JIT即时编译 Java程序的完整执…

C++抽象类、纯虚函数和接口

在C中&#xff0c;抽象类是一种特殊的类&#xff0c;旨在作为其他类的基类使用。它定义了一组接口&#xff0c;派生类应该实现这些接口。 抽象类的主要特征 至少包含一个纯虚函数&#xff0c;不能被直接实例化&#xff0c;为派生类提供基础结构 纯虚函数&#xff08;Pure Vi…

会声会影2024新功能及剪辑视频步骤教程

会声会影2024的新功能主要包括&#xff1a; 全新的标题动态与特效&#xff1a;用户可以为文字标题指定进入、中场和退出的不同动态效果&#xff0c;比如闪现进入、中场弹跳和淡出退出等&#xff0c;让文字标题更具动感。此外&#xff0c;还新增了多个标题特效&#xff0c;包括…

作物模型狂奔 Apsim 脚本并行思路

这里没图&#xff0c;去B站看看 整体思路&#xff1a;Python -》R -》Apsimx 0、准备工作 0.0 电脑环境 我用的Win10啦&#xff0c;Linux、Mac可能得自己再去微调一下。 PS&#xff1a;一直没上win11&#xff0c;因为win11 开始菜单用着实在难顶。 !在这里插入图片描述](h…

037-安全开发-JavaEE应用JNDI注入RMI服务LDAP服务JDK绕过调用链类

037-安全开发-JavaEE应用&JNDI注入&RMI服务&LDAP服务&JDK绕过&调用链类 #知识点&#xff1a; 1、JavaEE-JNDI注入-RMI&LDAP 2、JavaEE-漏洞结合-FastJson链 3、JavaEE-漏洞条件-JDK版本绕过 演示案例&#xff1a; ➢JNDI注入-RMI&LDAP服务 ➢JNDI注…

一文彻底搞懂MySQL主从同步

文章目录 1. 简介2. 基本原理3. 实现方式4. 常见的主从架构模式4.1 一主一从4.2 一主多从4.3 双M4.4 联级复制4.5 多主一从 5. 常见问题 1. 简介 MySQL主从同步是一种数据库复制技术&#xff0c;它可以将一台MySQL数据库&#xff08;称为主服务器&#xff09;的数据复制到另一…

阿里云香港服务器cn2速度测试和租用价格表

阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品&#xff0c;中国电信CN2高速网络高质量、大规格BGP带宽&#xff0c;运营商精品公网直连中国内地&#xff0c;时延更低&#xff0c;优化海外回中国内地流量的公网线路&#xff0c;可以提高国际业务访问质量。阿里云服务…

YOLO v5项目实战 P5 解决运行detect文件时设置了--view-img但是显示不出来的问题

up主讲的实时显示目标检测后的图片的两种方法&#xff1a; &#xff08;1&#xff09;在下面的Terminal中输入下列命令&#xff1a; python detect.py --view-img &#xff08;2&#xff09;点击进入右上方的detect的Edit Configurations 然后在这个参数这里输入 --view img…

人工智能学习与实训笔记(八):百度飞桨套件使用方法介绍

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 本篇目录 八、百度飞桨套件使用 8.1 飞桨预训练模型套件PaddleHub 8.1.1 一些本机CPU可运行的飞桨预训练简单模型&#xff08;亲测可用&#xff09; 8.1.1.1 人脸检测模型 8.1.1.2 中文分词模型 8.1…

自然语言编程系列(四):GPT-4对编程开发的支持

在编程开发领域&#xff0c;GPT-4凭借其强大的自然语言理解和代码生成能力&#xff0c;能够深刻理解开发者的意图&#xff0c;并基于这些需求提供精准的编程指导和解决方案。对于开发者来说&#xff0c;GPT-4能够在代码片段生成、算法思路设计、模块构建和原型实现等方面给予开…

《数字电子电路》 课程设计:十字路口红绿灯自动控制系统(上)(multisim仿真及PCB实现)

&#xff08;一&#xff09;前言 本系列文章就笔者在大二下学期进行《数字电子线路》课程设计的题目&#xff1a;十字路口红绿灯自动控制系统 进行详细的讲解&#xff0c;希望对读者有所帮助。 &#xff08;二&#xff09;目录 一、主要指标及要求 二、电路工作原理 1、工作原…

P15---总电磁转矩T

正弦波驱动模式工作的永磁同步电动机的总电磁转矩 T clear clc% 15页表达式 syms Omega theta E I e_A E*sind(theta) e_B E*sind(theta-120) e_C E*sind(theta-240)i_A I*sind(theta) i_B I*sind(theta-120) i_C I*sind(theta-240)P e_A*i_A e_B*i_B e_C*i_CT P/Om…