Web后端开发_07
SpringBoot_02
SpringBoot原理
1.配置优先级
1.1配置
- SpringBoot中支持三种格式的配置文件:
application.properties
application.yml
application.yaml
properties、yaml、yml三种配置文件,优先级最高的是properties
配置文件优先级排名(从高到低):
- properties配置文件
- yml配置文件
- yaml配置文件
注意事项
- 虽然springboot支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置(yml是主流)
- SpringBoot除了支持配置文件属性配置,还支持Java系统属性和命令参数的方式进行属性配置
#Java系统属性
-Dserver.port=9000
#命令行参数
--server.port=10010
重启服务,同时配置Tomcat端口(三种配置文件、系统属性、命令行参数),测试哪个Tomcat端口号生效:
优先级: 命令行参数 > 系统属性参数 > properties参数 > yml参数 > yaml参数
1.2问题引出
如果项目已经打包上线了,这个时候我们又如何来设置Java系统属性和命令行参数呢?
java -Dserver.port=9000 -jar XXXXX.jar --server.port=10010
下面我们来演示下打包程序运行时指定Java系统属性和命令行参数:
- 执行maven打包指令package,把项目打成jar文件
- 使用命令:java -jar 方式运行jar文件程序
注意事项
SpringBoot项目进行打包时,需要引入插件
spring-boot-maven-plugin
(基于官方骨架创建的项目,会自动添加该插件)
<skip>true</skip>
需要改为false
原因:
这是一个 Java 项目的 Maven 配置文件 pom.xml 的一部分。 元素指定了项目的主类,也就是在执行项目时会调用的入口程序。在这个示例中,主类是com.bowen.SpringbootWebConfigApplication
,也就是 Spring Boot 项目的启动类。skip 元素设置为 true 时,Maven 会跳过这个项目的构建过程,也就是说项目不会被编译打包。这个设置通常在调试或测试阶段使用,可以避免重复构建和打包,加快开发速度。
我的是用阿里云镜像构建的springboot项目,使用的JDK1.8/Java8
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.bowen.SpringbootWebConfigApplication</mainClass>
<skip>false</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
若<skip>true</skip>
,运行打包后的文件时,会出现以下报错
E:\java_study\020-Maven\springboot-web-config\target>java -jar springboot-web-config-0.0.1-SNAPSHOT.jar
springboot-web-config-0.0.1-SNAPSHOT.jar中没有主清单属性
1.3项目打包
运行jar程序:
- 直接运行
- 同时设置Java系统属性和命令行参数
- 仅设置Java系统属性
1.4配置优先级
在SpringBoot项目当中,常见的属性配置方式有5种, 3种配置文件,加上2种外部属性的配置(Java系统属性、命令行参数)。通过以上的测试,得出了优先级(从低到高):
优先级(从低到高)
- application.yaml(忽略)
- application.yml
- application.properties
- java系统属性(-Dxxx=xxx)
- 命令行参数(–xxx=xxx)
2.Bean管理
2.1获取bean
默认情况下,SpringBoot项目在启动的时候会自动的创建IOC容器(也称为Spring容器),并且在启动的过程当中会自动的将bean对象都创建好,存放在IOC容器当中。应用程序在运行时需要依赖什么bean对象,就直接进行依赖注入就可以了。
而在Spring容器中提供了一些方法,可以主动从IOC容器中获取到bean对象,下面介绍3种常用方式:
-
根据name获取bean
Object getBean(String name)
-
根据类型获取bean
<T> T getBean(Class<T> requiredType)
-
根据name获取bean(带类型转换)
<T> T getBean(String name, Class<T> requiredType)
思考:要从IOC容器当中来获取到bean对象,需要先拿到IOC容器对象,怎么样才能拿到IOC容器呢?
- 想获取到IOC容器,直接将IOC容器对象注入进来就可以了
控制器:DeptController
@RestController
@RequestMapping("/depts")
public class DeptController {
@Autowired
private DeptService deptService;
public DeptController(){
System.out.println("DeptController constructor ....");
}
@GetMapping
public Result list(){
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
deptService.delete(id);
return Result.success();
}
@PostMapping
public Result save(@RequestBody Dept dept){
deptService.save(dept);
return Result.success();
}
}
业务实现类:DeptServiceImpl
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
List<Dept> deptList = deptMapper.list();
return deptList;
}
@Override
public void delete(Integer id) {
deptMapper.delete(id);
}
@Override
public void save(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.save(dept);
}
}
Mapper接口:
@Mapper
public interface DeptMapper {
//查询全部部门数据
@Select("select * from dept")
List<Dept> list();
//删除部门
@Delete("delete from dept where id = #{id}")
void delete(Integer id);
//新增部门
@Insert("insert into dept(name, create_time, update_time) values (#{name},#{createTime},#{updateTime})")
void save(Dept dept);
}
测试类:
@SpringBootTest
class SpringbootWebConfig2ApplicationTests {
@Autowired
private ApplicationContext applicationContext; //IOC容器对象
//获取bean对象
@Test
public void testGetBean(){
//根据bean的名称获取
DeptController bean1 = (DeptController) applicationContext.getBean("deptController");
System.out.println(bean1);
//根据bean的类型获取
DeptController bean2 = applicationContext.getBean(DeptController.class);
System.out.println(bean2);
//根据bean的名称 及 类型获取
DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);
System.out.println(bean3);
}
}
程序运行后控制台日志:
输出的bean对象地址值是一样的,说明IOC容器当中的bean对象只有一个(默认情况下,IOC中的bean对象是单例)
如何将bean对象设置为非单例的(每次获取的bean都是一个新对象)?使用bean作用域
注意事项:
- 上述所说的 【Spring项目启动时,会把其中的bean都创建好】还会受到作用域及延迟初始化影响,这里主要针对于默认的单例非延迟加载的bean而言。
2.2bean作用域
- spring支持五种作用域,后三种在web环境才生效
作用域 | 说明 |
---|---|
singleton | 容器内同名称的bean只有一个实例(单例)(默认) |
prototype | 每次使用该bean时会创建新的实例(非单例) |
request | 每个请求范围内会创建新的实例(web环境中,了解) |
session | 每个会话范围内会创建新的实例(web环境中,了解) |
application | 每个应用范围内会创建新的实例(web环境中,了解) |
- 可以通过
@Scope
注解来进行配置作用域
注意事项:
- 默认singleton的bean,在容器启动时被创建,可以使用
@Lazy
注解来延迟初始化(延迟到第一次使用时)- prototype的bean,每一次使用该bean的时候都会创建一个新的实例
- 实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性。
2.2.1测试一
//bean的作用域
@Test
public void testScope(){
for (int i = 0; i < 10; i++) {
DeptController deptController = applicationContext.getBean(DeptController.class);
System.out.println(deptController);
}
}
在项目启动的时候DeptController的构造方法已经运行了,说明这个bean对象已经实例化了,是在容器启动的时候实例化的,这时已经将实例化的对象放到了IOC容器当中。
放行后,输出了同一个对象十次,因为没有设置Scope
默认Scope
的取值是singleton单例的
2.2.2测试二
在DeptController里加个注解@Lazy
延迟初始化
放行
2.2.3测试三
在DeptController里加个注解@Scope("prototype")
设置为非单例的
2.3第三方bean
2.3.1@Bean
- 如果要管理的bean对象来自于第三方(不是自定义的),是无法用
@Component
及衍生注解声明bean
的,就需要用到@Bean
注解- 若要管理的第三方bean对象,建议对这些bean进行集中分类配置,可以通过
@Configuration
注解声明一个配置类。
使用最快速的方法声明第三方Bean对象,即在启动类创建(不建议这样使用)
注意事项 :
通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名。
如果第三方bean需要依赖其它bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配。
在启动类定义一个saxReader方法
@SpringBootApplication
public class SpringbootWebConfig2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebConfig2Application.class, args);
}
//声明第三方bean
@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean
public SAXReader saxReader(){
return new SAXReader();
}
}
测试类
@Autowired
private SAXReader saxReader;
//第三方bean的管理
@Test
public void testThirdBean() throws Exception {
// SAXReader saxReader = new SAXReader();
Document document = saxReader.read(this.getClass().getClassLoader().getResource("1.xml"));
Element rootElement = document.getRootElement();
String name = rootElement.element("name").getText();
String age = rootElement.element("age").getText();
System.out.println(name + " : " + age);
}
加断点debug
2.3.2单独建立一个配置类
在config包下创建CommonConfig.java
类
@Configuration //配置类
public class CommonConfig {
//声明第三方bean
@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean
//通过@Bean注解的name/value属性指定bean名称, 如果未指定, 默认是方法名
public SAXReader reader(DeptService deptService){
System.out.println(deptService);
return new SAXReader();
}
}
完成自动装配
2.3.3关于Bean只需要保持一个原则
- 如果是在项目当中我们自己定义的类,想将这些类交给IOC容器管理,直接使用@Component以及它的衍生注解来声明就可以。
- 如果这个类它不是我们自己定义的,而是引入的第三方依赖当中提供的类,而且我们还想将这个类交给IOC容器管理。此时我们就需要在配置类中定义一个方法,在方法上加上一个@Bean注解,通过这种方式来声明第三方的bean对象。
3.SpringBoot原理
3.1spring
3.2启动依赖
起步依赖原理
Spring框架需要引入的依赖,各个依赖的版本还需要匹配
spring-webmvc依赖:这是Spring框架进行web程序开发所需要的依赖
servlet-api依赖:Servlet基础依赖
jackson-databind依赖:JSON处理工具包
如果要使用AOP,还需要引入aop依赖、aspect依赖
项目中所引入的这些依赖,还需要保证版本匹配,否则就可能会出现版本冲突问题。
使用SpringBoot仅需要引入一个依赖即可,web开发的起步依赖:springboot-starter-web。主要使用的就是依赖传递。
为什么我们只需要引入一个web开发的起步依赖,web开发所需要的所有的依赖都有了呢?
- 因为Maven的依赖传递。
在SpringBoot给我们提供的这些起步依赖当中,已提供了当前程序开发所需要的所有的常见依赖(官网地址:https://docs.spring.io/spring-boot/docs/2.7.7/reference/htmlsingle/#using.build-systems.starters)。
比如:springboot-starter-web,这是web开发的起步依赖,在web开发的起步依赖当中,就集成了web开发中常见的依赖:json、web、webmvc、tomcat等。我们只需要引入这一个起步依赖,其他的依赖都会自动的通过Maven的依赖传递进来。
结论:起步依赖的原理就是Maven的依赖传递。
3.3自动配置
- SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要手动去声明,从而简化了开发,省去了繁琐的配置
自动配置示例
3.3.1自动配置原理
3.3.1.1 概述
准备工作:在Idea中导入"资料\03. 自动配置原理"下的itheima-utils工程
1、在SpringBoot项目 spring-boot-web-config2 工程中,通过坐标引入itheima-utils依赖
添加模块
我在做的时候,该模块重复导入了三次,才引入成功
在本项目中引入模拟的第三方依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>itheima-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
2、在测试类中,添加测试方法
@SpringBootTest
public class AutoConfigurationTests {
@Autowired
private Gson gson;
@Autowired
private ApplicationContext applicationContext;
@Test
public void testJson() {
String json = gson.toJson(Result.success());
System.out.println(json);
}
//获取TokenParser
@Test
public void testTokenParser() {
System.out.println(applicationContext.getBean(TokenParser.class));
}
//获取HeaderParser
@Test
public void testHeaderParser() {
System.out.println(applicationContext.getBean(HeaderParser.class));
}
//获取HeaderGenerator
@Test
public void testHeaderGenerator() {
System.out.println(applicationContext.getBean(HeaderGenerator.class));
}
}
3、执行测试方法
异常信息描述: 没有com.example.HeaderParser类型的bean
说明:在Spring容器中没有找到com.example.HeaderParser类型的bean对象
思考:引入进来的第三方依赖当中的bean以及配置类为什么没有生效?
- 原因在我们之前讲解IOC的时候有提到过,在类上添加@Component注解来声明bean对象时,还需要保证@Component注解能被Spring的组件扫描到。
- SpringBoot项目中的@SpringBootApplication注解,具有包扫描的作用,但是它只会扫描启动类所在的当前包以及子包。
- 当前包:com.itheima, 第三方依赖中提供的包:com.example(扫描不到)
那么如何解决以上问题的呢?
- 方案1:@ComponentScan 组件扫描
- 方案2:@Import 导入(使用@Import导入的类会被Spring加载到IOC容器中)
3.3.1.2 方案一
@ComponentScan组件扫描
在启动类加上注解@ComponentScan({"com.example","com.bowen"})
@ComponentScan({"com.example","com.bowen"})
@SpringBootApplication
public class SpringbootWebConfig2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebConfig2Application.class, args);
}
}
如果采用以上这种方式来完成自动配置,那我们进行项目开发时,当需要引入大量的第三方的依赖,就需要在启动类上配置N多要扫描的包,这种方式会很繁琐。而且这种大面积的扫描性能也比较低。
缺点:
- 使用繁琐
- 性能低
结论:SpringBoot中并没有采用以上这种方案。
3.3.1.3 方案二
@Import导入
- 导入形式主要有以下几种:
- 导入普通类
- 导入配置类
- 导入ImportSelector接口实现类
1). 使用@Import导入普通类:
@Import({TokenParser.class})//导入普通类,交给IOC容器管理
@SpringBootApplication
public class SpringbootWebConfig2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebConfig2Application.class, args);
}
}
2). 使用@Import导入配置类:
- 配置类
@Configuration
public class HeaderConfig {
@Bean
public HeaderParser headerParser(){
return new HeaderParser();
}
@Bean
public HeaderGenerator headerGenerator(){
return new HeaderGenerator();
}
}
- 启动类
@Import({HeaderConfig.class})//导入配置类,交给IOC容器管理
@SpringBootApplication
public class SpringbootWebConfig2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebConfig2Application.class, args);
}
}
- 测试类
@SpringBootTest
public class AutoConfigurationTests {
@Autowired
private ApplicationContext applicationContext;
//获取HeaderParser
@Test
public void testHeaderParser() {
System.out.println(applicationContext.getBean(HeaderParser.class));
}
//获取HeaderGenerator
@Test
public void testHeaderGenerator() {
System.out.println(applicationContext.getBean(HeaderGenerator.class));
}
}
- 执行测试方法
3). 使用@Import导入ImportSelector接口实现类:
- ImportSelector接口实现类
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//返回值字符串数组(数组中封装了全限定名称的类)
return new String[]{"com.example.HeaderConfig"};
}
}
- 启动类
@Import(MyImportSelector.class) //导入ImportSelector接口实现类
@SpringBootApplication
public class SpringbootWebConfig2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebConfig2Application.class, args);
}
}
- 执行测试方法
使用@Import注解通过这三种方式都可以导入第三方依赖中所提供的bean或者是配置类。
思考:如果基于以上方式完成自动配置,当要引入一个第三方依赖时,是不是还要知道第三方依赖中有哪些配置类和哪些Bean对象?
- 答案:是的。 (对程序员来讲,很不友好,而且比较繁琐)
思考:当我们要使用第三方依赖,依赖中到底有哪些bean和配置类,谁最清楚?
- 答案:第三方依赖自身最清楚。
结论:我们不用自己指定要导入哪些bean对象和配置类了,让第三方依赖它自己来指定。
怎么让第三方依赖自己指定bean对象和配置类?
- 比较常见的方案就是第三方依赖给我们提供一个注解,这个注解一般都以@EnableXxxx开头的注解,注解中封装的就是@Import注解
4). 使用第三方依赖提供的 @EnableXxxxx注解
- 第三方依赖中提供的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableHeaderConfig {
}
- 在使用时只需在启动类上加上@EnableXxxxx注解即可
@EnableHeaderConfig
@SpringBootApplication
public class SpringbootWebConfig2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebConfig2Application.class, args);
}
}
- 执行测试方法
以上四种方式都可以完成导入操作,但是第4种方式会更方便更优雅,而这种方式也是SpringBoot当中所采用的方式。
- 源码跟踪
过程略
@SpringBootApplication
注解
@SpringBootApplication
- 该注解标识在SpringBoot工程引导类上,是SpringBoot中最重要的注解。该注解由三个部分组成:
@SpringBootConfiguration
:该注解与@Configuration
注解作用相同,用来声明当前也是一个配置类。@CommponentScan
:组件扫描,默认扫描当前引导类所在包及其子包。@EnableAutoConfiguration
:SpringBoot实现自动化配置的核心注解。
@Conditional
注解
@Conditional
- 作用:按照一定的条件进行判断,在满足给定条件后,才会注册对应的bean对象到Spring IOC容器中。
- 位置:方法、类
@Conditional
本身是一个父注解,派生出大量的子注解:
@ConditionalOnClass
:判断环境中是否有对应字节码文件,才注册bean到IOC容器。@ConditionalOnMissingBean
:判断环境中没有对应的bean(类型 或 名称),才注册bean到IOC容器。@ConditionalOnProperty
:判断配置文件中有对应的属性和值,才注册到bean和IOC容器。
3.4案例(自定义starter)
3.4.1场景
前面解析了SpringBoot中自动配置的原理,下面就通过一个自定义starter案例来加深大家对于自动配置原理的理解。首先介绍一下自定义starter的业务场景,再来分析一下具体的操作步骤。
所谓starter指的就是SpringBoot当中的起步依赖。在SpringBoot当中已经给我们提供了很多的起步依赖了,我们为什么还需要自定义 starter 起步依赖?这是因为在实际的项目开发当中,我们可能会用到很多第三方的技术,并不是所有的第三方的技术官方都给我们提供了与SpringBoot整合的starter起步依赖,但是这些技术又非常的通用,在很多项目组当中都在使用。
业务场景:
- 我们前面案例当中所使用的阿里云OSS对象存储服务,现在阿里云的官方是没有给我们提供对应的起步依赖的,这个时候使用起来就会比较繁琐,我们需要引入对应的依赖。我们还需要在配置文件当中进行配置,还需要基于官方SDK示例来改造对应的工具类,我们在项目当中才可以进行使用。
- 大家想在我们当前项目当中使用了阿里云OSS,我们需要进行这么多步的操作。在别的项目组当中要想使用阿里云OSS,是不是也需要进行这么多步的操作,所以这个时候我们就可以自定义一些公共组件,在这些公共组件当中,我就可以提前把需要配置的bean都提前配置好。将来在项目当中,我要想使用这个技术,我直接将组件对应的坐标直接引入进来,就已经自动配置好了,就可以直接使用了。我们也可以把公共组件提供给别的项目组进行使用,这样就可以大大的简化我们的开发。
在SpringBoot项目中,一般都会将这些公共组件封装为SpringBoot当中的starter,也就是我们所说的起步依赖。
- 在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会将这些公共组件封装为SpringBoot的Starter。
Mybatis提供了配置类,并且也提供了springboot会自动读取的配置文件。当SpringBoot项目启动时,会读取到spring.factories配置文件中的配置类并加载配置类,生成相关bean对象注册到IOC容器中。
结果:可以直接在SpringBoot程序中使用Mybatis自动配置的bean对象。
在自定义一个起步依赖starter的时候,按照规范需要定义两个模块:
- starter模块(进行依赖管理[把程序开发所需要的依赖都定义在starter起步依赖中])
- autoconfigure模块(自动配置)
将来在项目当中进行相关功能开发时,只需要引入一个起步依赖就可以了,因为它会将autoconfigure自动配置的依赖给传递下来。
3.4.2需求
需求:自定义aliyun-oss-spring-boot-starter,完成阿里云OSS操作工具类AliyunOSSUtils的自动配置。
目标:引入起步依赖引入之后,要想使用阿里云OSS,注入AliyunOSSUtils直接使用即可。
步骤
- 创建aliyun-oss-spring-boot-starter模块
- 创建aliyun-oss-spring-boot-autoconfigure模块,在starter中引入该模块
- 在aliyun-oss-spring-boot-autoconfigure模块中的定义自动配置功能,并定义自动配置文件META-INF/spring/xxx.imports
示例
- 创建aliyun-oss-spring-boot-starter模块
- 选择SpringBoot版本2.7.6
-
删除不必要的文件,留下pom.xml文件,不要学黑马教程随便删pom.xml(看不懂不要删,看明白了在删)
-
创建aliyun-oss-spring-boot-autoconfigure模块,在starter中引入该模块
- 选择SpringBoot版本2.7.6
在aliyun-oss-spring-boot-autoconfigure
模块删除不必要的文件,留下src
、pom.xml
文件,
在aliyun-oss-spring-boot-autoconfigure
模块中的定义自动配置功能,
- 在这个
pom.xml
文件中引入阿里云的依赖和配置文件的依赖
<!--阿里云OSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
<!--配置文件的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.7.16</version>
</dependency>
- 在
aliyun-oss-spring-boot-autoconfigure
模块下,复制AliOSS工具包 AliOSSUtils.java
该工具包直接从上一个项目中拷贝即可
package com.aliyun.oss;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* 阿里云 OSS 工具类
*/
@Component
public class AliOSSUtils {
private AliOSSProperties aliOSSProperties;
public AliOSSProperties getAliOSSProperties() {
return aliOSSProperties;
}
public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
this.aliOSSProperties = aliOSSProperties;
}
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws IOException {
//获取阿里云OSS参数
String endpoint = aliOSSProperties.getEndpoint();
String accessKeyId = aliOSSProperties.getAccessKeyId();
String accessKeySecret = aliOSSProperties.getAccessKeySecret();
String bucketName = aliOSSProperties.getBucketName();
// 获取上传的文件的输入流
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的路径返回
}
}
AliOSSAutoConfiguration.java
package com.aliyun.oss;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName AliOSSAutoConfiguration
* @Description TODO
* @Author Bowen
* @Date 2023/12/5 16:36
* @Version 1.0
**/
@Configuration
@EnableConfigurationProperties(AliOSSProperties.class)
public class AliOSSAutoConfiguration {
@Bean
public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){
AliOSSUtils aliOSSUtils = new AliOSSUtils();
aliOSSUtils.setAliOSSProperties(aliOSSProperties);
return aliOSSUtils;
}
}
AliOSSProperties.java
package com.aliyun.oss;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @ClassName AliOSSProperties
* @Description 阿里云OSS的实体类
* @Author Bowen
* @Date 2023/11/29 23:27
* @Version 1.0
**/
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
}
-
定义自动配置文件META-INF/spring/xxx.imports,在
aliyun-oss-spring-boot-autoconfigure
模块的resources
目录下创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.aliyun.oss.AliOSSAutoConfiguration
- 在
aliyun-oss-spring-boot-starter
模块的pom.xml
文件引入aliyun-oss-spring-boot-autoconfigure
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
- 最后使用黑马提供的资料中的测试工程
- 导入
springboot-autoconfiguration-test
模块 - 引入自定义的阿里云OSS依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
这里只需引入aliyun-oss-spring-boot-starter
依赖即可,根据依赖传递功能,相当于同时引入了aliyun-oss-spring-boot-autoconfigure
依赖
UploadController.java
中使用@Autowired
注入AliOSSUtils,最终上传到阿里云OSS存储,拿到并返回url
@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;
}
}
- 在启动该项目前,需要配置阿里云的AS
#阿里云配置
aliyun:
oss:
endpoint: 地域节点
accessKeyId: AccessKey ID
accessKeySecret: AccessKey Secret
bucketName: 存储空间名称
- springboot启动~~~
- 测试图片
- 使用Apipost进行测试
- 在阿里云OSS控制台查看