Configuration 如何在几个maven项目之间共享公共属性?

Configuration 如何在几个maven项目之间共享公共属性?,configuration,maven-2,properties-file,Configuration,Maven 2,Properties File,我有几个由maven构建的项目,我想在它们之间共享一些共同的属性——spring版本、mysql驱动程序版本、svn基本url等等——所以我可以对它们进行一次更新,它将反映在所有项目上 我曾想过拥有一个具有所有属性的超级pom,但如果我改变了其中一个问题,我需要增加它的版本(并更新它继承的所有pom),或者从所有开发人员的机器上删除它,我不想这样做 可以在pom外部指定这些参数吗?我仍然希望在父pom中具有外部位置定义。您可以使用。这将允许您在外部文件中定义属性,插件将读取此文件 使用此配置:

我有几个由maven构建的项目,我想在它们之间共享一些共同的属性——spring版本、mysql驱动程序版本、svn基本url等等——所以我可以对它们进行一次更新,它将反映在所有项目上

我曾想过拥有一个具有所有属性的超级pom,但如果我改变了其中一个问题,我需要增加它的版本(并更新它继承的所有pom),或者从所有开发人员的机器上删除它,我不想这样做


可以在pom外部指定这些参数吗?我仍然希望在父pom中具有外部位置定义。

您可以使用。这将允许您在外部文件中定义属性,插件将读取此文件

使用此配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>properties-maven-plugin</artifactId>
            <version>1.0-alpha-1</version>
            <executions>
                <execution>
                    <phase>initialize</phase>
                    <goals>
                        <goal>read-project-properties</goal>
                    </goals>
                    <configuration>
                        <files>
                            <file>my-file.properties</file>
                        </files>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
这与您在pom.xml中编写以下行是一样的:

spring-version=1.0
mysql-version=4.0.0
<properties>
    <spring-version>1.0</spring-version>
    <mysql-version>4.0.0</mysql-version>
</properties>

1
4.0.0
使用此插件,您将获得以下好处:

  • 轻松设置一长串属性
  • 修改这些属性的值,而不修改父pom.xml
    • 请注意,我这里的原始想法是我正在做的事情,但我可能已经找到了一个更好的想法,我也在下面列出了。为了完整起见,我想把这两个想法都保留在这里,以防新想法不起作用


      我认为您可以使用父pom解决这个问题,但是您需要有一个maven存储库和一个CI构建工具

      我有几个项目都从父POM继承基本属性。我们使用Java1.5,所以在那里设置了build属性。一切都是UTF-8。我希望运行的所有报告、声纳设置等都在父POM中

      假设您的项目处于版本控制中,并且您有一个CI工具,当您签入时,您的CI工具可以构建到POM项目,并将快照部署到maven repos。如果您的项目指向父POM的快照版本,它们将检查存储库以验证是否具有最新版本…如果没有,则下载最新版本。因此,如果更新父项目,所有其他项目都将更新

      我想关键在于发布快照。我要说的是,你的发布会比你的更改来得少得多。因此,您执行POM的发布,然后更新从POM继承的POM,并将其签入版本控制。让开发人员知道他们需要进行更新并从那里开始

      您可以在那里触发构建,强制将新POM放入存储库,然后让所有开发人员在构建时自动获取更改


      我删除了最新发布的关键字,因为它们不适用于父级POM。它们只适用于依赖项或插件。问题区域位于DefaultMavenProjectBuilder中。本质上,它很难确定要查找哪个存储库来确定最新版本或发布版本。不过,我不知道为什么这与依赖项或插件不同



      听起来这比每次更改父POM时都要更新POM要轻松得多。

      从长远来看,我认为properties maven插件是正确的方法,但当您回答这个问题时,它不允许继承属性。maven共享io中有一些工具允许您发现项目类路径上的资源。我在下面包含了一些扩展属性插件的代码,以在插件的依赖项中查找属性文件

      配置声明了属性文件的路径,因为描述符项目是在插件配置上声明的,所以ClassPathResourceLocator策略可以访问它。配置可以在父项目中定义,并将由所有子项目继承(如果这样做,请避免声明任何文件,因为它们不会被发现,请仅设置filePaths属性)

      下面的配置假定存在另一个名为name.seller.rich:testproperties descriptor:0.0.1的jar项目,该项目将一个名为external.properties的文件打包到jar中(即,它是在src/main/resources中定义的)

      
      org.codehaus.mojo
      *@作者
      *@version$Id:ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier$
      *@goal读取项目属性
      */
      公共类ReadPropertiesMojo扩展了AbstractMojo{
      /**
      *@parameter default value=“${project}”
      *@必需
      *@readonly
      */
      私人马文项目;
      /**
      *读取属性时将使用的属性文件。
      *RS:为避免继承插件的问题,将其设置为可选
      *@参数
      */
      私有文件[]文件;
      //开始:RS添加
      /**
      *要使用的属性文件的可选路径。
      * 
      *@参数
      */
      私有字符串[]文件路径;
      //完:RS加法
      /**
      *如果没有找到任何文件,插件是否应该保持安静
      * 
      *@parameter default value=“false”
      */
      私人布尔安静;
      public void execute()引发MojoExecutionException异常{
      //开始:RS添加
      readPropertyFiles();
      //完:RS加法
      Properties projectProperties=新属性();
      对于(int i=0;i<plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>properties-ext-maven-plugin</artifactId>
        <version>0.0.1</version>
        <executions>
          <execution>
            <id>read-properties</id>
            <phase>initialize</phase>
            <goals>
              <goal>read-project-properties</goal>
            </goals>
          </execution>
        </executions>                              
        <configuration>
          <filePaths>
            <filePath>external.properties</filePath>
          </filePaths>
        </configuration> 
        <dependencies>
          <!-- declare any jars that host the required properties files here -->
          <dependency>
            <groupId>name.seller.rich</groupId>
            <artifactId>test-properties-descriptor</artifactId>
            <version>0.0.1</version>
          </dependency>
        </dependencies>
      </plugin>
      
      <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>properties-ext-maven-plugin</artifactId>
        <packaging>maven-plugin</packaging>
        <version>0.0.1</version>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>properties-maven-plugin</artifactId>
            <version>1.0-alpha-1</version>
          </dependency>
          <dependency>
            <groupId>org.apache.maven.shared</groupId>
            <artifactId>maven-shared-io</artifactId>
            <version>1.1</version>
          </dependency>
        </dependencies>
      </project>
      
      package org.codehaus.mojo.xml;
      
      /*
       * Licensed to the Apache Software Foundation (ASF) under one
       * or more contributor license agreements.  See the NOTICE file 
       * distributed with this work for additional information
       * regarding copyright ownership.  The ASF licenses this file
       * to you under the Apache License, Version 2.0 (the
       * "License"); you may not use this file except in compliance
       * with the License.  You may obtain a copy of the License at
       * 
       *   http://www.apache.org/licenses/LICENSE-2.0
       * 
       * Unless required by applicable law or agreed to in writing, 
       * software distributed under the License is distributed on an
       * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
       * KIND, either express or implied.  See the License for the 
       * specific language governing permissions and limitations 
       * under the License.
       */
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.Enumeration;
      import java.util.List;
      import java.util.Properties;
      
      import org.apache.maven.plugin.AbstractMojo;
      import org.apache.maven.plugin.MojoExecutionException;
      import org.apache.maven.project.MavenProject;
      import org.apache.maven.shared.io.location.ClasspathResourceLocatorStrategy;
      import org.apache.maven.shared.io.location.FileLocatorStrategy;
      import org.apache.maven.shared.io.location.Location;
      import org.apache.maven.shared.io.location.Locator;
      import org.apache.maven.shared.io.location.LocatorStrategy;
      import org.apache.maven.shared.io.location.URLLocatorStrategy;
      import org.codehaus.plexus.util.cli.CommandLineUtils;
      
      /**
       * The read-project-properties goal reads property files and stores the
       * properties as project properties. It serves as an alternate to specifying
       * properties in pom.xml.
       * 
       * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
       * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
       * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
       * @goal read-project-properties
       */
      public class ReadPropertiesMojo extends AbstractMojo {
          /**
           * @parameter default-value="${project}"
           * @required
           * @readonly
           */
          private MavenProject project;
      
          /**
           * The properties files that will be used when reading properties.
           * RS: made optional to avoid issue for inherited plugins
           * @parameter
           */
          private File[] files;
      
          //Begin: RS addition
          /**
           * Optional paths to properties files to be used.
           * 
           * @parameter
           */
          private String[] filePaths;
          //End: RS addition
      
          /**
           * If the plugin should be quiet if any of the files was not found
           * 
           * @parameter default-value="false"
           */
          private boolean quiet;
      
          public void execute() throws MojoExecutionException {
              //Begin: RS addition
              readPropertyFiles();
              //End: RS addition
      
              Properties projectProperties = new Properties();
              for (int i = 0; i < files.length; i++) {
                  File file = files[i];
      
                  if (file.exists()) {
                      try {
                          getLog().debug("Loading property file: " + file);
      
                          FileInputStream stream = new FileInputStream(file);
                          projectProperties = project.getProperties();
      
                          try {
                              projectProperties.load(stream);
                          } finally {
                              if (stream != null) {
                                  stream.close();
                              }
                          }
                      } catch (IOException e) {
                          throw new MojoExecutionException(
                                  "Error reading properties file "
                                          + file.getAbsolutePath(), e);
                      }
                  } else {
                      if (quiet) {
                          getLog().warn(
                                  "Ignoring missing properties file: "
                                          + file.getAbsolutePath());
                      } else {
                          throw new MojoExecutionException(
                                  "Properties file not found: "
                                          + file.getAbsolutePath());
                      }
                  }
              }
      
              boolean useEnvVariables = false;
              for (Enumeration n = projectProperties.propertyNames(); n
                      .hasMoreElements();) {
                  String k = (String) n.nextElement();
                  String p = (String) projectProperties.get(k);
                  if (p.indexOf("${env.") != -1) {
                      useEnvVariables = true;
                      break;
                  }
              }
              Properties environment = null;
              if (useEnvVariables) {
                  try {
                      environment = CommandLineUtils.getSystemEnvVars();
                  } catch (IOException e) {
                      throw new MojoExecutionException(
                              "Error getting system envorinment variables: ", e);
                  }
              }
              for (Enumeration n = projectProperties.propertyNames(); n
                      .hasMoreElements();) {
                  String k = (String) n.nextElement();
                  projectProperties.setProperty(k, getPropertyValue(k,
                          projectProperties, environment));
              }
          }
      
          //Begin: RS addition
          /**
           * Obtain the file from the local project or the classpath
           * 
           * @throws MojoExecutionException
           */
          private void readPropertyFiles() throws MojoExecutionException {
              if (filePaths != null && filePaths.length > 0) {
                  File[] allFiles;
      
                  int offset = 0;
                  if (files != null && files.length != 0) {
                      allFiles = new File[files.length + filePaths.length];
                      System.arraycopy(files, 0, allFiles, 0, files.length);
                      offset = files.length;
                  } else {
                      allFiles = new File[filePaths.length];
                  }
      
                  for (int i = 0; i < filePaths.length; i++) {
                      Location location = getLocation(filePaths[i], project);
      
                      try {
                          allFiles[offset + i] = location.getFile();
                      } catch (IOException e) {
                          throw new MojoExecutionException(
                                  "unable to open properties file", e);
                      }
                  }
      
                  // replace the original array with the merged results
                  files = allFiles;
              } else if (files == null || files.length == 0) {
                  throw new MojoExecutionException(
                          "no files or filePaths defined, one or both must be specified");
              }
          }
          //End: RS addition
      
          /**
           * Retrieves a property value, replacing values like ${token} using the
           * Properties to look them up. Shamelessly adapted from:
           * http://maven.apache.
           * org/plugins/maven-war-plugin/xref/org/apache/maven/plugin
           * /war/PropertyUtils.html
           * 
           * It will leave unresolved properties alone, trying for System properties,
           * and environment variables and implements reparsing (in the case that the
           * value of a property contains a key), and will not loop endlessly on a
           * pair like test = ${test}
           * 
           * @param k
           *            property key
           * @param p
           *            project properties
           * @param environment
           *            environment variables
           * @return resolved property value
           */
          private String getPropertyValue(String k, Properties p,
                  Properties environment) {
              String v = p.getProperty(k);
              String ret = "";
              int idx, idx2;
      
              while ((idx = v.indexOf("${")) >= 0) {
                  // append prefix to result
                  ret += v.substring(0, idx);
      
                  // strip prefix from original
                  v = v.substring(idx + 2);
      
                  idx2 = v.indexOf("}");
      
                  // if no matching } then bail
                  if (idx2 < 0) {
                      break;
                  }
      
                  // strip out the key and resolve it
                  // resolve the key/value for the ${statement}
                  String nk = v.substring(0, idx2);
                  v = v.substring(idx2 + 1);
                  String nv = p.getProperty(nk);
      
                  // try global environment
                  if (nv == null) {
                      nv = System.getProperty(nk);
                  }
      
                  // try environment variable
                  if (nv == null && nk.startsWith("env.") && environment != null) {
                      nv = environment.getProperty(nk.substring(4));
                  }
      
                  // if the key cannot be resolved,
                  // leave it alone ( and don't parse again )
                  // else prefix the original string with the
                  // resolved property ( so it can be parsed further )
                  // taking recursion into account.
                  if (nv == null || nv.equals(nk)) {
                      ret += "${" + nk + "}";
                  } else {
                      v = nv + v;
                  }
              }
              return ret + v;
          }
      
          //Begin: RS addition
          /**
           * Use various strategies to discover the file.
           */
          public Location getLocation(String path, MavenProject project) {
              LocatorStrategy classpathStrategy = new ClasspathResourceLocatorStrategy();
      
              List strategies = new ArrayList();
              strategies.add(classpathStrategy);
              strategies.add(new FileLocatorStrategy());
              strategies.add(new URLLocatorStrategy());
      
              List refStrategies = new ArrayList();
              refStrategies.add(classpathStrategy);
      
              Locator locator = new Locator();
      
              locator.setStrategies(strategies);
      
              Location location = locator.resolve(path);
              return location;
          }
          //End: RS addition
      }