我可以使用 Gradle 在我的类路径中强制依赖的顺序吗?

mat*_*rns 4 java google-app-engine classpath dependency-management gradle

一个项目在 Google App Engine 上运行。该项目的依赖项使用了由于安全限制而无法在 App Engine 上调用的类(它不在白名单中)。我的(非常hacky)解决方案是将该类的修改版本复制到我的项目中(匹配原始类的名称和包),不需要受限类。这适用于 dev 和 live,我假设是因为我的源出现在我的外部依赖项之前的类路径中。

为了使它更简洁,我决定将该类的修改版本放入它自己的项目中,该项目可以打包在一个 jar 中并发布给其他任何遇到此问题的人使用。

这是我的 build.gradle:

// my jar that has 'fixed' version of Class.
compile files('path/to/my-hack-0.0.1.jar')

// dependency that includes class that won't run on appengine
compile 'org.elasticsearch:elasticsearch:1.4.4'
Run Code Online (Sandbox Code Playgroud)

在我的本地开发服务器上,这工作正常,代码在运行时首先找到我的类的黑客版本。在直播中,由于某些未知原因,首先加载 elasticsearch 依赖项中的版本。

我知道在类路径中拥有同一个类的两个版本并不理想,但我希望我可以可靠地强制我的版本位于类路径的开头。有任何想法吗?或者,有没有更好的方法来解决这个问题?

Gul*_*ats 9

不确定这是否是访问此问题的人正在寻找的内容,但这就是我的问题和我所达到的解决方案。Jar A:包含类 XYZ Jar B:还包含类 XYZ 我的项目在 Jar A 之前需要在类路径上的 Jar B 才能被编译。

问题是 Gradle 根据字母顺序对依赖项进行排序后解决它们,这意味着 Jar B 将在生成的类路径中出现在 Jar A 之后,导致编译时出错。

解决方案:声明一个自定义配置并修补compileClasspath。这就是 的相关部分的build.gradle样子。

configurations {
    priority
    sourceSets.main.compileClasspath = configurations.priority + sourceSets.main.compileClasspath
}

dependencies {
    priority 'org.blah:JarB:2.3'
    compile 'org.blah:JarA:2.4'
    ...
}
Run Code Online (Sandbox Code Playgroud)


mat*_*rns 3

这是我应该研究的应用程序引擎类加载器,而不是 gradle...

App Engine 允许您使用appengine-web.xml. 就我而言:

<class-loader-config>
    <priority-specifier filename="my-hack-0.0.1.jar"/>
</class-loader-config>
Run Code Online (Sandbox Code Playgroud)

这将my-hack-0.0.1.jar作为第一个要搜索类的 JAR 文件,排除目录中的类war/WEB-INF/classes/

...感谢 @Danilo Tommasina 的正确方向推动:)

2020 年更新:

我刚刚再次遇到同样的问题,并遇到了我自己的问题...这一次,实时应用程序引擎加载的版本org.json与开发中加载的版本不同。非常令人沮丧,无论对构建脚本进行多少修改都无法修复它。对于未来的搜索者,如果您收到以下信息:

java.lang.NoSuchMethodError: org.json.JSONObject.keySet()Ljava/util/Set;
Run Code Online (Sandbox Code Playgroud)

org.json这是因为它正在从天知道在哪里加载旧的依赖项。我通过将其添加到我的 appengine-web.xml 来修复它:

<class-loader-config>
    <priority-specifier filename="json-20180130.jar"/>
</class-loader-config>
Run Code Online (Sandbox Code Playgroud)

build.gradle如果您还没有匹配的依赖项,您还需要一个匹配的依赖项:

compile 'org.json:json:20180130'
Run Code Online (Sandbox Code Playgroud)