【发布时间】:2019-01-10 18:24:44
【问题描述】:
我有一个与 Liquibase 集成的多模块 Spring Boot 应用程序。从 IDE 运行它时,liquibase 脚本工作得很好。但是,当从 jar 中运行它时,它们不会。经过一番调查,似乎 liquibase 本身在尝试从嵌入式 jar 中读取时存在重大问题。 liquibase 脚本本身存在于 fat jar 内的嵌入式 jar 中,主 xml 文件如下所示:
<includeAll path="classpath*:config/liquibase/changelog/"/>
经过进一步调查,我将所有问题缩小到 liquibase 本身的问题。我使用的版本是 liquibase-3.6.2。我怀疑 liquibase 中存在的错误属于以下类: liquibase.resource.ClassLoaderResourceAccessor 我把它缩小到的方法是
public Set<String> list(String relativeTo, String path, boolean includeFiles, boolean includeDirectories, boolean recursive) throws IOException
此方法的输入如下:
relativeTo = null
path = jar:file:/C:/#{SOME_PATH}/xxx-1.0.0.0-SNAPSHOT.jar!/BOOT-INF/lib/yyy-1.0.0.0-SNAPSHOT.jar!/config/liquibase/changelog/
includeFiles = true
includeDirectories = false
recursive = true
当然,您需要将#{SOME_PATH} 替换为磁盘上的有效路径。出于安全目的,我将其编辑了。我们已经可以注意到,liquibase 发现在 fat jar xxx 内的嵌入式 yyy jar 中可能有一些脚本。
这个方法的问题是它不是返回 jar 中的 XML 脚本,而是返回 yyy jar 本身。这只会在稍后的代码中导致错误,因此我假设此方法负责查找 XML 文件(因为如果我直接从 IDE 而不是从 jar 运行我的项目,它会成功)。
我注意到主要问题的行是第 134 行:
String returnPath = SpringBootFatJar.getSimplePathForResources(entry.getName(), path);
此时path变量被破坏,SpringBootFatJar返回一个被破坏的返回路径。在下面的部分中,我将描述会发生什么:
- 在第 105 行,路径变量被拆分并变为“config/liquibase/changelog/”。根据第 134 行的使用方式和 SpringBootFatJar 类中的 javadoc,这可能非常糟糕。
- 快进到第 134 行,entry.getName() 返回“BOOT-INF/lib/yyy-1.0.0.0-SNAPSHOT.jar”,路径同上。基于 SpringBootFatJar 中的 javadoc,这是非常糟糕的。
- 在第 134 行之后,returnPath 变为“BOOT-INF/lib/yyy-1.0.0.0-SNAPSHOT.jar”,其余为历史记录,因为第 143 行的nestedEntries 永远不会以该路径开头。
不幸的是,我本周没有时间进一步调查这个问题,我想在 stackoverflow 上发布这个问题,看看是否有其他人有这个问题,是否是一个已知的 liquibase 错误,以及是否有一个简单的解决方法它。下周我将尝试自己进一步调查,并检查是否所有这些问题都来自第 105 行看似糟糕的分割路径参数,因为输入的路径参数中有两个“!/”实例。
谢谢
【问题讨论】:
标签: spring spring-boot liquibase