使用Maven和Spring控制项目:如何使用Maven配置文件设置Spring配置文件?

11

我正在尝试根据特定的Maven配置文件来配置一个Spring配置文件中的数据库信息。我已经看到了一些相关的答案,但是我很难将它们整合起来。

我有一个像这样的Maven配置文件:

<profiles>
    <profile>
        <id>production</id>
        <activation>
            <property>
                <name>environment.type</name>
                <value>prod</value>
            </property>
        </activation>
    </profile>

    <profile>
        <id>development</id>
        <activation>
            <property>
                <name>environment.type</name>
                <value>dev</value>
            </property>
        </activation>

        <!-- Database properties for Spring -->
        <properties>
            <db.driver>oracle.jdbc.driver.OracleDriver</db.driver>
            <db.type>oracle</db.type>
            <db.host>192.168.0.0</db.host>
            <db.port>1521</db.port>
            <db.name>myDb</db.name>
            <db.url>jdbc:${db.type}:thin:@${db.host}:${db.port}:${db.name}</db.url>
        </properties>

还有一个像这样的 settings.xml 文件:

<servers>
  <server>
    <id>development</id>
    <username>jsmith</username>
    <password>secret</password>
  </server>
</servers>

....

<profiles>
  <profile>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>

    <properties>
      <environment.type>dev</environment.type>
    </properties>
  </profile>
</profiles>

而在 servlet-context.xml 文件中:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
    <property name="driverClassName">
        <value>${db.driver}</value>
    </property>

    <property name="url">
        <value>${db.url}</value>
    </property>

    <property name="username">
        <value>${db.username}</value>
    </property>

    <property name="password">
        <value>${db.password}</value>
    </property>

    <property name="maxActive">
        <value>10</value>
    </property>

    <property name="maxIdle">
        <value>1</value>
    </property>
</bean>

我的问题基本上是,我如何将Maven属性获取到servlet-context.xml文件中?我需要一个.properties文件吗?我知道一些关于在Maven中过滤和在Spring中使用PropertyPlaceholderConfigurer的知识,但我不知道如何将它们结合起来--或者它们是否应该结合在一起?还是有更简单的方法?

3个回答

10

我需要使用 .properties 文件吗?

一般来说,是的,你需要使用 .properties 文件,这通常是我们做的事情,尤其是在 Spring 上下文文件中处理数据库连接配置。

.properties 文件的目的是提供在应用程序运行时配置数据库连接的能力(对于 Web 应用程序来说,通常需要在更改 .properties 文件后重新启动应用程序容器/服务器)。这通常是在不同环境(DEV/TEST/UAT/PROD)的应用程序部署/安装步骤中完成的。

在 pom.xml 中存储这些数据库连接设置并不是一个好的实践,因为 pom.xml 的目的是项目描述,并且仅在应用程序构建时使用一次(例如 mvn deploy)。并且大多数情况下,即使它被打包到最终的 jar/war 文件中,我们在构建应用程序后也不会真正关心和操作它。

要在 Spring 上下文中使用 .properties 文件,请在 applicationContext 中定义一个 propertyConfigurer bean,例如:

<bean id="propertyConfigurer"
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
    <list>
      <!-- Default location inside war file -->
      <value>classpath:db.properties</value>
      <!-- Environment specific location, a fixed path on server -->
      <value>file:///opt/my-web-app/conf/db.properties</value>
    </list>
  </property>
  <property name="ignoreResourceNotFound" value="true"/>
</bean>
希望这有意义。

可以的,谢谢!我在让servlet-context.xml“看到”配置文件方面遇到了麻烦。此外,有没有办法让Maven配置文件控制servlet-context.xml看到哪个配置文件? - ksnortum
你的applicationContext将通过PropertyPlaceholderConfigurer查看配置文件。您可以使用maven配置文件来包含/排除特定环境依赖的资源,但是对于配置文件我们通常不这样做。 - yorkw
@yorkw 独立应用程序怎么样?为什么我不能随时更改独立应用程序的属性呢? - VB_

5

根据我所学和研究的两个答案,我成功地创建了一个由pom控制的开发/生产系统,可以设置正确的数据库值。

首先,在pom中,我创建了两个配置文件。

<!-- Production and Development Profiles -->

<profiles>
    <!-- Nike profile needs go here -->
    <profile>
        <id>production</id>
        <activation>
            <property>
                <name>environment.type</name>
                <value>prod</value>
            </property>
        </activation>
    </profile>

    <!-- Catalyst profile needs go here -->
    <profile>
        <id>development</id>
        <activation>
            <property>
                <name>environment.type</name>
                <value>dev</value>
            </property>
        </activation>

        <build>

            <!-- This holds the properties for the Spring context file.
                 Database values will be changes to development. -->
            <filters>
                <filter>src/main/resources/dev.database.properties</filter>
            </filters>

            <resources>

                <!-- This is the directory that holds the Spring context
                     file.  The entire folder is searched, so either no
                     other file should have place holders or you should
                     exclude other files from being filtered. -->
                <resource>
                    <directory>src/main/webapp/WEBINF/</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
    </profile>
</profiles>

在WEB-INF目录下的servlet-context.xml文件中,我放置了占位符:
<!-- For database, uses maven filtering to fill in placeholders -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url"             value="${db.url}" />
    <property name="username"        value="${db.username}" />
    <property name="password"        value="${db.password}" />
    <property name="maxActive">
        <value>10</value>
    </property>
    <property name="maxIdle">
        <value>1</value>
    </property>
</bean>

接下来,我创建了一个属性文件,放置在src/main/resources目录下。

#
# Development database properties file
#
db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:[USER/PASSWORD]@[HOST][:PORT]:SID
db.username=jsmith
db.password=s3cr3t

我可以通过以下命令启动Maven

mvn -P developement clean install

或者我有一个settings.xml文件,可以为我设置正确的配置文件:

<settings>
  <profiles>
    <profile>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>

      <properties>
        <environment.type>dev</environment.type>
      </properties>
    </profile>
  </profiles>   
</settings>

3
主要问题是:您将如何将WAR文件部署到不同的环境中?通过RPM、Jenkins构建,还是手动操作?此外,您是否希望将相同的WAR文件部署到所有环境中?
a) 如果您想通过JENKINS作业(或通过maven手动处理)来部署WAR文件,只需处理资源并在jar的构建过程中使用配置文件(mvn -P production clean deploy),maven pom应包含类似以下的代码:
    <filters>
        <filter>${config.maven.plattform.resources}/environment/${config.environment.dir}/your_proyect.properties</filter>
    </filters>
    <resources>
        <resource>
            <directory>resources/servlet-context.xml</directory>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>target/generated-resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>

你应该在文件your_project.properties中定义你的属性 (每个环境一个) , 并且为所有不同的配置文件定义config.environment.dir。
b) 你希望为所有项目使用相同的WAR/RPM等,则必须将环境定义为应用服务器Java启动时的一个属性:-DENVIRONMENT=production,然后使用参数化的PropertyPlaceholderConfigurer加载所有属性,正如yorkw所指出的那样。
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
        <value>classpath:environment/${ENVIRONMENT}/your_project.properties</value>
        </list>
    </property>
</bean>

也要记得将所有属性放在WAR中,WAR构建的pom应该包含以下代码:
                <execution>
                    <id>copy-env-resources</id>
                    <!-- here the phase you need -->
                    <phase>validate</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${basedir}/src/main/webapp/WEB-INF/classes/environment/</outputDirectory>
                        <overwrite>true</overwrite>
                        <resources>
                            <resource>
                                <directory>${basedir}/${build_to_all_your_environments}</directory>
                                <includes>
                                    <include>**/*.properties</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>

c) 混合型:您可以手动选择一个环境,覆盖服务器属性(-D)中定义的环境。如果使用默认属性未找到,则回退到该环境的属性。这一步相当复杂,因为它需要另一组属性。如果您感兴趣,请查看我的帖子:使用Maven和Spring进行不同环境的部署。我也对c)有更好的解决方案感兴趣。


谢谢,我会尝试这些方法。在开发中,我们只是通过Eclipse运行Tomcat来运行应用程序,并且需要将其指向dev DB。对于生产环境,它将是一个WAR文件,在JBoss中指向生产DB。 - ksnortum

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