欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring开发笔记(4)spring mvc多环境下配置文件的设置

程序员文章站 2022-04-13 23:11:05
...

在实际开发时经常需要把一些配置信息写在配置文件,比如mysql的主机地址、端口号、用户名和密码等。另外,在开发代码时可能用一套配置参数,而部署到测试环境时又会用另一套配置参数,测试完毕再部署到线上环境时,又需要使用线上环境下的另一套参数。因此,实际开发中面临着如何给工程添加多个环境下的配置文件、且要保证不同环境下能自动使用不同的配置文件的问题。

spring提供了spring.profiles.active参数,通常情况下,这个值我们会设置为dev、test和online中的一个,分别代表开发环境、测试环境和线上生产环境。比如当spring.profiles.active的值为dev时,表示当前运行于开发环境下,应当使用开发环境下的配置文件。

有两种方式可以解决不同运行环境下使用不同配置文件的问题,一种是在工程构建打包阶段进行选择另一种是在运行阶段进行选择。

构建阶段选择配置文件

构建阶段选择配置文件,就是先准备好几个不同环境下的配置文件,然后在项目构建打包时,选择其中一个打包到项目中来。我们在上一篇spring mvc示例的基础上进行演示。

首先,在工程的src/main目录下创建conf目录,conf目录下再分别创建dev、test和online三个子目录,每个子目录下分别创建一个名为application.properties的配置文件,这三个目录下的配置文件分别是在开发环境、测试环境和线上环境中使用:

spring开发笔记(4)spring mvc多环境下配置文件的设置

dev的配置文件的内容为:

env.name=env-dev

test的配置文件内容为:

env.name=env-test

online的配置文件内容为:

env.name=env-online

可以看出,我们在配置文件中配置了一个名为env.name的参数,这个参数在开发环境下的值为env-dev,在测试环境下的值为env-test,而在线上环境的值为env-online。

因为程序中的代码要引用配置文件中的参数,而这些参数通常是在spring容器创建各个类对象时注入进各个对象中的,因此我们需要告诉spring容器配置文件在哪里。这里,spring容器是通过xml文件来配置的,因此我们在spring.xml文件中添加如下的一行配置:

<context:property-placeholder location="classpath:application.properties"/>

这个配置告诉spring容器去哪加载应用的配置文件,这里是从类路径下加载配置文件application.properties。也许你会觉得奇怪,上面我们写了3个application.properties文件,这里传给spring容器的到底是哪个呢?上面虽然创建了3个application.properties配置文件,但最终只会有一个在构建时被打包到项目中。为实现这一目标,我们修改pom.xml文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mytest</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>
        </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>

与原来的pom.xml文件相比,一是在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的代码如下:

package com.mytest.service.impl;

import com.mytest.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。

最后在浏览器中输入http://localhost:8080/mvc-test/hello?name=tom,可以看到返回结果为:

spring开发笔记(4)spring mvc多环境下配置文件的设置

可以看到输出的env.name的值为env-dev,因此确实是选择了开发环境下的配置文件。

我们再试下生产环境下。在maven命令行执行如下命令来构建并打包整个工程:

clean package -Dspring.profiles.active=online

此时会选择conf/online目录下的application.properties文件打包到项目中。将war包部署到tomcat中启动,在浏览器中访问http://localhost:8080/mvc-test/hello?name=tom,结果如下:

spring开发笔记(4)spring mvc多环境下配置文件的设置

可以看到输出的env.name的值为env-online,因此确实是选择了线上环境下的配置文件。

再试下测试环境下。在maven命令行执行如下命令来编译并打包整个工程:

clean package -Dspring.profiles.active=test

此时会选择conf/test目录下的application.properties文件打包到项目中。将war包部署到tomcat中启动,在浏览器中访问http://localhost:8080/mvc-test/hello?name=tom,结果如下:

spring开发笔记(4)spring mvc多环境下配置文件的设置

可以看到输出的env.name的值为env-test,因此确实是选择了测试环境下的配置文件。

接下来再看一下tomcat中mvc-test下的内容:

spring开发笔记(4)spring mvc多环境下配置文件的设置

可以看出,只有一个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个则分别对应开发环境、测试环境和线上环境的配置:

spring开发笔记(4)spring mvc多环境下配置文件的设置

因为配置文件要到工程运行时才会进行选择,因此,所有的配置文件都是需要打包到项目中的。先在3个环境下都通用的application.properties文件中加入一个配置项,参数为city.name,值为beijing:

city.name=beijing

和前面的例子一样,dev、test和online环境的配置文件都配置了一个名为env.name的参数,值分别为env-dev、env-test和env-online。

接下来修改spring.xml,增加如下一行配置如下:

<context:property-placeholder location="classpath:application.properties, classpath:application-${spring.profiles.active}.properties"/>

这一行是告诉spring容器去哪加载配置文件。这里添加了两个配置文件,一个是所有环境都通用的application.properties文件,另一个则取决于spring.profiles.active参数的值是多少,如果是dev(即开发环境),则是application-dev.properties文件;同理,如果是test(测试环境)则是application-test.properties文件;如果是online(线上环境)则是application-online.properties文件。

为了观察配置的效果,修改HelloServiceImpl文件的内容如下:

package com.mytest.service.impl;

import com.mytest.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;

    @Value("${city.name}")
    private String cityName;

    @Override
    public String sayHello(String to) {
        return "hello " + to + ", env.name:" + envName + ", cityName:" + cityName;
    }
}

HelloServiceImpl除了引用了配置文件中的env.name参数外,还引用了通用配置文件中的city.name参数。

接下在maven命令行中执行如下命令构建整个工程:

clean package

这里构建时没有再传入任何参数了。

接下来将打包好的mvc-test-1.0-SNAPSHOT.war文件拷贝到tomcat的webapps目录下,并改名为mvc-test.war。

运行时进行配置文件的选择,其原理就是在用java命令执行java程序时传入给spring.profiles.active参数不同的值,比如:

java xxx -Dspring.profiles.active=dev

这样就在启动程序时就把spring.profiles.active参数的设置为dev了。

因为tomcat是我们通常是用它自身bin目录下的catalina.sh脚本来启动的,所以我们把启动参数写到这个脚本里。打开catalina.sh脚本,搜索到如下行:

JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS"

将其改成:

JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS -Dspring.profiles.active=dev"

表示现在是开发环境。保存并退出,然后在tomcat的bin目录下执行以下命令以启动tomcat:

sh ./catalina.sh run

然后在浏览器中输入http://localhost:8080/mvc-test/hello?name=tom,回车即可看到结果:

spring开发笔记(4)spring mvc多环境下配置文件的设置

可以看到,程序正确地选择了开发环境下的配置文件。

用同样的方法,将spring.profiles.active设置为test,并重新启动tomcat,在浏览器中访问,可以看到程序正确地选择了测试环境下的配置文件:

spring开发笔记(4)spring mvc多环境下配置文件的设置

将spring.profiles.active设置为online,并重新启动tomcat,在浏览器中访问,可以看到程序正确地选择了线上环境的配置文件:

spring开发笔记(4)spring mvc多环境下配置文件的设置

我们再看下tomcat的webapps目录下,mvc-test的目录结构:

spring开发笔记(4)spring mvc多环境下配置文件的设置

可以看到所有的配置文件都打包到WEB-INF/classes目录下了,因为是运行时才选择配置文件,所以所有的配置文件都要打包过来。

综上,可以将所有环境都通用的配置信息写入到application.properties文件中,而不同运行环境下不同的配置信息则分别写入到application-dev.properties、application-test.properties和application-online.properties文件中,再通过运行程序时给sring.profiles.active参数传入不同的值(dev或test或online)即可完成不同运行环境下选择不同的配置文件的功能。





相关标签: spring mvc spring