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。