将我的依赖项放入我的 JAR
Getting my dependencies into my JAR
我可以打包一个我写的JAVA项目。一个将 Gson
库用于 JSON 功能。我是 JAVA 的新手,所以我可能犯了一个愚蠢的错误,但这是我的假设:
在源代码中我有:
import com.google.gson.Gson;
然后像这样使用这个导入:
Gson gson = new Gson();
String json = gson.toJson(result);
在我的 Maven pom.xml
中,我在依赖项部分包含了以下内容:
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
正如我所说,它 确实 打包到 JAR 文件没有错误(使用 Maven 打包)但我的 JAR 文件在 AWS 上用作无服务器函数等我相信我需要做的是将 Gson 依赖项包含在我的 JAR 文件中(可能是错误的)。这似乎得到了我在 AWS 上遇到的错误的支持:
进行了一些 google 搜索后,看起来 Maven 的 "shade" 插件可能是票证。我像这样将它添加到我的 pom.xml
中:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<artifactSet>
<includes>
<include>com/google/gson/**</include>
</includes>
</artifactSet>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
但是在生成的 JAR 文件中我看不出有什么不同。我需要做什么才能让它发挥作用?
完整的 POM 文件可以在这里找到:pom.xml
如果您有将从运行时容器提供的依赖项,您应该设置提供给这些依赖项的范围。
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
并从插件配置中删除 <artifactSet>
部分,执行 mvn package
然后将创建具有所需依赖项的 jar。
我不熟悉其他人引用的 shade
插件。在我看来,您需要一个可执行 jar 的工件:一个 jar,及其依赖项。
这是我使用 Maven 的方法:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.groupId</groupId>
<artifactId>artifact-id</artifactId>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.company.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-javadoc</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-source</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
你要注意的是构建插件,maven-assembly-plugin
。这告诉 Maven 如何 assemble/package 构建的结果。在其配置中,您定义包含 运行nable 应用程序的主要 class,它通常位于您的 public static void main(String[] args)
声明所在的位置。您还定义了一个 descriptor-ref,这是一个将附加到 jar 名称的字符串。所以,以我的 POM 为例,你最终会得到 artifactId-1.0.0-jar-with-dependencies.jar
。
为了进一步解释发生了什么,在没有我建议的更改的情况下,您的 POM 告诉 Maven 只构建您的代码。作为其中的一部分,您声明依赖项,您现在有两个依赖项:aws-lambda-java-core
和 gson
。当您不提供范围时,它默认为 compile
范围。这告诉 Maven 在编译程序时获取该依赖项,以便程序可以使用该依赖项的代码。但是,在打包程序的构建工件时,默认情况下,Maven 不会将这些依赖项包含在最终的 jar 中;它期望当您 运行 jar 时,您将在 class 路径上拥有这些依赖项。
通过添加程序集构建插件,您可以将这些指令更改为 Maven。使用该插件,您告诉 Maven,当它构建程序时,它需要 assemble 它以这样一种方式将所有声明的依赖项包含在程序中(阅读:assembled),并且在构建的打包阶段执行此操作;您将在构建工件的 lib
文件夹中看到这些依赖项。然后,就像我之前提到的,descriptorRef 是描述性信息,将附加到构建工件的名称上。
顺便说一句,与您的问题并不真正相关,我建议您研究 FasterXML 以了解 JSON 处理和操纵。如此强大,如此简单,并且得到了广泛的支持和使用,这意味着它背后有一个强大的社区。
我可以打包一个我写的JAVA项目。一个将 Gson
库用于 JSON 功能。我是 JAVA 的新手,所以我可能犯了一个愚蠢的错误,但这是我的假设:
在源代码中我有:
import com.google.gson.Gson;
然后像这样使用这个导入:
Gson gson = new Gson();
String json = gson.toJson(result);
在我的 Maven pom.xml
中,我在依赖项部分包含了以下内容:
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
正如我所说,它 确实 打包到 JAR 文件没有错误(使用 Maven 打包)但我的 JAR 文件在 AWS 上用作无服务器函数等我相信我需要做的是将 Gson 依赖项包含在我的 JAR 文件中(可能是错误的)。这似乎得到了我在 AWS 上遇到的错误的支持:
进行了一些 google 搜索后,看起来 Maven 的 "shade" 插件可能是票证。我像这样将它添加到我的 pom.xml
中:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<artifactSet>
<includes>
<include>com/google/gson/**</include>
</includes>
</artifactSet>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
但是在生成的 JAR 文件中我看不出有什么不同。我需要做什么才能让它发挥作用?
完整的 POM 文件可以在这里找到:pom.xml
如果您有将从运行时容器提供的依赖项,您应该设置提供给这些依赖项的范围。
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
并从插件配置中删除 <artifactSet>
部分,执行 mvn package
然后将创建具有所需依赖项的 jar。
我不熟悉其他人引用的 shade
插件。在我看来,您需要一个可执行 jar 的工件:一个 jar,及其依赖项。
这是我使用 Maven 的方法:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.groupId</groupId>
<artifactId>artifact-id</artifactId>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.company.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-javadoc</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-source</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
你要注意的是构建插件,maven-assembly-plugin
。这告诉 Maven 如何 assemble/package 构建的结果。在其配置中,您定义包含 运行nable 应用程序的主要 class,它通常位于您的 public static void main(String[] args)
声明所在的位置。您还定义了一个 descriptor-ref,这是一个将附加到 jar 名称的字符串。所以,以我的 POM 为例,你最终会得到 artifactId-1.0.0-jar-with-dependencies.jar
。
为了进一步解释发生了什么,在没有我建议的更改的情况下,您的 POM 告诉 Maven 只构建您的代码。作为其中的一部分,您声明依赖项,您现在有两个依赖项:aws-lambda-java-core
和 gson
。当您不提供范围时,它默认为 compile
范围。这告诉 Maven 在编译程序时获取该依赖项,以便程序可以使用该依赖项的代码。但是,在打包程序的构建工件时,默认情况下,Maven 不会将这些依赖项包含在最终的 jar 中;它期望当您 运行 jar 时,您将在 class 路径上拥有这些依赖项。
通过添加程序集构建插件,您可以将这些指令更改为 Maven。使用该插件,您告诉 Maven,当它构建程序时,它需要 assemble 它以这样一种方式将所有声明的依赖项包含在程序中(阅读:assembled),并且在构建的打包阶段执行此操作;您将在构建工件的 lib
文件夹中看到这些依赖项。然后,就像我之前提到的,descriptorRef 是描述性信息,将附加到构建工件的名称上。
顺便说一句,与您的问题并不真正相关,我建议您研究 FasterXML 以了解 JSON 处理和操纵。如此强大,如此简单,并且得到了广泛的支持和使用,这意味着它背后有一个强大的社区。