如何使用 Maven 配置文件设置弹簧活动配置文件

Posted

技术标签:

【中文标题】如何使用 Maven 配置文件设置弹簧活动配置文件【英文标题】:How to set spring active profiles with maven profiles 【发布时间】:2014-10-14 18:10:07 【问题描述】:

我有一个使用 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 作为活动配置文件。

【问题讨论】:

【参考方案1】:

您必须过滤应用程序的资源,例如属性文件,其中包含要在 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:这实际上是一种不好的做法,您应该在运行时使用系统属性设置配置文件

【讨论】:

为什么这是不好的做法?我想要做的是根据 maven 配置文件启用某些 bean,这些 bean 与不同环境的配置相得益彰。我没有使用网络应用程序。这是一个简单的可执行jar。使用资源解决方案,我需要首先提升我的上下文,然后设置活动配置文件,然后刷新可能会删除一些创建的 bean 并创建其他的。我希望在没有开关的情况下加载正确的 bean @Gleeb 好吧,总的来说,提供一个独特的版本会更好(因为更灵活),它会根据运行时配置的不同而表现不同,而不是生成 3 个不同的二进制文件。但这仍然取决于您的业务。这取决于你:p 在 java 基本配置中的任何示例? (非 web.xml) 关于你的第一个笔记,命令是 >mvn help:active-profiles【参考方案2】:

有一种更优雅的方式可以同时在 2 个 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 DB 上运行我的网络应用 使用mvn clean jetty:run -Dspring.profiles.active=h2 在 H2 DB 上运行我的网络应用程序

【讨论】:

这对我的用例来说要好得多。这次真是万分感谢。请注意,如果 Maven 配置文件在 spring.profiles.active 旁边显式设置,那么它将优先【参考方案3】:

我目前正在构建一个小型 webapp(由于我无法控制的原因)必须能够在仅支持 Servlet 2.5 和 Java 6 的旧服务器/容器上运行。还需要 webapp 配置完全独立,因此即使是系统变量和/或 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 文件更改

<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 
    // ...

【讨论】:

【参考方案4】:

您首先需要两个属性文件来保存您的配置。文件的名称应与模式 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 表示法。

效果非常好。希望对您有所帮助。

【讨论】:

我只是想补充一点,你也可以在生成战争时选择配置文件:mvn package -P release(释放你在POM中定义的maven配置文件的id) 这仅在 Spring boot 或 Spring Framework 中有效吗?我的意思是application.properties 部分中的spring.profiles.active?请您指导我查看讨论此问题的文档部分吗?【参考方案5】:

在 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>

在运行mvn package -Pprofile1mvn package -Pprofile2时添加maven-war-plugin并设置&lt;filteringDeploymentDescriptors&gt;true&lt;/filteringDeploymentDescriptors&gt;替换占位符:

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

【讨论】:

【参考方案6】:

对于 Spring Boot 应用程序,可以在 pom.xml 的 Maven 配置文件中添加一个属性,然后在 application.properties 中引用该属性。

将 Maven 配置文件添加到 pom.xml,例如使用名为 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 会将 postgres Spring 配置文件添加到 Spring 的活动配置文件列表中,而使用 noDb 运行 maven Maven 配置文件会添加 noDb将 Spring 配置文件添加到 Spring 的活动配置文件列表中。

【讨论】:

【参考方案7】:

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>

【讨论】:

【参考方案8】:

在spring boot应用中,设置profile有几种方式(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

【讨论】:

以上是关于如何使用 Maven 配置文件设置弹簧活动配置文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 bootWar 设置活动弹簧配置文件

如何从环境变量中添加活动弹簧配置文件?

在 docker 中使用 gradle 设置活动弹簧配置文件没有任何效果

如何强制弹簧只有一个活动配置文件?

Maven 配置文件属性不会覆盖弹簧配置中的值

使用 maven 构建时选择弹簧配置文件