简体   繁体   中英

Selectively copy resources in maven, based on a input parameter?

I am in the process of migrating an Application from Ant to Maven. There are two kinds of environment, this application can be deployed to. One configuration is called Local and the other caller dev, and hence naturally there are two ant targets. Each of ant targets, copies resources from two different folders and makes it part of the final war file.

How do I mimic this behavior in maven? I was thinking of passing a parameter at build time and based on this parameter, we can use maven resources plugin to copy the corresponding folder. Something like this.

<resources>
          <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <excludes>
                    <exclude>${local}/**</exclude>
                </excludes>
            </resource>
        </resources>

Am I in the right path? If yes, how do I substitute "local" at run time? Also, I am doing a complement operation, if we want to build for Dev, then I am excluding local and vice versa. Is there a better way to handle this?

Also if I use this method, the target war, has the entire folder copied to it. How can i configure maven to only copy the folder contents not the entire folder.

When copying resources, Maven will apply the include/exclude pattern to the <directory> value defined, and maintain the path structure from that directory down. There isn't any equivalent to ant's flattenmapper that I've been able to find.

For the rest, consider Maven build profiles . You define profiles that contain the config you want to change at build time, then activate the right profile from the command line. With the config shown below, the command

mvn -Dtarget.env=local process-resources

would copy files from /src/main/resources/local into target/classes . Since 'local' is included in the resource's directory element, it will not appear in the path for the copied resources.

<profiles>
    <profile>
        <id>local</id>
        <activation>
            <property>
                <name>target.env</name>
                <value>local</value>
            </property>
        </activation>
        <properties>
            <resource.dir>local</resource.dir>
        </properties>
    </profile>

    <!-- add a similar profile for dev -->
</profiles>

<resources>
    <resource>
        <directory>src/main/resources/${resource.dir}</directory>
        <filtering>true</filtering>
    </resource>
</resources>

You can do a lot more with profiles that what I showed here. I hope this gets you started even if it doesn't solve your whole use case.

The best thing i can recommend is to create a structure like the following (only with the properties file):

.
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |-- resources
    |   |-- environment
    |   |   |-- test
    |   |   |   `-- database.properties
    |   |   `-- production
    |   |       `-- database.properties
    |   `-- webapp

Create a assembly descriptor like the following to use in combination with the maven-assembly-plugin for each environment one:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">

  <id>test</id>
  <formats>
    <format>war</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>true</unpack>
      <useProjectArtifact>true</useProjectArtifact>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <outputDirectory>WEB-INF</outputDirectory>
      <directory>${basedir}/src/main/environment/test/</directory>
      <includes>
        <include>**</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>

And finally you need an execution for each environment:

 <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
      <execution>
        <id>test</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
        <configuration>
          <descriptors>
            <descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
          </descriptors>
        </configuration>
      </execution>
      <execution>
        <id>production</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
        <configuration>
          <descriptors>
            <descriptor>${project.basedir}/src/main/assembly/production.xml</descriptor>
          </descriptors>
        </configuration>
      </execution>
    </executions>
  </plugin>

The result will be to have via a single build two war files which have been configured for production and the other for development.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM