读取外部配置文件_SpringBoot外部配置、优先级及配置详解

一、外部配置及优先级

SpringBoot的外部配置属性值官方给出了很多种方式,以便可以在不同的环境中使用相同的代码。

其使用了非常特别的PropertySource命令,旨在允许合理的覆盖值。当然,如果属性值不同,则这些配置方式中的属性值都会被加载;按照从高到低的排序如下:

(1)、在您的HOME目录设置的Devtools全局属性(~/.spring-boot-devtools.properties)。

(2)、单元测试中的 @TestPropertySource 注解。

(3)、单元测试中的 @SpringBootTest#properties 注解属性

(4)、命令行参数。

SPRING_APPLICATION_JSON=‘{"foo":{"bar":"spam"}}‘ java -jar myapp.jar

(6)、ServletConfig 初始化参数。

(7)、ServletContext 初始化参数。

(8)、来自 java:comp/env 的JNDI属性。

(9)、Java系统属性(System.getProperties())。

(10)、操作系统环境变量。

(11)、RandomValuePropertySource,只有随机的属性 random.* 中。

(12)、jar包外面的 Profile-specific application properties (application- {profile} .properties和YAML)

(13)、jar包内的 Profile-specific application properties (application-{profile}.properties和YAML)

(14)、jar包外的应用属性文件(application.properties和YAML)。

(15)、jar包内的应用属性文件(application.properties和YAML)。

(16)、在@Configuration上的@PropertySource注解。

(17)、默认属性(使用SpringApplication.setDefaultProperties设置)。

在具体的讲解这些配置的时候我们先来做一些准备工作,

(1)、书写一个Controller

@RestController
@Slf4j
public class MyController {@Value("${name}")private String name;@GetMapping("/getDefaultProperties")public String getDefaultProperties() {return name;}

1、使用SpringApplication.setDefaultProperties设置默认属性

在应用程序主类main方法中在调用run方法之前,设置默认值

@SpringBootApplication
public class Application {public static void main(String[] args) {//SpringApplication.run(Application.class, args);Properties properties = new Properties();properties.setProperty("name", "(17)、默认属性(使用SpringApplication.setDefaultProperties设置)");SpringApplication application = new SpringApplication(Application.class);application.setDefaultProperties(properties);application.run(args);//new SpringApplicationBuilder()// .sources(Application.class)// .bannerMode(Banner.Mode.OFF)// .properties(properties)// .run(args);}
}

此时你访问http://localhost:8080/getDefaultProperties在页面上输出的内容为

3a046447c48aa502c425d694deb73f92.png

备注:如果你想把你项目中的所有的配置放到配置中心Apollo的话,这种方式也是可以很方法的实现的。2、在@Configuration上的@PropertySource注解

@SpringBootApplication
@PropertySource(value = {"classpath:test/propertySource.properties"}, encoding = "UTF-8")
public class Application {public static void main(String[] args) {Properties properties = new Properties();properties.setProperty("name", "(17)、默认属性(使用SpringApplication.setDefaultProperties设置)");SpringApplication application = new SpringApplication(Application.class);application.setDefaultProperties(properties);application.run(args);}
}

d72e14b5b2401b542d573c46cbddcdff.png

3、jar包内的应用属性文件(即默认的配置文件)

987dde616e6a65fd0b0ec3a472098e5d.png
name=(15)、jar包内的应用属性文件

705a5e8bb727e29136455722d797eaf6.png

4、jar包外的应用属性文件

(1)、将你的应用程序打包成可运行的jar,在jar包的同级目录中放置一个application.properties文件,里面的内容如下:

name=(14)、jar包外的应用属性文件

8ac526e8053f2b34c21d58270c43b89e.png

5、jar包内的 Profile-specific application properties

新建application-test.properties文件,里面的内容如下

name=(13)、jar包内的 Profile-specific application properties

设置启动参数

e77ca6a3e89b04863e89ce7d095fd6c8.png

访问链接得到下图结果

7310eb9397dc094fc86df4551811896a.png

6、jar包外面的 Profile-specific application properties

(1)、将你的应用程序打包成可运行的jar,在jar包的同级目录中放置一个application-test.properties文件,里面的内容如下:

name=(14)、jar包外的应用属性文件

(2)、java -jar -Dspring.profiles.active=test ***.jar

cbc6cb00b5d721e37bfce20ed638a563.png

springboot读取外部和内部配置文件的方法,如下优先级:

第一种是在执行命令的目录下建config文件夹。(在jar包的同一目录下建config文件夹,执行命令需要在jar包目录下才行),然后把配置文件放到这个文件夹下。

第二种是直接把配置文件放到jar包的同级目录。

第三种在classpath下建一个config文件夹,然后把配置文件放进去。

第四种是在classpath下直接放配置文件。

springboot默认是优先读取它本身同级目录下的一个config/application.properties 文件的。

在src/main/resources 文件夹下创建的application.properties 文件的优先级是最低的

7、命令行属性

默认情况下,SpringApplication将任何命令行选项参数(以'-- '开头,例如--server.port=9000)转换为属性,并将其添加到Spring环境中。 如上所述,命令行属性始终优先于其他属性来源。

b39a3bc13d46196e2a22456a78bdc715.png

如果不希望将命令行属性添加到环境中,可以使用SpringApplication.setAddCommandLineProperties(false)禁用它们。

二、properties文件中的占位符

application.properties中的值在使用时通过已有的环境进行过滤,以便可以引用之前已经定义好的值

app.name=MyApp
app.description=${app.name} is a Spring Boot application

三、使用YAML替代 Properties

YAML是JSON的超集,因此这是分层配置数据一种非常方便的格式,。 每当您的类路径中都有SnakeYAML库时,SpringApplication类将自动支持YAML作为 properties 的替代方法。

如果您使用“Starters”,SnakeYAML将通过spring-boot-starter自动提供。

1、加载yaml

Spring Framework提供了两个方便的类,可用于加载YAML文档。 YamlPropertiesFactoryBean将YAML作为Properties加载,YamlMapFactoryBean将YAML作为Map加载。

例如下面这个YAML文档

environments:dev:url: http://dev.bar.comname: Developer Setupprod:url: http://foo.bar.comname: My Cool App

将转换为属性

environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App

YAML列表表示为具有[index] dereferencers的属性键,例如YAML:

my:servers:- dev.bar.com- foo.bar.com

将转化为属性:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

2、通过@ConfigurationProperties将配置绑定到Bean

(1)、配置bean的书写

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "my")
public class MyServerProperties {private String name;private List<String> servers = new ArrayList<>();
}

(2)、application.yaml文件书写

my:servers:- dev.bar.com- foo.bar.comname: myName

3、YAML的缺点

YAML文件无法通过@PropertySource注解加载。 因此,在需要以这种方式加载值的情况下,需要使用properties文件。

四、类型安全的配置属性

使用@Value(“${property}”)注释来注入配置属性有时可能很麻烦(类型常规配置),特别是如果您正在使用多个层次结构的属性或数据时。 Spring Boot提供了一种处理属性的替代方法,允许强类型Bean管理并验证应用程序的配置。

(1)、Bean的定义

/*** 类型安全的配置属性** @Author YUBIN* @create 2019-06-16*/
@ConfigurationProperties("foo")
public class FooProperties {private boolean enabled;private InetAddress remoteAddress;private final Security security = new Security();public boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}public InetAddress getRemoteAddress() {return remoteAddress;}public void setRemoteAddress(InetAddress remoteAddress) {this.remoteAddress = remoteAddress;}public Security getSecurity() {return security;}public static class Security {private String username;private String password;private List<String> roles = new ArrayList<>(Collections.singleton("USER"));public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public List<String> getRoles() {return roles;}public void setRoles(List<String> roles) {this.roles = roles;}}
}

(2)、YAML文件中的配置

foo:remote-address: 192.168.1.1security:username: fooroles:- USER- ADMIN

(3)、应用程序主类上加上必要的注解

@EnableConfigurationProperties({FooProperties.class})
public class Application {

这样在程序中就可以使用@Autowired的形式注入配置类了

@RestController
@Slf4j
public class MyController {@Autowiredprivate FooProperties fooProperties;@GetMapping("/getFooProperties")public String getFooProperties() {return JSON.toJSONString(fooProperties);}

五、第三方配置

现在我们在构建一个名为"yubin-common",类型为jar的maven项目

1、书写一个配置类

@ConfigurationProperties(prefix = "bar")
public class BarComponent {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

在之前的项目中引入此项目的依赖;这时如果在之前的项目中需要使用BarComponent这个属性类的话,则需要通过@EnableConfigurationProperties(BarComponent.class)这个注解来引入类,但是这样做是否合理呢?一个项目这么做,当有其它的项目也需要这个类的话是不是也要这么做呢?

public class BarComponent {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}
@Configuration
public class ConfigurationBean {@Bean@ConfigurationProperties(prefix = "bar")public BarComponent barComponent() {return new BarComponent();}
}

2、小结

@ConfigurationProperties导入外部属性填充到这个Bean的实例,有三种方式:

(1)、@ConfigurationProperties + @Component 注解到bean定义类上

(2)、@ConfigurationProperties + @Bean注解在配置类的bean定义方法上

(3)、@ConfigurationProperties注解到普通类然后通过@EnableConfigurationProperties定义为bean

六、宽松的绑定

Spring Boot使用一些宽松的规则将环境属性绑定到@ConfigurationProperties bean,因此不需要在Environment属性名称和bean属性名称之间进行完全匹配。 常用的例子是这样有用的:虚分离(例如上下文路径绑定到contextPath)和大写(例如PORT绑定到端口)环境属性。

配置bean

/*** 属性bean宽松绑定演示** @Author YUBIN* @create 2019-06-16*/
@Component
@ConfigurationProperties(prefix = "person")
@Getter
@Setter
public class OwnerProperties {private String firstName; //person.firstName 标准骆峰命名法。private String secondName; // person.second-name 虚线符号,推荐用于.properties和.yml文件。private String thirdName; // person.third_name 下划线符号,用于.properties和.yml文件的替代格式。private String fourName; // PERSON_FOUR_NAME 大写格式 推荐使用系统环境变量时。
}

测试类

@RestController
@Slf4j
public class MyController {@Autowiredprivate OwnerProperties ownerProperties;@GetMapping("/getOwnerProperties")public String getOwnerProperties() {return JSON.toJSONString(ownerProperties);}
}

8c262e4a76c8e79e0d45a2b784f7f974.png

七、@ConfigurationProperties验证

如果你需要验证@ConfigurationProperties类。 您可以直接在配置类上使用JSR-303 javax.validation约束注解 @Validated。 只需确保您的类路径中符合JSR-303实现,然后在您的字段中添加约束注释:

@ConfigurationProperties("foo")
@Validated
public class FooProperties {private boolean enabled;@NotNullprivate InetAddress remoteAddress;
// ... getters and setters

为了验证嵌套属性的值,您必须将关联字段注释为@Valid以触发其验证。 例如,基于上述FooProperties示例:

@ConfigurationProperties(prefix="connection")
@Validated
public class FooProperties {@NotNullprivate InetAddress remoteAddress;@Validprivate final Security security = new Security();// ... getters and setterspublic static class Security {@NotEmptypublic String username;// ... getters and setters}
}

@ConfigurationProperties 对比 @Value

@Value是核心容器功能,它不提供与类型安全配置属性相同的功能。 下表总结了@ConfigurationProperties和@Value支持的功能:

ce8a6af3bdfca4d4d20b9e8193c9d881.png

八、配置文件Profiles

1、代码层面区分环境

Spring 配置文件提供了将应用程序配置隔离的方法,使其仅在某些环境中可用。 任何@Component或@Configuration都可以使用@Profile进行标记,以限制其在什么时候加载:

(1)、测试环境

@Service
@Profile({"test"})
public class TestProfileServiceImpl implements ProfileService {@Overridepublic String getEnvironment() {return "test环境";}
}

(2)、dev环境

@Service
@Profile({"dev"})
public class DevProfileServiceImpl implements ProfileService {@Value("${spring.profiles.active}")private String profileActive;@Overridepublic String getEnvironment() {return "dev环境";}
}

(3)、测试类

@RestController
@Slf4j
public class MyController {@Autowiredprivate ProfileService profileService;@GetMapping("/getProfileService")public String getProfileService() {return profileService.getEnvironment();}
}

当设置启动参数为 spring.profiles.active=dev时,页面展示效果:

a22ff355319eaf94d40dda0cc7040a99.png

image.png

当设置启动参数为 spring.profiles.active=test时,页面展示效果:

8849ce342677c0b1e03143adae26f590.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/470098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jquery 禁用浏览器的 后退和前进按钮

使用js,Jquery 禁用浏览器的back 和 next 按钮&#xff1a; 有时为了防治用户乱了访问顺序&#xff0c;不得不禁掉浏览器的前进后退按钮。 jQuery(document).ready(function () {if (window.history && window.history.pushState) {$(window).on(popstate, function ()…

JS数据结构与算法——冒泡排序(把大的数字依次往后放)

一、图解排序过程 注意&#xff1a;比较次数和交换次数之所以不一致&#xff0c;是因为&#xff1a;比较了并不一定就需要交换两个数字的位置&#xff0c;比如比较 1 和 2两个数字&#xff0c;由于 后者本身就比前者大&#xff0c;所以不需要交换两者的位置。 二、代码实现 三…

手机长曝光怎么设置_摄影教程丨手机如何拍摄长曝光照片,流光快门,星空银河搞起来!...

微信搜一搜定格取景框长曝光摄影可以拍摄出一些很酷的照片。这是一种非常灵活的摄影技术。它可以用来拍摄城市夜景&#xff0c;记录光绘&#xff0c;也可以拍摄水景片。甚至可以拍摄银河或捕捉星轨。其实长曝光不仅仅适合专业摄影师&#xff01;任何人都可以用手机进行慢门拍摄…

JS数据结构与算法——选择排序(把小的数字依次往前放)

一、图解排序过程 注意&#xff1a;选择排序一样是需要进行两两的比较&#xff0c;但比较过程中不进行交换&#xff0c;只有比较完成后&#xff0c;找到最小的那个数&#xff0c;才会进行交换&#xff0c;把它放到最前面。 二、代码实现 三、完整代码 <!DOCTYPE html> &…

插入模板_WordPress在文章列表和内容页插入广告

本文已同步到专业技术网站 www.sufaith.com, 该网站专注于前后端开发技术与经验分享, 包含Web开发、Nodejs、Python、Linux、IT资讯等板块.一、在文章列表插入广告文章列表模板 包括以下几个类型以及对应的主体文件:首页模板 (index.php)搜索结果页 (search.php)文章归档 (arch…

JS数据结构与算法——插入排序

一、图解排序过程 二、代码实现 三、完整代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><script>// 创建列表类function ArrayList() {//…

cad完全卸载教程_CAD室内设计中厨房布置实例

▲ 点击“CAD教学”&#xff0c;获取海量学习资料和免费教程本文介绍CAD室内设计中厨房布置方法&#xff1a;1、如下图是把另一边墙砌好&#xff0c;因为不砌的话门太大的话不好。在煮菜的烟容易在烟到不胜客厅里。2、在用矩形画宽为40长为800的玻璃门。3、在把厨房的台画出来&…

CSS布局(圣杯布局、双飞翼布局、水平垂直居中)

一、圣杯布局 要求&#xff1a;三列布局&#xff1b;中间主体内容前置&#xff0c;且宽度自适应&#xff1b;两边内容定宽 好处&#xff1a;重要的内容放在文档流前面可以优先渲染 原理&#xff1a;利用相对定位、浮动、负边距布局&#xff0c;而不添加额外标签 <!DOCTYPE …

cad怎么设置线的粗细_CAD软件中怎么设置CAD线宽?

在使用CAD软件绘制CAD图纸的过程中&#xff0c;不同线宽的用处是不同的。在机械制图中&#xff0c;零部件的外轮廓就是用粗实线&#xff0c;图形内部的剖开线使用细实线。一般情况下&#xff0c;都是在绘制图形过程中先设置好图形的线宽对象&#xff0c;但也有些需要在后面的绘…

检测范围_论文检测系统的检测范围有哪些

为了能够让研究人员&#xff0c;甚至一些专业的学术专家在进行论文创作的时候&#xff0c;端正自己的学术态度&#xff0c;很多人都会要求他们在提交甚至是发表论文之前&#xff0c;附上自己的查重证明&#xff0c;只有查重率低于一定程度时&#xff0c;提交的论文才是合格的。…

2学习率调整_学习率衰减

之前我们的优化&#xff0c;主要是聚焦于对梯度下降运动方向的调整&#xff0c;而在参数迭代更新的过程中&#xff0c;除了梯度&#xff0c;还有一个重要的参数是学习率α&#xff0c;对于学习率的调整也是优化的一个重要方面。01—学习率衰减首先我们以一个例子&#xff0c;来…

mysql 用户管理表_Mysql—用户表详解(mysql.user)

MySQL数据库Mysql—用户表详解(mysql.user)MySQL是一个多用户管理的数据库&#xff0c;可以为不同用户分配不同的权限&#xff0c;分为root用户和普通用户&#xff0c;root用户为超级管理员&#xff0c;拥有所有权限&#xff0c;而普通用户拥有指定的权限。MySQL是通过权限表来…

Orchard商城模块(Commerce)设计与后台部分

前言&#xff1a;使用CMS开发网站为目标&#xff0c;编写一个扩展性比较好的商城模块。 首先是整体流程图&#xff0c;大概介绍功能与设计。 接下来我们逐个模块功能介绍。 一。商品管理模块 商品模块中可发布需要在线售卖的商品 (套餐商品) 1.1 添加一个商品 1. 商品正常价&…

mysql数据库架构_MySQL数据库之互联网常用架构方案

一、数据库架构原则高可用高性能可扩展一致性二、常见的架构方案方案一&#xff1a;主备架构&#xff0c;只有主库提供读写服务&#xff0c;备库冗余作故障转移用jdbc:mysql://vip:3306/xxdb高可用分析&#xff1a;高可用&#xff0c;主库挂了&#xff0c;keepalive(只是一种工…

laravel方法汇总详解

1.whereRaw() 用原生的SQL语句来查询&#xff0c;whereRaw(select * from user) 就和 User::all()方法是一样的效果 2.whereBetween() 查询时间格式 whereBetween(problem_date, [2016-10-05 19:00:00, 2016-10-05 20:35:10]) 这种可以查到&#xff0c;时间格式类似这种, 查询日…

输入输出优化

被各种变态的出题者出的数据坑到了这里/sad 1 int read() 2 { 3 int num0; char chgetchar(); 4 while(ch<0&&ch>9) chgetchar(); //过滤前面非数字字符 5 while(ch>0&&ch<9) {num*10;numch-0;chgetchar();} 6 return num…

mysql整数索引没用到_MYSQL 索引无效和索引有效的详细介绍

1、WHERE字句的查询条件里有不等于号(WHERE column!...)&#xff0c;MYSQL将无法使用索引2、类似地&#xff0c;如果WHERE字句的查询条件里使用了函数(如&#xff1a;WHERE DAY(column)...)&#xff0c;MYSQL将无法使用索引3、在JOIN操作中(需要从多个数据表提取数据时)&#x…

如何参与一个GitHub开源项目

Github作为开源项目的著名托管地&#xff0c;可谓无人不知&#xff0c;越来越多的个人和公司纷纷加入到Github的大家族里来&#xff0c;为开源尽一份绵薄之力。对于个人来讲&#xff0c;你把自己的项目托管到Github上并不表示你参与了Github开源项目&#xff0c;只能说你开源了…

mysql数据库的多实例_MySQL数据库多实例应用实战 - 橙子柠檬's Blog

本文采用的是/data目录作为mysql多实例总的根目录&#xff0c;然后规划不同 的MySQL实例端口号来作为/data下面的二级目录&#xff0c;不同的端口号就是不同实例目录&#xff0c;以区别不同的实例&#xff0c;二级目录下包含mysql数据文件&#xff0c;配置文件以及启动文件的目…

微信企业号开发[二]——获取用户信息

注&#xff1a;文中绿色部分为摘自微信官方文档 在《微信企业号开发[一]——创建应用》介绍了如何创建应用&#xff0c;但是当用户点击应用跳转到我们设定的URL时&#xff0c;其实并没有带上用户的任何信息&#xff0c;为了获取用户信息&#xff0c;我们需要借助微信提供的OAut…