文章目录

  • SpringBoot高级特性
  • 1、Profile
  • 1.1、定制我们不同环境下的配置文件
  • 1.2、定制我们不同环境下的类和方法
  • 1.3、Profile分组
  • 2、外部化配置
  • 2.1 SpringBoot常用外部化配置源
  • 2.2 SpringBoot配置源的优先级
  • 2.2 SpringBoot配置文件的查找顺序和加载顺序
  • 3、自定义我们自己的starter


SpringBoot高级特性

1、Profile

1.1、定制我们不同环境下的配置文件

Profile主要用于环境切换。让我们在不同的环境下(比如测试和生产环境)能快速地切换所需的配置等等。

怎么用呢?首先,新建一个Controller如下:

package com.example.boot.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    /**
     *  @Value注解中加${}用于获取yaml文件的值,取不到则用默认值李四
     */
    @Value("${person.name: 李四}")
    private String name;

    @GetMapping("/hello")
    public String toHello(){
        return "Hello, "+ name;
    }
}

然后写生产环境下的yaml文件和测试环境下的yaml文件。(可以通过-prop和-test来区别)
application-prop.yaml

person:
  name: prop-张三

application-test.yaml

person:
  name: test-张三

此时运行结果:(因为默认读取的是application.yaml,而在application.yaml中,我们并没有配置person.name的值)

spring boot 高通量_spring boot 高通量


那么,我们怎么让他去读取我们的test或者prop后缀的yaml文件呢?简单。在我们的application.yaml文件中,我们配置下面这个属性的值为test,就读取application-test.yaml文件,赋值prop,就读取application-prop.yaml文件。

spring:
  profiles:
    active: test

比如我们设置他为test,那么,此时我们的结果为:

spring boot 高通量_配置文件_02


注意:
1、环境配置与默认配置是同时生效的。换言之,如果是在默认环境中配的属性,那么所有的环境都生效。
2、如果同一个属性在默认配置和环境配置中都配置的话,那么优先使用环境配置的属性。

1.2、定制我们不同环境下的类和方法

我们还可以通过@Profile注解为我们不同的环境配置不同的类或方法。
这里,我们以类为例,方法其实也一样,就是@Profile加在类上还是方法上的区别而已:
先写一个Person接口

package com.example.boot.bean;

public interface Person {
    public String getName();
    public Integer getAge();
}

然后写两个类:Boss和Worker分别实现Person。

1、@Profile(“prop”):用来配置他属于哪个环境
2、@ConfigurationProperties(“person”):用来告诉SpringBoot,他跟配置文件的哪个属性捆绑在一起。

Boss.java

package com.example.boot.bean;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Profile("prop")
@Data
@Component
@ConfigurationProperties("person")
public class Boss implements Person{
    private String name;
    private Integer age;
}

Worker.java

package com.example.boot.bean;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties("person")
@Profile("test")
public class Worker implements Person{
    private String name;
    private Integer age;
}

之后,我们给我们的配置文件添加age属性(也可以不加,不加的话age就是null)
application-prop.yaml

person:
  name: prop-张三
  age: 28

application-test.yaml

person:
  name: test-张三
  age: 18

然后修改我们的Controller方法:(注入Person并返回,如果没有配置环境的话,其实他是会报错的,因为Person接口有两个实现类。)

package com.example.boot.controller;

import com.example.boot.bean.Person;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class HelloController {

    @Resource
    private Person person;

    @GetMapping("/hello")
    public Person toHello(){
        return person;
    }
}

结果:

spring boot 高通量_spring_03

1.3、Profile分组

有些时候,我们的环境配置文件可能还不止一个。这个时候,我们就可以对他们进行分组。
情景假设:
假如现在,我们的生产环境要引用的环境配置文件有application-prod.yaml和application-haha.yaml,而我们的测试环境要引用的环境配置文件有application-test.yaml。那么,我们在生产环境下就可以这么用。

spring:
  profiles:
    #激活的配置文件为myProd
    active: myProd
    #分组,一个叫myProd,一个叫myTest。其中,prod包括prop和haha两个环境
    group:
      myProd: ['prop','haha']
      myTest: test

2、外部化配置

什么是外部化配置呢?举个实例吧,以前在学Spring的时候,我们写过一个jdbc.properties文件,这个jdbc.properties就是外部化配置文件。

2.1 SpringBoot常用外部化配置源

那么,我们SpringBoot中常用的外部化配置源都有哪些呢?
1、Java属性文件(properties)
2、Yaml文件
3、环境变量(系统或者用户的环境变量)
4、命令行参数

2.2 SpringBoot配置源的优先级

Spring Boot 使用一个非常特殊的PropertySource顺序,旨在允许合理地覆盖值。属性按以下顺序考虑(下面是他们的优先级,且优先级低的可以覆盖优先级高的配置):

  1. 默认属性(由 setting 指定SpringApplication.setDefaultProperties)。
  2. @PropertySource你的@Configuration类的注释。请注意,Environment在刷新应用程序上下文之前,不会将此类属性源添加到。现在配置某些属性(例如在刷新开始之前读取的logging.和)为时已晚spring.main.
  3. 配置数据(如application.properties文件)最常用
  4. 一RandomValuePropertySource,只有在拥有性能random.*。
  5. 操作系统环境变量。
  6. Java 系统属性 ( System.getProperties())。
  7. JNDI 属性来自java:comp/env.
  8. ServletContext 初始化参数。
  9. ServletConfig 初始化参数。
  10. 来自SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的内联 JSON)的属性。
  11. 命令行参数。
  12. properties属性在您的测试中。可用于测试应用程序的特定部分@SpringBootTest的测试注释。
  13. @TestPropertySource 测试中的注释。
  14. $HOME/.config/spring-boot当 devtools 处于活动状态时,目录中的Devtools 全局设置属性。

2.2 SpringBoot配置文件的查找顺序和加载顺序

配置文件的查找顺序

  • classpath 根路径
  • classpath 根路径下的config目录
  • jar包当前目录
  • jar包当前目录的config目录
  • /config 的一级子目录

配置文件的加载顺序:(后面加载的会覆盖前面同名的加载项)

  1. 当前jar包内部的application.properties和application.yaml
  2. 当前jar包内部的application-{profile}.properties和application-{profile}.yaml
  3. 引用的外部jar包的application.properties和application.yaml
  4. 引用的外部jar包的application-{profile}.properties和application-{profile}.yaml

3、自定义我们自己的starter

先创建一个空项目(空项目可以放多个springboot的moodle)

spring boot 高通量_配置文件_04

spring boot 高通量_spring_05


然后我们整个maven模块:

spring boot 高通量_spring boot 高通量_06


这个moodle就按照Springboot官方规定的第三方starter的命名格式来:thirdpartyproject-spring-boot-starter

spring boot 高通量_spring_07


然后我再创建一个Moodle:这个Moodle以SpringInitializr来创建:(无需自动导入任何的依赖)

spring boot 高通量_spring_08


完成后,我们在hello场景的依赖导入hello-configure场景,将我们的配置都写在hello-configure中即可:

spring boot 高通量_配置文件_09


由于我们的hello-configure不单独启动,所以,我们可以删掉他的test场景和他的插件(蓝色区域都可以删掉):

spring boot 高通量_spring boot_10


test文件夹以及他给我们的类和配置文件也都可以删了。

spring boot 高通量_spring_11


然后我们可以写我们的业务逻辑代码:

比如我们经常用这个HelloService组件,他的sayHello方法可以通过自定义前后缀的方式,对传入的name值进行问候。

HelloService.class

package com.example.hellospringbootstarterautoconfigure.service;

import com.example.hellospringbootstarterautoconfigure.properties.HelloProperties;

import javax.annotation.Resource;
public class HelloService {

    @Resource
    HelloProperties properties;

    public String sayHello(String name){
        return properties.getPrefix() + name + properties.getSuffix();
    }
}

然后我们就写一下他的绑定类(Properties)
HelloProperties.class

package com.example.hellospringbootstarterautoconfigure.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("hstc.hello")
public class HelloProperties {
    private String prefix;
    private String suffix;

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

最后,我们模仿以前那些场景,写一下他的自动配置类:
HelloServiceAutoConfiguration.class

package com.example.hellospringbootstarterautoconfigure.auto;

import com.example.hellospringbootstarterautoconfigure.properties.HelloProperties;
import com.example.hellospringbootstarterautoconfigure.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
//没有HelloService类的时候,该配置才生效
@ConditionalOnMissingBean(HelloService.class)
//绑定我们的HelloProperties
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {

    @Bean
    public HelloService helloService(){
        HelloService helloService = new HelloService();
        return helloService;
    }
}

最后,我们在resource目录下新建一个META-INF的文件夹,放我们的spring.factories,并加入以下代码,让SpringBoot默认加载我们的配置类:

#自动配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.hellospringbootstarterautoconfigure.auto.HelloServiceAutoConfiguration

完成后,咱们就可以打包了,使用clean,然后install将他放到我们的本地仓库。

spring boot 高通量_spring boot 高通量_12


将我们的hello场景也放入仓库:

spring boot 高通量_spring boot_13


接下来,我们再新建一个Moodle,这个是我们的实际的开发场景。

spring boot 高通量_java_14


整一个Web开发场景。

spring boot 高通量_spring boot_15


此时,我们的hello场景和hello-configure场景已经在我们的仓库中了。我们只需要在我们的开发场景demo中引入就可以直接用他了。(注意引入的是hello场景不是hello-configure场景

<dependency>
     <groupId>org.example</groupId>
     <artifactId>hello-spring-boot-starter</artifactId>
     <version>1.0-SNAPSHOT</version>
 </dependency>

然后我们在我们的配置文件中,配置我们刚才的prefix和suffix:

hstc.hello.prefix= Dear 
hstc.hello.suffix= , Nice to meet you!!!

然后我们写我们的控制器方法来看看刚才那个能不能用:

package com.example.demo.controller;

import com.example.hellospringbootstarterautoconfigure.service.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class HelloController {

    @Resource
    HelloService helloService;

    @GetMapping("/hello")
    public String sayHello(){
        return helloService.sayHello("张三");
    }
}

启动我们SpringBoot的主程序,我们来看下运行结果:

spring boot 高通量_spring boot 高通量_16