有没有可能让`mvn tomcat6:run`与过滤的web.xml一起正常工作?

时间:2017-11-15 15:05:27

标签: java maven tomcat

我有一个项目需要将${}占位符替换应用于web.xml我希望使用mvn tomcat6:run运行的开发模式。是否可以设置它?

这是一个遗留代码库,我试图引入这两个部署环境,以摆脱之前的过程,即复制web.xml变体并编辑配置文件并将其保持在源代码之外控制&#34。我还想避免维护Tomcat安装并设置IDE以进行部署,并且只需使用tomcat6-maven-plugin执行应用程序。

到目前为止,我所拥有的是这个项目布局:

foo
│   pom.xml
│
└───src
    └───main
        ├───environments
        │   ├───BAR
        │   │       filter.properties
        │   │
        │   └───FOO
        │           filter.properties
        │
        ├───java
        │   └───se
        │       └───millimoo
        │               IndexServlet.java
        │
        └───webapp
            └───WEB-INF
                    web.xml

pom.xml

...
<build>
    <filters>
        <filter>src/main/environments/${environment}/filter.properties</filter>
    </filters>
    <resources>
        <resource>
            <directory>src/main/environments/${environment}</directory>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat6-maven-plugin</artifactId>
            <version>2.2</version>
        </plugin>
    </plugins>
</build>

<profiles>
    <profile>
        <id>env-foo</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <environment>FOO</environment>
        </properties>
    </profile>
    <profile>
        <id>env-bar</id>
        <properties>
            <environment>BAR</environment>
        </properties>
    </profile>
</profiles>
...

即:我将环境的目录添加为资源;告诉Maven从该目录中的filter.properties加载占位符值;并告诉WAR插件过滤部署描述符。我还设置了两个配置文件来在环境之间切换。

FOO\filter.properties

filter.environment=foofoo

BAR\filter.properties

filter.environment=barbar

web.xml

...
<servlet>
    <servlet-name>Index</servlet-name>
    <servlet-class>se.millimoo.IndexServlet</servlet-class>
    <init-param>
        <param-name>environment</param-name>
        <param-value>${filter.environment}</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>Index</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
...

IndexServlet.java

打印environment init参数的值。

当我使用mvn tomcat6:run运行时,会使用未经过滤的web.xml,这显然不是我想要的。我使用mvn tomcat6:run-war时会使用过滤后的版本,但我并不喜欢它:它速度较慢,而且我的实际代码中存在其他问题,通常会减慢周转时间,这就是练习的重点。 (它使用依赖项目的JAR文件,其中后端代码来自Maven存储库以构建JAR,如果我在版本号颠簸后没有安装它们,它可能会过时或根本不可用;而不是使用当前代码。)

有没有办法在这里获得两全其美?能够通过maven或其他易于嵌入的方式运行应用服务器,同时还应用于web.xml的过滤?最好不要显着改变应用程序本身,即我不想在不使用servlet init参数的情况下加载配置值。 (在实际代码中,servlet是第三方的。)

2 个答案:

答案 0 :(得分:1)

我认为您需要在pom.xml中添加此内容,以便Maven知道他也需要过滤此目录:

<build>
    <resources>
        <resource>
            <directory>src/main/webapp/WEB-INF</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
...
</build>

修改

正如评论中所讨论的,这种方法可能不是一个好的解决方案。

另一种解决方案:

  

覆盖默认目标目录

     

默认情况下,Web资源被复制到WAR的根目录,如图所示   在前面的例子中。覆盖默认目标   目录,指定目标路径。

        ...
        <configuration>
          <webResources>
            <resource>
              ...
            </resource>
            <resource>
              <directory>configurations</directory>
              <!-- override the destination directory for this resource -->
              <targetPath>WEB-INF</targetPath>
              <!-- enable filtering -->
              <filtering>true</filtering>
              <excludes>
                <exclude>**/properties</exclude>
              </excludes>
            </resource>
          </webResources>
        </configuration>
        ...

在此示例中,我们覆盖了一个目录,但也许可以覆盖单个文件。

答案 1 :(得分:0)

似乎我想要的目标是tomcat6:run-war-only,它会在target/中的已组装的webapp上启动Tomcat。但是,此目标在单独运行时不会调用生命周期的其余部分,这意味着应用程序可能无法组装或更新。我首先在生命周期的war:war阶段用war:war-exploded替换package目标,然后在下一个生命周期阶段将tomcat6:run-war-only绑定到verify,从而解决了这个问题。 (对于war项目来说,这很方便,并没有任何目标,并且在语义上似乎是合适的。)为了保持这一点,我将其放入一个配置文件中:

<profile>
    <id>embedded</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <!-- Replace running war:war with war:exploded in the lifecycle -->
                    <execution>
                        <id>embedded-war</id>
                        <goals>
                            <goal>exploded</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                    <execution>
                        <id>default-war</id>
                        <phase>none</phase>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat6-maven-plugin</artifactId>
                <version>2.2</version>
                <executions>
                    <!-- Run Tomcat over the assembled webapp -->
                    <execution>
                        <id>embedded-verify</id>
                        <goals>
                            <goal>run-war-only</goal>
                        </goals>
                        <phase>verify</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

结合问题中已经提供的内容,运行foo环境,您可以使用:

mvn -P embedded,env-foo verify

这样做的一个缺陷是,它不会反映视图等的实时更改,但在Tomcat服务器运行时运行mvn war:exploded重新组装应用程序时应该注意这一点。