Spring-Boot 多环境配置说明
作者: 一字马胡
多环境配置是一件非常重要的事情,在日常开发过程中,我们都会有多套开发环境,比如在本地快速开发自测,然后提交到测试环境让专门的人来测试验收,测试环境验收完毕之后再上线到线上环境提供服务,这是比较标准的开发流程,也相应的需要多套开发环境的配置,本文主要介绍在Spring Boot项目中如何进行多环境配置的方法。
在maven项目中,我们有一种简洁的多环境配置方式,maven的思路是资源文件根据环境进行隔离,在打包的时候去加载正确的配置资源进行配置,使用maven的多环境资源隔离配置,需要在build里面走增加下面的内容
<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>
这里的配置主要做的事情就是标记资源文件,我把src/main/profile/{conf-dir}也标记为了资源文件,{conf-dir}的具体值见下面的配置:
<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>
在这里设置了三个环境,分别为dev、test和product,分别代表本地开发,测试环境以及线上环境,这样的话,我们在打包的时候使用-P命令即可指定相应的环境资源。maven配置好了之后,需要在src/main/profile/目录下新建三个文件,名字分别叫dev、test和product,然后可以创建一个config.properties文件,里面可以使用key=value的形式配置变量。
在Spring boot项目中,如果想要使用maven的分环境功能,需要额外引入一个Spring的xml文件,具体的做法就是在boot里面使用@ImportResource注解,比如@ImportResource(locations = "classpath:/spring/applicationContext.xml"),这样在classpath:/spring/applicationContext.xml这个文件里面就可以使用具体的环境配置了。下面是xml文件的具体内容:
<?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">
<!-- 导入属性配置文件 -->
<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里面导入了我们的分环境配置文件,并且在profileCheck bean里面注入了配置文件中的变量。这个时候我们就可以获取相应环境下的变量了。
在Springboot项目中,不建议使用xml的配置,spring boot提供了一种新的分环境功能,具体的做法如下:
(1)、除了原有的application.properties之外,新建三个配置文件,分别叫application-dev.properties,application-test.properties,application-product.properties,分别代表开发环境、测试环境以及线上环境的配置文件。
(2)、在不同环境的配置文件中使用key=value的形式配置变量。
(3)、在bean配置的时候使用${key}的形式来使用配置即可,当然,bean的属性注入有多种方式,可以根据各自的情况去使用合适的方式去注入。
(4)、在执行的时候使用 --spring.profiles.active来指定环境,比如--spring.profiles.active=product指定为线上环境。
下面以一个配置数据源的例子来具体说明一下。写一个新的配置类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")来加载配置文件中的属性值,在各个环境的配置文件中分别配置几个数据源属性,比如在开发环境的配置如下:
### 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
写一个Controller来测试效果:
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;
}
}
为了方便启动项目,写一个脚本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
最后,进入到脚本目录,然后执行execute.sh,就可以启动项目,可以看到在execute.sh中设置了--spring.profiles.active=product,你可以试着改变--spring.profiles.active=product来看最后的效果,比如--spring.profiles.active=product的时候,可以看到Controller返回的json为: