2012-08-22 49 views
7

我需要從我的項目之外的位置讀取和過濾屬性文件,例如$ {user.home} /my.properties。此屬性文件看起來是這樣的:如何從Maven POM中的文件設置構建屬性?

res.dir=/my/stuff/here 
resource.dir=C:/${res.dir} 
bin.dir=${resource.dir}/bin 
cfg.dir=${resource.dir}/config 

我必須這樣做,既在我的構建和我的應用程序在運行時。在Ant中使用PROPERTY tag很容易。但是,在Maven中似乎沒有一種好方法。

到目前爲止,我已經嘗試了Maven <property>標記,Maven <filter>標記和其他標記的各種排列。我的構建失敗或者單元測試失敗,或者兩者都失敗。

如果我將這些屬性硬編碼到POM中,一切正常,所以我知道問題只是讀取屬性。我看着properties-maven-plugin,但插件似乎不再被維護。

有沒有辦法做到這一點?

+0

我看到了關於該插件的評論,所以刪除了我的答案。只是想讓你知道,無論是維持還是不維護,它都有效。 (或者至少,用於工作)。 – crnlx

+0

感謝您的回覆。是的,我會認爲,如果插件不再被維護,甚至被開發出來(它被列爲「Alpha」),那麼它是如此的棒極了,沒有進一步的發展是可能的(可疑的),或者有更好的方法來做到這一點。我希望有人會指點我「更好的方式」。 – user1071914

+1

是什麼使你認爲插件不再被維護?此外,Maven項目之外的屬性將使您的項目依賴於那些會破壞Maven概念的項目,以便爲項目內部的Maven項目提供所有需要的東西。問題是爲什麼你需要這個? – khmarbaise

回答

7

你可以簡單地實施你自己的maven-plugin,這將爲你照顧這個。

這裏是具有以下結構的示例:

. 
|-- pom.xml 
|-- plugin 
| `-- pom.xml 
| `-- src 
|  `-- main 
|   `-- java 
`-- app 
    `-- pom.xml 
    `-- src 
     `-- main 
      `-- java 

你將需要創建一個魔,是以屬性文件作爲輸入,並然後傳播特性的apppom.xmlpom.xml實際上不會更新,只是其中的項目數據。

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.stackoverflow</groupId> 
    <artifactId>Q12082277</artifactId> 
    <version>1.0-SNAPSHOT</version> 
    <packaging>pom</packaging> 

    <name>${project.artifactId}-${project.version}</name> 

    <modules> 
     <module>plugin</module> 
     <module>app</module> 
    </modules> 

</project> 

plugin/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <parent> 
     <groupId>com.stackoverflow</groupId> 
     <artifactId>Q12082277</artifactId> 
     <version>1.0-SNAPSHOT</version> 
    </parent> 

    <artifactId>Q12082277-plugin</artifactId> 
    <packaging>maven-plugin</packaging> 

    <name>${project.artifactId}-${project.version}</name> 

    <dependencies> 
     <dependency> 
      <groupId>org.apache.maven</groupId> 
      <artifactId>maven-plugin-api</artifactId> 
      <version>3.0.4</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.maven</groupId> 
      <artifactId>maven-project</artifactId> 
      <version>2.2.1</version> 
     </dependency> 
    </dependencies> 
</project> 

plugin/src/main/java/com/stackoverflow/Q12082277/plugin/PropertiesMojo.java

package com.stackoverflow.Q12082277.plugin; 

import org.apache.maven.plugin.AbstractMojo; 
import org.apache.maven.plugin.MojoExecutionException; 
import org.apache.maven.plugin.MojoFailureException; 
import org.apache.maven.plugin.logging.Log; 
import org.apache.maven.project.MavenProject; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.util.Properties; 

/** 
* @author maba, 2012-08-24 
* 
* @goal extract 
*/ 
public class PropertiesMojo extends AbstractMojo { 

    private Log log; 

    /** 
    * The current project representation. 
    * @parameter expression="${project}" 
    * @required 
    * @readonly 
    */ 
    private MavenProject project; 

    /** 
    * A properties file 
    * 
    * @parameter expression="${propertiesFile}" 
    * @required 
    */ 
    private File propertiesFile; 

    @Override 
    public void execute() throws MojoExecutionException, MojoFailureException { 
     log.info("Executing PropertiesMojo on " + propertiesFile.getAbsolutePath()); 

     try { 
      Properties fileProperties = new Properties(); 
      fileProperties.load(new FileInputStream(propertiesFile)); 
      Properties projectProperties = project.getProperties(); 
      for (Object key : fileProperties.keySet()) { 
       projectProperties.setProperty((String)key, (String) fileProperties.get(key)); 
      } 
      project.getProperties().list(System.out); 
     } catch (FileNotFoundException e) { 
      throw new MojoFailureException("The file " + propertiesFile.getAbsolutePath() + " was not found!", e); 
     } catch (IOException e) { 
      log.error(""); 
     } 

    } 

    @Override 
    public void setLog(Log log) { 
     this.log = log; 
    } 
} 

您將使用這個插件從以下app/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <parent> 
     <groupId>com.stackoverflow</groupId> 
     <artifactId>Q12082277</artifactId> 
     <version>1.0-SNAPSHOT</version> 
    </parent> 

    <artifactId>Q12082277-app</artifactId> 

    <name>${project.artifactId}-${project.version}</name> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>com.stackoverflow</groupId> 
       <artifactId>Q12082277-plugin</artifactId> 
       <version>1.0-SNAPSHOT</version> 
       <executions> 
        <execution> 
         <phase>initialize</phase> 
         <goals> 
          <goal>extract</goal> 
         </goals> 
         <configuration> 
          <propertiesFile>${user.home}/my.properties</propertiesFile> 
         </configuration> 
        </execution> 
       </executions> 
      </plugin> 
      <plugin> 
       <groupId>org.codehaus.mojo</groupId> 
       <artifactId>exec-maven-plugin</artifactId> 
       <version>1.2.1</version> 
       <executions> 
        <execution> 
         <goals> 
          <goal>java</goal> 
         </goals> 
        </execution> 
       </executions> 
       <configuration> 
        <mainClass>com.stackoverflow.Q12082277.App</mainClass> 
       </configuration> 
      </plugin> 
     </plugins> 
     <resources> 
      <resource> 
       <directory>src/main/resources</directory> 
       <filtering>true</filtering> 
      </resource> 
     </resources> 
    </build> 
</project> 

,然後你將不得不添加以下app.properties,將工作作爲模板,並採取我們剛纔從文件中讀取和設置它們的值,並創建一個具體的文件app.properties,這將是從罐子內到達。

app/src/main/resources/app.properties

res.dir=${res.dir} 
resource.dir=${resource.dir} 
bin.dir=${bin.dir} 
cfg.dir=${cfg.dir} 

最後這裏是剛剛從加載classpath中app.properties並打印出結果的測試應用程序。

app/src/main/java/com/stackoverflow/Q12082277/App.java

package com.stackoverflow.Q12082277; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Properties; 

/** 
* @author maba, 2012-08-23 
*/ 
public class App { 

    public static void main(String[] args) throws IOException { 
     ClassLoader loader = App.class.getClassLoader(); 
     InputStream in = loader.getResourceAsStream("app.properties"); 
     Properties properties = new Properties(); 
     properties.load(in); 
     properties.list(System.out); 
    } 
} 

現在你可以站在頂層目錄並執行

mvn install 

然後下到app文件夾,並執行

mvn exec:java 

它將打印

-- listing properties -- 
resource.dir=C://my/stuff/here 
cfg.dir=C://my/stuff/here/config 
bin.dir=C://my/stuff/here/bin 
res.dir=/my/stuff/here 

這正是你想要的。

+0

這似乎是最好的答案 - 我並不高興Maven的工具集中的這個大漏洞尚未解決,但嘿,我想,歡迎來到開源。 :-( – user1071914

3

我認爲如果將屬性文件轉換爲模板文件並使用pom.xml使用maven resource filtering來獲取屬性會更好。

一個簡單的設置看起來像這樣

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.stackoverflow</groupId> 
    <artifactId>Q12082277</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <name>${project.artifactId}-${project.version}</name> 

    <properties> 
     <res.dir>/default/stuff/here</res.dir> 
     <resource.dir>${res.dir}</resource.dir> 
     <bin.dir>${resource.dir}/bin</bin.dir> 
     <cfg.dir>${resource.dir}/config</cfg.dir> 
    </properties> 

    <dependencies> 
    <!-- Your dependencies --> 
    </dependencies> 

    <build> 
     <resources> 
      <resource> 
       <directory>src/main/resources</directory> 
       <filtering>true</filtering> 
      </resource> 
     </resources> 
    </build> 

</project> 

src/main/resources/app.properties

res.dir=${res.dir} 
resource.dir=${resource.dir} 
bin.dir=${bin.dir} 
cfg.dir=${cfg.dir} 

src/main/java/com/stackoverflow/Q12082277/App.java

package com.stackoverflow.Q12082277; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Properties; 

/** 
* @author maba, 2012-08-23 
*/ 
public class App { 

    public static void main(String[] args) throws IOException { 
     ClassLoader loader = App.class.getClassLoader(); 
     InputStream in = loader.getResourceAsStream("app.properties"); 
     Properties properties = new Properties(); 
     properties.load(in); 
     properties.list(System.out); 
    } 
} 

System.out

-- listing properties -- 
resource.dir=/default/stuff/here 
cfg.dir=/default/stuff/here/config 
bin.dir=/default/stuff/here/bin 
res.dir=/default/stuff/here 

pom.xml將有被大家使用的默認屬性。

如果你想要覆蓋的值,然後調用行家帶輸入參數:

mvn install -Dres.dir=/my/stuff/here -Dresource.dir="C:/${res.dir}" 

System.out

-- listing properties -- 
resource.dir=C://my/stuff/here 
cfg.dir=C://my/stuff/here/config 
bin.dir=C://my/stuff/here/bin 
res.dir=/my/stuff/here 

通過做這樣每個人都會有相同的性能視圖,可以如果你想在自己的機器上運行時覆蓋它們。

+0

感謝您的建議,不幸的是,它目前的佈局方式(將這些屬性放在一個單獨的文件中)是一個公司標準,並不適合討論,所以我堅持使用它的方式。 – user1071914

+0

@ user1071914嘗試使用maven antrun插件。它可能會做你需要的。 – maba

+0

@ user1071914我添加了另一個答案,它實現了一個簡單的mojo,它可以做你想做的。 – maba

相關問題