Play 框架手册(18) – 依赖管理


Play 的依赖管理系统允许你通过一个单独的 dependencies.yml 文件来描述你的应用程序所采用的扩展依赖。 

Play 应用程序可以有三种类型的依赖:

  • Play 框架自身,这是因为 play 应用程序总是要依赖 play 框架
  • 任何提供了 jar 文件并复制到应用程序 lib/目录下的 java 库
  • 安装在应用程序 modules 目录下的 Play 模块 module (实现是一些程序碎片)

一旦在 conf/dependencies.yml 文件里描述了应用程序的依赖,Play 将会进行检索、下载并安装所有需要的依赖。

18.1. 依赖格式

在 dependencies.yml 文件里用开发模拟的组织名称+所依赖的模块名称和对应的版本号就可以描述一个依赖关系,如:

organisation -> name revision

因此,1.0 版本的 Play PDF module 应该描述为:

play -> pdf 1.0

有些时候组织名称和依赖名称完全一致,比如 commons-lang

commons-lang -> commons-lang 2.5

在这种情况下,你可以省略组织名称:

commons-lang 2.5

动态版本 

修订本可以是已经修订好的(应用于 play1.2 版本)或是动态的。 一个动态的修订本的表示需要指定范围,比如: 

  • [1.0,2.0] 匹配 1.0 至 2.0 版本(含 1.0 和 2.0)
  • [1.0,2.0[匹配 1.0 至 2.0 版本(含 1.0,不含 2.0)
  • ]1.0,2.0] 匹配 1.0 至 2.0 版本(不含 1.0,但含 2.0)
  • ]1.0,2.0[匹配 1.0 至 2.0 版本(不含 1.0 和 2.0)
  • [1.0,) 匹配 1.0 及以上版本
  • ]1.0,) 匹配 1.0 以上版本
  • (,2.0] 匹配 2.0 及以下版本
  • (,2.0[匹配 2.0 以下版本

18.2. dependencies.yml 

当创建一个新 play 应用程序时,系统会自动在 conf 目录下创建一个 dependencies.yml 描述文件,其内容如下:

# Application dependencies

require:
    - play 1.2

require 节用于列出所有的依赖。在这里,新创建的 play 只依赖 Play version 1.2,如果应用程序需要依赖 Google Guava,那么应该修改为:

# Application dependencies

require:
    - play 1.2
    - com.google.guava -> guava r07

play dependencies 命令 

为了让 play 检索、下载并安装上面描述的新依赖,请运行 play dependencies: 

$ play dependencies
~        _            _
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/
~
~ play! 1.2, http://www.playframework.org
~ framework ID is gbo
~
~ Resolving dependencies using ~/Documents/coco/conf/dependencies.yml,
~
~
com.google.guava->guava r07 (from mavenCentral)
~
com.google.code.findbugs->jsr305 1.3.7 (from mavenCentral)
~
~ Downloading required dependencies,
~
~
downloaded
http://repo1.maven.org/maven2/com/google/guava/guava/r07/guava-r07.ja
r
~
downloaded
http://repo1.maven.org/maven2/com/google/code/findbugs/jsr305/1.3.7/j
sr305-1.3.7.jar
~
~ Installing resolved dependencies,
~
~
lib/guava-r07.jar
~
lib/jsr305-1.3.7.jar
~
~ Done!
~

这时, play会从Maven仓库里为Google Guava下载两个jar文件 (guava-r07.jar, jsr305-1.3.7.jar) ,并将它们安装到应用程序的 lib 目录下。 

为什么只声明了一个依赖,但 play 却下载了两个 jars 文件?这是因为 Google Guava 还有一个透明依赖。事实上 jsr305-1.3.7.jar 我们并不需要,我们可以排除它。 

透明依赖 

默认情况下,任何透明依赖都会被 play 自动恢复和找回。如果需要,可以使用以下方式排除它们:

1. 在描述时使用 particular:false 设置来实现:

# Application dependencies

require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false

2. 对整个项目禁用透明依赖:

# Application dependencies

transitiveDependencies: false

require:
    - play 1.2
    - com.google.guava -> guava r07

3.或排除特定依赖:

# Application dependencies

require:
    - play 1.2
    - com.google.guava -> guava r07:
        exclude:
            - com.google.code.findbugs -> *

保持 lib/和 modules/目录同步 

现在如果再次运行 play dependencies 命令时,jsr305-1.3.7.jar 依赖将被忽略:

$ play deps
~        _            _
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/
~
~ play! 1.2, http://www.playframework.org
~ framework ID is gbo
~
~ Resolving dependencies using ~/Documents/coco/conf/dependencies.yml,
~
~
com.google.guava->guava r07 (from mavenCentral)
~
~ Installing resolved dependencies,
~
~
lib/guava-r07.jar
~
~
********************************************************************
~ WARNING: Your lib/ and modules/ directories and not synced with
~ current dependencies (use --sync to automatically delete them)
~
~
Unknown: ~/Documents/coco/lib/jsr305-1.3.7.jar
~
********************************************************************
~
~ Done!
~

然而之前下载的 jsr305-1.3.7.jar 仍旧在 lib/目录里。 

play 的依赖管理系统负责保持 lib/和 modules/目录同步,这里可以使用 –sync 作为 play dependencies 命令的参数:

play deps --sync

如果再次运行 play deps 命令,不想要的 jar 文件将会被删除。

当部署应用程序到生产环境时, 可以通过删除模块源代码和模块文档来减少模块的大小,方法是使用 –forProd 参数运行如下命令:

play dependencies --forProd

这时, 将删除每个模块下的 documentation/, src/, tmp/, *sample*/ 和 *test*/ 等目录。

18.3. 冲突判定 Conflict resolution

当两个组件需要不同修订版本的同一个依赖时, 冲突管理只选择一个作为最终依赖。默认情况下是使用最新版本,放弃其他版本。 

但这里有一个例外情况:当 play 框架自己的核心依赖发生冲突时,在 $PLAY/framework/lib 目录下的可用版本具有最高优先级。比如,Play 依赖于commons-lang 2.5,如果你的应用程序需要 commons-lang 3.0 时:

# Application dependencies

require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false
    - commons-lang 3.0

运行 play dependencies 命令将不会采用 commons-lang 3.0,虽然它是最新的: 

play dependencies
~        _            _
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/
~
~ play! 1.2, http://www.playframework.org
~ framework ID is gbo
~
~ Resolving dependencies using ~/Documents/coco/conf/dependencies.yml,
~
~
com.google.guava->guava r07 (from mavenCentral)
~
~ Some dependencies have been evicted 驱逐,
~
~
commons-lang 3.0 is overriden by commons-lang 2.5
123

~
~ Installing resolved dependencies,
~
~
lib/guava-r07.jar
~
~ Done!
~

同样要注意,在$PLAY/framework/lib 下可用的依赖将不会安装到你的应用程序的 lib 目录下。

有时你可能需要强制指定一个依赖的版本,要么是为了覆盖核心依赖,或是为了选择最新发布的修订版本。 

这时就可以在某个依赖上指定 force 选项:

# Application dependencies

require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false
    - commons-lang 3.0:
        force: true

18.4. 增加要的仓库 

默认情况下,play 将搜索 central Maven repository 下的所有 jar 依赖,同时搜索 central Play modules repository 下的所有 Play 模块。 

在配置文件的 repositories 节里,你可以指定新的定制仓库:

# Application dependencies

require:
    - play 1.2
    - com.google.guava -> guava r07:
        transitive: false
    - commons-lang 3.0:
        force: true
    - com.zenexity -> sso 1.0

# My custom repositories
repositories:
    - zenexity:
        type:       http
        artifact:
"http://www.zenexity.com/repo/[module]-[revision].[ext]"
        contains:
            - com.zenexity -> *

使用这个配置后,所有 com.zenexity organisation 下的依赖都会被检索,并且从远程 http 服务器进行下载。

Maven 仓库

使用 iBiblio(公共库和数字档案)类型,也可以增加 maven2-compatible 兼容仓库,比如:

# Application dependencies

require:
    - play
    - play -> scala 0.8
    - org.jbpm -> jbpm-persistence-jpa 5.0.0:
        exclude:
            - javassist -> javassist *
            - org.hibernate -> hibernate-annotations *
            - javax.persistence -> persistence-api *
repositories:
    - jboss:
        type: iBiblio
        root:
"http://repository.jboss.org/nexus/content/groups/public-jboss/"
        contains:
            - org.jbpm -> *
            - org.drools -> *

本地仓库 

最后,最重要的是你可能想要定义一个引用本地模块的仓库。就和在application.conf 配置文件中配置模块一样(play1.2 开始不再赞成使用),依赖可以很好工作。

首先创建以下目录结构:

myplayapp/
myfirstmodule/
mysecondmodule/

然后如下设置 myplayapp/conf/depencencies.yml 就可以实现了:

# Application dependencies

require:
    - play
    - myfirstmodule -> myfirstmodule
    - mysecondmodule -> mysecondmodule

repositories:
    - My modules:
        type:       local
        artifact:   ${application.path}/../[module]
        contains:
            - myfirstmodule
            - mysecondmodule

注意:不要忘记了运行 play dependencies myplayapp 命令。

定制 ivy 设置(Apache ivy:项目依赖管理工具) 

Play 在 hood 下使用 Ivy 来管理项目依赖。如果你需要指定一个特定配置,比如调协一个代理 proxy 用于验证内部 maven 网络仓库,那么你可以修改 ivysettings.xml 文件,这个文件位于 play 主目录的.ivy2 目录。

示例 1,让 ivy 忽略 checksums:

<!-- .ivy2/ivysettings.xml -->
<ivysettings>
  <property name="ivy.checksums" value=""/>
</ivysettings>

示例 2,使用基本验证:

<!-- .ivy2/ivysettings.xml -->
<ivysettings>
  <credentials host="maven-repo.xxx" realm="Sonatype Nexus Repository
Manager"
    username="user" passwd="reallygreatpassword"/>
</ivysettings>

示例 3,重用本地 maven 仓库,并进行仓库管理:

<!-- .ivy2/ivysettings.xml -->
<ivy-settings>
  <!-- path to local maven repo and default maven layout -->
  <property name="local-maven2-pattern" value="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision]" override="false" />

  <!-- set resolver chain as default -->
  <settings defaultResolver="main" />

  <!-- configure caches -->
  <caches repositoryCacheDir="${user.home}/.ivy2/cache">
    <!-- do not cache from local .m2-->
    <cache name="nocache" useOrigin="true" />
    <cache name="default" />
  </caches>

  <resolvers>
    <chain name="main">
      <!-- as this is not cached, even changing SNAPSHOT dependencies are resolved correctly -->
      <filesystem name="local-maven-2" m2compatible="true" local="true" cache="nocache">
        <ivy pattern="${local-maven2-pattern}.pom" />
        <artifact pattern="${local-maven2-pattern}(-[classifier]).[ext]" />
      </filesystem>
      <!-- use repository manager as proxy to maven-central  (and all other repositories)-->
      <ibiblio name="repomanager" m2compatible="true" root="http://your.repomanager.intra/path/to/repo" cache="default"/>
    </chain>
  </resolvers>
</ivy-settings>

详见 Ivy settings documentation

清除 Ivy 缓存 

Ivy 缓存可能会损坏, 特别是在 conf/dependencies.yml 文件里的 repositories 节使用 http 类型时很容易损坏。如果发生这样的事,并且依赖解决方案不能正常工作时,可以使用—clearcache 选项清除 ivy 缓存。

$ play dependencies --clearcache

这个命令等效于 rm -r ~/.ivy2/cache。


前一篇:
后一篇:

发表评论