自定义starter是SpringBoot将功能封装成可复用组件的方式,可以让其他的项目简单的进入依赖,即可快速使用该功能,无需重复配置可以减少许多配置.既然自定义strarter可以减少配置,那么先来讲怎么实现自定义starter.
一、自定义 Starter的实现
命名规范:
一. 官方Starter和自定义Starter有所不同,是为了防止出现自定义的和官方的出现冲突.
- 官方:
spring-boot-autoconfigure-xxx(如spring-boot-autoconfigure-web) - 自定义:
xxx-spring-boot-autoconfigure(如log-spring-boot-autoconfigure)
二. 在自定义的模块下的xxx-spring-boot-autoconfigure的实现
pom.xml文件中添加Spring Boot自动配置的核心依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>3.0.2</version> <!-- 需与目标项目Spring Boot版本匹配,也可以省略 -->
</dependency
- 定义配置属性类
- 定义一个xxxProperties,用于接收外部配置,如:
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOSSProperties {
private String endpoint;
private String bucketName;
private String region;
- 定义核心功能类(需要实现的功能),格式:xxxAutoConfiguration,如阿里云OSS上传文件实现类
public class AliyunOSSOperator {
private AliyunOSSProperties aliyunOSSProperties;
public AliyunOSSOperator(AliyunOSSProperties aliyunOSSProperties) {
this.aliyunOSSProperties = aliyunOSSProperties;
}
public void deleteByUrls(List<String> keys) throws Exception {
//log.info("old keys:{}", keys);
String endpoint = aliyunOSSProperties.getEndpoint();
String bucketName = aliyunOSSProperties.getBucketName();
String region = aliyunOSSProperties.getRegion();
String urlPrefix = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/";
keys = keys.stream()
.map(item -> item.replaceAll(urlPrefix, ""))
.toList();
// log.info("new keys:{}", keys);
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 创建OSSClient实例。
// 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
//批量删除OSS文件
DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys).withEncodingType("url"));
List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
for(String obj : deletedObjects) {
String deleteObj = URLDecoder.decode(obj, "UTF-8");
System.out.println(deleteObj);
}
} catch (Exception oe) {
System.out.println(oe.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
public String upload(byte[] content, String originalFilename) throws Exception {
String endpoint = aliyunOSSProperties.getEndpoint();
String bucketName = aliyunOSSProperties.getBucketName();
String region = aliyunOSSProperties.getRegion();
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。
//获取当前系统日期的字符串,格式为 yyyy/MM
String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));
//生成一个新的不重复的文件名
String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
String objectName = dir + "/" + newFileName;
// 创建OSSClient实例。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
} catch (Exception oe) {
System.out.println(oe.getMessage());
} finally{
ossClient.shutdown();
}
return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
}
}
- 编写自动配置类(用于完成bean的创建和注入),格式:xxAutoConfiguration 类
@EnableConfigurationProperties({AliyunOSSProperties.class})
public class AliyunOssAutoConfiguration {
@Bean
public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties aliyunOSSProperties) {
return new AliyunOSSOperator(aliyunOSSProperties);
}
}
- 通过Spring自动化装配原理完成 XxxAutoConfiguration 类的初始化操作
- 在
src/main/resources/META-INF/目录下创建additional-spring-configuration-metadata.json文件 - 在文件中写入XxxAutoConfiguration 的全类名
三.xxx-spring-boot-start模块下实现
pom.xml文件中添加Spring Boot自动配置的核心依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
2.在xml文件中添加,xxx-spring-boot-autoconfigure的依赖
<dependencies>
<dependency>
<groupId>com.itheima</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
- xxx-spring-boot-start模块只负责管理依赖(导入下面的xxx-spring-boot-autoconfigure的依赖),不实现功能
四. 打包发布和使用
1.打包发布
- 用黑窗口执行
mvn clean install将 Starter 安装到本地仓库(或发布到私服),供其他项目依赖。 - 或用IDE打包发布
- 使用
- 在其他Spring Boot项目中进入该依赖,在
pom.xml中引入,如
<dependency>
<groupId>com.itheima</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- 使用功能 直接注入即可使用