将不同的Java类打包在一个单独的JAR文件中

5
基本上我有一个运行liferay门户的应用程序服务器。 我们还有自定义的portlet,其中包括共享的自定义库和第三方库。 例如dwr-3.0、几个drools jar文件、spring-webmvc、spring等。
问题在于这对服务器管理来说是一场噩梦,因为当有部署时,总会有人忘记服务器上的版本等信息。
我们使用maven 2,我的想法是做一个类似于maven项目的东西,从parent pom中拉取依赖项(使用dependencyManagement),默认目标是“解压所有依赖项并将它们打包成一个唯一的jar”。 这样,我们就会有一个带有标准版本的唯一的jar,与其他文件一起部署,而不必进行单独的部署。
如果可能的话,你们知道我该怎么做吗? 我一直在试用maven-assembly-plugin,但没有太大的成功。如果assembly是正确的方法,你们有例子可以给我一个启动吗?
提前感谢。

我有些困惑,不太明白你想做什么,但听起来像是需要使用OSGI - http://www.osgi.org/Main/HomePage。如果你在pom中为每个项目都有明确的依赖关系,那么你将始终获得该版本(假设你指定了SNAPSHOT)。但如果你想让每个portlet都能独立运行,并避免相互影响,那么OSGI可以帮助你实现这一点。 - Tim
Tim,我认为OSGi肯定是正确的选择,但这将需要整个团队改变工作方式,而且管理层可能会拒绝批准这种方向。此外,我不知道OSGi模型在JBoss EAP 4.3.0中是否适用,可能需要更多的麻烦和测试,不值得这样做。 - feniix
5个回答

2

另一个选择是使用maven-shade-plugin或者jarjar。我曾经都用过,并且进行了包重命名,没有遇到任何问题。


我会看一下那个插件,看起来更直接地实现了我的需求。 - feniix

1

我认为你所描述的是可能的。首先,创建一个父POM,在其中在<dependencyManagement>元素中声明依赖项:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>groupIdA<groupId>
  <artifactId>parent</artifactId>
  <packaging>pom<packaging>
  <version>1-SNAPSHOT</version>
  ...
  <dependencyManagement>
    <!-- Standard dependencies used in several build modules. Ensures all modules
         use the same version for these dependencies -->
    <dependencies>
      <dependency>
        <groupId>org.directwebremoting</groupId>
        <artifactId>dwr</artifactId>
        <version>3.0.M1</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>3.0.0.RELEASE</version>
      </dependency>
      ...
    </dependencies>
  <dependencyManagement>
  ...
</project>

然后,在子项目中,声明你需要的依赖项,而不声明它们的版本。
<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>parent</artifactId>
    <groupId>groupIdA</groupId>
    <version>1-SNAPSHOT</version>
  </parent>
  <artifactId>childB</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <dependencies>
    <dependency>
      <groupId>org.directwebremoting</groupId>
      <artifactId>dwr</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
    </dependency>
      ...
  </dependencies>
  ...
</project>

最后,使用默认的 jar-with-dependencies 预定义程序集描述符创建一个 通用装配件,其中包括所有依赖库,解压缩在归档文件内的二进制包
<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2-beta-5</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id> <!-- this is used for inheritance merges -->
            <phase>package</phase> <!-- append to the packaging phase. -->
            <goals>
              <goal>single</goal> <!-- goals == mojos -->
            </goals>
          </execution>
        </executions>
      </plugin>
      [...]
    </plugins>
  </build>
</project>

为了创建项目的汇编,触发 package 阶段:

mvn package

而这将在目标目录中生成以下汇编:

target/child-1.0-SNAPSHOT-jar-with-dependencies.jar

我不确定你想用这个程序集来做什么(在门户项目中使用它作为依赖项还是从父POM中拉取依赖项?只是简化Liferay部署吗?)。不过所有选项都是可能的。

请参考Maven Assembly插件文档以获取更多详细信息。


嗨Pascal,我尝试了几种不同的汇编插件配置,但没有太大的成功,也就是说我无法让它做我想要的事情。 我想要用生成的jar文件创建一个唯一的jar文件,将其加载到jboss的共享lib目录中,以便所有不同的portlet共享类。 目前,我们在server/servername/lib/ext中拥有所有的jar文件,但当库发生变化时,这是非常痛苦和容易出错的。通过这种方式,我们只有一个包含所需库的唯一jar文件,只需放置一个文件即可完成。 - feniix
@feniix 我所建议的方法可以让你做到这一点(我已经多次使用了这个描述符),而且是最直接的方式(特别是因为你只需要复制和粘贴配置)。 - Pascal Thivent
我并不是说它不起作用 :) 在我的情况下,使用我想要的库列表,组装方法会漏掉一些库,我认为这是一个bug,但依赖方法确实包含了所有依赖项的类,而组装方法则缺少一些。虽然很奇怪,但我会尝试向Apache FSF报告这个bug。 - feniix

1

我最终通过以下方式解决了这个问题,虽然我还没有在应用服务器上测试过,但生成的归档文件是一个包含所有所需依赖项内容的jar文件。 感谢Vincent的提示 :)

<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>com.test.jarbundle</groupId>
<artifactId>bundle</artifactId>
<version>1.0</version>
<name>bundle</name>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<dependencies>
    <dependency>
        <groupId>org.directwebremoting</groupId>
        <artifactId>dwr</artifactId>
        <version>3.0.M1</version>
        <scope>runtime</scope>
        <exclusions>
         <exclusion>
          <artifactId>cometd</artifactId>
          <groupId>org.mortbay.jetty</groupId>
         </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5</version>
        <scope>runtime</scope>
        <exclusions>
         <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
         </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>2.5</version>
        <scope>runtime</scope>
        <exclusions>
         <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
         </exclusion>
         <exclusion>
          <artifactId>aopalliance</artifactId>
          <groupId>aopalliance</groupId>
         </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc-portlet</artifactId>
        <version>2.5</version>
        <scope>runtime</scope>
        <exclusions>
         <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
         </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-core</artifactId>
        <version>4.0.3</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
        <version>4.0.3</version>
        <scope>runtime</scope>
        <exclusions>
         <exclusion>
          <artifactId>antlr-runtime</artifactId>
          <groupId>org.antlr</groupId>
         </exclusion>
         <exclusion>
          <artifactId>core</artifactId>
          <groupId>org.eclipse.jdt</groupId>
         </exclusion>
         <exclusion>
          <artifactId>janino</artifactId>
          <groupId>janino</groupId>
         </exclusion>
         <exclusion>
          <artifactId>xercesImpl</artifactId>
          <groupId>xerces</groupId>
         </exclusion>
         <exclusion>
          <artifactId>xml-apis</artifactId>
          <groupId>xml-apis</groupId>
         </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-jsr94</artifactId>
        <version>4.0.3</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-decisiontables</artifactId>
        <version>4.0.3</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>jar.App</mainClass>
                    </manifest>
                </archive>
            </configuration> 
        </plugin>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/target/dependency</directory>
        </resource>
    </resources>
</build>

然后你运行

mvn package

{{链接1:链接文字}}


1

听起来你可能需要 Dependency Plugin

我想你可以将所有依赖的 jar 包解压到指定位置,然后重新打包到你的新 jar 包中。

希望对你有所帮助。


0

最终的最佳解决方案是使用maven-shade-plugin插件:

(snip)
    <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <finalName>${artifactId}-${version}-tmp</finalName>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.3.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <shadedArtifactAttached>true</shadedArtifactAttached>
                        <shadedClassifierName>full</shadedClassifierName>
                        <artifactSet>
                            <excludes>
                                <exclude>classworlds:classworlds</exclude>
                                <exclude>junit:junit</exclude>
                                <exclude>jmock:*</exclude>
                                <exclude>org.apache.maven:lib:tests</exclude>
                                <exclude>log4j:log4j:jar:</exclude>
                            </excludes>
                        </artifactSet>
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

(省略)

Shade插件的优点在于,它会在您包含重叠类时发出警告(例如,使用spring jar(完整版)和aopalliance类)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接