SpringBoot讀取Resource下文件的幾種方式
最近在項目中涉及到Excle的導入功能,通常是我們定義完模板供用戶下載,用戶按照模板填寫完后上傳;這里模板位置resource/excelTemplate/test.xlsx,嘗試了四種讀取方式,並且測試了四種讀取方式分別的windows開發環境下(IDE中)讀取和生產環境(linux下jar包運行讀取)。
第一種:
第一種:
ClassPathResource classPathResource = new ClassPathResource("excleTemplate/test.xlsx"); InputStream inputStream =classPathResource.getInputStream();
第二種:
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("excleTemplate/test.xlsx");
第三種:
InputStream inputStream = this.getClass().getResourceAsStream("/excleTemplate/test.xlsx");
第四種:
File file = ResourceUtils.getFile("classpath:excleTemplate/test.xlsx"); InputStream inputStream = new FileInputStream(file);
經測試:
前三種方法在開發環境(IDE中)和生產環境(linux部署成jar包)都可以讀取到,第四種只有開發環境 時可以讀取到,生產環境讀取失敗。
推測主要原因是springboot內置tomcat,打包后是一個jar包,因此通過文件讀取獲取流的方式行不通,因為無法直接讀取壓縮包中的文件,讀取只能通過類加載器讀取。
前三種都可以讀取到其實殊途同歸,直接查看底層代碼都是通過類加載器讀取文件流,類加載器可以讀取jar包中的編譯后的class文件,當然也是可以讀取jar包中的文件流了。
用解壓軟件打開jar包查看結果如下:
前三種方法在開發環境(IDE中)和生產環境(linux部署成jar包)都可以讀取到,第四種只有開發環境 時可以讀取到,生產環境讀取失敗。
推測主要原因是springboot內置tomcat,打包后是一個jar包,因此通過文件讀取獲取流的方式行不通,因為無法直接讀取壓縮包中的文件,讀取只能通過類加載器讀取。
前三種都可以讀取到其實殊途同歸,直接查看底層代碼都是通過類加載器讀取文件流,類加載器可以讀取jar包中的編譯后的class文件,當然也是可以讀取jar包中的文件流了。
用解壓軟件打開jar包查看結果如下:

其中cst文件中是編譯后class文件存放位置,excleTemplate是模板存放位置,類加載器讀取的是cst下class文件,同樣可以讀取excleTemplate下的模板的文件流了。
springboot項目獲取resources路徑(相對路徑)
springboot文件上傳保存到resources里,用
System.getProperty("user.dir");參數即可獲得項目相對路徑。(ps:不知道是不是springboot內嵌tomcat容器的原因,用網上的request.getServletContext().getRealPath("/")方法獲得的路徑不是項目路徑,而是c盤下一個tomcat目錄路徑)
File directory = new File("src/main/resources"); String courseFile = directory.getCanonicalPath();這種方式也能獲取到一樣的結果
最終版:ResourcesController.java

1 package tb.view.sbmsm.easyuidemo.controller; 2 3 import org.apache.commons.lang3.StringUtils; 4 import org.springframework.core.io.ClassPathResource; 5 import org.springframework.stereotype.Controller; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.ResponseBody; 8 import tb.helper.IOHelper; 9 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 import java.io.IOException; 13 import java.io.InputStream; 14 import java.util.regex.Matcher; 15 import java.util.regex.Pattern; 16 17 /** 18 * <pre> 19 * 20 * </pre> 21 * 22 * @author wangyunpeng 23 * @date 2020/1/19 13:55 24 */ 25 26 @Controller 27 @RequestMapping("/Resources") 28 public class ResourcesController { 29 /** 30 * http://stackoverflow.com/questions/19721820/pattern-matching-to-get-only-class-names-from-css-file 31 */ 32 private final Pattern _regex = Pattern.compile("\\.(.*)\\s?\\{", Pattern.MULTILINE); 33 private String _icons; 34 /** 35 * Logger for this class 36 */ 37 private final org.slf4j.Logger _logger = org.slf4j.LoggerFactory.getLogger(this.getClass()); 38 39 @RequestMapping(value = "IconData", produces = "application/json;charset=UTF-8") 40 @ResponseBody 41 public String iconData(HttpServletRequest request, HttpServletResponse response) throws IOException { 42 if (this._icons == null) { 43 44 // region 第一種方式:springboot項目獲取resources路徑(相對路徑),只能開發用,部署路徑不知道什么 45 // //https://blog.csdn.net/qq_29669265/article/details/89678077?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task 46 // String physicalUserDir = System.getProperty("user.dir");//項目的物理路徑 47 // File virtualPathFile = new File("src/main/resources/static/Content/jquery.easyUI/1.5.1/themes/icon.css");//相對路徑,只能開發用,部署路徑不知道什么 48 // String physicalPath = virtualPathFile.getCanonicalPath();//物理路徑 49 // if (!IOHelper.isExistFilePath(physicalPath)) { 50 // return "[]"; 51 // } 52 // String iconsText = null; 53 // try { 54 // iconsText = IOHelper.readAllText(physicalPath); 55 // } catch (IOException e) { 56 // this._logger.error("ResourcesController.iconData()", e); 57 // } 58 // endregion 59 60 // region SpringBoot讀取Resource下文件的幾種方式(通過類加載器讀取文件流,類加載器可以讀取jar包中的編譯后的class文件,當然也是可以讀取jar包中的文件流了) 61 //https://www.jianshu.com/p/7d7e5e4e8ae3 62 ClassPathResource classPathResource = new ClassPathResource("static/Content/jquery.easyUI/1.5.1/themes/icon.css"); 63 if (classPathResource == null) { 64 return "[]"; 65 } 66 String iconsText = null; 67 try (InputStream inputStream = classPathResource.getInputStream()) { 68 iconsText = IOHelper.readAllText(inputStream); 69 } catch (IOException e) { 70 this._logger.error("ResourcesController.iconData()", e); 71 return "[]"; 72 } 73 // endregion 74 75 StringBuilder sb = new StringBuilder("[{\"text\":\"無\",\"value\":\"\"}"); 76 if (StringUtils.isNotBlank(iconsText)) { 77 Matcher matcher = this._regex.matcher(iconsText); 78 String value = null; 79 while (matcher.find()) { 80 value = matcher.group(1).trim(); 81 sb.append(String.format(",{\"text\":\"%s\",\"value\":\"%s\"}", value, value)); 82 } 83 } 84 sb.append("]"); 85 this._icons = sb.toString(); 86 sb = null; 87 } 88 return this._icons; 89 } 90 }