如题,本篇我们介绍在springboot中多环境profile的使用。
在我们的项目开发、测试、上线过程中,不可避免的需要反复地修改配置文件。譬如,开发环境连接的数据库ip和测试、生产环境的不同;开发环境开发的app版本和测试、生产线上的app版本信息也不同,等等。。我们发现,尽管在springboot中使用application.properties (或者yml)作为整个项目的全局配置文件,但是生产、测试环境往往都会有些不同于开发环境的配置,这时候profile就派上用场了。
使用profile还有个明显的用处——可以抽取application.yml中的配置信息到其他文件。
如当我们的项目越来越大时,项目配置信息太多,application.yml配置文件会比较大,这时我们可以通过定义profile,将一些配置信息从application.yml中抽取到一个单独的文件中,如建立:
application-devFtp.yml 只存放开发环境ftp相关的配置信息
application-devRedis.yml 只存放开发环境redis相关的配置信息
application-testFtp.yml 只存放测试环境ftp相关的配置信息
application-testRedis.yml 只存放测试环境redis相关的配置信息
然后在application.yml中 ,切换开发环境,配置spring.profiles.active=dev, devFtp,devRedis 来引入dev、devFtp、devRedis的配置 即可。
切换测试环境,配置spring.profiles.active=test, testFtp,testRedis 来引入test、testFtp、testRedis的配置 即可。
另外,properties的配置文件中含中文,spring的属性文件加载后读取乱码,而在yml中不会,因此也建议大家使用yml配置替换properties。
profile允许在项目中同时配置多套与环境相关的配置,profile的文件名称为application-{profile}.properties(以properties文件为例),其中profile可以为dev(开发)、test(测试)、prod(生产)等,这些名称是用户自定义的。当需要切换到指定环境配置时,只需将application.properties中spring.profiles.active设置为指定的profile名称即可。 如:
application.properties
# profile 配置 dev test prod spring.profiles.active=dev #spring.profiles.active=test #spring.profiles.active=prod
application-dev.properties
app.myname=dev_appapplication-test.properties
app.myname=test_appapplication-prod.properties
app.myname=prod_app
SpringContextEventHandler .java 中使用@Value("${app.myname}")注入值,并打印之
package com.tingcream.springWeb.spring.eventListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextStartedEvent; import org.springframework.context.event.ContextStoppedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import com.tingcream.springWeb.common.SpringContextHelper; import com.tingcream.springWeb.spring.event.MyAppEvent; @Component public class SpringContextEventHandler { @Value("${app.myname}") private String myname; @EventListener public void stopped(ContextStoppedEvent event){ System.out.println("SpringContextEventHandler stopped执行"); } @EventListener public void started(ContextStartedEvent event){ System.out.println("SpringContextEventHandler started执行"); } @EventListener public void refreshed(ContextRefreshedEvent event){ System.out.println("SpringContextEventHandler refreshed执行"); System.out.println("myname:"+myname);//打印@value注入的值 SpringContextHelper.getApplicationContext().publishEvent(new MyAppEvent("这是一段事件消息")); } @EventListener public void closed(ContextClosedEvent event){ System.out.println("SpringContextEventHandler closed执行"); } // ready @EventListener public void ready(ApplicationReadyEvent event){ System.out.println("SpringContextEventHandler ready执行.."); } }
当我们修改application.properties中spring.profiles.active为不同值时,@Value("${app.myname}")所注入的值也不同。
@Profile注解可以标记在任何被标记了@Configuration或@Component的java配置类声明或方法声明上。
如,我们开发环境、测试环境、生产环境中的android app版本信息不同,可以配置3个bean,分别指定不同的profile 。
AndroidAppConfiguration.java
package com.tingcream.springWeb.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import com.tingcream.springWeb.model.AndroidApp; /** * android app版本 对象配置 * @author jelly * */ @Configuration public class AndroidAppConfiguration { @Bean @Profile("dev") public AndroidApp devAndroidApp(){ System.out.println("dev androidApp对象创建"); return new AndroidApp("我的e家掌上app", "v2.1.0", "2012-09-20", "开发环境,app描述信息"); } @Bean @Profile("test") public AndroidApp testAndroidApp(){ System.out.println("test androidApp对象创建"); return new AndroidApp("我的e家掌上app", "v2.0.0", "2012-09-20", "测试环境,app描述信息"); } @Bean @Profile("prod") public AndroidApp prodAndroidApp(){ System.out.println("prod androidApp对象创建"); return new AndroidApp("我的e家掌上app", "v1.5.0", "2012-09-20", "生产环境,app描述信息"); } }
AndroidApp.java
package com.tingcream.springWeb.model; public class AndroidApp { private String name; private String version; private String publishDate; private String describe; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getPublishDate() { return publishDate; } public void setPublishDate(String publishDate) { this.publishDate = publishDate; } public String getDescribe() { return describe; } public void setDescribe(String describe) { this.describe = describe; } public AndroidApp() { super(); } public AndroidApp(String name, String version, String publishDate, String describe) { super(); this.name = name; this.version = version; this.publishDate = publishDate; this.describe = describe; } @Override public String toString() { return "AndroidApp [name=" + name + ", version=" + version + ", publishDate=" + publishDate + ", describe=" + describe + "]"; } }
SpringContextEventHandler.java
package com.tingcream.springWeb.spring.eventListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextStartedEvent; import org.springframework.context.event.ContextStoppedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import com.tingcream.springWeb.common.SpringContextHelper; import com.tingcream.springWeb.model.AndroidApp; import com.tingcream.springWeb.spring.event.MyAppEvent; @Component public class SpringContextEventHandler { @Value("${app.myname}") private String myname; @Autowired private AndroidApp androidApp;//注入androidApp版本对象 @EventListener public void stopped(ContextStoppedEvent event){ System.out.println("SpringContextEventHandler stopped执行"); } @EventListener public void started(ContextStartedEvent event){ System.out.println("SpringContextEventHandler started执行"); } @EventListener public void refreshed(ContextRefreshedEvent event){ System.out.println("SpringContextEventHandler refreshed执行"); System.out.println("myname:"+myname);//打印@value注入的值 System.out.println(androidApp);//打印注入的android对象,根据指定的profile不同(dev、test、prod)打印的内容也不同 SpringContextHelper.getApplicationContext().publishEvent(new MyAppEvent("这是一段事件消息")); } @EventListener public void closed(ContextClosedEvent event){ System.out.println("SpringContextEventHandler closed执行"); } // ready @EventListener public void ready(ApplicationReadyEvent event){ System.out.println("SpringContextEventHandler ready执行.."); } }
当我们修改application.properties配置文件中spring.profiles.active的值为不同值时,容器中使用@Autowire 注入的AndroidApp对象也不同。
---------
当然,@Profile 注解也可以标记在类上,如我们在代码中配置三个环境特有的配置:DevConfiguration、TestConfiguration、ProdConfiguration
DevConfiguration.java
package com.tingcream.springWeb.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import com.tingcream.springWeb.model.AndroidApp; /** * dev profile 特有配置 * @author jelly * */ @Configuration @Profile("dev") public class DevConfiguration { @Bean public AndroidApp androidApp(){ System.out.println("dev androidApp对象创建"); return new AndroidApp("我的e家掌上app", "v2.1.0", "2012-09-20", "开发环境,app描述信息"); } }
TestConfiguration.java
package com.tingcream.springWeb.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import com.tingcream.springWeb.model.AndroidApp; /** * test profile 特有配置 * @author jelly * */ @Configuration @Profile("test") public class TestConfiguration { @Bean public AndroidApp androidApp(){ System.out.println("test androidApp对象创建"); return new AndroidApp("我的e家掌上app", "v2.0.0", "2012-09-20", "测试环境,app描述信息"); } }
ProdConfiguration.java
package com.tingcream.springWeb.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import com.tingcream.springWeb.model.AndroidApp; /** * prod profile 特有配置 * @author jelly * */ @Configuration @Profile("prod") public class ProductionConfiguration { @Bean public AndroidApp androidApp(){ System.out.println("prod androidApp对象创建"); return new AndroidApp("我的e家掌上app", "v1.5.0", "2012-09-20", "生产环境,app描述信息"); } }
--------
除了在配置文件可指定激活哪个profile,我们也可以通过VM参数或程序参数在程序运行时手动指定profile, 如:
配置文件 spring.profiles.active=test
VM 参数 -Dspring.profiles.active=test
程序参数 --spring.profiles.active=test
Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1