• SpringBoot 文件操作 整合思路


    文件上传后,不仅可以保存在部署应用的服务器,也可以保存在阿里云,华为云obs,本文主要分享 SpringBoot 整合这三种不同文件存储服务器的思路

    1.既然要实现存储到三种不同的文件存储服务器,那自然想到接口和实现类,然后将实现类提供给 controller 调用。为了在程序中方便的知道实现类的简单类名和全类名来进行测试,可以新建一个抽象类。
    接口

    public interface FileService {
        FileInfoVo upload(MultipartFile multipartFile);
        String getSimpleClassName();
        String getFullClassName();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    抽象类

    public abstract class AbstractFileServiceImpl implements FileService {
        @Override
        public String getSimpleClassName() {
            return this.getClass().getSimpleName();
        }
    
        @Override
        public String getFullClassName() {
            return this.getClass().getName();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    三个实现类

    // 文件上传到部署应用的服务器
    @Service
    public class LocalFileServiceImpl extends AbstractFileServiceImpl {
        @Override
        public FileInfoVo upload(MultipartFile multipartFile) {
            return null;
        }
    }
    
    // 文件上传到阿里云
    @Service
    public class AliyunFileServiceImpl extends AbstractFileServiceImpl {
        @Override
        public FileInfoVo upload(MultipartFile multipartFile) {
            return null;
        }
    }
    
    // 文件上传到华为 obs
    @Service
    public class HuaweiObsFileServiceImpl extends AbstractFileServiceImpl {
        @Override
        public FileInfoVo upload(MultipartFile multipartFile) {
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.具体实现文件相关操作的逻辑如果写在 service 里,不利于程序的扩展,所以我们再新建三个工具类给 service 实现类调用,所以需要在三个 service 实现类中注入对应的工具类,同时由于在工具类中写的都是具体的功能实现逻辑,想要上传到阿里云华为云,就需要参考官网,进行导包和相应的配置
    导包

    
    <dependency>
        <groupId>com.aliyun.ossgroupId>
        <artifactId>aliyun-sdk-ossartifactId>
        <verison>3.15.1version>
        <optional>trueoptional>
    dependency>
    
    
    <dependency>
        <groupId>com.huaweicloudgroupId>
        <artifactId>esdk-obs-java-bundleartifactId>
        <verison>3.22.12version>
        <optional>trueoptional>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    配置文件

    # appliation.yml 文件
    file:
      local:
        path: xxx
      aliyun:
        endpoint: xxx
        access-key-id: xxx
        access-key-secret: xxx
        bucket-name: xxx
      huawei-obs:
        endpoint: xxx
        access-key-id: xxx
        access-key-secret: xxx
        bucket-name: xxx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    配置类

    // 文件上传到部署应用的服务器的配置类
    @Configuration
    public class LocalFileConfig {
        @Bean
        public LocalFileUtil localFileUtil() {
            return new LocalFileUtil();
        }
    }
    
    // 文件上传到阿里云的配置类
    @Configuration
    public class AliyunFileConfig {
        @Value("${file.aliyun.endpoint:}")
        private String endpoint;
        @Value("${file.aliyun.access-key-id:}")
        private String accessKeyId;
        @Value("${file.aliyun.access-key-secret:}")
        private String accessKeySecret;
    
        /**
         * 阿里云文件存储 client
         */
        @Bean
        public OSSClient ossClient() {
            return new OSSClient(endpoint, accessKeyId, accessKeySecret);
        }
    
        @Bean
        public AliyunFileUtil aliyunFileUtil() {
            return new AliyunFileUtil();
        }
    }
    
    // 文件上传到华为 obs 的配置类
    @Configuration
    public class HuaweiObsConfig {
        @Value("${file.huawei-obs.endpoint:}")
        private String endpoint;
        @Value("${file.huawei-obs.access-key-id:}")
        private String accessKeyId;
        @Value("${file.huawei-obs.access-key-secret:}")
        private String accessKeySecret;
    
        @Bean
        public ObsClient obsClient() {
            return new ObsClient(accessKeyId, accessKeySecret, endpoint);
        }
    
        @Bean
        public HuaweiObsFileUtil huaweiObsFileUtil() {
            return new HuaweiObsFileUtil();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    工具类

    // 文件上传到部署应用的服务器的工具类
    public class LocalFileUtil {
        public FileInfoVo upload(MultipartFile file) {
            return null;
        }
    }
    
    // 文件上传到阿里云的工具类
    public class AliyunFileUtil {
        @Value("${file.aliyun.bucket-name:}")
        private String bucketName;
    
        public FileInfoVo upload(MultipartFile file) {
            return null;
        }
    }
    
    // 文件上传到华为 obs 的工具类
    public class HuaweiObsFileUtil {
        @Value("${file.huawei-obs.bucket-name:}")
        private String bucketName;
    
        public FileInfoVo upload(MultipartFile file) {
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    service 实现类

    // 文件上传到部署应用的服务器
    @Service
    public class LocalFileServiceImpl extends AbstractFileServiceImpl {
        @Resource
        private LocalFileUtil localFileUtil;
    
        @Override
        public FileInfoVo upload(MultipartFile multipartFile) {
            // 自己写具体的上传逻辑
            return localFileUtil.upload(multipartFile);
        }
    }
    
    // 文件上传到阿里云
    @Service
    public class AliyunFileServiceImpl extends AbstractFileServiceImpl {
        @Resource
        private AliyunFileUtil aliyunFileUtil;
    
        @Override
        public FileInfoVo upload(MultipartFile multipartFile) {
            // 参考阿里云示例程序写具体的上传逻辑
            return aliyunFileUtil.upload(multipartFile);
        }
    }
    
    // 文件上传到华为 obs
    @Service
    public class HuaweiObsFileServiceImpl extends AbstractFileServiceImpl {
        @Resource
        private HuaweiObsFileUtil huaweiObsFileUtil;
    
        @Override
        public FileInfoVo upload(MultipartFile multipartFile) {
            // 参考华为云 obs 示例程序写具体的上传逻辑
            return huaweiObsFileUtil.upload(multipartFile);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    3.这样就可以在 controller 中注入三个实现类来调用方法了,当然为了后续扩展方便,可以通过 factory 类和枚举类来获得 service 实现类,然后在 controller 中注入 factory 类,通过 factory 来获得 service 实现类
    枚举类

    @Getter
    public enum FileUploadTypeEnum {
        LOCAL("0", FileConstants.LOCAL_FILE_SERVICE_BEAN),
        ALIYUN("1", FileConstants.ALIYUN_FILE_SERVICE_BEAN),
        HUAWEI_OBS("2", FileConstants.HUAWEI_OBS_FILE_SERVICE_BEAN);
        private final String code;
        private final String desc;
    
        FileUploadTypeEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }
    
        public static FileUploadTypeEnum getFileUploadTypeEnumByCode(String code) {
            for (FileUploadTypeEnum fileUploadTypeEnum : FileUploadTypeEnum.values()) {
                if (fileUploadTypeEnum.getCode().equals(code)) {
                    return fileUploadTypeEnum;
                }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    常量类

    public interface FileConstants {
        // FileService 实例   值为 beanName
        String LOCAL_FILE_SERVICE_BEAN = "localFileServiceImpl";
        String ALIYUN_FILE_SERVICE_BEAN = "aliyunFileServiceImpl";
        String HUAWEI_OBS_FILE_SERVICE_BEAN = "huaweiObsFileServiceImpl";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    factory 类

    @Component
    public class FileServiceFactory {
        // beanMap 的结构: key: beanName  value: FileService 实例
        private Map<String, FileService> beanMap = new HashMap<>();
        @Resource
        private ApplicationContextUtil applicationContextUtil;
    
        @PostConstruct
        private void initFileService() {
            beanMap = applicationContextUtil.getApplicationContext().getBeansOfType(FileService.class);
        }
    
        public FileService getFileService(FileUploadTypeEnum typeEnum) {
            return beanMap.get(typeEnum.getDesc());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ApplicationContextUtil

    @Component
    public class ApplicationContextUtil implements ApplicationContextAware {
        private ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    
        public ApplicationContext getApplicationContext() {
            return this.applicationContext;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.在 controller 中通过 factory 来获取 service 实例,调用相关方法。

    以上就是本文的全部内容,希望对大家有所帮助,如有错误欢迎指正!!!

  • 相关阅读:
    Spring 更简单的读取和存储Bean【注解篇,属性注入,set注入,构造方法注入】
    2021icpc南京 H. Crystalfly
    Windows 下 MSVC 编译器在 CMake 生成时提示 RC failed 或库文件缺失
    Python进阶必备之JS逆向-某榜某博数据采集
    vue.draggable拖动插件的使用
    iwebsec靶场 数据库漏洞通关2-Redis数据库漏洞
    【STM32+OPENMV】二维云台颜色识别及追踪
    简单的晚餐
    Nexus私服仓库Linux、Windows部署教程
    Ubuntu 安装lightdm后,重启后一直转圈,进不了用户界面
  • 原文地址:https://blog.csdn.net/Wushuge_heiYe/article/details/132635921