如何只打包 Google App Engine Project(Java) 中需要的库?
How to package only the necessary libs in Google App Engine Project(Java)?
让我先解释一下必要的库是什么意思。我正在使用 Google App Engine for Java with the official Google Maven Plugin 创建我的第一个项目,将 Maven 作为打包解决方案(或者可能是整个 Java 开发)的主要问题是如果依赖树增长 太多,发布过程可能会更难。
让我举个例子来说明。让我们从 Jackson JSON 库开始(这是一个很好的起点,因为它没有父依赖项),现在有人制作了一个 JSON-RPC 库并将 Jackson 用于 JSON serialization/deserialization.想象一下,这个库不仅提供了一个 JSON-RPC 客户端实现,而且还提供了一个服务器,这意味着这个库的 POM 将添加一些 Java EE 相关库作为依赖项,例如 Jetty。
可能指南说应用程序应该分为模块或将服务器相关的 deps 标记为可选,但你知道很多人不遵循标准。
现在有人需要JSON-RPC client for his/her project,叫Project X,用上面提到的lib,编译时不会有问题,Maven会成功下载所需的库和应用程序可以正常编译,但是当那个人想要发布应用程序时就会出现问题。 哪些依赖项 应与包一起分发(例如在 lib 文件夹中)?
实际上这就是发生在我身上的事情,我对 Maven 不太熟悉所以我使用了 Eclipse Runnable Jar Exporter,它生成的 jar 文件将所有 Maven 库复制到 lb 子文件夹,所以解决方法然后我所做的就是删除 看起来不必要的库 然后测试应用程序是否仍在运行。如果有 类 没有被执行,据我所知它们没有被 ClassLoader
加载,所以它们可以被省略并且是不必要的
我现在不能使用相同的技巧,因为场景要复杂得多,我们谈论的是 Java Web 应用程序,而不是像另一个应用程序那样的桌面应用程序,以及我想要的库包括一个 Liquid Template Engine, which uses the ANTLR 框架来生成解析器加上 Jackson 用于 JSON 处理程序和 Jsoup 用于 HTML 解析。
哪些库应该打包到 WEB-INF/lib 文件夹中?我确定我需要 Jackson 来进行 JSON 解析,但我不太确定 Jsoup,而 ANTLR 呢,它是必要的还是只在编译时使用?
更新:我想我需要重新表述我的问题,实际上我想要的是确定哪些依赖项是真正必要的对于应用程序,并将它们打包到应用程序 WEB-INF/lib 文件夹
解决方法: web app的WAR文件中打包的POM文件好像是用的一旦应用程序在 Google App Engine 生产环境中检索必要的依赖项,并且可能 appengine:update
目标只打包那些无法从 maven 中央仓库检索的依赖项,因此没有需要担心这个。
感谢David指出这一点。
您可以排除任何传递依赖。
对于您的情况,要从此 json-rpc-library 中删除码头,您需要:
<dependency>
<groupId>com.somecomp</groupId>
<artifactId>jsonrpclib</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
</exclusions>
</dependency>
查看文档:http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
你应该检查 Maven 的 dependency scopes。这是文档的摘录:
There are 6 scopes available:
- compile This is the default scope, used if none is specified. Compile
dependencies are available in all classpaths of a project.
Furthermore, those dependencies are propagated to dependent projects.
- provided This is much like compile, but indicates you expect the JDK
or a container to provide the dependency at runtime. For example, when
building a web application for the Java Enterprise Edition, you would
set the dependency on the Servlet API and related Java EE APIs to
scope provided because the web container provides those classes. This
scope is only available on the compilation and test classpath, and is
not transitive.
- runtime This scope indicates that the dependency is
not required for compilation, but is for execution. It is in the
runtime and test classpaths, but not the compile classpath.
- test This
scope indicates that the dependency is not required for normal use of
the application, and is only available for the test compilation and
execution phases.
- system This scope is similar to provided except that
you have to provide the JAR which contains it explicitly. The artifact
is always available and is not looked up in a repository.
- import (only
available in Maven 2.0.9 or later) This scope is only used on a
dependency of type pom in the section. It
indicates that the specified POM should be replaced with the
dependencies in that POM's section. Since they
are replaced, dependencies with a scope of import do not actually
participate in limiting the transitivity of a dependency.
因此在 Maven 项目中,开发人员指示应用程序中应该捆绑哪些依赖项,哪些不应该。
这里基本上有两种情况:
如果您正在构建一个 Web 应用程序(WAR 或 EAR 格式)并想要部署它,或者如果您正在构建一个实际的可运行 jar,那么您将需要将其与范围为 compile
和 runtime
.
的所有依赖项捆绑在一起
如果您正在构建一个库,那么您不会将任何依赖项与您的库打包在一起。相反,您包含 pom.xml
以便其他人知道您的库需要什么依赖项。要让 Maven 知道如何找到给定 jar 的关联 POM,最好和最常见的解决方案是将库部署到 Maven 存储库。 Repos 有一个目录结构,可以帮助 Maven 找到正确版本的库,并找到指示所需依赖项的 POM。
根据您的库是否开源,您将能够被一些存储库免费托管,例如 Sonatype (complete list here). But you can also setup your own repository either by installing a dedicated software such as Nexus or by configuring a Github project as the repo, as is explained on this blog.
让我先解释一下必要的库是什么意思。我正在使用 Google App Engine for Java with the official Google Maven Plugin 创建我的第一个项目,将 Maven 作为打包解决方案(或者可能是整个 Java 开发)的主要问题是如果依赖树增长 太多,发布过程可能会更难。
让我举个例子来说明。让我们从 Jackson JSON 库开始(这是一个很好的起点,因为它没有父依赖项),现在有人制作了一个 JSON-RPC 库并将 Jackson 用于 JSON serialization/deserialization.想象一下,这个库不仅提供了一个 JSON-RPC 客户端实现,而且还提供了一个服务器,这意味着这个库的 POM 将添加一些 Java EE 相关库作为依赖项,例如 Jetty。
可能指南说应用程序应该分为模块或将服务器相关的 deps 标记为可选,但你知道很多人不遵循标准。
现在有人需要JSON-RPC client for his/her project,叫Project X,用上面提到的lib,编译时不会有问题,Maven会成功下载所需的库和应用程序可以正常编译,但是当那个人想要发布应用程序时就会出现问题。 哪些依赖项 应与包一起分发(例如在 lib 文件夹中)?
实际上这就是发生在我身上的事情,我对 Maven 不太熟悉所以我使用了 Eclipse Runnable Jar Exporter,它生成的 jar 文件将所有 Maven 库复制到 lb 子文件夹,所以解决方法然后我所做的就是删除 看起来不必要的库 然后测试应用程序是否仍在运行。如果有 类 没有被执行,据我所知它们没有被 ClassLoader
加载,所以它们可以被省略并且是不必要的
我现在不能使用相同的技巧,因为场景要复杂得多,我们谈论的是 Java Web 应用程序,而不是像另一个应用程序那样的桌面应用程序,以及我想要的库包括一个 Liquid Template Engine, which uses the ANTLR 框架来生成解析器加上 Jackson 用于 JSON 处理程序和 Jsoup 用于 HTML 解析。
哪些库应该打包到 WEB-INF/lib 文件夹中?我确定我需要 Jackson 来进行 JSON 解析,但我不太确定 Jsoup,而 ANTLR 呢,它是必要的还是只在编译时使用?
更新:我想我需要重新表述我的问题,实际上我想要的是确定哪些依赖项是真正必要的对于应用程序,并将它们打包到应用程序 WEB-INF/lib 文件夹
解决方法: web app的WAR文件中打包的POM文件好像是用的一旦应用程序在 Google App Engine 生产环境中检索必要的依赖项,并且可能 appengine:update
目标只打包那些无法从 maven 中央仓库检索的依赖项,因此没有需要担心这个。
感谢David指出这一点。
您可以排除任何传递依赖。
对于您的情况,要从此 json-rpc-library 中删除码头,您需要:
<dependency>
<groupId>com.somecomp</groupId>
<artifactId>jsonrpclib</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
</exclusions>
</dependency>
查看文档:http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
你应该检查 Maven 的 dependency scopes。这是文档的摘录:
There are 6 scopes available:
- compile This is the default scope, used if none is specified. Compile dependencies are available in all classpaths of a project. Furthermore, those dependencies are propagated to dependent projects.
- provided This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
- runtime This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
- test This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.
- system This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
- import (only available in Maven 2.0.9 or later) This scope is only used on a dependency of type pom in the section. It indicates that the specified POM should be replaced with the dependencies in that POM's section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
因此在 Maven 项目中,开发人员指示应用程序中应该捆绑哪些依赖项,哪些不应该。
这里基本上有两种情况:
如果您正在构建一个 Web 应用程序(WAR 或 EAR 格式)并想要部署它,或者如果您正在构建一个实际的可运行 jar,那么您将需要将其与范围为
compile
和runtime
. 的所有依赖项捆绑在一起
如果您正在构建一个库,那么您不会将任何依赖项与您的库打包在一起。相反,您包含
pom.xml
以便其他人知道您的库需要什么依赖项。要让 Maven 知道如何找到给定 jar 的关联 POM,最好和最常见的解决方案是将库部署到 Maven 存储库。 Repos 有一个目录结构,可以帮助 Maven 找到正确版本的库,并找到指示所需依赖项的 POM。
根据您的库是否开源,您将能够被一些存储库免费托管,例如 Sonatype (complete list here). But you can also setup your own repository either by installing a dedicated software such as Nexus or by configuring a Github project as the repo, as is explained on this blog.