工作上遇到一个实际问题,我的产品用到文件存储,文件存储有很多种,如:minio、oss(阿里)、CFS(腾讯)、fdfs。我们不知道客户会选择哪种配置,就需要我们的程序支持切换配置,我想到了数据源的切换,如果模仿着写了个starter。

1、创建一个工程,根据springboot规范,我们取名为store-spring-boot-starter,pom.xml依赖如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zhi.store</groupId>
    <artifactId>store-spring-boot-starter</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

2、定义文件操作接口并实现

/**
 * 文件操作接口
 * 
 * @author 张远志
 * @since 2022年3月8日20:06:23
 *
 */
public interface FileOperater {
    /**
     * 存储文件
     * 
     * @param input       文件输入流
     * @param fileName    文件名
     * @param contentType 文件类型
     */
    FileModel storeFile(InputStream input, String fileName, String contentType);

    /**
     * 文件下载
     * 
     * @param output   文件输出流
     * @param filePath 文件路径
     */
    void downFile(OutputStream output, String filePath);

    /**
     * 删除文件
     * 
     * @param filePath 文件路径
     */
    void deleteFile(String filePath);

    /**
     * 获取文件上传地址
     * 
     * @param fileName 文件名
     * @return
     */
    String generateUploadUrl(String fileName);

    /**
     * 获取文件下载地址
     * 
     * @param filePath 文件路径
     * @return
     */
    String generateDownloadUrl(String filePath);

}

具体实现类MinoFileOperater和AliOssFileOperater略

3、定义自动装配类和属性定义类

StroeAutoConfiguration:

@Configuration
@EnableConfigurationProperties(StoreProperties.class)
@ConditionalOnProperty(prefix = StoreProperties.prefix, name = {
        "enabled" }, havingValue = "true", matchIfMissing = true)
@Import({ StoreConfiguration.Minio.class, StoreConfiguration.AliSSO.class })
public class StroeAutoConfiguration {
}

StoreConfiguration:

public class StoreConfiguration {
    @Configuration
    @ConditionalOnClass(MinioClient.class)
    @ConditionalOnMissingBean(FileOperater.class)
    @ConditionalOnProperty(name = StoreProperties.prefix + ".storeType", havingValue = "minio", matchIfMissing = true)
    static class Minio {
        @Bean
        public MinioFileOperater fileOperater(StoreProperties properties) {
            MinioFileOperater fileOperater = new MinioFileOperater(properties);
            return fileOperater;
        }
    }

    @Configuration
    @ConditionalOnClass(OSS.class)
    @ConditionalOnMissingBean(FileOperater.class)
    @ConditionalOnProperty(name = StoreProperties.prefix + ".storeType", havingValue = "alioss", matchIfMissing = true)
    static class AliSSO {
        @Bean
        public AliOssFileOperater fileOperater(StoreProperties properties) {
            AliOssFileOperater fileOperater = new AliOssFileOperater(properties);
            return fileOperater;
        }
    }
}

StoreProperties:

@ConfigurationProperties(prefix = StoreProperties.prefix)
public class StoreProperties {
    public static final String prefix = "zhi.store";
    /**
     * 是否开启,默认开启
     */
    private boolean enabled;
    /**
     * 存储类型
     */
    private String storeType;
    /**
     * 存储地址
     */
    private String endpoint;
    private String accessKey;
    private String secretKey;
    /**
     * 默认存储桶
     */
    private String bucket;
    /**
     * 文件是否重命名
     */
    private boolean rename;
}

4、在resources/META-INF目录创建文件spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhi.store.StroeAutoConfiguration

5、生成spring-configuration-metadata.json文件,定义属性元数据

属性类中存在@ConfigurationProperties注解时,执行mvn package生成的jar包会自动添加spring-configuration-metadata.json文件,效果如下:

 

posted on 2022-03-12 21:36  玄同太子  阅读(156)  评论(0)    收藏  举报