如何复制Jar包内资源到其他地方
背景
最近一直在做自己的代码生成器项目,遇到一个需求,需要把线上运行Jar包里resources文件夹下的某些文件夹按照原本的文件结构,复制到Jar包外的另一处位置。
解决
一开始在IDEA里开发很简单,调用FileUtils.copyDirectory(src, dest)
就解决了,本地调试运行也很顺利,文件都按照预想的复制过去了,接下来准备打包部署到服务器上试一下,这一试就试出问题了,直接抛了异常如下
class path resource xxx cannot be resolved to absolute file path because it does not reside in the file system
搜索了一下,才知道Jar包里的文件是不能被当作文件系统里的文件来处理的,而只能用流的方式去处理。但试了一圈也没发现有什么简单的方法可以把Jar包下某个文件夹的流复制到Jar包外,
不过倒是让我找到一个方法FileUtils.copyURLToFile(url, file)
,按着这个方法想到了一个思路,不关心文件夹,而是把文件夹下的文件独立地通过流复制到目的地。
spring本身有许多方便的方法去处理ClassPathResource,通过ClassPathResource可以拿到对应的InputStream,于是便有了以下思路
- 获取Jar包某些文件夹下所有文件的流
- 筛选需要复制的流
- 复制
1
2
3
4
5
6
7
8
9
10
11
12// 通过spring提供的方法,用匹配路径字符串获取需要复制的resources
val resourceResolver = PathMatchingResourcePatternResolver()
val resources = resourceResolver.getResources("/templates/layui/**")
resources.filter { ReUtil.isMatch(".*?\\.[a-zA-Z]*?", it.filename!!) } // 进一步筛选需要复制哪些文件,同时过滤掉文件夹路径的resource
.forEach {
val url = it.url
val filePath = url.path.substring(url.path.indexOf("layui") + 5)
if (!filePath.contains("page")) {
val destination = File("${pathConstant.resourcesDirPath()}/templates/$filePath")
FileUtils.copyURLToFile(url, destination) // 复制
}
}
最后打包测试,一切OK。