使用 Maven 时 manifest 的生成规则


使用 Maven 时 manifest 的生成规则

译自 http://maven.apache.org/plugins/maven-jar-plugin/examples/manifest-customization.html

默认的 Manifest

由 Maven Archiver 创建的默认的 manifest 文件包含以下内容

Manifest-Version: 1.0
Created-By: Apache Maven ${maven.version}
Build-Jdk: ${java.version}
注意:Build-Jdk项 不会考虑工具链配置,这是和运行Maven实例时相同的JDK版本

增加实现和规范细节(Adding Implementation And Specification Details)

maven-jar-plugin 从 2.1 版本开始,开始使用 3.5.0 版本的 Maven Archiver, 该版本的 Maven Archiver 默认不会向 manifest 中添加 Implementation 和 Specification 细节。如果需要这些,你需要显示进行配置。

注意:由于这是 Maven Archive 最近才有的变动,有些插件可能会还没有开始采用它。你需要检查相关插件的文档。这个例子中,我们使用 maven-jar-plugin 2.1,这是插件可以使用该特性的第一个版本。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.1</version>
        ...
        <configuration>
          <archive>
            <manifest>
              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>

生成的 manifest 文件内容如下

Manifest-Version: 1.0
Created-By: Apache Maven ${maven.version}
Build-Jdk: ${java.version}
Specification-Title: ${project.name}
Specification-Version: ${project.artifact.selectedVersion.majorVersion}.${project.artifact.selectedVersion.minorVersion}
Specification-Vendor: ${project.organization.name}
Implementation-Title: ${project.name}
Implementation-Version: ${project.version}
Implementation-Vendor: ${project.organization.name}
注意:如果你的 pom.xml 文件中没有 <organization>/<name> 元素,则 Specification-Vendor 和 Implementation-Vendor 条目不会出现在 manifest 文件中

自定义 Customization the Manifest

默认的 manifest 可以通过 archive 配置项来改变。下面例子中你可以找到一些可用的配置项。更多的信息参见 Maven Archiver reference

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          <archive>
            <index>true</index>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
            <manifestEntries>
              <mode>development</mode>
              <url>${project.url}</url>
              <key>value</key>
            </manifestEntries>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>

Manifest 条目(Manifest Entries)

如果你发现 Maven Archiver 配置项不足以操作 manifest,则可以向 manifest 添加自己的条目。 这是通过<manifestEntries>配置元素来完成的。

在下面的例子中,我们将通过在 maven-jar-plugin 的<configuration> / <archive>元素中指定所需的内容,向清单中添加一些条目。

注意:与这里的所有示例一样,此配置可以在所有使用Maven Archiver的插件中使用,而不仅仅是本示例中的maven-jar-plugin。
<project>
  <url>http://some.url.org/</url>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <manifestEntries>
              <mode>development</mode>
              <url>${project.url}</url>
            </manifestEntries>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>

如上所示,您可以使用字面值(literal values),也可以将POM中的值插入到字面值中,或者仅使用直接的POM表达式。 最后生成的 manifest 文件如下

Manifest-Version: 1.0
Created-By: Apache Maven ${maven.version}
Build-Jdk: ${java.version}
mode: development
url: http://some.url.org/
Note: If your pom.xml does not have the <url> element, referenced through interpolation, then the entry url will not be in the manifest.

Manifest Sections

<manifestSections> 元素提供了一种方式用来自定义 manifest 段 (manifest sections)。它包含一个 list of <manifestSection> elements

注意:与这里的所有示例一样,此配置可以在所有使用Maven Archiver的插件中使用,而不仅仅是本示例中的maven-jar-plugin。

使用如下配置

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <manifestSections>
              <manifestSection>
                <name>foo</name>
                <manifestEntries>
                  <id>nice foo</id>
                </manifestEntries>
              </manifestSection>
              <manifestSection>
                <name>bar</name>
                <manifestEntries>
                  <id>nice bar</id>
                </manifestEntries>
              </manifestSection>
            </manifestSections>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>

生成的 manifest 文件如下

Manifest-Version: 1.0
Created-By: Apache Maven ${maven.version}
Build-Jdk: ${java.version}
 
Name: foo
id: nice foo
 
Name: bar
id: nice bar

设置 Classpath

添加一个 Class-Path Entry 到 Manifest

通过<addClasspath> 配置项, Maven Archiver 可以把你项目的 classpath 添加到 manifest,

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.1</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
  ...
</project>

生成的 manifest 如下

Manifest-Version: 1.0
Created-By: Apache Maven ${maven.version}
Build-Jdk: ${java.version}
Class-Path: plexus-utils-1.1.jar commons-lang-2.1.jar

让 JAR 可执行 (Make The Jar Executable)

如果要创建可执行的jar文件,则需要相应地配置Maven Archiver。 您需要告诉它要使用哪个主类。 这是通过<mainClass>配置元素完成的。 下面是一个示例pom.xml,配置为添加 classpath 并将full.qualified.MainClass类用作主类:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <mainClass>fully.qualified.MainClass</mainClass>
            </manifest>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.1</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
  ...
</project>

生成结果

Manifest-Version: 1.0
Created-By: Apache Maven ${maven.version}
Build-Jdk: ${java.version}
Main-Class: fully.qualified.MainClass
Class-Path: plexus-utils-1.1.jar commons-lang-2.1.jar

修改classpath,添加文件夹前缀(Altering The Classpath: Defining a Classpath Directory Prefix)

有时,能够更改classpath 很有用,例如,在创建瘦的war文件(creating skinny war-files)时。 这可以通过<classpathPrefix>配置元素来实现。

<project>
  ...
  <build>
    <plugins>
      <plugin>
         <artifactId>maven-war-plugin</artifactId>
         <configuration>
           <archive>
             <manifest>
               <addClasspath>true</addClasspath>
               <classpathPrefix>lib/</classpathPrefix>
             </manifest>
           </archive>
         </configuration>
      </plugin>
    </plugins>
  </build>
  ...
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.1</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
  ...
</project>

生成的 manifest 文件中的 classpath 看起来像这样:

Class-Path: lib/plexus-utils-1.1.jar lib/commons-lang-2.1.jar

修改classpath,使用 Maven Repository-Style Classpath

Occasionally, you may want to include a Maven repository-style directory structure in your archive. If you wish to reference the dependency archives within those directories in your manifest classpath, try using the <classpathLayoutType> element with a value of 'repository', like this:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <classpathLayoutType>repository</classpathLayoutType>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.1</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
  ...
</project>

The manifest classpath produced using the above configuration would look like this:

Class-Path: lib/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar lib/commons-lang/commons-lang/2.1/commons-lang-2.1.jar

修改classpath,使用自定义的 classpath 格式 (Altering The Classpath: Using a Custom Classpath Format)

At times, you may have dependency archives in a custom format within your own archive, one that doesn't conform to any of the above classpath layouts. If you wish to define a custom layout for dependency archives within your archive's manifest classpath, try using the <classpathLayoutType> element with a value of 'custom', along with the <customClasspathLayout> element, like this:

<project>
  ...
  <build>
    <plugins>
      <plugin>
         <artifactId>maven-war-plugin</artifactId>
         <configuration>
           <archive>
             <manifest>
               <addClasspath>true</addClasspath>
               <classpathLayoutType>custom</classpathLayoutType>
               <customClasspathLayout>WEB-INF/lib/$${artifact.groupIdPath}/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}</customClasspathLayout>
             </manifest>
           </archive>
         </configuration>
      </plugin>
    </plugins>
  </build>
  ...
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.1</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
  ...
</project>

This classpath layout is a little more involved than the previous examples. To understand how the value of the <customClasspathLayout> configuration is interpreted, it's useful to understand the rules applied when resolving expressions within the value:

  1. If present, trim off the prefix 'artifact.' from the expression.
  2. Attempt to resolve the expression as a reference to the Artifact using reflection (eg. 'artifactId' becomes a reference to the method 'getArtifactId()').
  3. Attempt to resolve the expression as a reference to the ArtifactHandler of the current Artifact, again using reflection (eg. 'extension' becomes a reference to the method 'getExtension()').
  4. Attempt to resolve the expression as a key in the special-case Properties instance, which contains the following mappings:
    • 'dashClassifier': If the Artifact has a classifier, this will be '-$artifact.classifier', otherwise this is an empty string.
    • 'dashClassifier?': This is a synonym of 'dashClassifier'.
    • 'groupIdPath': This is the equivalent of '$artifact.groupId', with all '.' characters replaced by '/'.

The manifest classpath produced using the above configuration would look like this:

Class-Path: WEB-INF/lib/org/codehaus/plexus/plexus-utils-1.1.jar WEB-INF/lib/commons-lang/commons-lang-2.1.jar

Handling Snapshot Versions

Depending on how you construct your archive, you may have the ability to specify whether snapshot dependency archives are included with the version suffix '-SNAPSHOT', or whether the unique timestamp and build-number for that archive is used. For instance, the Assembly Plugin allows you to make this decision in the <outputFileNameMapping> element of its <dependencySet> descriptor section.

Forcing the use of -SNAPSHOT versions when using the simple (default) or repository classpath layout

To force the use of '-SNAPSHOT' version naming, simply disable the <useUniqueVersions> configuration element, like this:

<useUniqueVersions>false</useUniqueVersions>

Forcing the use of -SNAPSHOT versions with custom layouts

To force the use of '-SNAPSHOT' version naming, simply replace '$artifact.version' with '$artifact.baseVersion' in the custom layout example above, so it looks like this:

<customClasspathLayout>WEB-INF/lib/${artifact.groupIdPath}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</customClasspathLayout>

The full example configuration would look like this:

<project>  ...  <build>    <plugins>      <plugin>         <artifactId>maven-war-plugin</artifactId>         <configuration>           <archive>             <manifest>               <addClasspath>true</addClasspath>               <classpathLayoutType>custom</classpathLayoutType>               <customClasspathLayout>WEB-INF/lib/${artifact.groupIdPath}/${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}</customClasspathLayout>             </manifest>           </archive>         </configuration>      </plugin>    </plugins>  </build>  ...</project>

使用你自己的 Manifest File

默认情况下,Maven Archiver 会为你产生 manifest 文件。你也可以通过配置项 manifestFile 来指定并使用你自己的 manifest 文件。自己指定的文件的内容,会被 merge 到 Maven Archiver 生成 manifest 文件中。如果你自己的文件和默认生成的文件有相同的条目,则自定义的条目会覆盖掉自动生成的条目。

注意:与这里的所有示例一样,此配置可以在所有使用Maven Archiver的插件中使用,而不仅仅是本示例中的maven-jar-plugin。
<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        ...
        <configuration>
          <archive>
            <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
          </archive>
        </configuration>
        ...
      </plugin>
    </plugins>
  </build>
  ...
</project>


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM