Maven - 如何在jar中添加任意类路径条目?

时间:2009-10-02 14:59:45

标签: maven-2 build jar classpath

我有一个不寻常的情况,我需要在可执行jar的清单中添加一个任意的类路径条目(指向一个jar文件)。 (这适用于Swing桌面应用程序。)

maven-jar-plugin使用maven依赖项为jar清单生成“Class-Path”条目,似乎没有任何添加任意条目的方法。

我还看了使用“-classpath”参数将任意类路径条目硬编码到启动应用程序的批处理文件中,但我无法弄清楚如何让Maven将类路径过滤到批处理文件中

4 个答案:

答案 0 :(得分:69)

我发现这个问题有一个简单的解决方案。您可以向<Class-Path>元素添加<manifestEntries>元素,并将<addClassPath>true</addClassPath>设置为<manifest>元素。因此<Class-Path>元素的值会自动添加到类路径中。示例:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
        <addClasspath>true</addClasspath>
        <mainClass>your.main.Class</mainClass>
      </manifest>
      <manifestEntries>
        <Class-Path>../conf/</Class-Path>
      </manifestEntries>
    </archive>
  </configuration>
</plugin>

答案 1 :(得分:18)

更新:以下是如何将类路径过滤到自定义清单中。

maven-dependency-plugin的build-classpath目标可以配置为以类型格式(即classpath = [classpath])将类路径输出到文件。然后,配置filters元素以使用生成的类路径文件,并配置要过滤的资源目录。

例如:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>2.1</version>
      <executions>
        <execution>
          <phase>generate-resources</phase>
          <goals>
            <goal>build-classpath</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <outputFilterFile>true</outputFilterFile>
        <outputFile>${project.build.directory}/classpath.properties</outputFile>
      </configuration>
    </plugin>
    <plugin>
      <artifactId>maven-jar-plugin</artifactId>
      <configuration>
        <archive>
          <manifestFile>
            ${project.build.outputDirectory}/META-INF/MANIFEST.MF
          </manifestFile>
        </archive>
      </configuration>
    </plugin>
  </plugins>
  <filters>
    <filter>${project.build.directory}/classpath.properties</filter>
  </filters>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

然后在src / main / resources / META-INF / Manifest.MF中指定以下内容:

Bundle-Version: 4.0.0
...
Classpath: ${classpath};[specify additional entries here]

注意:使用标准窗口路径分隔符(\)进行此处理时出现错误,生成路径被剥离了分隔符(注意它在Linux上运行正常)。您可以通过在<fileSeparator>\\\\</fileSeparator>目标配置中指定build-classpath来为Windows正确生成类路径。


您可以在jar-plugin的配置中自定义清单。为此,你可以在你的pom中添加这样的东西。

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

完整archiver specification提供了不少选项。有关配置类路径的选项,请参阅examples page

如果这些都不适合您,您可以define your own Manifest设置包含所需条目的属性,并使用filter使用这些属性填充清单

答案 2 :(得分:5)

尝试像在这个bug中那样做,即使用manifestEntries / Class-Path元素合并条目

https://issues.apache.org/jira/browse/MJAR-41

答案 3 :(得分:0)

我能够对 Rich Seller 的方法稍加修改,避免了评论中提到的 Error assembling JAR: Unable to read manifest file (line too long) 问题。

我想通过 .jar 文件的清单类路径中引用的 dependency-maven-plugin 复制所有依赖项。我无法使用 Maven Jar 插件的 <addClasspath>true</addClasspath> 选项,因为它在我的 Jar 类路径中放置了太多内容(我只是复制了一些依赖项)。

这是我如何让它工作的。

首先我使用 Maven Dependency Plugin 进行复制,同时构建一个类路径变量。使用 <outputProperty> 我把它放在一个属性而不是一个文件中:

  <plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
      <execution>
        <phase>generate-resources</phase>
        <goals>
          <goal>copy-dependencies</goal>
          <goal>build-classpath</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/lib</outputDirectory>              

          <!-- These properties are for build-classpath. It creates a classpath for the copied
               dependencies and puts it in the ${distro.classpath} property. The jar Class-Path
               uses spaces as separators. Unfortunately <pathSeparator> configuration property
               does not work with a space as value, so the pathSeparator is set to a character
               here and this is then replaced later using the regex-property plugin. -->
          <prefix>lib</prefix>
          <outputProperty>distro.classpath</outputProperty>
          <pathSeparator>:</pathSeparator>
        </configuration>
      </execution>
    </executions>
  </plugin>

Jar Manifest Class-Path 的语法使用 空格 作为分隔符。虽然依赖插件有一个 <pathSeparator> 属性,但不幸的是,如果它是一个空格,这个值会被忽略。所以我只是将它硬编码为某个值,然后使用 build-helper-maven-plugin 将其替换为我需要的空间:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
      <execution>
        <phase>process-resources</phase>
        <goals>
          <goal>regex-property</goal>
        </goals>
        <configuration>
          <!-- Here the value of property for the jar the Class-Path is replaced to have a space
               as separator. Unfortunately <replacement> does not work if a single space if specified
               so this uses the surrounding .jar and lib to provide some content. -->
          <name>distro.classpath.replaced</name>
          <value>${distro.classpath}</value>
          <regex>[.]jar[:]lib</regex>
          <replacement>.jar lib</replacement>
        </configuration>
      </execution>
    </executions>
  </plugin>

这里,如果 <replacement> 值只是一个空格,它也不起作用,所以我用它周围存在的文本包围它。

最后,我可以使用 Maven Jar 插件来获取被空格替换的属性作为分隔符。因为我在 maven 定义中传递了 classpath 的值(而不是从过滤的文件中获取),Manifest 文件的行长约束将自动处理,不会出现“行太长”问题:

  <plugin>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
      <archive>
        <manifest>
          <mainClass>org.acme.Main</mainClass>
        </manifest>
        <manifestEntries>
          <!-- Include the computed classpath with all copied dependencies in the jar here -->
          <Class-Path>${distro.classpath.replaced}</Class-Path>
        </manifestEntries>
      </archive>
    </configuration>
  </plugin>