### 需求 在nookblog博客项目开发过程中,有一个初始化博客的功能:其中需要将项目`resources/static/blog`目录下所有资源资源复制到指定目录。 ### 思路 根据我的需求,复制的思路大概是,先获取到`resources/static/blog`目录下文件清单,然后通过清单,循环将文件复制到指定位置(相对路径需要确保一致) 因为项目会被打成jar包,所以不能用传统的目录文件复制方式,这里需要用到Spring Resource: > Resource接口,简单说是整个Spring框架对资源的抽象访问接口。它继承于InputStreamSource接口。后续文章会详细的分析。 Resource接口的方法说明: | 方法 | 说明 | | :------------ | :------------ | | exists() | 判断资源是否存在,true表示存在。 | | isReadable() | 判断资源的内容是否可读。需要注意的是当其结果为true的时候,其内容未必真的可读,但如果返回false,则其内容必定不可读。 | | isOpen() | 判断当前Resource代表的底层资源是否已经打开,如果返回true,则只能被读取一次然后关闭以避免资源泄露;该方法主要针对于InputStreamResource,实现类中只有它的返回结果为true,其他都为false。 | | getURL() | 返回当前资源对应的URL。如果当前资源不能解析为一个URL则会抛出异常。如ByteArrayResource就不能解析为一个URL。 | | getURI() | 返回当前资源对应的URI。如果当前资源不能解析为一个URI则会抛出异常。 | | getFile() | 返回当前资源对应的File。 | | contentLength() | 返回当前资源内容的长度。 | | lastModified() | 返回当前Resource代表的底层资源的最后修改时间。 | | createRelative() | 根据资源的相对路径创建新资源。[默认不支持创建相对路径资源] | | getFilename() | 获取资源的文件名。 | | getDescription() | 返回当前资源底层资源的描述符,通常就是资源的全路径(实际文件名或实际URL地址)。 | | getInputStream() | 获取当前资源代表的输入流。除了InputStreamResource实现类以外,其它Resource实现类每次调用getInputStream()方法都将返回一个全新的InputStream。 | 获取Resource清单,我需要通过ResourceLoader接口获取资源,在这里我选择了`org.springframework.core.io.support.PathMatchingResourcePatternResolver` ### 实现代码 ```java ... //资源清单获取 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources = resolver.getResources("static/blog/**"); for (Resource resource : resources) { FreeMarkerUtil.copyResourceToFile(resource, aPath,"/static/blog/"); } ... ``` ```java /** * 复制指定spring资源到指定路径 * * @param resource * @param targetPath 目标路径 * @param relativeRootPath 资源所在相对路径,如果填写了relativeRootPath,会连同相对relativeRootPath路径后的目录一起建立,反之直接在targetPath复制资源 * @throws IOException */ public static void copyResourceToFile(Resource resource, String targetPath, String relativeRootPath) throws IOException { InputStream inputStream = null; try { inputStream = resource.getInputStream(); } catch (Exception e) { log.warn(String.format("[%s]获取输入流发生异常!", resource.getURL())); throw new RuntimeException(String.format("[%s]获取输入流发生异常!", resource.getURL())); } String filename = resource.getFilename(); //分析相对目录 String appenPath = ""; if (!StringX.isEmpty(relativeRootPath)) { String sUrl = resource.getURL().toString(); if (sUrl.startsWith("jar:file:")) { String[] tempArr = sUrl.split("!"); appenPath = tempArr[tempArr.length - 1]; } else if (sUrl.startsWith("file:")) { appenPath = sUrl.substring("file:".length() - 1); } int rootPathIndex = appenPath.indexOf(relativeRootPath); if (rootPathIndex < 0) { throw new RuntimeException("relativeRootPath有误:无法分析相对目录"); } appenPath = appenPath.substring(rootPathIndex + relativeRootPath.length(), appenPath.length() - filename.length()); if (StringX.isEmpty(appenPath)) { appenPath = File.separator; } } String filePath = targetPath + File.separator + appenPath; checkAndMkdirs(filePath); String fileName = filePath + filename; File file = new File(fileName); FileUtils.copyInputStreamToFile(inputStream, file); } ``` :smile: ------------ > 本文由 [叶不空](https://yebukong.com "叶不空") 创作,采用 [知识共享署名 4.0 国际许可协议](https://creativecommons.org/licenses/by/4.0/ "知识共享署名 4.0 国际许可协议")进行许可,转载请附上链接! > 本文链接: [https://yebukong.com/article/1102629952022507521.html](https://yebukong.com/article/1102629952022507521.html "SpringBoot将resources目录资源复制到指定位置")