如何在Google App Engine Project(Java)中仅打包必要的库?

时间:2015-03-19 15:41:18

标签: eclipse maven google-app-engine java-ee packaging

让我先解释必要的库的含义。我使用Google App Engine for Java和官方Google Maven Plugin创建我的第一个项目,Maven作为打包解决方案(或者整个Java开发)的主要问题是,如果依赖树生长太多,释放过程可能会更难。

让我用一个例子来说明。让我们从Jackson JSON库开始(它是一个很好的起点,因为它没有父依赖项),现在有人制作一个JSON-RPC库并使用Jackson进行JSON序列化/反序列化。想象一下,这个库不仅提供了JSON-RPC客户端实现,还提供了服务器,这意味着该lib的POM将添加一些Java EE相关库,例如我们Jetty作为依赖项。

指南可能会说应用程序应该分为模块或将服务器相关的deps标记为可选,但是你知道很多人都不遵守这些标准。

现在有人为他/她的项目需要一个JSON-RPC客户端,称之为Project X,并使用上面提到的lib,在编译时没有问题,Maven将成功下载所需的libs并且应用程序将编译很好,但问题来自那个人想要发布应用程序。 哪些依赖项应该与软件包一起分发(例如在lib文件夹中)?

实际上发生在我身上的事情,我对Maven并不太熟悉,所以我使用Eclipse Runnable Jar Exporter生成jar文件,将所有maven库复制到lb子文件夹,所以我做的解决方法是删除看起来不必要的库,然后测试应用程序是否仍在工作。如果有没有执行的类,据我所知它们没有被ClassLoader加载,所以可以省略它们并且是不必要的

我现在无法使用相同的技巧,因为场景要复杂得多,我们谈的是Java Web应用程序,而不是像其他应用程序那样的桌面应用程序,而我想要包含的库是Liquid模板Engine,它使用ANTLR框架为JSON处理程序生成解析器和Jackson,为HTML解析生成Jsoup。

应该在WEB-INF / lib文件夹中打包哪些库?我确信我需要Jackson进行JSON解析,但我对Jsoup不太确定,那么ANTLR是什么,它是必要的还是仅在编译时使用?

更新我认为我需要重新制定我的问题,实际上我想要的是确定应用程序真正需要哪些依赖项,并将其打包成app WEB-INF / lib文件夹

解决方案:一旦应用程序位于Google App Engine生产环境中,似乎已将使用打包在Web应用程序的WAR文件中的POM文件检索必要的依赖项,并且appengine:update目标可能只包装那些无法从maven中央存储库中检索到的依赖项,因此无需担心这一点。

感谢David指出这一点。

2 个答案:

答案 0 :(得分:0)

您可以排除任何传递依赖。

对于您的情况,要从此json-rpc库中删除jetty,您需要:

<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

答案 1 :(得分:0)

你应该检查Maven的dependency scopes。以下是文档摘录:

  

有6个范围:

     
      
  • 编译这是默认范围,如果未指定,则使用此范围。编   依赖项在项目的所有类路径中都可用。   此外,这些依赖项将传播到依赖项目。
  •   
  • 提供这很像编译,但表示您期望JDK   或者在运行时提供依赖性的容器。例如,何时   您可以为Java Enterprise Edition构建Web应用程序   设置对Servlet API和相关Java EE API的依赖   提供范围是因为Web容器提供了这些类。这个   scope仅在编译和测试类路径上可用,并且是   不是过渡性的。
  •   
  • 运行时此范围表示依赖项是   不需要编译,但是用于执行。它在   运行时和测试类路径,但不是编译类路径。
  •   
  • 测试这个   scope表示正常使用时不需要依赖项   应用程序,仅适用于测试编译和   执行阶段。
  •   
  • 系统此范围与提供的类似,但不包括   你必须提供明确包含它的JAR。神器   始终可用,不会在存储库中查找。
  •   
  • 导入(仅限   在Maven 2.0.9或更高版本中可用)此范围仅用于   pom类型的依赖关系。它   表示应该用。替换指定的POM   POM部分中的依赖关系。自从他们   被替换,实际上并不具有导入范围的依赖项   参与限制依赖的传递性。
  •   

因此,在Maven项目中,开发人员会指出应该在应用程序中捆绑哪些依赖项,哪些不应该捆绑。

基本上有两种情况:

  • 如果您正在构建Web应用程序(WAR或EAR格式)并想要部署它,或者如果您正在构建一个实际的可运行jar,那么您将需要将其与所有依赖项一起捆绑在一起compileruntime

  • 如果您正在构建一个库,那么就不会对您的库打包任何依赖。而是包含pom.xml,以便其他人知道您的库需要什么依赖。要让Maven知道如何为给定的jar找到关联的POM,最好和最常见的解决方案是将库部署到Maven存储库。 Repos有一个目录结构,可以帮助Maven找到正确的库版本,并找到指示所需依赖关系的POM。

根据您的库是否是开源的,您可以通过某些存储库(如Sonatype(complete list here)免费托管。但您也可以通过安装Nexus等专用软件或将Github项目配置为repo as is explained on this blog来设置自己的存储库。