所谓Profile,就是一组配置环境,各种程序组件的合集。

实际开发中,经常要在不同的环境间切换,比如,开发时应用的是开发场的部署环境;测试时,用的是测试场的部署环境;上线时,用的是产品场的部署环境。传统做法是手动更改配置信息,但实际项目中配置信息比较多,这样做起来很麻烦,还容易出错,而Profile就是来解决这个问题的。

每个Profile都包含一组配置文件和程序组件等,对应有一个部署环境。只要为每个环境提供对应的Profile,当需要切换不同的部署环境时,只要切换到对应的Profile即可。

配置和切换Profile

声明程序组件和配置文件的Profile有以下方式:

  1. 使用@Profile注解修饰@Component、@Configuration、@ConfigurationProperties等注解修饰的类,这限制了这些类仅对特定的Profile有效
  2. 通过配置文件名限制Profile。比如application-dev.properties(或application-dev.yml)文件仅对dev Profile有效。application-test.properties(或application-test.yml)文件仅对test Profile有效。
  3. 在配置文件中使用特定语法限制某些属性对特定的Profile有效。这种特殊的配置文件称为“多Profile配置文件”。

对于@ConfigurationProperties类的必要说明:

  1. 如果@ConfigurationProperties类是通过@EnableConfigurationProperties注解来启用的,则需要在@EnableConfigurationProperties注解所在的@Configuration类上使用@Profile注解。
  2. 如果@ConfigurationProperties类是通过@ConfigurationPropertiesScan注解(扫描方式)来启用的,则需要在@ConfigurationProperties类本身上使用@Profile注解。

代码示例:\resources\application-default.yml

spring:
datasource:
# 指定连接deft数据库
url: jdbc:mysql://localhost:3306/deft?serverTimezone=UTC
username: root
password: 32147

代码示例:\resources\application-dev.yml

spring:
datasource:
# 指定连接dev数据库
url: jdbc:mysql://localhost:3306/dev?serverTimezone=UTC
username: root
password: 32147

代码示例:\resources\application-test.yml

spring:
datasource:
# 指定连接test数据库
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
username: root
password: 32147

代码示例:\resources\application-prod.yml

spring:
datasource:
# 指定连接prod数据库
url: jdbc:mysql://localhost:3306/prod?serverTimezone=UTC
username: root
password: 32147

控制器类:

@RestController
// 指定当前控制器的Profile为"default"
@Profile("default")
public class DefaultController
{
private final DataSource dataSource;
@Autowired
public DefaultController(DataSource dataSource)
{
this.dataSource = dataSource;
}
@GetMapping
public Map<String, String> hello() throws SQLException
{
return Map.of("class", "默认场的控制器","数据库",
dataSource.getConnection().getCatalog());
}
}

在运行应用时,可通过spring.profiles.active属性指定激活哪个Profile,主要使用如下方式来指定:

  1. 通过application.properties(或application.yml)指定
  2. 使用操作系统的SPRING_PROFILES_ACTIVE环境变量指定
  3. 使用系统属性指定
  4. 使用命令行参数指定

以上4种方式按加载顺序排列,先加载的属性具有低优先级,因此通过命令行参数指定会覆盖前面几种方式指定的属性。

如果程序没有指定spring.profiles.active属性,则会默认使用default profile。

如果程序中定义了通用的配置文件application.properties(或application.yml),SpringBoot也会加载它,但特定的profile配置文件优先级更高,它会覆盖通用配置文件中的同名属性。

添加活动Profile

除了可以改变激活的Profile,SpringBoot还允许添加额外的活动Profile,新增的活动Profile不会彻底替换原有的Profile,而是对原有的Profile进行追加:当追加的Profile的配置属性与原有的冲突时,追加的配置属性会覆盖原有的属性,否则依然使用原有的Profile设定。

添加新Profile方式:

  1. 使用spring.profiles.include属性
  2. 调用SpringApplication的setAdditionalProfiles()方法来添加新的活动Profile

代码示例:\resources\application-addition.yml

spring:
datasource:
# 指定连接addition数据库
url: jdbc:mysql://localhost:3306/ali2?serverTimezone=UTC

其他配置文件依然使用上一小节的例子,这里不再展示。

配置如下命令行参数:--spring.profiles.active=prod

主程序代码:

@SpringBootApplication
public class App
{
public static void main(String[] args)
{
var app = new SpringApplication(App.class);
// 添加Profile
app.setAdditionalProfiles("addition");
app.run(args);
}
}

运行结果:

Profile组

有些情况下,我们按不同的功能组定义了多个配置文件,但这些配置文件依然应该属于一个特定的Profile。在这种需求下,可以将他们定义成Profile组。

代码示例:\resources\application-prod.yml

spring:
datasource:
# 指定连接prod数据库
url: jdbc:mysql://localhost:3306/prod?serverTimezone=UTC
username: root
password: 32147

代码示例:\resources\application-banner.yml

# 定义图片Banner的大小
spring:
banner:
image:
height: 20
width: 60
# 设置字符串的色深
bitdepth: 4

代码示例:\resources\application-server.yml

server:
port: 9090

\resources\application.yml文件内容:通过group属性来设定组。

spring:
profiles:
# 定义Profile组,该组还包括banner和server两个Profile
group:
prod:
- banner
- server
# 将prod设为活动Profile
active: prod

这里同时加载了上面的prod、banner、server三个Profile。

混合复合类型

当SpringBoot从多个配置文件中加载List类型的属性时,后加载的List集合总是完全替换先加载的List集合,比如:先加载的List集合包含2个元素,后加载的List集合包含1个元素,那么这个List属性最终只有一个元素。

当SpringBoot从多个配置文件中加载Map类型的属性时,后加载的Map的key-value对会被添加到先加载的Map中,比如:先加载的Map集合有2个key-value对,后加载的Map集合有1个key-value对,最终这个Map属性会包含3个key-value对。

代码示例:属性处理类

@ConfigurationProperties("crazyit")
public class CrazyitProperties
{
private final List<Book> list = new ArrayList<>();
// Book类包含了title、description属性
private final Map<String, Book> map = new HashMap<>();
public List<Book> getList()
{
return this.list;
}
public Map<String, Book> getMap()
{
return this.map;
}
}

代码示例:\resources\application-prod.yml

spring:
datasource:
# 指定连接prod数据库
url: jdbc:mysql://localhost:3306/prod?serverTimezone=UTC
username: root
password: 32147
crazyit:
list:
- title: a
description: b
- title: 疯狂Java讲义
description: 北京大学信息科学学院的Java推荐教材
map:
prod:
title: 产品级
description: 产品级

代码示例:\resources\application-banner.properties

crazyit.list[0].title = 疯狂Android讲义
crazyit.list[0].description = 最全面的Adnroid编程图书
crazyit.map["banner"].title = Banner级
crazyit.map["banner"].description = Banner级

代码示例:\resources\application-server.yml

crazyit:
list:
- title: 疯狂Spring Boot终极讲义
description: “此书一出再无书”的Spring Boot
map:
server:
title: 服务器级
description: 服务器级

\resources\application.yml文件内容

spring:
profiles:
# 定义Profile组,该组还包括banner和server两个Profile
group:
prod:
- banner
- server
# 将prod设为活动Profile
active: prod

这里同时加载了上面的prod、banner、server三个Profile。加载顺序为prod->banner->server。

控制器类:

@RestController
@Profile("prod")
public class ProdController
{
private final DataSource dataSource;
private CrazyitProperties crazyitProperties;
@Autowired
public ProdController(DataSource dataSource,
CrazyitProperties crazyitProperties)
{
this.dataSource = dataSource;
this.crazyitProperties = crazyitProperties;
}
@GetMapping
public Map<String, Object> hello() throws SQLException
{
return Map.of("class", "产品场的控制器","数据库",
dataSource.getConnection().getCatalog(),
"crazyit", crazyitProperties);
}
}

运行结果:

根据环境自动更新Profile

SpringBoot允许使用三个减号(---)将一份 *.yml分割成逻辑上的多个片段( *. properties文件使用 #--- 进行分割),每个片段都会被加载成单独的配置。

当分割成多个配置之后,可通过如下属性指定“条件性”生效.

  1. spring.config.activate.on-profile:指定此行配置以下的配置仅当指定的profile激活时才有效。改属性也支持取反运算符(!),比如“!dev”表示非dev profile时有效
  2. spring.config.activate.on-cloud-platform:指定此行配置以下的配置仅当处于指定的云平台上时才有效

比如配置片段

myprop=always-set
#---
spring.config.activate.on-profile=prod
otherprop=prod-value

myprop的属性为always-set,总是生效。当prod Profile处于活动时,otherprop=prod-value才生效。

比如配置片段

myprop: always-set
---
spring:
config:
activate:
on-cloud-platform: kubernetes
otherprop: other-set

myprop的属性为always-set,总是生效。当应用被部署在k8s云平台时,otherprop=other-set才生效。

代码示例:\resources\application.yml文件内容

spring:
datasource:
username: root
password: root
---
spring:
config:
activate:
on-profile: default
datasource:
# 指定连接deft数据库
url: jdbc:mysql://localhost:3306/deft?serverTimezone=UTC
---
spring:
config:
activate:
on-profile: dev
datasource:
# 指定连接dev数据库
url: jdbc:mysql://localhost:3306/dev?serverTimezone=UTC
---
spring:
config:
activate:
on-profile: prod
datasource:
# 指定连接prod数据库
url: jdbc:mysql://localhost:3306/prod?serverTimezone=UTC
---
spring:
config:
activate:
on-profile: test
datasource:
# 指定连接test数据库
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC

不知道活动的profile,运行结果

配置如下命令行参数:--spring.profiles.active=prod 启动后运行结果

SpringBoot--Profile你用对了吗的更多相关文章

  1. SpringBoot Profile使用详解及配置源码解析

    在实践的过程中我们经常会遇到不同的环境需要不同配置文件的情况,如果每换一个环境重新修改配置文件或重新打包一次会比较麻烦,Spring Boot为此提供了Profile配置来解决此问题. Profile ...

  2. 【第十四章】 springboot + profile(不同环境读取不同配置)

    具体做法: 不同环境的配置设置一个配置文件,例如:dev环境下的配置配置在application-dev.properties中:prod环境下的配置配置在application-prod.prope ...

  3. 第十四章 springboot + profile(不同环境读取不同配置)

    具体做法: 不同环境的配置设置一个配置文件,例如:dev环境下的配置配置在application-dev.properties中:prod环境下的配置配置在application-prod.prope ...

  4. Spring-Boot:Profile简单示例

    //Resources目录下创建 application.properties spring.profiles.active=prod //Resources目录下创建 application-pro ...

  5. SpringBoot——Profile多环境支持

    1.多profile文件形式 主配置文件编写时, 文件名可以是application-{profile}.properties/yml 默认使用的application.properties的配置. ...

  6. springboot~Profile开发环境与单元测试用不同的数据库

    期望 希望开发环境dev用mysql 单元测试使用本机的h2数据库 引入依赖 compile('org.springframework.boot:spring-boot-starter-data-jp ...

  7. docker 带参数启动 配合springboot profile

    dockerfile FROM frolvlad/alpine-oraclejdk8:slim VOLUME /tmp ADD test-push-service--SNAPSHOT.jar app. ...

  8. java~springboot~目录索引

    回到占占推荐博客索引 最近写了不过关于java,spring,微服务的相关文章,今天把它整理一下,方便大家学习与参考. java~springboot~目录索引 Java~关于开发工具和包包 Java ...

  9. 【附5】springboot之配置文件

    本文转载自http://www.jianshu.com/p/80621291373b,作者:龙白一梦 我的boss 代码从开发到测试要经过各种环境,开发环境,测试环境,demo环境,线上环境,各种环境 ...

  10. 附 5 springboot之配置文件

    本文转载自http://www.jianshu.com/p/80621291373b,作者:龙白一梦 我的boss 代码从开发到测试要经过各种环境,开发环境,测试环境,demo环境,线上环境,各种环境 ...

随机推荐

  1. jmeter之请求体类型

    一.当post方法的提交数据类型(content-type)为multipart/form-data,请求体为文件文件上传. fiddler抓包请求体的name对应jmerter文件上传的参数名称,f ...

  2. Kali安装JDK8以及JDK11、JDK17切换

    声明:本文分享的安全工具和项目均来源于网络,仅供安全研究与学习之用, 如用于其他用途,由使用者承担全部法律及连带责任,与工具作者和本公众号无关. 瓜神学习网络安全 公众号 背景 很久之前更新了一次ka ...

  3. MCP Server On FC 之旅1: MCP 协议的深度解析与云上适配最佳实践

    在人工智能技术高速发展的今天,数据孤岛.工具碎片化.上下文割裂问题已成为制约大模型发挥潜力的关键瓶颈.Model Context Protocol(MCP)作为 Anthropic 于 2024 年推 ...

  4. 测试获取 Github 信息

    import json import requests from .fetch_github_info import AUTHENTICATED_USER_ENDPOINT, fetch_github ...

  5. DOM基础操作小结

    最近一个多月都在看看前端的内容. 因为这半年都在做BI嘛, 感觉有些东西呀, 还是用前端来做会更加能满足客户的需求, 于是呢, 就网上找了一些资料, 学习了一波前端基础. 这里也是做个简单的笔记, 关 ...

  6. 集成学习双雄:Boosting和Bagging简介

    在机器学习的世界里,集成学习(Ensemble Learning)是一种强大的技术,它通过组合多个模型来提高预测性能. 集成学习通过组合多个基学习器的预测结果,获得比单一模型更优秀的性能.其核心思想是 ...

  7. Seata源码—7.Seata TCC模式的事务处理

    大纲 1.Seata TCC分布式事务案例配置 2.Seata TCC案例服务提供者启动分析 3.@TwoPhaseBusinessAction注解扫描源码 4.Seata TCC案例分布式事务入口分 ...

  8. 记一次burp抓不到包的排查与处理

    ​ 一次遇到了burp上奇怪的bug.访问某个页面显示 No response received from remote server , ​ 但是使用 yakit 进行抓包之后发现网站可以正常抓包 ...

  9. WindowsPE文件格式入门04.导入表

    https://bpsend.net/thread-307-1-1.html PE 内部保存了导入的dll 和 api信息,这些信息保存到一个表里面.称为导入表, 导入表就是 记住一个可执行文件导入了 ...

  10. 面试题:java Runnable与Callable 的区别

    相同点 都是接口:(废话,当然是接口了) 都可用来编写多线程程序: 都需要调用Thread.start()启动线程. Callable是类似于Runnable的接口,实现Callable接口的类和实现 ...