如何使用Maven配置Spring的活动环境(profiles)

75

我有一个使用Maven作为构建工具的应用程序。

我正在使用Maven配置文件来设置不同配置文件的属性。

我想做的是将所有活动的Maven配置文件也传输到Spring的活动配置文件中,以便我可以在bean签名(@profile)中引用它们。但我不确定如何做。

例如:考虑以下Maven设置。

<profiles>
    <profile>
        <id>profile1</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
        </properties>
    </profile>
    <profile>
        <id>profile2</id>
        <properties>
        </properties>
    </profile>
    <profile>
        <id>development</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
        </properties>
    </profile>
    <profile>
        <id>production</id>
        <properties>    
        </properties>
    </profile>
</profiles>

假设我在没有指定任何其他配置文件的情况下运行Maven,我希望Spring拥有 profile1development 作为活动配置文件。

假设我未指定其他配置文件运行Maven,则希望Spring将 profile1development 视为活动配置文件。

8个回答

48

有一种更优雅的方式可以同时切换两个Maven+Spring配置文件。

首先,在POM中添加配置文件(注意:Maven+Spring配置文件通过单个系统变量激活):

<profiles>
    <profile>
        <id>postgres</id>
        <activation>
            <activeByDefault>true</activeByDefault>
            <property>
                <name>spring.profiles.active</name>
                <value>postgres</value>
            </property>
        </activation>
        <dependencies>
            <dependency>
                <groupId>postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <version>9.1-901.jdbc4</version>
            </dependency>
        </dependencies>
    </profile>
    <profile>
        <id>h2</id>
        <activation>
            <property>
                <name>spring.profiles.active</name>
                <value>h2</value>
            </property>
        </activation>           
        <dependencies>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <version>1.4.191</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

第二步,为Spring设置默认配置文件(对于Maven,已经在POM中设置)。对于Web应用程序,我在web.xml中插入了以下行:

<context-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>postgres</param-value>
</context-param>

第三步,在您的配置中添加与配置文件相关的bean。在我的情况下(XML配置),它是:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="mainDataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties" ref="hibProps"/>
    <property name="packagesToScan">
        <list>
            <value>my.test.model</value>
        </list>
    </property>
</bean>
...
<beans profile="postgres">
    <bean name="mainDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://127.0.0.1:5432/webchat" />
        <property name="username" value="postgres" />
        <property name="password" value="postgres" />
    </bean>
</beans>

<beans profile="h2">
    <bean name="mainDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:file:./newsdb;INIT=RUNSCRIPT FROM 'classpath:init.sql';TRACE_LEVEL_FILE=0" />
        <property name="username" value="sa" />
        <property name="password" value="" />
    </bean>
</beans>

现在可以:

  • 使用mvn jetty:runmvn jetty:run -Dspring.profiles.active=postgres命令在Postgres数据库上运行我的Web应用程序
  • 使用mvn clean jetty:run -Dspring.profiles.active=h2命令在H2数据库上运行我的Web应用程序

1
这对我的使用情况来说好多了。谢谢你。请注意,如果 Maven 配置文件与 spring.profiles.active 显式设置在一起,则前者将优先生效。 - secondbreakfast

32

首先,您需要两个属性文件来保存配置。文件名应该与模式application-{custom_suffix}.properties匹配。在Maven项目的src/main/resources目录下创建它们,与主应用程序属性文件(application.properties)并排放置,稍后您将使用该文件激活其中一个文件并保存两个配置文件共享的值。

然后,现在是修改pom.xml的时候了。您需要在每个Maven配置文件中定义一个自定义属性,并将其值设置为要与相应属性文件的后缀匹配的值,以便使用特定配置文件。以下示例还将第一个配置文件标记为默认运行,但这不是强制性的。

<profile>
    <id>dev</id>
    <properties>
        <activatedProperties>dev</activatedProperties>
    </properties>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
</profile>
<profile>
    <id>release</id>
    <properties>
        <activatedProperties>release</activatedProperties>
    </properties>
</profile>
在同一文件的构建部分中,配置资源插件的过滤器。这将允许您在资源目录中的任何文件中插入在上一步中定义的属性,这是下一步骤。
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    …
</build>

最后,在 application.properties 文件中添加以下行。

spring.profiles.active=@activatedProperties@
当构建运行时,资源插件将使用活动的Maven配置文件中定义的属性值替换占位符。启动应用程序后,Spring框架将根据活动的Spring配置文件的名称加载适当的配置文件,该名称由spring.profiles.active属性的值描述。请注意,Spring Boot 1.3替换了过滤值的默认资源插件语法,并使用@activatedProperties@而不是${activatedProperties}符号。
它完美地运作了。希望这可以帮到你。

2
我想补充一下,你也可以在生成war包时选择配置文件:mvn package -P release(其中release是你在POM中定义的maven配置文件的ID)。 - ihebiheb
这个只在Spring Boot中有效吗,还是在Spring Framework中也适用?我的意思是application.properties部分的spring.profiles.active。您能指导我查看相关文档吗? - admdev

25
你需要过滤应用程序中的资源,例如属性文件,其中包含有关在Spring中要激活哪个配置文件的信息。
例如:
spring.profile = ${mySpringProfile}

对于每个配置文件,定义一个这个变量(mySpringProfile)的值。

在构建过程中,将根据当前激活的配置文件的值进行过滤。

然后在应用程序引导期间,您将根据该文件选择适当的配置文件(由于您未提供更多信息,因此无法提供更多帮助,但这很容易)。

注意:我找不到在Maven中获取当前活动的配置文件的方法(例如project.profiles.active保存您的-P值),这就是为什么您必须为每个配置文件设置一个新变量的原因。

注意2:如果您正在运行Web应用程序,而不是使用此中间文件,请在您的web.xml中过滤此值。

<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>${mySpringProfile}</param-value>
</context-param>

注3:这实际上是一种不良实践,您应该通过系统属性在运行时设置配置文件。


3
为什么这是不好的做法?我想要做的是根据Maven配置文件启用特定的Bean,以补充不同环境下的配置。我没有使用Web应用程序,而是一个简单的可执行JAR文件。如果使用资源解决方案,我需要先加载上下文,然后设置活动的配置文件并刷新,这可能会删除一些已创建的Bean并创建其他Bean。我希望能够在不进行切换的情况下正确加载所需的Bean。 - Gleeb
5
总的来说,提供一个根据运行时配置表现不同的唯一发布版本比生成三个不同的二进制文件更好(因为更灵活)。但这仍然取决于您的业务。由您决定 :p - poussma
有没有Java基础配置的示例?(非web.xml) - xedo
关于您的第一个注释,命令是>mvn help:active-profiles。 - BenL

8
对于一个Spring Boot应用程序,可以在Maven配置文件pom.xml中添加一个属性,并在application.properties文件中引用该属性。
在pom.xml文件中添加Maven配置文件,例如,添加一个名为spring.profile.from.maven的属性:
<profiles>
    <profile>
        <id>postgres</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profile.from.maven>postgres</spring.profile.from.maven>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </profile>
    <profile>
        <id>noDb</id>
        <properties>
            <spring.profile.from.maven>noDb</spring.profile.from.maven>
        </properties>
    </profile>
</profiles>

application.properties 中引用 Maven 属性:

spring.profiles.include=@spring.profile.from.maven@

使用此配置,使用postgres Maven配置文件或不使用任何配置文件运行maven时,将向Spring的活动配置列表中添加postgres Spring配置文件,而使用noDb Maven配置文件运行maven时,则将noDb Spring配置文件添加到Spring的活动配置列表中。


3
在web.xml中添加占位符${activeProfile}
<context-param>
  <param-name>spring.profiles.active</param-name>
  <param-value>${activeProfile}</param-value>
</context-param>

为每个配置文件设置pom.xml属性:

<profiles>
  <profile>
    <id>profile1</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
      <activeProfile>profile1</activeProfile>
    </properties>
  </profile>
  <profile>
    <id>profile2</id>
    <properties>
      <activeProfile>profile2</activeProfile>
    </properties>
  </profile>
</profiles>

添加maven-war-plugin并设置<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>以便在运行mvn package -Pprofile1mvn package -Pprofile2时替换占位符:

<build>
  <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.2.2</version>
    <configuration>
      <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
    </configuration>
  </plugin>
</build>

2

Spring Boot插件本身可以帮助:

  <profiles>
    <profile>
      <id>postgres</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
              <jmxPort>9001</jmxPort>
              <environmentVariables>
                <SPRING_PROFILES_ACTIVE>postgres</SPRING_PROFILES_ACTIVE>
              </environmentVariables>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
    <profile>
      <id>h2</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
              <jmxPort>9002</jmxPort>
              <environmentVariables>
                <SPRING_PROFILES_ACTIVE>h2</SPRING_PROFILES_ACTIVE>
              </environmentVariables>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

2
我目前正在构建一个小型Web应用程序,由于某些原因,它必须能够在仅支持Servlet 2.5和Java 6的旧服务器/容器上运行。此外,Web应用程序配置需要完全自包含,因此甚至不能使用系统变量和/或JVM参数。管理员只希望为每个环境提供一个.war文件,以便将其放入容器进行部署。
我在我的Web应用程序中使用了Spring 4.x。以下是我如何配置应用程序,使活动Maven配置文件用于设置活动的Spring 4.x配置文件。 pom.xml文件更改
我向我的POM文件添加了以下内容。我的POM使用模型版本4.0.0,并且在构建时我运行的是Maven 3.1.x。
<modelVersion>4.0.0</modelVersion>

...

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <!-- Default to dev so we avoid any accidents with prod! :) -->
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <!-- This can be a single value, or a comma-separated list -->
            <spring.profiles.to.activate>dev</spring.profiles.to.activate>
        </properties>
    </profile>
    <profile>
        <id>uat</id>
        <properties>
            <!-- This can be a single value, or a comma-separated list -->
            <spring.profiles.to.activate>uat</spring.profiles.to.activate>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <!-- This can be a single value, or a comma-separated list -->
            <spring.profiles.to.activate>prod</spring.profiles.to.activate>
        </properties>
    </profile>
</profiles>

...

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <webResources>
                    <webResource>
                        <filtering>true</filtering>
                        <directory>src/main/webapp</directory>
                        <includes>
                            <include>**/web.xml</include>
                        </includes>
                    </webResource>
                </webResources>
                <failOnMissingWebXml>true</failOnMissingWebXml>
            </configuration>
        </plugin>
        ...
    </plugins>
</build>

web.xml file changes

<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Setup for root Spring context
-->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-core-config.xml</param-value>
</context-param>
<!--
Jim Tough - 2016-11-30
Per Spring Framework guide: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-environment

...profiles may also be activated declaratively through the spring.profiles.active 
property which may be specified through system environment variables, JVM system 
properties, servlet context parameters in web.xml, or even as an entry in JNDI.
-->
<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>${spring.profiles.to.activate}</param-value>
</context-param>
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->

现在我可以创建基于Java的配置类,就像下面这个例子一样,只有在特定的Spring配置文件被激活时才会使用。
@Configuration
@Profile({"dev","default"})
@ComponentScan
@EnableTransactionManagement
@EnableSpringDataWebSupport
public class PersistenceContext {
    // ...
}

0
在Spring Boot应用程序中,有几种设置配置文件的方式(如dev、uat、prod等)。
例如:您可以将以下内容添加到配置文件中:
spring.profiles.active=dev

编程方式:

SpringApplication.setAdditionalProfiles("dev");

要指定哪些配置文件是活动的,请使用此行代码

@ActiveProfiles("dev")

在Unix环境中
export spring_profiles_active=dev

使用dev配置文件运行jar文件。

java -jar -Dspring.profiles.active=dev JARNAME.jar

这里的 JARNAME.jar 指的是你的应用程序的jar包


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接