快速创建springboot, springboot配置(yml, 注入, @PropertySource和@ImportSource, 占位符, Profile, 配置文件加载顺序[内'外])
使用Spring Initializer快速创建SpringBoot项目
![]()
![]()
![]()
- 选好模块后, idea会联网帮我们导入相应的依赖.
- 这样主程序就生成好了, 只需要我们编写自己的逻辑即可.
- resources文件夹中目录结构
![]()
- static: 保存所有的静态资源; js, css, image.
- templates: 保存所有的模板页面
- SpringBoot默认jar包使用嵌入式的Tomcat, 不支持jsp, 但可以使用模板引擎thymeleaf.
- application.properties: SpringBoot应用的配置文件, 可以修改一些默认设置.
SpringBoot配置
配置文件
- SpringBoot使用一个全局的配置文件
- application.properties
- 或application.yml
- 配置文件的作用: 修改SpringBoot自动配置的默认值.
- 配置文件放在src/main/resources目录下.
YAML语法
- 以前我们的配置文件大多是xml文件, 而yml是以数据为中心的, 比起xml, json更适合做配置文件
- 基本语法
- k: v 表示一对键值对(冒号后必须有空格)
- 以空格的缩进控制层级关系: 左对齐的一列数据都是同一层级的.
server:
port: 8080
path: /hello
- 属性和值大小写敏感.
- 值的写法
- 字面量: 普通值(数字,字符串,布尔)
- k: v 字面量直接来写, 字符串默认不用加引号.
- "xxx": 双引号不会转义字符串中的特殊字符.
- 'xxx': 单引号会转义字符串中的特殊字符(特殊字符最终只是一个普通字符串输出)
- 对象: Map(键值对) 在下一行来写对象的属性和值的关系
- 对象还是k: v的形式
friends:
lastName: zhangsan
age: 20
- 行内写法
friends: {lastName: zhangsan, age: 18}
- 数组(List, Set)
配置文件的注入
- yml配置文件
server:
port: 8081
person:
lastName: zhangsan
age: 18
boss: false
birth: 2020/5/11
map: {k1: v1, k2: v2}
list:
- lisi
- zhaoliu
dog:
name: 小狗
age: 2
- 实体类
/**
* 将配置文件中每个属性的值映射到这个组件中
* @ConfigurationProperties: 告诉SpringBoot将本类中所有属性和配置文件中的相关配置绑定
* prefix = "person": 与配置文件中哪个属性的下面一一对应.
* 只有这个组件是容器的组件, 才能提供@ConfigurationProperties的功能.
*/
@Component
@ConfigurationProperties(prefix = "person")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> map;
private List<Object> list;
private Dog dog;
}
- 再pom.xml中导入配置文件处理器, 这样以后写yml时就有提示了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- 测试程序
/**
* SpringBoot单元测试
* 可以在测试期间类似编码一样进行自动注入等容器功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigApplicationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
- properties配置文件注入的写法
person.last-name=张三
person.age=18
person.birth=2017/12/15
person.boss=false
person.map.k1=v1
person.map.k2=14
person.list=a,b,c
person.dog.name=dog
person.dog.age=15
- 倘若出现了中文的乱码问题
![]()
配置文件注入时的对比
- @Value获取值和@ConfigurationProperties获取值比较
- @ConfigurationProperties: 批量注入配置文件中的属性
- 支持松散绑定语法
- 不支持SpEL表达式
- 支持JSR303数据校验
- 支持复杂类型的封装
- @Value: 一个一个指定注入
- 不支持松散绑定语法
- 支持SpeL表达式
- 不支持JSR303数据校验
- 不支持复杂类型的封装
- 松散绑定
- 如 lastName 和 last-name 和 last_name 同义
- SpEL表达式
/**
* <bean class="Person">
* <property name="lastName" value="${SpeL}"></property>
* </bean>
*/
${}内是表达式的值, 可以放在配置文件中.
@Value("${person.last-name}")
private String lastName;
- JSR303数据校验: 类上带 @Validated
@Component
@ConfigurationProperties(prefix = "person")
@Validated
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
@Email
private String lastName;
private Integer age;
}
- 这样lastName必须为email格式的数据, 否则将报错.
- 总结
- 如果我们只是在某个业务逻辑中获取下配置文件中的某项值, 使用@Value, 如
@RestController
public class HelloController {
@Value("${person.last-name}")
private String name;
@RequestMapping("/sayHello")
public String sayHello() {
return "Hello " + name;
}
}
- 如果我们专门编写javaBean来和配置文件进行映射, 则用@ConfigurationProperties
@PropertySource和@ImportSource
- @PropertySource: 加载指定的配置文件(不写的话会加载全局配置文件)
- value属性: 指定要加载的配置文件的位置
@Component
@PropertySource(value = "classpath:person.properties")
@ConfigurationProperties(prefix = "person")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> map;
private List<Object> list;
private Dog dog;
}
- @ImportResource: 导入Spring的配置文件, 让配置文件中的内容生效.
- SpringBoot里边没有Spring的配置文件(xxx.xml), 我们自己编写, 也不能自动识别; 想让Spring的配置文件生效, 就需要把@ImportResource标注在配置类上
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class MainType {
public static void main(String[] args) {
SpringApplication.run(MainType.class, args);
}
}
- 编写beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="top.binwenhome.service.HelloService"></bean>
</beans>
- SpringBoot推荐给容器添加组件的方式: 使用全注解的方式
- 不用加@ImportResource了
- 配置类@Configuration
- 使用@Bean给容器中添加组件
/**
* 指明这是一个配置类, 来替代Spring的配置文件
*/
@Configuration
public class MyAppConfig {
/**
* 将方法的返回值添加到容器中, 容器中这个组件默认id是方法名
*/
@Bean
public HelloService helloService() {
System.out.println("添加组件了");
return new HelloService();
}
}
- 测试程序
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigApplicationTests {
@Autowired
ApplicationContext ioc;
@Test
public void test() {
boolean b = ioc.containsBean("helloService");
System.out.println(b);
}
}
配置文件占位符
- 随机数
${random.value}, ${random.int}, ${random.long}
${random.int(10)}, ${random.int[100,1000]}
- 属性配置占位符
- 可以在配置文件中引用前面配置过的属性.
- 可以引用随机数
- ${xxx.xxx: 指定默认值}
person.last‐name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
Profile
- Profile是Spring对不同环境提供不同配置功能的支持, 可以通过激活指定参数等方式快速切换环境.
- 多profile文件形式
- 文件名格式: application-{profile}.properties/yml
#application.properties
server.port=8080
spring.profiles.active=dev #指定要用的环境
==================分界线===================
#application-dev.properties
server.port=8081
==================分界线===================
#application-product.properties
server.port=8082
- yml支持多文档块方式
server:
port: 8081
spring:
profiles:
active: prod #指定用哪个环境
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: product
- 激活指定profile
- 在配置文件中指定: spring.profiles.active=dev
- 命令行方式: --spring.profiles.active=dev
![]()
- 虚拟机参数: -Dspring.profiles.active=dev
![]()
配置文件加载位置
- springboot启动后会扫描以下位置的application.properties/yml文件作为springboot的默认配置文件.
- -file: ./config/
- -file: ./
- -classpath: /config/
- -classpath: /
- 优先级从高到低, 高优先级的配置会覆盖低优先级的配置, 并且是互补配置.
![]()
- 另外, 我们可以通过spring.config.location来改变默认的配置文件位置
- 项目打包好以后, 我们可以使用命令行参数的形式, 启动项目时来指定配置文件新位置, 同样是互补配置.
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties
外部配置的加载顺序
- springboot也可以从以下位置加载配置: 优先级从高到低, 高优先级覆盖低优先级, 互补配置.
- 命令行参数.
- 所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
- 多个配置用空格分开; --配置项=值
- 当然, 这样写比较复杂, 我们可以通过命令行的方式访问外部配置文件.
- jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件.
- jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件
- jar包内部的application.properties或application.yml(不带spring.profile)配置文件
- 当然, 实际上有17种加载来源, 其他的用的不多