当前位置: 首页 > article >正文

SpringBoot 原理篇(day14)

配置优先级

SpringBoot 中支持三种格式的配置文件:

配置文件优先级排名(从高到低):

  1. properties 配置文件
  2. yml 配置文件
  3. yaml 配置文件

注意事项

  • 虽然 springboot 支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置 (yml 是主流)。

SpringBoot 除了支持配置文件属性配置,还支持 Java 系统属性 和 命令行参数 的方式进行属性配置。

 那在idea当中运行程序时,如何来指定Java系统属性和命令行参数呢?

编辑启动程序的配置信息

重启服务,同时配置Tomcat端口(三种配置文件、系统属性、命令行参数),测试哪个Tomcat端口号生 效:

优先级: 命令行参数 > 系统属性参数 > properties 参数 > yml 参数 > yaml 参数

项目已经打包上线了,这个时候我们又如何来设置Java系统属性和命令行参数呢?

注意事项

  • Springboot 项目进行打包时,需要引入插件 spring-boot-maven-plugin (基于官网骨架创建项目,会自动添加该插件)
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>                
            </plugin>
        </plugins>
    </build>

打包操作:

1. 执行maven打包指令package,把项目打成jar文件
2. 使用命令:java -jar 方式运行jar文件程序

运行jar程序:

同时设置Java系统属性和命令行参数

Bean 管理

获取 Bean

默认情况下,Spring 项目启动时,会把 bean 都创建好放在 IOC 容器中,如果想要主动获取这些 bean,可以通过如下方式:

上述所说的 【Spring 项目启动时,会把其中的 bean 都创建好】还会受到作用域及延迟初始化影响,这里主要针对于 默认的单例非延迟加载的 bean 而言。

@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);
    }
}

@Autowired
 private ApplicationContext applicationContext; //IOC容器对象

Bean 作用域

Spring 支持五种作用域

可以通过 @Scope 注解来进行配置作用域:

//@Lazy
@Scope("prototype")
@RestController
@RequestMapping("/depts")
public class DeptController {
}

注意事项:

默认 singleton 的 bean,在容器启动时被创建,可以使用 @Lazy 注解来延迟初始化(延迟到第一次使用时)。
prototype 的 bean,每一次使用该 bean 的时候都会创建一个新的实例。
实际开发当中,绝大部分的 Bean 是单例的,也就是说绝大部分 Bean 不需要配置 scope 属性。

//默认bean的作用域为:singleton (单例)
 @Lazy //延迟加载(第一次使用bean对象时,才会创建bean对象并交给ioc容器管理)
@RestController
@RequestMapping("/depts")
public class DeptController {
    @Autowired
    private DeptService deptService;
    public DeptController(){
    System.out.println("DeptController constructor ....");
  }
    //省略其他代码...
}
@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    //bean的作用域
    @Test
    public void testScope(){
        for (int i = 0; i < 10; i++) {
            DeptController deptController = applicationContext.getBean(DeptController.class);
            System.out.println(deptController);
        }
    }
}

第三方 Bean

之前我们所配置的bean,像controller、service,dao三层体系下编写的类,这些类都是我们在项 目当中自己定义的类(自定义类)。当我们要声明这些bean,也非常简单,我们只需要在类上加上 @Component以及它的这三个衍生注解(@Controller、@Service、@Repository),就可以来声 明这个bean对象了。 但是在我们项目开发当中,还有一种情况就是这个类它不是我们自己编写的,而是我们引入的第三方依 赖当中提供的。

如果要管理的 bean 对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明 bean 的,就需要用到 @Bean 注解。

解决方案1:在启动类上添加 @Bean 标识的方法(不建议,项目中要保证启动类的纯粹性)

启动类: 

@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();
    }
}

测试类 

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    @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);
    }
}

解决方案2:在配置类中定义@Bean标识的方法

  • 若要管理的第三方 bean 对象,建议对这些 bean 进行集中分类配置,可以通过 @Configuration 注解声明一个配置类。

配置类
注释掉SpringBoot启动类中创建第三方bean对象的代码,重启服务,执行测试方法,查看控制台日 志: 

@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();
    }

}

注意事项:

  • 通过 @Bean 注解的 name 或 value 属性可以声明 bean 的名称,如果不指定,默认 bean 的名称就是方法名。
  • 如果第三方 bean 需要依赖其它 bean 对象,直接在 bean 定义方法中设置形参即可,容器会根据类型自动装配。

@Component 及衍生注解 与 @Bean 注解使用场景?

  • 项目中自定义的,使用 @Component 及其衍生注解
  • 项目中引入第三方的,使用 @Bean 注解

SpringBoot 原理

通过 SpringBoot 来简化 Spring 框架的开发(是简化不是替代)。我们直接基于 SpringBoot 来构建 Java 项目,会让我们的项目开发更加简单,更加快捷。

SpringBoot框架之所以使用起来更简单更快捷,是因为SpringBoot框架底层提供了两个非常重要的 功能:一个是起步依赖一个是自动配置

  • 通过 SpringBoot 所提供的起步依赖,就可以大大的简化 pom 文件当中依赖的配置,从而解决了 Spring 框架当中依赖配置繁琐的问题。
  • 通过自动配置的功能就可以大大的简化框架在使用时 bean 的声明以及 bean 的配置。我们只需要引入程序开发时所需要的起步依赖,项目开发时所用到常见的配置都已经有了,我们直接使用就可以了。

起步依赖

为什么我们只需要引入一个 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 的依赖传递。

自动配置

概述:SpringBoot 的自动配置就是当 spring 容器启动后,一些配置类、bean 对象就自动存入到了 IOC 容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

比如:我们要进行事务管理、要进行AOP程序的开发,此时就不需要我们再去手动的声明这些 bean对象了,我们直接使用就可以从而大大的简化程序的开发,省去了繁琐的配置操作。

运行SpringBoot启动类

大家会看到有两个CommonConfig,在第一个CommonConfig类中定义了一个bean对象,bean对象的 名字叫reader。 在第二个CommonConfig中它的bean名字叫commonConfig,为什么还会有这样一个bean对象呢?原因是在CommonConfig配置类上添加了一个注解@Configuration,而@Configuration底层就是 @Component

在IOC容器中除了我们自己定义的bean以外,还有很多配置类,这些配置类都是SpringBoot在启动的 时候加载进来的配置类。这些配置类加载进来之后,它也会生成很多的bean对象。

当我们想要使用这些配置类中生成的bean对象时,可以使用@Autowired就自动注入了

自动配置原理

解析自动配置的原理就是分析在 SpringBoot项目当中,我们引入对应的依赖之后,是如何将依赖jar包当中所提供的bean以及 配置类直接加载到当前项目的SpringIOC容器当中的。

准备工作: 自动配置原理"下的itheima-utils工程

1、在SpringBoot项目 spring-boot-web-config2 工程中,通过坐标引入itheima-utils依赖

@Component
 public class TokenParser {
    public void parse(){
        System.out.println("TokenParser ... parse ...");
    }
 }

在测试类中,添加测试方法

 @SpringBootTest
 public class AutoConfigurationTests {
    @Autowired
    private ApplicationContext applicationContext;
    @Test
    public void testTokenParse(){
       
     System.out.println(applicationContext.getBean(TokenParser.class));
    }
  //省略其他代码...
 }

3、执行测试方法

思考:引入进来的第三方依赖当中的bean以及配置类为什么没有生效?

  • 原因在我们之前讲解IOC的时候有提到过,在类上添加@Component注解来声明bean对象时,还需要保证@Component注解能被Spring的组件扫描到。
  • SpringBoot项目中的@SpringBootApplication注解,具有包扫描的作用,但是它只会扫描启 动类所在的当前包以及子包。
  • 当前包:com.itheima, 第三方依赖中提供的包:com.example(扫描不到)

那么如何解决以上问题的呢?

  • 方案1:@ComponentScan 组件扫描
  • 方案2:@Import 导入(使用@Import导入的类会被Spring加载到IOC容器中)

方案一,@ComponentScan 组件扫描

@ComponentScan({"com.example","com.itheima"})
@SpringBootApplication
public class SpringbootWebConfig2Application {
}

缺点:

  1. 使用繁琐
  2. 性能低

方案二,@Import 导入

使用 @Import 导入的类会被 Spring 加载到 IOC 容器中,导入形式主要有以下几种:

  1. 导入 普通类
  2. 导入 配置类
  3. 导入 ImportSelector 接口实现类
  4. @EnableXxxx 注解,封装 @Import 注解(第三方依赖自己指定)
//@Import({TokenParser.class})//导入普通类,交给IOC容器管理
//@Import({HeaderConfig.class})//导入配置类,交给IOC容器管理
@Import({MyImportSelector.class})//导入ImportSelector接口实现类,交给IOC容器管理
@SpringBootApplication
public class SpringbootWebConfig2Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebConfig2Application.class, args);
    }
}
public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.example.HeaderConfig"};
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableHeaderConfig {
}
@EnableHeaderConfig
@SpringBootApplication
public class SpringbootWebConfig2Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebConfig2Application.class, args);
    }
}

怎么让第三方依赖自己指定bean对象和配置类?

比较常见的方案就是第三方依赖给我们提供一个注解,这个注解一般都以@EnableXxxx开头的注 解,注解中封装的就是@Import注解

使用第三方依赖提供的 @EnableXxxxx注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)//指定要导入哪些bean对象或配置类
public @interface EnableHeaderConfig { 
}

在使用时只需在启动类上加上@EnableXxxxx注解即可

@EnableHeaderConfig  //使用第三方依赖提供的Enable开头的注解
@SpringBootApplication
 public class SpringbootWebConfig2Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebConfig2Application.class, args);
    }
 }

原理分析

要搞清楚SpringBoot的自动配置原理,要从SpringBoot启动类上使用的核心注解

@SpringBootApplication开始分析:

我们先来看第一个注解:@SpringBootConfiguration

@SpringBootConfiguration注解上使用了@Configuration,表明SpringBoot启动类就是 一个配置类。
@Indexed注解,是用来加速应用启动的(不用关心)。

接下来再先看@ComponentScan注解:

  • @ComponentScan注解是用来进行组件扫描的,扫描启动类所在的包及其子包下所有被@Component及其衍生注解声明的类。
  • SpringBoot启动类,之所以具备扫描包功能,就是因为包含了@ComponentScan注解。

最后我们来看看@EnableAutoConfiguration注解(自动配置核心注解):

使用@Import注解,导入了实现ImportSelector接口的实现类。 AutoConfigurationImportSelector类是ImportSelector接口的实现类。

AutoConfigurationImportSelector类中重写了ImportSelector接口selectImports()方 法:

selectImports()方法底层调用getAutoConfigurationEntry()方法,获取可自动配置的 配置类信息集合
getAutoConfigurationEntry()方法通过调用 getCandidateConfigurations(annotationMetadata, attributes)方法获取在配置文 件中配置的所有自动配置类的集合

getCandidateConfigurations方法的功能:
获取所有基于META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imp orts文件、META-INF/spring.factories文件中配置类的集合

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件和META-INF/spring.factories文件这两个文件在哪里呢?

通常在引入的起步依赖中,都有包含以上两个文件

在前面在给大家演示自动配置的时候,我们直接在测试类当中注入了一个叫gson的bean对象,进行 JSON格式转换。虽然我们没有配置bean对象,但是我们是可以直接注入使用的。原因就是因为在自动配置类当中做了自动配置。到底是在哪个自动配置类当中做的自动配置呢?我们通过搜索来查询一下。

在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 配置文件中指定了第三方依赖Gson的配置类:GsonAutoConfiguration

第三方依赖中提供的GsonAutoConfiguration类:

在GsonAutoConfiguration类上,添加了注解@AutoConfiguration,通过查看源码,可以明确:GsonAutoConfiguration类是一个配置。

综上

原理就是在配置类中定义一个@Bean标识的方 法,而Spring会自动调用配置类中使用@Bean标识的方法,并把方法的返回值注册到IOC容器中。

自动配置源码小结

自动配置原理源码入口就是@SpringBootApplication注解,在这个注解中封装了3个注解,分别 是:

  • @SpringBootConfiguration 声明当前类是一个配置类
  • @ComponentScan 进行组件扫描(SpringBoot中默认扫描的是启动类所在的当前包及其子包)
  • @EnableAutoConfiguration封装了@Import注解(Import注解中指定了一个ImportSelector接口的实现类)
    • 在实现类重写的selectImports()方法,读取当前项目下所有依赖jar包中META-INF/spring.factories、META-INF/spring/org.springframework.boot.autoconfigure.AutoConfigurat ion.imports两个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)。
    • 当SpringBoot程序启动时,就会加载配置文件当中所定义的配置类,并将这些配置类信息(类的全限定 名)封装到String类型的数组中,最终通过@Import注解将这些配置类全部加载到Spring的IOC容器 中,交给IOC容器管理。

@Conditional

一个问题:在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imp orts文件中定义的配置类非常多,而且每个配置类中又可以定义很多的bean,那这些bean都会 注册到Spring的IOC容器中吗?

答案:并不是。 在声明bean对象时,上面有加一个以@Conditional开头的注解,这种注解的 作用就是按照条件进行装配,只有满足条件之后,才会将bean注册到Spring的IOC容器中(下面会详细来讲解)

以 Conditional开头的这些注解都是条件装配的注解。下面我们就来介绍下条件装配注解。

@Conditional注解:

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容 器中。
  • 位置:方法、类
  • @Conditional本身是一个父注解,派生出大量的子注解:
    • @ConditionalOnClass:判断环境中有对应字节码文件,才注册bean到IOC容器。
    • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册 bean到IOC容器。
    • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

@Configuration
public class HeaderConfig {

    @Bean
    @ConditionalOnClass(name = "io.jsonwebtoken.Jwts")// 环境中存在指定的这个类,才会将该bean加入IOC容器
    public HeaderParser headerParser1(){
        return new HeaderParser();
    }

    @Bean
//    @ConditionalOnMissingBean //当不存在当前类型(HeaderGenerator)的bean时,才声明该bean
//    @ConditionalOnMissingBean(name = "deptController2") //不存在指定名称的bean,才会将该bean加入IOC容器
    @ConditionalOnMissingBean(HeaderConfig.class)//不存在指定类型的bean,才会将bean加入IOC容器
    public HeaderGenerator headerGenerator(){
        return new HeaderGenerator();
    }

    @Bean
    @ConditionalOnProperty(name = "name" ,havingValue = "itheima")//配置文件中存在指定的属性与值,才会将该bean加入IOC容器
    public HeaderParser headerParser2(){
        return new HeaderParser();
    }

}

 自定义 starter 实现

场景

需求

  • 自定义 aliyun-oss-spring-boot-starter,完成阿里云 OSS 操作工具类 AliyunOSSUtils 的自动配置。
  • 目标:引入起步依赖引入之后,要想使用阿里云OSS,注入 AliyunOSSUtils直接使用即可。

步骤

  • 创建 aliyun-oss-spring-boot-starter 模块  (进行依赖管理)
    • 把阿里云OSS所有的依赖统一管理起来
  • 创建 aliyun-oss-spring-boot-autoconfigure 模块,在 starter 中引入该模块
  • 在 aliyun-oss-spring-boot-autoconfigure 模块中的定义自动配置功能,并定义自动配置文件 META-INF/spring/xxxx.imports
    • 定义一个自动配置类,在自动配置类中将所要配置的bean都提前配置好
    • 定义配置文件,把自动配置类的全类名定义在配置文件中

自定义starter实现

首先我们先来创建两个Maven模块:

1、aliyun-oss-spring-boot-starter模块

创建完starter模块后,删除多余的文件,最终保留内容如下:

2). aliyun-oss-spring-boot-autoconfigure模块

创建完starter模块后,删除多余的文件,最终保留内容如下:

删除pom.xml文件中多余的内容

按照我们之前的分析,是需要在starter模块中来引入autoconfigure这个模块的。打开starter模 块中的pom文件:

<?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>
        <!--引入autoconfigure模块-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-oss-spring-bootautoconfigure</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
 </project>

在autoconfigure模块当中来完成自动配置操作。

我们将之前案例中所使用的阿里云OSS部分的代码直接拷贝到autoconfigure模块下,然后进行 改造就行了。

拷贝过来后,还缺失一些相关的依赖,需要把相关依赖也拷贝过来:

<?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>
        <!--引入web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--阿里云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>
    </dependencies>
</project>

现在大家思考下,在类上添加的@Component注解还有用吗?

答案:没用了。 在SpringBoot项目中,并不会去扫描com.aliyun.oss这个包,不扫描这个包那 类上的注解也就失去了作用。

@Component注解不需要使用了,可以从类上删除了。

删除AliOSSUtils类中的@Component注解、@Autowired注解

下面我们就要定义一个自动配置类了,在自动配置类当中来声明AliOSSUtils的bean对象。

AliOSSAutoConfiguration类:

@Configuration//当前类为Spring配置类
@EnableConfigurationProperties(AliOSSProperties.class)//导入
AliOSSProperties类,并交给SpringIOC管理
public class AliOSSAutoConfiguration {
    //创建AliOSSUtils对象,并交给SpringIOC容器
    @Bean
    public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){
        AliOSSUtils aliOSSUtils = new AliOSSUtils();
        aliOSSUtils.setAliOSSProperties(aliOSSProperties);
        return aliOSSUtils;
    }
}

AliOSSProperties类:

/*阿里云OSS相关配置*/
 @Data
 @ConfigurationProperties(prefix = "aliyun.oss")
 public class AliOSSProperties {
    //区域
    private String endpoint;
    //身份ID
    private String accessKeyId ;
    //身份密钥
    private String accessKeySecret ;
    //存储空间
    private String bucketName;
 }

AliOSSUtils类:

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@Data
public class AliOSSUtils {
    private AliOSSProperties aliOSSProperties;
    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile multipartFile) throws
            IOException {
        // 获取上传的文件的输入流
        InputStream inputStream = multipartFile.getInputStream();
        // 避免文件覆盖
        String originalFilename =
                multipartFile.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() +
                originalFilename.substring(originalFilename.lastIndexOf("."));
        //上传文件到 OSS
        OSS ossClient = new
                OSSClientBuilder().build(aliOSSProperties.getEndpoint(),
                aliOSSProperties.getAccessKeyId(),
                aliOSSProperties.getAccessKeySecret());
        ossClient.putObject(aliOSSProperties.getBucketName(),
                fileName, inputStream);
        //文件访问路径
        String url =aliOSSProperties.getEndpoint().split("//")[0] +
                "//" + aliOSSProperties.getBucketName() + "." +
                aliOSSProperties.getEndpoint().split("//")[1] + "/" + fileName;
        // 关闭ossClient
        ossClient.shutdown();
        return url;// 把上传到oss的路径返回
    }
}

在aliyun-oss-spring-boot-autoconfigure模块中的resources下,新建自动配置文件:

  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.impo rts


自定义starter测试

阿里云OSS的starter我们刚才已经定义好了,接下来我们就来做一个测试。

1. 在test工程中引入阿里云starter依赖       通过依赖传递,会把autoconfigure依赖也引入了

2. 在test工程中的application.yml文件中,配置阿里云OSS配置参数信息(从以前的工程中拷 贝即可)

3. 在test工程中的UploadController类编写代码

 @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;
    }
 
}

编写完代码后,我们启动当前的SpringBoot测试工程

随着SpringBoot项目启动,自动配置会把AliOSSUtils的bean对象装配到IOC容器中

上一节

SpringBootWeb 事务&AOP(day13)-CSDN博客

下一节

Web后端开发总结(day14)-CSDN博客


http://www.kler.cn/a/488900.html

相关文章:

  • CI/CD 流水线
  • 【GlobalMapper精品教程】093:将tif影像色彩映射表(调色板)转为RGB全彩模式
  • 【华为OD-E卷 - 篮球比赛 100分(python、java、c++、js、c)】
  • 手机的ip地址是根据电话卡归属地定吗
  • 机器学习无处不在,AI顺势而为,创新未来
  • 清理Mac硬盘超大占用:.Spotlight-V100
  • 【python自写包模块的标准化方法】
  • 「sql之窗口函数」
  • MongoDB中的索引是提高查询效率的重要工具
  • win32汇编环境,窗口程序中对按钮控件常用操作的示例
  • Redis:持久化机制
  • Golang 并发之 Goroutine
  • Django管理后台实现ECS服务管理:权限控制与重启功能
  • (vue)el-table-column type=“selection“表格选框怎么根据条件添加禁选
  • 【PyCharm】PyCharm CE免费版下载
  • ubuntu22.04 gcc,g++从10.5切换到低版本9.5
  • openwrt 常见编译问题及编译提速
  • 多台PC共用同一套鼠标键盘
  • STM32U575按键转换及设备驱动
  • 【2025 Rust学习 --- 12 实用工具特型02】
  • ubuntu安装ssh9.2
  • java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
  • 某地武警海警总队建筑物自动化监测
  • 20250110_ PyTorch中的张量操作
  • [ Android ] JetPack WorkManager Overview
  • Qt初识——下载与环境配置