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包查看结果如下:

spring获取resource目录路径 springboot获取resources下文件路径_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路径(相对路径),只能开发用,部署路径不知道什么
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 }

ResourcesController.java