springboot配置文件

项目地址:https://github.com/snjl/springboot.config_test.git

Spring Boot使用了一个全局的配置文件application.properties,放在src/main/resources目录下或者类路径的/config下。Sping Boot的全局配置文件的作用是对一些默认配置的配置值进行修改。

自定义属性

application.properties提供自定义属性的支持,这样我们就可以把一些常量配置在这里:

1
2
com.example.myproject.customer.id = 001
com.example.myproject.customer.name = jl

在类中引入可以用@Value(“${….}”)的注解形式,也可以如下引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.myproject.domain;

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

@Component
@ConfigurationProperties(prefix = "com.example.myproject.customer")
public class Customer {
private String id;
private String name;

//getter,setter,toString
}

需要在springboot入口类上加上@EnableConfigurationProperties({Customer.class})注解,指明使用了配置文件的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example.myproject;

import com.example.myproject.domain.Customer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties({Customer.class})

public class MyprojectApplication {

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

参数间引用

在application.properties中的各个参数之间也可以直接引用来使用,就像下面的设置:

1
2
3
com.example.myproject.customer.id = 001
com.example.myproject.customer.name = jl
com.example.myproject.customer.title = 序号${com.example.myproject.customer.id},姓名${com.example.myproject.customer.name}

运行测试,如果出现中文乱码,则进行以下步骤:

java开发工具Idea下解决方案:

File -> Settings -> Editor -> File Encodings

将Properties Files (*.properties)下的Default encoding for properties files设置为UTF-8,将Transparent native-to-ascii conversion前的勾选上。

注意:做了上面操作后,一定要重新创建application.properties,才有效。

输出效果:

1
Customer{id='001', name='jl', title='序号001,姓名jl'}

使用自定义配置文件

有时候我们不希望把所有配置都放在application.properties里面,这时候我们可以另外定义一个,这里我明取名为test.properties,路径跟也放在src/main/resources下面。

1
2
3
com.example.myproject.customer2.id = 0011
com.example.myproject.customer2.name = jlsdf
com.example.myproject.customer2.title = 序号${com.example.myproject.customer2.id},姓名${com.example.myproject.customer2.name}

注意,这里的自定义配置名字不能与之前相同,不然会读取不到(踩坑贼开心)。

我们新建一个bean类,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example.myproject.domain;

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

@Component
@PropertySource(value = "classpath:test.properties")
@ConfigurationProperties(prefix = "com.example.myproject.customer2")
public class Customer2 {
private String id;
private String name;
private String title;
//getter,setter,toString

}

其中使用@PropertySource(value = “classpath:test.properties”)指向了properties文件,使用@ConfigurationProperties(prefix = “com.example.myproject.customer2”)指向了前缀。

在CustomerService和CustomerController中增加函数与调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CustomerService.java
public Customer2 getCustomer2(){
return customer2;
}

CustomerController.java

@RequestMapping("/customer")
public String customer(ModelMap map) {
// Customer customer = customerService.getCustomer();
Customer2 customer = customerService.getCustomer2();
map.addAttribute("customer", customer);
return "index";
}

也可以在Test中进行输出测试。

注:出现错误Spring Boot Configuration Annotion Processor not found in classpath。

在pom.xml中引入:

1
2
3
4
5
<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-configuration-processor </artifactId>
<optional> true </optional>
</dependency>

重启idea,会出现Re-run Spring Boot Configuration Annotation Processor to update generated metadata,这个问题可以忽略,不影响代码执行。只是提醒用户,进行必要的重新编译。

随机值配置

配置文件中${random} 可以用来生成各种不同类型的随机值,从而简化了代码生成的麻烦,例如 生成 int 值、long 值或者 string 字符串。

range.properties写入:

1
2
3
4
5
6
range.secret=${random.value}
range.number=${random.int}
range.bignumber=${random.long}
range.uuid=${random.uuid}
range.number.less.than.ten=${random.int(10)}
range.number.in.range=${random.int[1024,65536]}

使用java接收,Range.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.myproject.domain;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@PropertySource(value = "classpath:range.properties")
@ConfigurationProperties(prefix = "range")
public class Range {
private String secret;
private int number;
private long bignumber;
private String uuid;
@Value("${range.number.less.than.ten}")
private int lessThanTen;
@Value("${range.number.in.range}")
private int rangeNumber;

//setter,getter,toString
}

配置相应的service和controller。
显示效果如下:
image

注意,不重启springboot应用,这些值不会改变。

外部配置-命令行参数配置

Spring Boot是基于jar包运行的,打成jar包的程序可以直接通过下面命令运行:

1
java -jar xx.jar

可以以下命令修改tomcat端口号:

1
java -jar xx.jar --server.port=9090

可以看出,命令行中连续的两个减号–就是对application.properties中的属性值进行赋值的标识。

所以java -jar xx.jar –server.port=9090等价于在application.properties中添加属性server.port=9090。

如果怕命令行有风险,可以使用SpringApplication.setAddCommandLineProperties(false)禁用它。

实际上,Spring Boot应用程序有多种设置途径,Spring Boot能从多重属性源获得属性,包括如下几种:

  • 根目录下的开发工具全局设置属性(当开发工具激活时为~/.spring-boot-devtools.properties)。
  • 测试中的@TestPropertySource注解。
  • 测试中的@SpringBootTest#properties注解特性。
  • 命令行参数
  • SPRING_APPLICATION_JSON中的属性(环境变量或系统属性中的内联JSON嵌入)。
  • ServletConfig初始化参数。
  • ServletContext初始化参数。
  • java:comp/env里的JNDI属性
  • JVM系统属性
  • 操作系统环境变量
  • 随机生成的带random.* 前缀的属性(在设置其他属性时,可以应用他们,比如${random.long})
  • 应用程序以外的application.properties或者appliaction.yml文件
  • 打包在应用程序内的application.properties或者appliaction.yml文件
  • 通过@PropertySource标注的属性源
  • 默认属性(通过SpringApplication.setDefaultProperties指定).

这里列表按组优先级排序,也就是说,任何在高优先级属性源里设置的属性都会覆盖低优先级的相同属性,列如我们上面提到的命令行属性就覆盖了application.properties的属性。

配置文件的优先级

application.properties和application.yml文件可以放在一下四个位置:

  • 外置,在相对于应用程序运行目录的/congfig子目录里。
  • 外置,在应用程序运行的目录里
  • 内置,在config包内
  • 内置,在Classpath根目录

同样,这个列表按照优先级排序,也就是说,src/main/resources/config下application.properties覆盖src/main/resources下application.properties中相同的属性,如图:

image

此外,如果你在相同优先级位置同时有application.properties和application.yml,那么application.yml里面的属性就会覆盖application.properties里的属性。

当应用程序需要部署到不同运行环境时,一些配置细节通常会有所不同,最简单的比如日志,生产日志会将日志级别设置为WARN或更高级别,并将日志写入日志文件,而开发的时候需要日志级别为DEBUG,日志输出到控制台即可。

如果按照以前的做法,就是每次发布的时候替换掉配置文件,这样太麻烦了,Spring Boot的Profile就给我们提供了解决方案,命令带上参数就搞定。

  • application-dev.properties:开发环境
  • application-prod.properties:生产环境

想要使用对应的环境,只需要在application.properties中使用spring.profiles.active属性来设置,值对应上面提到的{profile},这里就是指dev、prod这2个。

当然你也可以用命令行启动的时候带上参数:

1
java -jar xxx.jar --spring.profiles.active=dev

给不同的环境添加不同的端口属性server.port,然后根据指定不同的spring.profiles.active来切换使用。

除了可以用profile的配置文件来分区配置我们的环境变量,在代码里,还可以直接用@Profile注解来进行配置,例如数据库配置,这里我们先定义一个接口:

1
public  interface DBConnector { public  void  configure(); }

定义2个类实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
@Profile("devDb")
public class DevDBConnector implements DBConnector {

@Override
public void configure() {
System.out.println("devdb");

}
}


@Component
@Profile("testDb")
public class TestDBConnector implements DBConnector {
@Override
public void configure() {
System.out.println("testdb");
}
}

在application.properties配置,激活其中一个类:

1
spring.profiles.active=testDb

PS:这里一定要写对,如果写成testdb就会报错。

因为这里用的是thyemleaf模版,使用@RestController注解,应该是作为接口,所以可以用postman做测试,可以看到输出了testdb。

除了spring.profiles.active来激活一个或者多个profile之外,还可以用spring.profiles.include来叠加profile

1
2
spring.profiles.active: testdb  
spring.profiles.include: proddb,prodmq
-------------本文结束 感谢您的阅读-------------