spring开发笔记(4)springmvc多环境下配置⽂件的设置在实际开发时经常需要把⼀些配置信息写在配置⽂件,⽐如mysql的主机地址、端⼝号、⽤户名和密码等。另外,在开发代码时可能⽤⼀套配置参数,⽽部署到测试环境时⼜会⽤另⼀套配置参数,测试完毕再部署到线上环境时,⼜需要使⽤线上环境下的另⼀套参数。因此,实际开发中⾯临着如何给⼯程添加多个环境下的配置⽂件、且要保证不同环境下能⾃动使⽤不同的配置⽂件的问题。
spring提供了spring.profiles.active参数,通常情况下,这个值我们会设置为dev、test和online中的⼀个,分别代表开发环境、测试环境和线上⽣产环境。⽐如当spring.profiles.active的值为dev时,表⽰当前运⾏于开发环境下,应当使⽤开发环境下的配置⽂件。
有两种⽅式可以解决不同运⾏环境下使⽤不同配置⽂件的问题,⼀种是在⼯程构建打包阶段进⾏选择,另⼀种是在运⾏阶段进⾏选择。
构建阶段选择配置⽂件
构建阶段选择配置⽂件,就是先准备好⼏个不同环境下的配置⽂件,然后在项⽬构建打包时,选择其中⼀个打包到项⽬中来。我们在上⼀篇spring mvc⽰例的基础上进⾏演⽰。
⾸先,在⼯程的src/main⽬录下创建conf⽬录,conf⽬录下再分别创建dev、test和online三个⼦⽬录,每
个⼦⽬录下分别创建⼀个名为application.properties的配置⽂件,这三个⽬录下的配置⽂件分别是在开发环境、测试环境和线上环境中使⽤:
dev的配置⽂件的内容为:
env.name=env-dev
test的配置⽂件内容为:
springmvc的注解有哪些env.name=env-test
online的配置⽂件内容为:
env.name=env-online
可以看出,我们在配置⽂件中配置了⼀个名为env.name的参数,这个参数在开发环境下的值为env-dev,在测试环境下的值为env-test,⽽在线上环境的值为env-online。
因为程序中的代码要引⽤配置⽂件中的参数,⽽这些参数通常是在spring容器创建各个类对象时注⼊进各个对象中的,因此我们需要告诉spring容器配置⽂件在哪⾥。这⾥,spring容器是通过xml⽂件来配置的,因此我们在l⽂件中添加如下的⼀⾏配置:
<context:property-placeholder location="classpath:application.properties"/>
这个配置告诉spring容器去哪加载应⽤的配置⽂件,这⾥是从类路径下加载配置⽂件application.properties。也许你会觉得奇怪,上⾯我们写了3个application.properties⽂件,这⾥传给spring容器的到底是哪个呢?上⾯虽然创建了3个application.properties配置⽂件,但最终只会有⼀个在构建时被打包到项⽬中。为实现这⼀⽬标,我们修改l⽂件的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId&st</groupId>
<artifactId>mvc-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
<env>${spring.profiles.active}</env>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/conf/${env}</directory>
<includes>
<include>**</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**</include>
</includes>
</resource>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
与原来的l⽂件相⽐,⼀是在properties元素中定义了⼀个env元素:
<properties>
<java.version>1.8</java.version>
<env>${spring.profiles.active}</env>
</properties>
这个env元素引⽤是spring的spring.profiles.active参数的值,其值为dev、test和online中的⼀个。
⼆是在build元素中增加了对资源⽂件的说明:
<resources>
<resource>
<directory>src/main/conf/${env}</directory>
<includes>
<include>**</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**</include>
</includes>
</resource>
</resources>
maven在构建项⽬时,默认是把main/resoures⽬录作为资源⽂件所在⽬录的,现在我们在main/conf⽬录下也存放了资源⽂件(即application.properites⽂件),因此需要告诉maven资源⽂件所在的⽬录有哪些,通过build元素中增加resources元素就可以达到这⼀⽬的。这⾥告诉maven有两个地⽅存在资源⽂件,⼀个是默认的resources⽬录,另⼀个是在src/main/conf/${env}⽬录下,⽽${env}引⽤的是上⾯properties元素中定义的env的值,⽽它的值引⽤的⼜是spring.profiles.active的值(其值为dev、test和online中的⼀个),因此,⽬录要么是src/main/conf/dev,要么是src/main/conf/test,要么是main/conf/online,这最终取决于参数
spring.profiles.active的值。因此,根据参数spring.profiles.active的值的不同,在构建打包时最终会选择dev、test和online这三个⽬录中的⼀个中的application.properties打包到项⽬中来。
为了演⽰输出结果,接下来我们修改HelloServiceImpl的代码如下:
st.service.impl;
st.service.HelloService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class HelloServiceImpl implements HelloService {
@Value("${env.name}")
private String envName;
@Override
public String sayHello(String to) {
return "hello " + to + ", env.name:" + envName;
}
}
HelloServiceImpl类中定义了⼀个成员变量envName,其上添加了@Value("${env.name}")注解,表明它的值引⽤配置⽂件中的
env.name参数。spring容器在创建HelloServiceImpl对象时,就会从配置⽂件中获取env.name参数的值,并将其注⼊进来。在sayHello ⽅法中,将env.name的值返回,这样我们就可以在浏览器中看到结果了。
接下来在maven命令⾏执⾏如下命令来构建并打包整个⼯程:
clean package -Dspring.profiles.active=dev
可以看到,我们在打包命令中传⼊了spring.profiles.active参数的值,这⾥为dev。此时就会选择conf/dev⽬录下的
application.properties⽂件打包到项⽬中。接下来将打包出来的mvc-test-1.0-SNAPSHOT.war⽂件拷贝到tomcat的webapps⽬录下,改名为mvc-test.war,再启动tomcat。
可以看到输出的env.name的值为env-dev,因此确实是选择了开发环境下的配置⽂件。
我们再试下⽣产环境下。在maven命令⾏执⾏如下命令来构建并打包整个⼯程:
clean package -Dspring.profiles.active=online
可以看到输出的env.name的值为env-online,因此确实是选择了线上环境下的配置⽂件。
再试下测试环境下。在maven命令⾏执⾏如下命令来编译并打包整个⼯程:
clean package -Dspring.profiles.active=test
可以看到输出的env.name的值为env-test,因此确实是选择了测试环境下的配置⽂件。
接下来再看⼀下tomcat中mvc-test下的内容:
可以看出,只有⼀个application.properties⽂件被maven打包到了WEB-INF/classes⽬录下。
通过在构建打包时给spring.profiles.active参数传⼊不同的值,就可以为不同的运⾏环境选择不同的配置⽂件。由于配置⽂件的选择是在构建阶段完成的,因此这种⽅式的缺点是我们需要分别为不同的运⾏环境各打包⼀次。
运⾏阶段选择配置⽂件
另⼀种⽅式是将配置⽂件的选择留到运⾏阶段,通过在运⾏程序时给spring.profiles.active参数传⼊不同的值以选择不同的配置⽂件。这样只需要打包⼀次,不必为不同的环境各打包⼀次了。
下⾯来演⽰如何在运⾏阶段选择配置⽂件。在上⼀篇的⼯程的基础上进⾏修改(或者先将上⾯的⼯程恢复成最初的样⼦)。
⾸先在resoures⽬录下创建4个配置⽂件,分别为application.properties、application-dev.properties、application-test.properties 和application-online.properties。其中application.properties⽂件⾥存放的是所有环境下都通⽤的配置信息,另外3个则分别对应开发环境、测试环境和线上环境的配置:
因为配置⽂件要到⼯程运⾏时才会进⾏选择,因此,所有的配置⽂件都是需要打包到项⽬中的。先在3个环境下都通⽤的
application.properties⽂件中加⼊⼀个配置项,参数为city.name,值为beijing:
city.name=beijing
和前⾯的例⼦⼀样,dev、test和online环境的配置⽂件都配置了⼀个名为env.name的参数,值分别为env-dev、env-test和env-online。接下来修改l,增加如下⼀⾏配置如下:
<context:property-placeholder location="classpath:application.properties, classpath:application-${spring.profiles.active}.properties"/>