作者: 一字馬胡
多環(huán)境配置是一件非常重要的事情,在日常開(kāi)發(fā)過(guò)程中,我們都會(huì)有多套開(kāi)發(fā)環(huán)境,比如在本地快速開(kāi)發(fā)自測(cè),然后提交到測(cè)試環(huán)境讓專門的人來(lái)測(cè)試驗(yàn)收,測(cè)試環(huán)境驗(yàn)收完畢之后再上線到線上環(huán)境提供服務(wù),這是比較標(biāo)準(zhǔn)的開(kāi)發(fā)流程,也相應(yīng)的需要多套開(kāi)發(fā)環(huán)境的配置,本文主要介紹在Spring Boot項(xiàng)目中如何進(jìn)行多環(huán)境配置的方法。
在maven項(xiàng)目中,我們有一種簡(jiǎn)潔的多環(huán)境配置方式,maven的思路是資源文件根據(jù)環(huán)境進(jìn)行隔離,在打包的時(shí)候去加載正確的配置資源進(jìn)行配置,使用maven的多環(huán)境資源隔離配置,需要在build里面走增加下面的內(nèi)容
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/profile/${conf-dir}</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
這里的配置主要做的事情就是標(biāo)記資源文件,我把src/main/profile/{conf-dir}也標(biāo)記為了資源文件,{conf-dir}的具體值見(jiàn)下面的配置:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<conf-dir>dev</conf-dir>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<conf-dir>test</conf-dir>
</properties>
</profile>
<profile>
<id>product</id>
<properties>
<conf-dir>product</conf-dir>
</properties>
</profile>
</profiles>
在這里設(shè)置了三個(gè)環(huán)境,分別為dev、test和product,分別代表本地開(kāi)發(fā),測(cè)試環(huán)境以及線上環(huán)境,這樣的話,我們?cè)诖虬臅r(shí)候使用-P命令即可指定相應(yīng)的環(huán)境資源。maven配置好了之后,需要在src/main/profile/目錄下新建三個(gè)文件,名字分別叫dev、test和product,然后可以創(chuàng)建一個(gè)config.properties文件,里面可以使用key=value的形式配置變量。
在Spring boot項(xiàng)目中,如果想要使用maven的分環(huán)境功能,需要額外引入一個(gè)Spring的xml文件,具體的做法就是在boot里面使用@ImportResource注解,比如@ImportResource(locations = "classpath:/spring/applicationContext.xml"),這樣在classpath:/spring/applicationContext.xml這個(gè)文件里面就可以使用具體的環(huán)境配置了。下面是xml文件的具體內(nèi)容:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 導(dǎo)入屬性配置文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<bean id="profileCheck" class="io.spring.learn.configures.ProfileCheck">
<property name="env" value="${profile.env}"/>
</bean>
</beans>
在xml里面導(dǎo)入了我們的分環(huán)境配置文件,并且在profileCheck bean里面注入了配置文件中的變量。這個(gè)時(shí)候我們就可以獲取相應(yīng)環(huán)境下的變量了。
在Springboot項(xiàng)目中,不建議使用xml的配置,spring boot提供了一種新的分環(huán)境功能,具體的做法如下:
(1)、除了原有的application.properties之外,新建三個(gè)配置文件,分別叫application-dev.properties,application-test.properties,application-product.properties,分別代表開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境以及線上環(huán)境的配置文件。
(2)、在不同環(huán)境的配置文件中使用key=value的形式配置變量。
(3)、在bean配置的時(shí)候使用${key}的形式來(lái)使用配置即可,當(dāng)然,bean的屬性注入有多種方式,可以根據(jù)各自的情況去使用合適的方式去注入。
(4)、在執(zhí)行的時(shí)候使用 --spring.profiles.active來(lái)指定環(huán)境,比如--spring.profiles.active=product指定為線上環(huán)境。
下面以一個(gè)配置數(shù)據(jù)源的例子來(lái)具體說(shuō)明一下。寫一個(gè)新的配置類DataSourceBean:
package io.spring.learn.configures;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class DataSourceBean {
@Bean
@Primary
@ConfigurationProperties(prefix = "datasource")
public DruidDataSource getDrudDataSource() {
return new DruidDataSource();
}
}
可以看到使用 @ConfigurationProperties(prefix = "datasource")來(lái)加載配置文件中的屬性值,在各個(gè)環(huán)境的配置文件中分別配置幾個(gè)數(shù)據(jù)源屬性,比如在開(kāi)發(fā)環(huán)境的配置如下:
### datasource
datasource.username=root
datasource.password=localroot123
datasource.url=jdbc:mysql://127.0.0.1:3306/dev_db?useUnicode=true&characterEncoding=utf8
datasource.dbtype=mysql
datasource.maxactive=20
寫一個(gè)Controller來(lái)測(cè)試效果:
package io.spring.learn.web;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/api/db/source")
public class DataSourceController {
@Autowired
private DruidDataSource druidDataSource;
@RequestMapping(value = "/drud", method = RequestMethod.GET)
public DataSourceObject getDruidDataSource() {
return new DataSourceObject(
druidDataSource.getUsername(),
druidDataSource.getPassword(),
druidDataSource.getUrl(),
druidDataSource.getMaxActive(),
druidDataSource.getDbType());
}
@Setter
@Getter
@ToString
@AllArgsConstructor
private static class DataSourceObject {
private String username;
private String password;
private String url;
private int maxActive;
private String dbType;
}
}
為了方便啟動(dòng)項(xiàng)目,寫一個(gè)腳本execute/sh:
#!/bin/sh
./compile.sh &&
echo 'compile & package project success, start to run it' ||
echo 'failed to compile or package the project, check your project and re-try'
JAR=../target/spring-boot-starter-0.0.1-SNAPSHOT.jar
echo "jar location: $JAR"
java -jar $JAR --spring.profiles.active=product
compile.sh為:
#!/bin/sh
cd ../
mvn clean -U package -Ptest -Dmaven.test.skip=true
最后,進(jìn)入到腳本目錄,然后執(zhí)行execute.sh,就可以啟動(dòng)項(xiàng)目,可以看到在execute.sh中設(shè)置了--spring.profiles.active=product,你可以試著改變--spring.profiles.active=product來(lái)看最后的效果,比如--spring.profiles.active=product的時(shí)候,可以看到Controller返回的json為:
