Maven中的扁平化POM

来源:互联网 发布:java常见异常 编辑:程序博客网 时间:2024/05/16 18:30

Author:  Jia, Weigang.

Maven中的POM大致有两个目的:

  1. 开发人员用POM编译和发布构件
  2. 被其他项目用于依赖管理

对于第一个目的,POM中的关于编译和发布的元素都是有意义的。对于第二个目的,POM中的关于编译和发布的元素就没有意义了。比如,一个项目A依赖于构件B,项目A仅仅需要知道构件B的GroupId、ArtifactId、Version以及构件B的依赖,其他的元素意义都不是很大。

Maven的发布方式是把编译时的POM直接拷贝到远程仓库。这样对于构件的用户而言,他们将看到编译时期POM的各种元素。如果POM有多层父POM,用户也会看到。父POM中可能定义了许多<dependencyManagement>,如果用户需要确定一个依赖的版本,可能需要一层一层的向上层父POM查找,比较繁琐。

对于开发人员编译和发布时使用的POM应该和构件使用者的POM有所不同,对于后者,他们只需要关心构件的GroupId、ArtifactId、Version以及构件的依赖。扁平化POM可以解决这个问题,在扁平化POM中只有构件的GroupId、ArtifactId、Version以及构件的依赖,没有Parent元素。对于每个构件的依赖,它的Version都是被解析过的。

下面详细讨论扁平POM中的元素:

元素

在扁平化POM中变换

注释

modelVersion

“4.0.0”

固定值

groupId

artifactId

version

packaging

被解析过

可能从父POM中解析version

dependencies

被解析过

可能从父POM的<dependencyManagement>中解析出dependencies的所有属性(主要是version)。Scope是test的dependency将会被移除

Other Elements

被移除

构件的用户不关心这些元素

 

  我扩展了maven-deploy-plugin ,增加了一个enableFlatPom参数来实现了扁平化POM,如果这个参数的值是true,maven-deploy-plugin会生成扁平化POM并把它设置成当前项目的POM,然后发布到远程仓库。

 

下面是一个扁平化POM的例子:

原始的父POM


<project>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.ebay.test</groupId>

  <artifactId>webtestjavaParent</artifactId>

  <version>1.0.0-SNAPSHOT</version>

  <packaging>pom</packaging>

  <properties>

    <webtestjava.version>1.0.0-SNAPSHOT<webtestjava.version>

  </properties>

  <modules>

    <module>webtest-java</module>

  </modules>

  <dependencyManagement>

    <dependencies>

      <dependency>

        <groupId>junit</groupId>

        <artifactId>junit</artifactId>

        <version>4.10</version>

      </dependency>

      <dependency>

        <groupId>log4j</groupId>

        <artifactId>log4j</artifactId>

        <version>1.2.17</version>     

      </dependency>

    </dependencies>

  </dependencyManagement>

  <build>

           <plugins>

                  <plugin>

                        <groupId>org.apache.maven.plugins</groupId>

                   <artifactId>maven-deploy-plugin</artifactId>

                   <version>2.9-SNAPSHOT</version>

                   <configuration>

                                <enableFlatPom>true</enableFlatPom>

                         </configuration>

               </plugin>

           </plugins>

    </build>

</project>


原始的子POM

<project>

  <modelVersion>4.0.0</modelVersion>

  <parent>

    <groupId>com.ebay.test</groupId>

    <artifactId>webtestjavaParent</artifactId>

    <version>1.0.0-SNAPSHOT</version>

  </parent>

  <artifactId>webtestjava</artifactId>

  <version>${webtestjava.version}</version>

  <packaging>jar</packaging>

  <dependencies>

    <!-- Internal dependencies with project version -->

    <dependency>

      <groupId>com.ebay.test</groupId>

      <artifactId>webtestjava-module2</artifactId>

      <version>${webtestjava.version}</version>

    </dependency>

 

    <!-- External dependencies with managed version -->

    <dependency>

      <groupId>log4j</groupId>

      <artifactId>log4j</artifactId>

    </dependency>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <scope>test</scope>

    </dependency>

  </dependencies>

</project>


扁平化POM

<project>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.ebay.test</groupId>

  <artifactId>webtestjava</artifactId>

  <version>1.0.0-SNAPSHOT</version>

  <packaging>jar</packaging>

  <dependencies>

    <dependency>

      <groupId>com.ebay.test</groupId>

      <artifactId>webtestjava-module2</artifactId>

      <version>1.0.0-SNAPSHOT</version>

    </dependency>

    <dependency>

      <groupId>log4j</groupId>

      <artifactId>log4j</artifactId>

      <version>1.2.17</version>     

    </dependency>

  </dependencies>

</project>


扁平化POM实现:

修改maven-deploy-plugin中的类org.apache.maven.plugin.deploy. DeployMojo。

1. 增加enableFlatPom参数:

    @Parameter( property = "enableFlatPom", defaultValue = "false" )

    private boolean enableFlatPom;

2.当enableFlatPom参数设置为true的时候,生成扁平化的POM并设置为当前项目的POM。

   if ( enableFlatPom )

   {

       useFlatPom( request.getProject() );

       artifact = request.getProject().getArtifact();

       pomFile = request.getProject().getFile();

    }

   private void useFlatPom( MavenProject project )

        throws MojoExecutionException

   {

      generateFlatPom( project );

      applyFlatPom( project );

   }

3.useFlatPom方法会生成扁平化的POM并设置为当前项目的POM,createFlatPomFile方法生成一个空的POM文件,createFlatModel方法生成扁平化POM的模型,然后把扁平化POM的模型写入到POM文件。

   private void generateFlatPom( MavenProject project )

        throws MojoExecutionException

   {

 getLog().info( "Generating flat pom for project " + project.getName() );

 File flatPomFile = createFlatPomFile( project );

 Model flatPomModel = createFlatModel( project );

 MavenXpp3Writer pomWriter = new MavenXpp3Writer();

 Writer fileWriter = null;

try

{

      fileWriter = WriterFactory.newXmlWriter( flatPomFile );

      pomWriter.write( fileWriter, flatPomModel );

}

 catch ( IOException e )

{

throw new MojoExecutionException( "Cannot write to flat pom file for project " + project.getName(), e );

}

finally

{

      IOUtil.close( fileWriter );

}

}

4. applyFlatPom方法将扁平化POM设置为当前项目的POM并更新相应元数据。

private void applyFlatPom( MavenProject project )

        throws MojoExecutionException

{

  getLog().info( "Applying flat pom for project " + project.getName() );

  File flatPomFile = new File( getFlatPomDir( project.getBasedir() ), "pom.xml" );

  if ( !flatPomFile.exists() )

  {

      throw new MojoExecutionException( "Cannot find flat pom file in path " + flatPomFile.getAbsolutePath()+ " for project " + project.getName() );

  }

  project.setFile( flatPomFile );

  Artifact artifact = ArtifactUtils.copyArtifact( project.getArtifact() );

  Collection metadataList = project.getArtifact().getMetadataList();

  for ( ArtifactMetadata metadata : (Collection<ArtifactMetadata>) metadataList )

  {

       if ( metadata instanceof RepositoryMetadata )

       {

           artifact.addMetadata( metadata );

       }

  }

  artifact.addMetadata( new ProjectArtifactMetadata( artifact, flatPomFile ) );

  project.setArtifact( artifact );

}

 

扁平化POM是原始POM的精简版,它的目标用户是构件的使用者,所以对于项目的开发和编译发布的元素都会被移除。将扁平POM发布到远程仓库中将会对构件用户更加友好。

0 0
原创粉丝点击