【问题标题】:Bundling different java classes in a single jar files in a single jar将不同的 java 类捆绑在单个 jar 文件中的单个 jar 中
【发布时间】:2011-01-09 18:09:19
【问题描述】:

基本上我拥有的是一个运行 liferay 门户的应用程序服务器。 我们还拥有共享自定义库和第三方库的自定义 portlet。 比如dwr-3.0、几个drools jar文件、spring-webmvc、spring等

问题是这对于服务器管理来说是一场噩梦,因为当进行部署时,总会有人忘记服务器中的版本等。

我们使用 maven 2,我的想法是做一些类似于 maven 项目的事情,从父 pom 中提取依赖项(使用 dependencyManagement),默认目标是“解压缩所有依赖项并将它们 jar独特的罐子”。 这样,我们将拥有一个具有标准版本的唯一 jar,该 jar 与其余文件一起部署,而不必部署。

如果可能的话,你们知道我该怎么做吗? 我一直在玩 maven-assembly-plugin ,但没有取得多大成功。如果组装是要走的路,你有一个例子可以给我一个kickstart吗?

提前致谢

【问题讨论】:

  • 我无法准确理解您要做什么,但这听起来像是 OSGI - osgi.org/Main/HomePage。我认为,如果您对 pom 中的每个项目都有明确的依赖关系,那么您将始终获得该版本(假设您指示的是 SNAPSHOT)。但是,如果您试图让每个 portlet 使用自己的一组库并避免交互,OSGI 可以为您做到这一点。
  • Tim,我绝对认为 osgi 是要走的路,但会让整个团队改变做事的方式,管理层可能会拒绝批准朝这个方向发展。另外,我不知道在 jboss eap 4.3.0 中是否适合 osgi 模型,可能比值得的更麻烦和测试。

标签: java maven-2 jar dependencies


【解决方案1】:

最后最好的解决方案是使用 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 插件最棒的地方在于,当你包含重叠的类时它会发出警告(一个例子是带有 aopalliance 类的 spring jar(完整的))

【讨论】:

    【解决方案2】:

    我终于能够通过以下方式解决它,我没有在应用程序服务器中进行测试,但是生成的存档是一个 jar 文件,其中包含所有所需依赖项的内容。 Thanks Vincent for the tip :)

    <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
    

    link text

    【讨论】:

      【解决方案3】:

      另一种选择是maven-shade-plugin 甚至jarjar。我已经使用了两者,以及包重命名没有任何问题。

      【讨论】:

      • 我会看看那个插件,看起来更直接地做我想做的事。
      【解决方案4】:

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

      <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>
      

      要创建项目程序集,请触发阶段:

      mvn package
      

      这将在目标目录中生成以下程序集:

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

      我只是不确定你想用这个程序集做什么(将它用作 portlet 项目中的依赖项与从父 POM 中提取依赖项?仅简化 liferay 部署?)。不过,所有选项都是可能的。

      有关详细信息,请参阅Maven Assembly plugin 文档。

      【讨论】:

      • 嗨 Pascal,我尝试了几种不同的程序集插件配置,但都没有成功,这意味着我无法让它做我想做的事。我想要对生成的 jar 文件做的是在 jboss 的共享 lib 目录中加载一个唯一的 jar 文件,以便所有不同的 portlet 共享这些类。目前,我们在 server/servername/lib/ext 中拥有所有的 jar 文件,但是当库发生变化时非常烦人,真的很容易出错,这样我们就有了一个唯一的 jar 文件,它只有所需的库,放下一个文件,你就完成了。
      • @feniix 我的建议允许你这样做(我多次使用这个描述符)并且是最直接的方式(特别是因为你只需要复制和粘贴配置)。
      • 我并不是说它不起作用 :) 就我而言,对于我想要的库列表,组装方法留下了一些库,我认为这是一个错误,但依赖方法有依赖项和组装方法中的所有类都缺少一些。不过这很奇怪,我会看看我是否尝试向 apache fsf 报告错误
      【解决方案5】:

      听起来Dependency Plugin 可能是您所需要的。

      我认为您可以将所有依赖项 jar 解压到指定位置,然后将它们重新打包到新 jar 中。

      我希望它对你有用。

      【讨论】:

        猜你喜欢
        • 2018-04-06
        • 2016-10-17
        • 2013-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-18
        相关资源
        最近更新 更多