22-07-16 西安 springboot(01)入门使用、配置文件、springboot很多注解、自动配置原理、配置文件查找顺序

我们并不是没有梦想,更不是没有努力过,而是未曾坚持下去!       


SpringBoot

Spring Boot是Spring项目中的一个子工程,与我们所熟知的Spring-framework 同属于spring的产品(Spring家族中的一员)

springboot设计目的: 用来简化 Spring 应用的初始搭建以及开发过程

1、springboot主要特点

自动配置:不需要再关注各个框架的整合配置,springboot全部已经配置好了

起步依赖我们在需要使用某个框架的时候, 直接添加这个框架的启动器依赖即可 , 不需要在关注jar包的冲突和整合

 启动器依赖(starter):就是springboot提前封装的项目模块


2、SpringBoot、 SpringMVC和Spring有什么区别

Spring是一个IOC容器,用来管理Bean,使用依赖注入实现控制反转,可以很方便的整合各种框架,提供AOP机制弥补OOP的代码重复问题、更方便将不同类不同方法中的共同处理抽取成切面、自动注入给方法执行,比如日志、异常等

OOP:面向对象程序设计

SpringMVC是Spring对web框架的一个解决方案,提供了一个DispatcherServlet,用来接收请求,然后定义了一套路由策略(url到handle的映射)及适配执行handle,将handle结果使用视图解析技术生成视图展现给前端

SpringBoot是Spring提供的一个快速开发工具包,让程序员能更方便、更快速的开发spring+springmvc应用,简化了配置(约定了默认配置),整合了一系列的解决方案(starter机制)、redis.mongodb.es,可以开箱即用


3、SpringBoot 优势

spring boot 其实不是什么新的框架,它默认配置了很多框架的使用方式,就像 maven 整合了所有的 jar 包,spring boot 整合了所有的框架

1.快速构建项目

2.零配置,遵循“约定大于配置”   编码<配置<约定

3.集成第三方库变为启动器,做到“开销即用”

4.嵌入tomcat服务器

使用Spring Boot开发时, 不需要关注各种复杂的整合配置 , 也不用关注各个库之间的依赖及冲突问题 , Spring Boot已经默认帮我们整合配置好了 !

节省了大量的配置及依赖调整时间, 让我们能够把时间用在刀刃上, 专注业务逻辑的开发。


4、SpringBoot 左下角启动项目配置

  • 正常情况按下图打开view下的tool windows会有一个services的选项,但是这里没有

1.点击Run,找到 Edit  Configurations

2.点击Templates(不用展开),展开右侧Configurations available services,点击加号

3.点击加号,选择Spring Boot 确认后,效果如下

4.效果,左下角出现services


SpringBoot入门案例

该入门案例的需求很简单,如下。。

1、创建maven工程

如下图创建名为springboot_01的maven工程

注意下图中springboot_01和springboot是没有父子工程关系的;
springboot的存在完全是为了方便管理各个模块,它可以没有


2、pom.xml中添加启动器

SpringBoot可以帮我们方便的管理项目依赖 , 在Spring Boot提供了一个名为**spring-boot-starter-parent**的工程,里面已经对各种常用依赖的版本进行了管理

我们的项目需要以这个项目为父工程,这样我们就不用操心依赖的版本问题了,需要什么依赖,直接引入坐标(不需要添加版本)即可

在springboot_01工程的pom文件中:

添加父工程启动器 spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.6.RELEASE</version>
</parent>

添加web启动器:spring-boot-starter-web

为了让Spring Boot帮我们完成各种自动配置,我们必须引入Spring Boot提供的自动配置依赖,我们称为启动器。因为我们是web项目,这里我们引入web启动器

​<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

这个启动器的依赖,它已经把自己运行所需要的必要包集成在这个启动器中,通过Maven的依赖传递性,将这些包都依赖到咱们的项目里了


3、创建启动类 Application

Spring Boot项目通过main函数即可启动,我们需要创建一个启动类

启动类可以1.启动tomcat   2.管理各种bean对象(扫描包)

springboot默认就是jar包,因为tomcat内置了

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

启动类的位置:要以上帝视角。默认扫描启动类所在包及子包下的类身上的注解


4、编写HelloController控制器

里面写一个控制器方法,处理/hello请求

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String sayHello(){
        return "hello spring boot!!" ;
    }
}

启动springboot项目,如下图:

在浏览器测试,成功搭建springboot-web项目


5、使用Spring Initializr 快速创建

Spring Initializr 从本质上来说就是一个Web应用程序,它能为你生成Spring Boot项目结构。虽然不能生成应用程序代码,但它能为你提供一个基本的项目结构。

记得要改这里的配置URL    https://start.springboot.io 


6、启动参数(VM Options)传入配置项

SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数(VM Options)传入配置项,注意:通过启动参数传入的配置项会“顶掉”配置文件中的配置

在上文中,我们的项目启动端口是8080,现在做如下操作

-Dserver.port=5555

重新启动项目

IDEA 快捷键:

进入方法:  Ctrl + 鼠标左键

光标前进/后退: Ctrl + Shirt + 右方向键/左方向键


SpringBoot配置文件

配置文件必须放置在项目的类加载目录下, 并且名字必须是application

springboot项目在运行的时候会自动加载这些配置文件。名字必须是application.yaml,或

application.properties。选其一

1、properties文件

配置数据库连接信息,会重复去写“spring.jdbc.datasource”(这是properties文件的缺点)

spring.jdbc.datasource.driverClassName=com.mysql.jdbc.driver
spring.jdbc.datasource.url=jdbc:mysql://springboot_01
spring.jdbc.datasource.username=xiaoyumao
spring.jdbc.datasource.password=123456

根据配置文件中的属性,创建属性类DataSourceProperties,封装4个属性

@Value是spring中的注解,不是springboot的

import org.springframework.beans.factory.annotation.Value;

@Component
public class DataSourceProperties {
    @Value("${spring.jdbc.datasource.driverClassName}")
    private String driverClassName;
    @Value("${spring.jdbc.datasource.url}")
    private String url;
    @Value("${spring.jdbc.datasource.username}")
    private String username;
    @Value("${spring.jdbc.datasource.password}")
    private String password;
    //省略get/set方法/toString方法

}

在HelloController中,额外加入以下内容

浏览器重新发起请求 http://localhost:8080/hello

查看控制台打印输出:


2、@Value

@Value("${server.port:8080}")
private int serverPort;

如上,如果在配置文件没有配置对应的属性,则使用8080作为默认值

给参数注入,执行set方法

public static String zhifuUrl;   
@Value("${zhifu.url}")  
public void setZhifuUrl(String url) {  
CrmUtil.zhifuUrl = url;  
} 

注:在没有指定默认值的情况下,如果忘记在配置文件配置对应的属性,在程序启动时会报错,导致程序启动失败,这种情况可以为@Value指定默认值,来避免该问题


3、yaml 配置文件

当俩种格式(application.yaml,或application.properties)的配置文件都存在,读的是properties格式的配置文件。

yaml语法 :

1.数据结构用树形结构呈现,通过缩进来表示层级

2.连续的项目集合通过减号 ” - ” 来表示

3.键值结构里面的key/value对用冒号 ” : ” 来分隔。

4.YAML配置文件的扩展名是yaml 或 yml

server:
  port: 8080
  servlet:
    context-path: /demo

server.port  配置启动项目的tomact端口号

server.servlet.context-path 配置应用的上下文路径,也可以称为项目路径

  • server.servlet.context-path不配置时,默认为 / ,如:localhost:8080/xxxxxx
  • 当server.servlet.context-path有配置时,比如 /demo,此时的访问方式为localhost:8080/demo/xxxxxx

把上面说的properties属性文件,用yml的语法写就是如下:

spring:
  jdbc:
   datasource:
    driverClassName: com.mysql.jdbc.driver
    url: jdbc:mysql://springboot_01
    username: xiaoyumao
    password: 123456

上面这种数据源的连接方式是我们自定义的,以后数据源配置并不会这么使用

以后怎么连接数据库,使用下图框住的上面那个框下面那个框是自定义的,需要自己写配置类读取。上面的是springboot定义好的,直接可以用。


4、多环境profile切换配置

 [profile-配置文件]

场景:开发环境、测试环境、准生产环境、生产环境,每一个环境都有自己的数据库(需要通过yml配置)

Spring Boot项目中配置文件的名称只能是**application** , 如果我们把所有的配置全都写在一个配置文件中如果配置项比较多, 配置文件就会显得比较复杂和臃肿 ! 不利于后期的项目维护和开发

springboot中可以使用多个yaml配置文件,这些文件名称必须为application-***.yml,并且在application.yml中激活(文件中引用)

怎么快速灵活的切换数据库

spring.profiles.active    这个key就不是自定义的了。会自动提示的

-----------------------------------------------------

2个配置文件如下:

创建application-dev.yml,配置开发环境的数据库连接信息

创建application-test.yml,配置测试环境的数据库连接信息


5、修改tomcat端口号

上面的开发环境和测试环境配置里,tomcat的端口号默认都是8080。我们可以单独在不同的yml文件中为每一个不同的环境指定不同的tomcat端口号。

但是没必要,我们就直接在配置在application.yml中配置,让它们共用即可.

此时再次重启,浏览器访问,8080就不好使了,需要访问8089端口

那么为什么默认是8080呢,我来带你找一找

1.点开External Libraries

2.spring-boot-autoconfigure -->META_INF-->json文件


SpringBoot 很多注解

1、@SpringBootApplication

@SpringBootApplication注解是组合注解[@SpringBootConfiguration +@ComponentScan + @EnableAutoConfiguration ]

@SpringBootConfiguration 
标注这个类就是配置类,相当于xml配置文件,本质上就是一个@Configuration注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

@ComponentScan 上帝视角组件扫描

默认扫描启动类所在包及子包下的类身上的注解

@EnableAutoConfiguration 
启用自动配置,自动去读取spring.factories配置文件中的自动配置类

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

下面在自动配置原理中,会详细解释这个注解@EnableAutoConfiguration 


2、@Configuration+@Bean

@Configuration 告诉springboot这是一个配置类,等同于以前的application.xml配置文件

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

@Configuration(proxyBeanMethods = false)

proxyBeanMethods 是用来指定 @Bean 注解标注的方法是否使用CGLIB代理,默认是 true 使用代理。

proxyBeanMethods = false不代理bean方法,每次获取都是重新创建
反之,代理bean方法,代理干的事情:判断这个bean对象是否存在,如果存在就直接在ioc中拿
如果配置类中的@Bean标识的方法之间不存在依赖调用的话,可以设置为false,可以避免拦截方法进行代理操作

@Bean容器中添加组件,以方法名作为组件的id,返回类型就是组件的类型,返回的值,就是组件在容器中的实例

@Configuration //告诉springboot这是一个配置类,等同于以前的配置文件
public class MyConfig {
    @Bean//给容器中添加组件,
    App getApp(){
        App app = new App(1, "快手");
        return app;
    }
}

注意:配置类本身也是组件

@Bean 默认是单实例的,不管获取多少次这个组件,都是同一个,

在启动类的面方法中,用 ==判断测试

public static void main(String[] args) {
    ConfigurableApplicationContext run = SpringApplication.run(Spingboot01Application.class, args);
    //多次获取组件名是getApp的组件
    App app1 = run.getBean("getApp", App.class);
    App app2 = run.getBean("getApp", App.class);
    //==判断是不是获取的同一个组件
    System.out.println(app1==app2);
}

控制台打印,符合预期


3、@import+@Configuration

1.@Import要写在容器中的组件类

2.给容器导入自定义的组件User

@Configuration
@Import(User.class)
public class MyConfig {
}

//---User类是另外一个java文件

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer userId;
    private  String name;
    private  String password;
}

3.import方式导入的组件,默认组件名是全类名

在启动类的main方法里,去获取容器中的组件

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        //获取类型为User的所有组件的beanid
        String[] names = run.getBeanNamesForType(User.class);
        //遍历打印beanid
        for (String name : names) {
            System.out.println(name);
            //根据beanId获取容器中的bean
            User user = (User) run.getBean(name);
            System.out.println(user);
        }
    }
}

运行启动类,打印效果如下,@import注入,默认组件名beanid是全类名


4、@ImportResource+@Configuration

作用:迁移spring中xml方式配置的组件

使用方式:在某一个配置类上加@ImportResource

测试如下:

1.创建Phone类,并使用spring的方式在beans.xml中set注入

<bean id="phone" class="com.example.spingboot01.pojo.Phone">
    <property name="brand" value="华为"></property>
    <property name="name" value="mate50Pro"></property>
</bean>

2.在配置类上使用@ImportResource导入资源

@Configuration
@ImportResource("classpath:beans.xml")
public class MyConfig {
}

3.在启动类里的main方法获取

public static void main(String[] args) {
    ConfigurableApplicationContext run = SpringApplication.run(Spingboot01Application.class, args);
    //获取组件名是phone的组件
    Object phone = run.getBean("phone");
    System.out.println(phone);
}

4.控制台打印如下,符合预期效果


5、@ConfigurationProperties 配置绑定

该注解源码如下:

//springboot源码
public @interface ConfigurationProperties {
    @AliasFor("prefix")
    String value() default "";

    @AliasFor("value")
    String prefix() default "";
}

因为prefix和value互为别名,下面我就直接省略了,相当于使用了value

---------------------------

配置绑定:将一些配置属性批量注入到bean对象。

配置绑定方式一:@ConfigurationProperties+@Component

prefix=“公共的key值”,但是类中的属性必须和配置文件的属性一致(长得一样,才会自动注入),这种注入方式,属性再多,只要按照规则就可以一次性自动注入。

注意一定要加 @Component

容器中的组件才能拥有springboot给他提供的强大功能,比如配置绑定

@Component
@ConfigurationProperties("spring.jdbc.datasource")
@Data //提供get、set、toString方法
public class DataSourceProperties {

    private String driverClassName;

    private String url;

    private String username;

    private String password;

}

接着会弹出这么一个玩意

解决办法:在pom文件添加配置信息

spring-boot-configuration-processor其实是一个注解处理器,在编译阶段干活的,一般在maven的声明都是 ,optional 为true

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

---------------------详细介绍如下

optional表示是否会传递依赖,有两个可填值(假如不声明optional标签,默认就是false):false: 传递依赖
true:不传递依赖

举例:A引用了B的依赖,而B又引用了C依赖。

假如B引用C依赖的时候没有设置optional,那么A是可以使用C依赖的。
假如B引用C依赖的时候将optional标签设置为了true,那么在A当中就无法使用C依赖相关的方法,并且A调用B依赖的方法,而B依赖方法使用到了C,这时候会报找不到C依赖下的类,因为C不参与A的打包。

spring-boot-configuration-processor说白了就是给自定义的配置类生成元数据信息的,如上边使用@ConfigurationProperties("spring.jdbc.datasource")的类

项目编译后:

生成的内容如下

{
  "groups": [
    {
      "name": "spring.jdbc.datasource",
      "type": "com.xkcoding.properties.property.DataSourceProperties",
      "sourceType": "com.xkcoding.properties.property.DataSourceProperties"
    }
  ],
  "properties": [
    {
      "name": "spring.jdbc.datasource.driver-class-name",
      "type": "java.lang.String",
      "sourceType": "com.xkcoding.properties.property.DataSourceProperties"
    },
    {
      "name": "spring.jdbc.datasource.password",
      "type": "java.lang.String",
      "sourceType": "com.xkcoding.properties.property.DataSourceProperties"
    },
    {
      "name": "spring.jdbc.datasource.url",
      "type": "java.lang.String",
      "sourceType": "com.xkcoding.properties.property.DataSourceProperties"
    },
    {
      "name": "spring.jdbc.datasource.username",
      "type": "java.lang.String",
      "sourceType": "com.xkcoding.properties.property.DataSourceProperties"
    }
  ],
  "hints": []
}
name | String
属性的全名。名称采用小写的周期分隔形式(例如server.address)。此属性是强制性的。 

type | String
属性的数据类型的完整签名(例如java.lang.String),但也是完整的泛型类型(例如java.util.Map)。
您可以使用此属性来指导用户可以输入的值的类型。为了保持一致性,通过使用其包装对应项(例如,boolean变为java.lang.Boolean)来指定基元的类型。
请注意,此类可能是一个复杂类型,它从Stringas绑定的值转换而来。如果类型未知,则可以省略。 

description | String 
可以向用户显示的组的简短描述。如果没有可用的描述,则可以省略。建议描述为简短段落,第一行提供简明摘要。描述中的最后一行应以句点(.)结尾。 

sourceType | String
贡献此属性的源的类名称。例如,如果属性来自带注释的类@ConfigurationProperties,则此属性将包含该类的完全限定名称。如果源类型未知,则可以省略。 
defaultValue | Object | 默认值,如果未指定属性,则使用该值。如果属性的类型是数组,则它可以是值数组。如果默认值未知,则可以省略。

使用additional-spring-configuration-metadata.json进行提示。

@Data
@ConfigurationProperties(prefix = "developer")
@Component
public class DeveloperProperty {
    private String name;
    private String website;
    private String qq;
    private String phoneNumber;
}

它使用简单的 JSON 格式,其中的项目分类在 groups 或 properties 下,其他值提示分类在 hints 下

为自定义配置添加 hint 提醒。如自定义的开发人员配置信息

配置绑定方式二:@ConfigurationProperties+@EnableConfigurationProperties

某种情况下:我们使用的是第三方的类,人家没标@Component。怎么办,我们也改不了人家的源码

1、在属性类DataSourceProperties上去掉@Component

@ConfigurationProperties("spring.jdbc.datasource")
@Data //提供get、set、toString方法
public class DataSourceProperties {

    private String driverClassName;

    private String url;

    private String username;

    private String password;

}

2、一定要在配置类上写,替换了方式一的@Component(是不是一定在配置类上写还有待考究,但是在配置类上写了是可以用的)

使用@EnableConfigurationProperties(DataSourceProperties.class)

@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
//开启DataSourceProperties类的配置绑定功能
//把这个DataSourceProperties类组件自动注册到容器中
public class MyConfig {
}

经认证:再次启动该测试方法,也是没有问题的。

@SpringBootTest
class Spingboot01ApplicationTests {
    @Autowired
    DataSourceProperties dataSourceProperties;
    @Test
    void contextLoads() {
        System.out.println(dataSourceProperties);
    }
}


6、@Conditional 条件装配

满足Conditional 指定的条件,才进行组件的注入。

它有非常多的派生注解,常用如下 :

注解

作用

@ConditionalOnBean

如果存在某个Bean, 配置类生效

@ConditionalOnMissingBean

如果不存在某个Bean, 配置类生效

@ConditionalOnClass

如果存在某个类, 配置类生效

@ConditionalOnMissingClass

如果不存在某个类, 配置类生效

@ConditionalOnProperty

如果存在某个属性配置, 配置类生效

@ConditionalOnWebApplication

如果是一个web应用, 配置类生效

@ConditionalOnNotWebApplication

如果不是一个web应用, 配置类生效

举例:@ConditionalOnBean

1.条件注解加在方法上,当条件成立后,方法返回的组件才会被注册到容器中

2..条件注解加在类上,当条件成立后,这个类下的所有配置才能生效


SpringBoot自动配置

Springboot在启动的时候会调用run方法,run方法会执行refreshContext()方法刷新容器,

会在类路径下找到springboot-boot-autoconfigure/springboot-boot-autoconfigure.jar/META-INF/spring-factories文件,该文件中记录中众多的自动配置类,

容器会根据我们是否引入依赖是否书写配置文件的情况,将满足条件的Bean注入到容器中,于是就实现了springboot的自动装配

1、@EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

2、@AutoConfigurationPackage

直译:自动配置包

@Import@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

实际上就是一个@Import,用来给容器中导入一个组件

点击进入Registrar.class

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    Registrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
    }

    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
    }
}

利用Registrar给容器中导入一系列组件,哪一系列??

将指定的一个包(启动类所在包)下的所有组件导入进来。。

原因是从注解@AutoConfigurationPackage的元信息中获取的

3、@Import({AutoConfigurationImportSelector.class})

public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    } else {
        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
}

this.getAutoConfigurationEntry();//给容器中导入组件

它里面的一个核心方法,

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

getCandidateConfigurations();//获取所有导入到容器的配置类

它会使用spring的工厂加载器

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

再往下点点点。。

就会找到这个方法,加载我们所有的组件

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
}

说了这么多,总计就是从这个位置加载文件:META-INF/spring.factories


4、spring-boot-autoconfigure-2.3.7.RELEASE.jar

核心包

它里面也有 META-INF/spring.factories

打开这个文件META-INF/spring.factories

从22行一直到148行,正好是127个自动配置类。其实就是在配置文件里写死了,

springboot一启动就要给容器中加载的所有配置类,但是这些配置类哪些生效哪些不生效,就是按需开启了。得益于这个条件装配注解@ConditionalOnXXX,实现了按需配置

查看mvc 的自动配置类:WebMvcAutoConfiguration


SpringBoot配置文件的查找顺序

1、配置信息来源—环境变量

除了properties文件和yaml文件,配置信息也可以来源于环境变量,也可以是 命令行参数来配置,运行jar包的时候。。。

创建Controller,处理请求

@RestController
public class HelloController {
    @Value("${MAVEN_HOME}")
    private String msg;

    @RequestMapping("/hello")
    public String sayHello(){

        return msg;
    }
}

在浏览器访问,真牛逼啊 


2、配置文件查找位置

在生产环境下修改配置就非常简单了,无需修改代码

由上到下加载,配置文件的查找位置

(1)classpath 根路径(最常用)

(2)classpath 根路径下的config目录

(3)jar包当前目录

(4)jar包当前目录的config目录

(5)/config子目录的直接子目录

情况(5)是指linux目录的根目录下有一个config目录,在这个config目录的子目录是可以用的。

注意:下面的配置(后加载)会覆盖上面的同名项配置


3、验证配置文件加载覆盖

测试情况(1),这也是我们平时配置文件放的位置,在classpath根路径

文件内容是:

@RestController
public class HelloController {
    @Autowired
    DataSourceProperties dataSourceProperties;

    @RequestMapping("/hello")
    public String sayHello(){

        return dataSourceProperties.getUsername()+":"+dataSourceProperties.getPassword();
    }
}

浏览器访问,没啥问题,这是我们测试别的情况的基础

测试情况(1)和情况(2)同时存在的情况

配置文件的位置

文件内容,只修改了这一处 

 浏览器访问测试,没啥问题。后加载的配置会覆盖之前同名的配置

测试情况(1)和情况(2)测试情况(3)同时存在

使用idea打包后,创建测试文件夹,把jar包放到文件夹中,并创建application.yml

 对配置文件内容作如下修改

打开cmd, java - jar 运行我们的springboot项目

 

 在浏览器访问测试,符合预期效果

测试情况(1)、情况(2)、情况(3)、情况4 同时存在

在jar包所在目录创建config文件夹,并在文件夹里创建配置文件

 配置文件内容作如下修改

 浏览器访问测试,符合预期效果

总结一波

Springboot 程序启动时,会从以下位置查找配置文件并加载:

  1. 当前项目根目录下的/config目录下
  2. 当前项目的根目录下
  3. classpath:/config/:classpath的/config目录(即resource目录下的config目录)
  4. classpath:/ :classpath的根目录(即resource目录下)

配置文件加载优先级为由上至下,上面的优先级更高,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。


SpringBoot错误处理机制

1、默认错误处理机制

默认情况下:springboot提供/error 处理所有错误的映射

对于机器客户端(如postman),它将生成JSON响应,其中包含错误。HTTP状态和异常消息的详细信息。

对于浏览器客户端,响应一个"whitelabel"错误视图,以HTML格式呈现相同的数据

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值