starter定义
starter就是springboot中的起步依赖,虽然springboot已经提供了很多的起步依赖,但是在实际项目开发中可能会用到和第三方的技术,不是所有第三方在springboot中都有收录。
比如之前文章中有用到过的阿里云OSS,阿里云并没有提供起步依赖,导致每次使用时都要自己写一些类。
springboot官方提供的起步以来是spring-boot在前,其他提供的通常都是技术名在前。
下面mybatis的起步依赖中没有java代码,只是整合了mybatis开发需要的依赖的坐标 其中包含了一个依赖mybatis-spring-boot-autoconfigure,这个自动配置类里面声明了一堆Bean对象。
里面可以看见一些常用的类比如SqlSessionFactory
那么这些配置类配置好之后是如何被SpringBoot项目加载到IOC容器并完成自动配置的呢?
前面有说到过,SpringBoot在启动时会加载依赖中的两份文件,如果是老版本的就加载spring.factories,如果是新版本的就加载autoconfigure.import这个文件。
因此该自动配置类配置好之后,就可以在spring.factories或者是autoconfigure.import文件中配置这个自动配置类。
最终会儿被加载到spring的IOC容器当中.
因此自定义一个起步依赖starter的时候按照规范需要定义两个模块,一个是starter模块,其唯一的作用就是进行依赖管理。
另一个autoconifure的包就是完成自动配置的操作。
最终在项目中只会导入starter模块,因为starter已经导入了autoconfigure模块了。
上面就是简单介绍了自定义starter的场景以及自定义starter涉及的各个模块和各个模块涉及的功能.
自定义starter案例
需求说明
在不封装的时候,每次使用都要自己手动写一些OSS的工具类并添加到IOC容器当中去。
根据阿里云官方提供的示例SDK文件改造成如下一个工具类,并在yml配置文件当中配置需要的参数,然后还要一个实体类加载配置文件中的配置项。
最后才可以在工具类中获取到需要的参数,然后交给springIOC容器管理,然后在项目用到时就直接注入。
这个过程十分的繁琐
具体封装看这里一下两篇文章
云服务——阿里云OSS的入门使用_北岭山脚鼠鼠的博客-CSDN博客SpringBoot——SB整合mybatis案例(残缺版本)第三集_北岭山脚鼠鼠的博客-CSDN博客
上面的这个过程是十分繁琐且重复的一个过程,因此可以将其封装成一个依赖项,可以通过坐标引入后直接使用。
步骤分析
具体实现
创建好两个需要的模块
选择新建新模块
首先新建一个starter模块
规整starter模块的pom.xml文件如下
先改版本为2.7.5,再删除多余的依赖。
<?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 https://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.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
然后starter模块的项目文件删除的只剩下一个pom.xml和一个iml文件。
然后再新建一个autoconfigure的模块,按照上面的流程再走一次
然后修改 autoconfigure模块的pom.xml如下,将项目文件删成如下的结构,只比上面多一个src
<?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 https://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.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
将来autoconfigure是作为其他项目文件的依赖的,所以application这个启动类不需要,配置文件也不需要,测试单元也不需要。删除如下图所示的三个文件
模块创建工作结束 (上面就准备好了一个依赖所需要的两个基本模块了)
然后需要在starter模块引入autoconfigure模块,这是前面提到过的规范。
直接导入autoconfigure的坐标。
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
在autoconfigure中完成自动配置操作
根据目标需求,需要在autoconfigure准备一个AliyunOSSUtils工具类。
1.引入依赖
要在项目中使用阿里云OSS需要引入阿里云OSS的依赖,引入如下依赖在autoconfigure中
<!--阿里云OSS的依赖-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</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>
2.准备工具类和实体类
在之前的项目开发中使用阿里云OSS时需要用到的类有一个工具类和一个实体类
实体类里面封装的是阿里云的key和id还有资源桶的名字
package com.example.utils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
}
还有一个工具类
package com.example.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;
/**
* 阿里云 OSS 工具类
*/
@Component
public class AliOSSUtils {
// @Value("${aliyun.oss.endpoint}")
// private String endpoint ;
// @Value("${aliyun.oss.accessKeyId}")
// private String accessKeyId ;
// @Value("${aliyun.oss.accessKeySecret}")
// private String accessKeySecret ;
// @Value("${aliyun.oss.bucketName}")
// private String bucketName ;
/* @Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;*/
@Autowired
private AliOSSProperties aliOSSProperties;
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws IOException {
String endpoint=aliOSSProperties.getEndpoint();
String bucketName=aliOSSProperties.getBucketName();
String accessKeyId=aliOSSProperties.getAccessKeyId();
String accessKeySecret=aliOSSProperties.getAccessKeySecret();
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
// 避免文件覆盖
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
//上传文件到 OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, inputStream);
//文件访问路径
String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
// 关闭ossClient
ossClient.shutdown();
return url;// 把上传到oss的路径返回
}
}
将上面两个文件放到autoconfigure项目中时会有一个报错,需要引入两个新的依赖
一个是web开发的以来,一个是@Data注解的依赖,又或者可以不引入lombok的以来,然后手动提供get和set方法。直接把@Data的注解去掉即可,然后alt+insert即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
然后两个类都没有报错了,但是现在两个类上的component注解已经没有用了,因为将来这个依赖引入项目时包扫描也不会扫这个依赖模块的包,所以两个类上的@component注解可以删除了。
注意:这里删除会导致aliOSSProperties实体类出现红色报错,但是这里可以先不用管,下面会解决。
然后还有工具类里面的@Autowired也可以删除了,因为已经不是IOC容器里面的Bean了,不能进行autowired注入了。
但是根据需求提到的直接注入工具类直接使用,所以还是要将其交给spring容器进行管理。
因此现在需要准备一个自动配置类来声明阿里云OSS的这个工具类的Bean,然后将配置类交给spring容器管理。
3.新建自动配置类
这个配置类可以获取到AliOSSUtils这个工具类的,然后直接使用upload方法进行文件上传操作,但是在那之前upload方法里面是还需要一个aliOSSProperties成员变量的,所以在工具类当中还要准备它的get和set方法.
然后在获取到AliOSSUtils时还需要为里面的aliOSSProperties赋值。
然后aliOSSProperties当中需要的属性值都是从配置文件当中获取得到的,然后封装成一个aliOSSProperties实体类。
@ConfigurationProperties(prefix = "aliyun.oss")
这里需要解决上面这块的报错问题,可以直接在自动配置类上加上如下的注解,将AliOSSProperties变成一个IOC容器中Bean对象就不会报错了。
@EnableConfigurationProperties(AliOSSProperties.class)
再然后在配置类,声明一个第三方Bean时需要注入某一个对象可以直接在方法形参中指定,最终会自动装配进来。
@Configuration
@EnableConfigurationProperties(AliOSSProperties.class)
public class AliOSSAutoConfiguration {
@Bean
public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){
AliOSSUtils aliOSSUtils= new AliOSSUtils();
aliOSSUtils.setAliOSSProperties(aliOSSProperties);
return aliOSSUtils;
}
}
到这里,自动配置类已经配置好了,另外两个类别忘记删除@Component和@Autowried注解并且加上aliOSSProperties的get还有set方法就可以了。
4.最后一步
要想自动配置类被加载到项目中就需要在一个固定的配置文件中来配置。
就是META-INF/spring/xxx.imports中,所以现在autoconfigure模块的resources目录下新建一个对应的文件夹和需要的一个名字很长的文件。
注意名字不能打错。
在这个文件中的都是自动配置类的全类名,所以要把上面写好的一个自动配置类放到里面去。
com.aliyun.oss.AliOSSAutoConfiguration
到此,这个starter已经定义完了,在starter中进行依赖管理,在configure中进行自动配置。
在测试工程中对封装好的starter进行测试
在提供的资源中有一个测试工程。
在这个测试工程的Controller层中有一个uploadController如下,需要将接收到文件上传到阿里云OSS。
然后这里可以直接引入上面的起步依赖,然后就可以直接上传文件到OSS了。
在测试工程的pom文件当中,引入如下依赖。
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
然后就需要在配置文件当中需要一些阿里云账号的参数,需要的配置信息有如下的四项,都需要在测试工程的配置文件上准备好。
这里根据个人的实际账号资料进行配置。
最后在controller当中实现如下,将已经上传的文件交给阿里云OSS进行保存
@RestController
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
@PostMapping("/upload")
public String upload(MultipartFile image) throws Exception {
//上传文件到阿里云 OSS
String url=aliOSSUtils.upload(image);
return url;
}
}
项目运行测试 (使用postman测试)
上面那里将依赖导入别的项目时可能会有出现Cannot reconnect的傻狗报错,这时候只需要重启IDEA即可。
成功上传文件到阿里云并且获得了文件url。
完成了这个依赖封装,我就可以自己搞一个网页,然后自己上传自己的东西,然后自己下载自己的东西了。 真不错。