SpringBoot攻略三、配置文件说明

自动配置

SpringBoot启动的时候加载主配置类(@SpringBootApplication注解修饰), @SpringBootApplication开启了自动配置功能 @EnableAutoConfiguration。


@EnableAutoConfiguration作用:利用AutoConfigurationImportSelector给spring容器中导入一些组件。
@SpringBootConfiguration作用:表示类提供springboot应用功能,继@Configuration。


跟踪一下AutoConfigurationImportSelector中的selectImports方法:



扫描所有jar包类路径下 META-INF/spring.factories;
把扫描到的这些文件的内容包装成properties对象;
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们 添加在容器中;
即将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加 入到了容器中。


这里,我们分析一下HttpEncodingAutoConfiguration,其他类似:



@Configuration:
定义配置类。
@EnableConfigurationProperties(HttpEncodingProperties.class):
启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties的属性绑定起来;并把HttpEncodingProperties加入到ioc容器。
@ConditionalOnWebApplication:
判断当前应用是否是web应用,如果是,当前配置类 生效
@ConditionalOnClass(CharacterEncodingFilter.class):
判断当前项目有没有这个类, CharacterEncodingFilter:SpringMVC中解决乱码的过滤器。
@ConditionalOnProperty(prefix="spring.http.encoding",value="enabled", matchIfMissing=true):
//判断配置文件中是否存在某个配置spring.http.encoding.enabled;matchIfMissing表示,即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的;
@Conditional注解(Spring注解版):
条件注解,通过判断类路径下有没有配置相应jar包来确定是否加载和自动配置这个类。

所有在配置文件中能配置的属性都是在xxxxProperties类中封装的,配置文件的配置项 就可以参照其对应的这个属性类,默认就是UTF-8编码。



小结:
1、SpringBoot启动会加载大量的自动配置类;
2、首先检查SpringBoot默认的自动配置类是否满足我们的需求;
3、具体查看这个自动配置类中配置了哪些组件;
4、给容器中的自动配置类添加组件的时候,会从properties类中获取某些属性。我们 就可以在配置文件中指定这些属性的值;
5、xxxxAutoConfigurartion:自动配置类,给容器中添加组件Bean;xxxxProperties:封 装配置文件中相关属性;

Spring Boot提供了对应用进行自动化配置。相比以前 XML 配置方式,很多显式方式申 明是不需要的。二者,大多数默认的配置足够实现开发功能,从而更快速开发。

application.properties添加debug=true,可以在控制台查看自动配置报告信息。

拓展:@Conditional派生注解了解
核心:@Conditional指定的条件成立,才给容器中添加组件,配置类里面的所有内容才 生效;即自动配置类必须在一定的条件下才能生效:
@ConditionalOnJava: 系统的java版本是否符合要求
@ConditionalOnBean: 容器中存在指定Bean;
@ConditionalOnMissingBean: 容器中不存在指定Bean;
@ConditionalOnExpression: 满足SpEL表达式指定
@ConditionalOnClass: 系统中有指定的类
@ConditionalOnMissingClass: 系统中没有指定的类
@ConditionalOnSingleCandidate: 容器中只有一个指定的Bean,或者这个Bean是首 选Bean
@ConditionalOnProperty: 系统中指定的属性是否有指定的值
@ConditionalOnResource: 类路径下是否存在指定资源文件
@ConditionalOnWebApplication: 当前是web环境
@ConditionalOnNotWebApplication: 当前不是web环境

自定义属性(添加新属性、覆盖自动配置默认的属性)

Spring Boot使用默认的全局的配置文件:application.properties 或 application.yml,配置文件名固定。

实例
1、建立PersonProperties

package com.javasgj.springboot.configuration;

import java.util.List;
import java.util.Map;

import javax.validation.constraints.Email;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

/**
 * @Validated:对注入的值进行一些简单的校验;
 *              @Email          校验邮箱地址
 *              @AssertFalse    校验false
 *              @AssertTrue     校验true
 *              @DecimalMax(value=,inclusive=) 小于等于value,inclusive=true,是小于等于
 *              @DecimalMin(value=,inclusive=) 与上类似
 *              @Max(value=)    小于等于value
 *              @Min(value=)    大于等于value
 *              @NotNull        检查Null
 *              @Past           检查日期
 *              @Pattern(regex=,flag=)  正则
 *              @Size(min=, max=)       字符串,集合,map限制大小
 *              这些注解位于javax.validation.constraints包下,校验不通过时抛出异常。
 * @Component:作为Bean注入到spring容器,或者使用@Configuration;
 * @ConfigurationProperties:将配置文件中以person前缀的属性值自动绑定到对应的字段中;
 */
@Validated
@Component
@ConfigurationProperties(prefix="person")
public class PersonProperties {
    
    private String id;
    private String name;
    private int age;
    private String sex;
    @Email
    private String email;
    private String desc;
    private String desc1;
    private Map<String, String> maps;
    private List<String> list;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public String getDesc1() {
        return desc1;
    }
    public void setDesc1(String desc1) {
        this.desc1 = desc1;
    }
    public Map<String, String> getMaps() {
        return maps;
    }
    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }
    public List<String> getList() {
        return list;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
}

@ConfigurationProperties作用:默认加载classpath:application.properties或application.yml,如果同时存在则加载application.properties,并且把文件中以person前缀的属性值自动绑定到对应的l字段中。

当然如果是自定义属性值,也可以使用@PropertySource指定属性文件。
但是要覆盖框架自动配置的属性,只能使用默认的全局配置文件。

2、src/main/resources下建立:application.properties

#properties、yml同时存在,取properties内容


#调试信息,控制台查看自动配置报告信息
#debug=true


#自定义属性
person.name=Jim
person.age=28
person.sex=0
person.email=111@qq.com
#${}占位符,可以引用配置文件其他属性值,如果没有可以配置一个默认值:${person.name:default}
person.desc=I'm ${person.name}
#\n特殊字符,换行
person.desc1=I'm ${person.name} \n welcome!
#map数据类型,对象类型同理:person.对象名.属性名
person.maps.privince=js
person.maps.city=nj
#array、list、set集合
person.list[0]=0
person.list[1]=1
#随机数,通过 RandomValuePropertySource工具类。可以生成随机字符串、随机 int 、随机 long、某范围的随机数
#person.id=${random.int}
#person.id=${random.long}
#person.id=${random.long[1,100]}
#person.id=${random.uuid}
person.id=${random.value}

或者使用application.yml

person: 
 name: jim1
 age: 28
 sex: 0
 desc1: I am jim \n welcome!
 list: [0,1,2]
person.maps: {privince: js, city: nj}

注意:
1、yml格式冒号后面都要一个空格,属性前面也只能添加一个空格,可以使用在线编 辑yml(http://www.bejson.com/validators/yaml_editor/),有校验格式功能。
2、单引号:转义特殊字符,特殊字符只是一个普通的字符串数据,等同于没有引号
name: ‘zhangsan \n lisi’ 输出:zhangsan \n lisi
3、双引号:不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi" 输出:zhangsan
lisi

3、应用启动类

package com.javasgj.springboot.configuration;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * spring boot应用启动类
 */
@SpringBootApplication
public class Application {

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

4、编写测试类
pom.xml引入依赖

<!-- spring boot test -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

PersonPropertiesTest:

package com.javasgj.springboot.configuration;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes=Application.class)
public class PersonPropertiesTest {

    @Autowired
    PersonProperties personProperties;
    
    @Test
    public void testGetName() {
        
        /**
         * springboot默认以ISO-8859-1编码读取properties文件内容,所以会有中文乱码,我们可以做如下处理解决乱码,
         * 或者使用yml类型文件进行配置,没有中文乱码问题。
         */
        /*try {
            System.out.println(new String(personProperties.getName().getBytes("ISO-8859-1"), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }*/
        
        System.out.println("结果:" + personProperties.getId());
        System.out.println("结果:" + personProperties.getName());
        System.out.println("结果:" + personProperties.getEmail());
        System.out.println("结果:" + personProperties.getDesc1());
        System.out.println("结果:" + personProperties.getMaps().keySet().toString());
        System.out.println("结果:" + personProperties.getList().size());
    }
}

@SpringBootTest指定应用启动类Application
赶紧运行结果看看吧!

扩展:
Spring Boot不单单从application.properties获取配置,我们可以在程序中设置多种 配置属性。按照以下列表的优先级从高到低排列:
1、命令行参数
2、java:comp/env 里的 JNDI 属性
3、JVM 系统属性
4、操作系统环境变量
5、RandomValuePropertySource 属性类生成的 random.* 属性
6、应用外部的application-{profile}.properties或application.yml(带spring.profile)文件
7、应用内部的application-{profile}.properties或application.yml(带spring.profile)文件
6、应用以外的 application.properties(或 yml)文件
7、应用内部的 application.properties(或 yml)文件
8、在应用 @Configuration 配置类中,用 @PropertySource 注解声明的属性文件
9、SpringApplication.setDefaultProperties 声明的默认属性

注意一些特殊属性如:user.name,如果你在配置文件配置了此属性,但是确获取不到 配置文件中的值,为什么呢?因为系统属性有user.name,优先级又高,会获取到机器 当前用户账号。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。