配置文件位置
官方允许配置文件放在以下位置 ./
表示当前目录下的文件或文件夹 file
表示项目路径 config
表示建文件夹放配置件,无config的就直接建application.?
文件
file:./config
即项目路径下可以建一个config目录用于存放配置文件file:./
表示可以将配置文件直接放项目路径下classpath:/config
表示可以在类路径下创建一个config文件夹放配置文件,类路径即src/java。但是一般在同级的**resource**
下建config文件夹classpath:/
配置文件直接放类路径下 即项目默认在**resource**
目录下创建的配置
优先级
- 存在多个配置文件时,配置都会生效。如果存在冲突的配置,优先级高的生效
- 格式优先级:properties>yaml>yml (先加载的冲突配置会被后加载的覆盖)
-
多环境配置
profile
是spring对于不同环境提供不同配置的支持 ,可以通过激活不同环境版本实现快速切换环境
即通过使用不同的配置文件来激活不同的环境
当我们在主配置文件编写的时候,文件名可以是 **application-{profile}.properties/yml **
, 用来指定多个环境版本配置文件
例如:**application-test.properties**
代表测试环境配置**application-dev.properties**
代表开发环境配置
方法1-位置优先级
- (配置文件不同位置)利用配置文件的位置优先级进行覆盖当前配置
方法2-配置指定
- properties版
(配置文件同一位置)在一个文件夹中创建多个配置文件,此时优先级最高的是**application.properties**
,即优先级最高的是默认的配置文件 在该优先级最高的配置文件中指定使用其他配置文件
例如:在resource目录下存在**application.properties**
**application-test.properties**
**application-dev.properties**
这样三个文件,那么我们可以在默认配置文件application.properties中以如下配置指定使用其他配置文件**spring.profiles.active=profile**
如我们要使用dev环境,就**spring.profiles.active=dev**
- yaml版 ```yaml
server: port: 8081
选择要激活哪个环境
spring: profiles: active: prod #激活prod名称的环境
server: port: 8083 spring: profiles: dev #设置配置环境的名称
server: port: 8084 spring: profiles: prod #配置环境的名称
**---即表示创建一个新的环境配置,相当于properties里再创建一个新配置文件 **<br />**只有yaml里才可以多个环境写在一个文件里**<br />**但是配置庞大复杂时,还是建议分多个文件写**
<a name="DmGJf"></a>
# 配置文件使用简介
SpringBoot使用一个**全局**的配置文件 , 配置文件**名称固定(命名不仅仅是决定名称,文件后缀决定了配置的语法格式**<br />**yaml)**
- **必须以appliacation命名,其他名称无法识别**
**application.properties 默认命名 默认命名只是指默认后缀是properties,只是讲后缀可以修改,名称前缀不可以改**
- 语法结构 :`key=value` 如`server.port=8080`
**application.yml 官方推荐命名 后缀也可以是.yaml**
- 语法结构 :`key:空格 value` 如`server:port: 8080`
**转为xml: **`**<server><port>8080</port></server>**`现在很少转化去用了
**配置文件的作用 :修改SpringBoot自动配置的默认值 **如默认web服务器,web服务器默认端口 ...
<a name="QLJsS"></a>
# yaml优点
properties和yaml明显比xml简便。**为什么推荐yaml**而不是properties呢?<br />**因为yaml除了存储key-value,还能存对象。而properties只能存键值对.如**
<a name="laLLT"></a>
# yaml基础语法
说明:语法要求严格!
1. 空格不能省略
1. **以缩进来控制层级关系**,只要是左边对齐的一列数据都是同一个层级的。**缩进不当会产生歧义错误**
1. 属性和值的大小写都是十分敏感的。
1. **注释:还是**`**#...**`
1. 只要是`:或者-`后都要空格,空格可以不止一个
**对象语法 Map类型可看作对象 类类型即对象语法**
```yaml
student:
name: rao
age: 20
#行内写法
student: {name: rao,age: 20}
数组写法 List类型可看作数组
pets:
- cat
- dog
- pig
#行内写法
pets: [cat,dog,pig]
读取配置文件
@ConfigurationProperties 批量注入
**@ConfigurationProperties**
作用是将任意类型的配置文件注入实体类(默认是加载全局配置文件,只有一个配置文件时,则为全局 )- 注意是注入实体类,所以是将配置文件中的对象进行注入,对于单个属性注入不行
- 支持yaml,其他还不确定
- 貌似这种
ConfigurationProperties
方法必须有setter方法才能注入
原来我们是通过注解或者xml将配置文件中存储的实体类信息注入到实体类中。现在实体类信息存储在yaml中了
@Component //注册bean到容器中
@ConfigurationProperties(prefix = "person") //指定注入的配置文件中的对象
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
//一系列方法:有参无参构造、get、set方法、toString()方法 ...
}
- 这里不知道为什么不写无参数构造,有参数构造那里就报错 错误信息为
**could not autowire 没有找到?类型的beans**
- 可能跟spring 构造器自动装配 有关
@Component //注册bean到容器中 public class Dog { private String name; private Integer age; //有参无参构造、get、set方法、toString()方法 }
person: {name: qinjiang,age: 3,happy: false,birth: 2000/01/01} #这是birth对象的写法,见Date类 maps: {k1: v1,k2: v2} lists: [code,girl,music] dog: {name: 旺财,age: 1} name:rzd
可能出现的错误
写好后会有一个报错/警告(IDEA 提示,springboot配置注解处理器没有找到)。提升你进入一个网站。告诉你需要添加一个依赖。添加即可 依赖如下 ```xml
```java
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
@ConfigurationProperties进行校验
- 这种运用可以对配置文件注入进行限制,不正确的数据注入了对象,该对象被使用就会报错
my-profile:
name:Guide哥
email:koushuangbwcx@
publicclass ProfileProperties {
@NotEmpty
private String name;
@Email
@NotEmpty
private String email;
//配置文件中没有读取到的话就用默认值
private Boolean handsome = Boolean.TRUE;
}
@SpringBootApplication
@EnableConfigurationProperties(ProfileProperties.class)
publicclass ReadConfigPropertiesApplication implements InitializingBean {
privatefinal ProfileProperties profileProperties;
public ReadConfigPropertiesApplication(ProfileProperties profileProperties) {
this.profileProperties = profileProperties;
}
public static void main(String[] args) {
SpringApplication.run(ReadConfigPropertiesApplication.class, args);
}
@Override
public void afterPropertiesSet() {
System.out.println(profileProperties.toString());
}
}
@Value 单注入
@Value("${name}") String name
就这样实现了注入- 对于
yaml
和properties
都能用- 可以添加默认值
@Value("${name:rzd}")
当配置文件中name不存在时,使用默认值rzd - @value除了作用于字段,也可以作用于方法参数上,如
@Bean ZoneId createZoneId(@Value("${app.zone:Z}") String zoneId) { return ZoneId.of(zoneId); }
- 可以添加默认值
@value
除了读取配置文件注入字段,还可以读取一个bean的某个信息注入给字段。 ```java @Component public class SmtpConfig { @Value(“${smtp.host}”) private String host;@Value(“${smtp.port:25}”) private int port;
public String getHost() {
return host;
}
public int getPort() {
return port;
} }
//—————————————————————- @Component public class MailService { @Value(“#{smtpConfig.host}”) //表示从smtpConfig这个bean中读取host字段并注入,原理是调用get方法 private String smtpHost;
@Value("#{smtpConfig.port}")
private int smtpPort;
}
<a name="cFsLO"></a>
## @PropertySource() 读取配置文件
- 这是spring中的注解,不同于上面两种方式,**它的作用仅仅是读取配置文件,不会自动注入**。所以还需要配合`@Value`使用
```java
@Configuration
@ComponentScan //添加被扫描
@PropertySource("app.properties") // 表示读取classpath的app.properties
public class AppConfig {
@Value("${app.zone:Z}") //注入
String zoneId;
@Bean
ZoneId createZoneId() {
return ZoneId.of(zoneId);
}
}
或者
@Bean
ZoneId createZoneId(@Value("${app.zone:Z}") String zoneId) {
return ZoneId.of(zoneId);
}
可能遇到的读取value都是null的坑
见链接
Environment
@Autowired private Environment environment; @RequestMapping("/index") public String index(String hiName) { // 读取配置文件 String appName = environment.getProperty("app.name"); return "Hello, " + hiName + " |@" + appName; }
Se中读取classpath资源
try (InputStream input = getClass().getResourceAsStream("/default.properties")) { if (input != null) {...} //文件不存在返回空,不会报错 }
注入方式对比
1.@ConfiguretionProperties:只需要编写一次即可。而@Value需要每个字段都添加
2、松散绑定:这个什么意思呢? 比如我的yml中写的last-name,这个和lastName是一样的, - 后面跟着的字母默认是大写的。这就是松散绑定。可以测试一下
3、JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性
4、复杂类型封装,yml中可以封装对象 , 使用value就不支持
适合需要获取字段多的项目,可以专门编写一个JavaBean来获取值,这时使用该配置注解好用非常多
配置文件占位符
- 占位符yaml/properties都适用
- 配置文件还可以编写使用些系统功能
- 还可以yaml中定义变量,然后引用
${}
还可以读取jvm参数,如读取java命令
执行时传入的参数**@?@**
可以引用同项目的pom文件里的标签值,?为标签名,该标签必须为最小一级标签,即标签里没有其他标签(特殊标签除外,如profileActive
)person: name: qinjiang${random.uuid} # 随机uuid age: ${random.int} # 随机int happy: false birth: 2000/01/01 maps: {k1: v1,k2: v2} lists: - code - girl - music dog: name: ${person.hello:other}_旺财 age: 1
mytest: domainName: https://www.jb51.net defaultHead: ${mytest.domainName}/head.jpeg
redis: #数据库索引 database: ${REDIS_DB:0} //读取系统级参数REDIS_DB,未读取到就使用默认值0 host: ${REDIS_HOST:127.0.0.1} port: ${REDIS_PORT:6379} password: ${REDIS_PWD:} #连接超时时间 timeout: 6000 java -jar -DREDIS_HOST=172.16.0.36 -DREDIS_DB=2 xxx.jar #貌似追加参数需要额外添加 -D
@PropertySource指定配置文件
只支持
properties
文件配置文件中指定的默认配置文件是全局配置,而该注解是局部指定
//再以上基础上再新建一个properties文件,此时要指定配置文件。使用@PropertySource @PropertySource(value = "classpath:person.properties") @Component //注册beanpublic class Person { @Value("${person.name}") private String name; ...... }
使用properties时写中文可能会出现乱码,需要额外到设置里搜索properties然后设置下编码为utf-8
配置详细
配置应用服务器访问端口
server.port=8888
修改项目访问路径
server.servlet.context-path=/springboot-demo
server: port: 8080 servlet: context-path: /demo
读取配置文件
Resouce法
Spring提供了一个org.springframework.core.io.Resource可以用于读取配置文件( 注意不是javax.annotation.Resource),它可以像String、int一样使用@Value注入
- 路径一般有两种写法:
@Value("classpath:/logo.txt")
classpath一般指src/main/resources
目录@Value("file:/path/to/logo.txt")
@PostConstruct
:该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行- 一般用于需要在初始化bean前执行某些操作
Resource.getInputStream()就可以获取到输入流
@Component public class AppService { @Value("classpath:/logo.txt") private Resource resource; private String logo; @PostConstruct public void init() throws IOException { //此init()方法非jdk中的那个init,仅仅表明“初始化之意” try (var reader = new BufferedReader( new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) { this.logo = reader.lines().collect(Collectors.joining("\n")); } } }
注解法
@PropertySource
自动读取配置文件 ,一般使用properties
格式的配置文件。该方法读取到的配置会用于ioc容器全局,任何bean都可以读取并引用properties
以键值对的方式存储信息,使用.
可以直接获取子键- 使用
:
获取值
- 使用
@Value
获取配置信息并注入- “${app.zone}”表示读取key为app.zone的value,如果key不存在,启动将报错;
- “${app.zone:Z}”表示读取key为app.zone的value,但如果key不存在,就使用默认值Z。
- @Value还可以注入到方法参数中
@Value
还可以使用#{}
从bean中读取成员属性。会调用成员属性对应的get方法#{stmpConfig.host}
stmpConfig是bean的名称,host是属性@Bean
ZoneId createZoneId(@Value(“${app.zone:Z}”) String zoneId) {
return ZoneId.of(zoneId);
}
- 使用一个独立的JavaBean持有所有属性,然后在其他Bean中以#{bean.property}注入的好处是,多个Bean都可以引用同一个Bean的某个属性。例如,如果SmtpConfig决定从数据库中读取相关配置项,那么MailService注入的@Value(“#{smtpConfig.host}”)仍然可以不修改正常运行。