自定义 starter - SpringBoot 的起步依赖

自定义 starter

所谓 starter 指的就是 SpringBoot 当中的起步依赖。在 SpringBoot 当中已经给我们提供了很多的起步依赖了,我们为什么还需要自定义 starter 起步依赖?

这是因为在实际的项目开发当中,我们可能会用到很多第三方的技术,并不是所有的第三方的技术官方都给我们提供了与 SpringBoot 整合的 starter 起步依赖,但是这些技术又非常的通用,在很多项目组当中都在使用。

这里使用阿里云 OSS 文件上传举例。

1. 分析

首先先了解官方、第三方提供的起步依赖的框架是怎么设计的。

在 Springboot 中,官方提供的起步依赖 或 第三方提供的起步依赖,基本都会包含两个模块,如下所示:

其中,spring-boot-starterxxx-spring-boot-starter 这个模块主要是依赖管理的功能。 而 spring-boot-autoconfigurexxxx-spring-boot-autoconfigure 主要是起到自动配置的作用,自动配置的核心代码就在这个模块中编写。

SpringBoot 官方 starter 命名:spring-boot-starter-xxxx

第三组织提供的 starter 命名:xxxx-spring-boot-starter

而自动配置模块的核心,就是编写自动配置的核心代码,然后将自动配置的核心类,配置在核心的配置文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中。

SpringBoot 项目启动时,会读取到 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 配置文件中的配置类并加载配置类,生成相关 bean 对象注册到 IOC 容器中。

结论:我们可以直接在 SpringBoot 程序中使用自动配置的 bean 对象。

2. 实现

2.1 依赖管理

定义 aliyun-oss-spring-boot-start 模块,把阿里云 OSS 所有的依赖统一管理起来,创建完后的项目只需要保留 pom.xml 文件即可

配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<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>

  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-oss-spring-boot-start</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <java.version>17</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>3.0.2</spring-boot.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
      <groupId>com.aliyun.oss</groupId>
      <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>${spring-boot.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

</project>

2.2 启动依赖

创建 autoconfigure 模块 aliyun-oss-spring-boot-autoconfigure 配置启动依赖

修改配置依赖 pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>

  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>3.0.2</version>
    </dependency>

    <dependency>
      <groupId>com.aliyun.oss</groupId>
      <artifactId>aliyun-sdk-oss</artifactId>
      <version>3.17.4</version>
    </dependency>

    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.1</version>
    </dependency>
    <dependency>
      <groupId>javax.activation</groupId>
      <artifactId>activation</artifactId>
      <version>1.1.1</version>
    </dependency>
    <!-- no more than 2.3.3-->
    <dependency>
      <groupId>org.glassfish.jaxb</groupId>
      <artifactId>jaxb-runtime</artifactId>
      <version>2.3.3</version>
    </dependency>

    <!-- hutool:专门用来做工具类 -->
    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.8.27</version>
    </dependency>
  </dependencies>

</project>

2.3 搭建

将有关于文件上传的代码放入启动依赖中:

// 参数配置类
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOssProperties {

  private String domain;
  private String endpoint;
  private String bucketName;
  private String region;
  private String accessKeyId;
  private String secretAccessKey;

  // 注意:手动生成 Getter、Setter 方法,不推荐使用 lombok
}
// 阿里云文件上传工具类
public class AliyunOssUtils {

  private final AliyunOssProperties aliyunOssProperties;

  public AliyunOssUtils(AliyunOssProperties aliyunOssProperties) {
    this.aliyunOssProperties = aliyunOssProperties;
  }

  /**
	 * 上传文件
	 *
	 * @return: String 上传后文件的路径
	 * @param: file 文件
	 */
  public String uploadFile(MultipartFile file) {
    // 参数校验
    if (ObjUtil.isEmpty(file) || file.isEmpty()) {
      throw new RuntimeException("上传文件不能为空");
    }
    String filename = file.getOriginalFilename();
    if (StrUtil.isEmpty(filename)) {
      throw new RuntimeException("上传文件名错误!");
    }
    // 上传后的文件路径
    String path = null;
    OSS ossClient = null;
    try {
      // 参数设置
      // 单独保存域名,方便后续拼接文件名
      String domain = aliyunOssProperties.getDomain();

      // 设置 OSS Endpoint 和 Bucket 名称
      String endpoint = aliyunOssProperties.getEndpoint();
      String bucketName = aliyunOssProperties.getBucketName();

      // 替换为您的 Bucket 区域
      String region = aliyunOssProperties.getRegion();

      // 创建 OSSClient 实例
      String accessKeyId = aliyunOssProperties.getAccessKeyId();
      String secretAccessKey = aliyunOssProperties.getSecretAccessKey();

      // 自定义配置阿里云账号
      CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, secretAccessKey);
      // 创建 OSSClient 实例
      ossClient = OSSClientBuilder.create().endpoint(endpoint).credentialsProvider(credentialsProvider).credentialsProvider(credentialsProvider).region(region).build();

      // String.lastIndexOf() 方法返回指定字符串中最后一次出现的指定字符的索引位置,如果没有找到则返回 -1。
      // 获取文件名后缀(即文件类型),如:.jpg
      String suffix = filename.substring(filename.lastIndexOf("."));

      // 生成随机文件名,并拼接文件类型
      filename = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

      // 上传文件到阿里云
      ossClient.putObject(bucketName, filename, file.getInputStream());

      // 拼接文件路径
      path = "https://" + bucketName + "." + domain + "/" + filename;
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }
    return path;
  }

}
// 阿里云OSS自动配置类
@Configuration
@ConditionalOnClass(OSS.class)
@EnableConfigurationProperties(AliyunOssProperties.class)
public class AliOssAutoConfiguration {

  @Bean
  public AliyunOssUtils aliyunOssUtils(AliyunOssProperties aliyunOssProperties) {
    return new AliyunOssUtils(aliyunOssProperties);
  }

}

2.4 配置指定装配(重点)

在 src/main/resources 文件下新建 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件

只需要将自动配置类的全类名配置到 org.springframework.boot.autoconfigure.AutoConfiguration.imports 中即可

com.aliyun.oss.autoconfigure.AliOssAutoConfiguration

3. 使用自定义 starter

最终搭建完成的 starter 的项目结构应为:

3.1 引入依赖

<dependency>
  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-oss-spring-boot-start</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

3.2 配置

在 application.yml 配置文件中自行配置自己的阿里云 OSS 信息

# 自定义参数
aliyun:
  oss:
    # 单独保存域名,方便使用
    domain: oss-cn-**.aliyuncs.com
    # 设置 OSS Endpoint 和 Bucket 名称
    endpoint: https://oss-cn-**.aliyuncs.com
    bucketName: ***
    # 替换为您的 Bucket 区域
    region: cn-beijing # 这里以北京举例
    # 创建 OSSClient 实例
    accessKeyId: YOUR-ACCESS-KEY-ID
    secretAccessKey: YOUR-SECRET-ACCESS-KEY

3.3 正常使用即可

// 文件管理控制器
@RestController
@RequiredArgsConstructor
public class FileController {

  private final AliyunOssUtils aliyunOssUtils;

  @PostMapping("/upload")
  public Result uploadImg(@RequestParam("file") MultipartFile file) {
    String s = aliyunOssUtils.uploadFile(file);
    return Result.success(s);
  }
}

posted @ 2025-02-21 22:39  大一点的小孩  阅读(59)  评论(0)    收藏  举报