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 {

    @Resource
    private MinioUtil minioUtil;

    /**
     * minioUrl
     */
    @Value("${minio.url}")
    private String url;

    // 创建存储桶
    @Override
    @SneakyThrows
    public void createBucket(String bucket) {
        minioUtil.createBucket(bucket);
    }

    // 文件上传
    @Override
    @SneakyThrows
    public 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
    @SneakyThrows
    public List<String> getAllBuckets() {
        return minioUtil.getAllBucket();
    }

    // 获取所有文件
    @Override
    @SneakyThrows
    public List<FileInfo> getAllFiles(String bucket) {
        return minioUtil.getAllFile(bucket);
    }

    // 文件下载
    @Override
    @SneakyThrows
    public InputStream download(String bucket, String objectName) {
        return minioUtil.downLoad(bucket, objectName);
    }

    // 桶删除
    @Override
    @SneakyThrows
    public void deleteBucket(String bucket) {
        minioUtil.deleteBucket(bucket);
    }

    // 文件删除

    @Override
    @SneakyThrows
    public void deleteObject(String bucket, String objectName) {
        minioUtil.deleteObject(bucket, objectName);
    }

    @Override
    @SneakyThrows
    public 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 {

    @Resource
    private 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;

    /*@Resource
    private StorageAdapter aliStorageAdapterImpl;
    @Resource
    private StorageAdapter minioStorageServiceImpl;*/

    @Bean
    @RefreshScope
    public StorageAdapter storageService() {
        if ("minio".equals(storageType)){
            return new MinioStorageAdapter();
        } else if("aliyun".equals(storageType)) {
            return new AliStorageAdapter();
        } else {
            throw new IllegalArgumentException("未配置存储服务类型");
        }
    }


}

你可能感兴趣的:(工具,适配器模式,windows)