SpringBoot读取resource或template中的文件 | 您所在的位置:网站首页 › java获取resource下文件 › SpringBoot读取resource或template中的文件 |
Spring-Boot读取resource或template中的文件
1.项目场景:
以jar包方式部署系统,想读取resource或是template下面的文件时,报 File Not Found 我遇到的情况是,整个项目达成了一个包,在开发环境(windows + idea)读取文件没问题,但在预发布环境(centos, 打成一个jar部署),则报错。 2.问题描述: File file = ResourceUtils.getFile("classpath:templates/jumppage.html")使用上述方法读取模板文件当部署成jar包时读取不到文件 3.解决方案:方法1/2/3在开发环境、预发布环境都可以读取到jar包中的文件,方法4则只有开发环境中可以、直接从jar包读取失败。 3.1方法一 InputStream in = null; ClassPathResource classPathResource = new ClassPathResource("templates/jumppage.html"); in = classPathResource.getInputStream(); StringBuffer buff = new StringBuffer(); byte[] filecontent = new byte[1024]; while((in.read(filecontent)) != -1){ String strRead = new String(filecontent); buff.append(strRead); } byte[] bytes = buff.toString().getBytes();注:使用classPathResource.getFile()会报错找不到该文件,原因是springboot打成了jar包,classPathResource.getFile()无法读取jar包目录下的文件 3.2方法二 InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("templates/jumppage.html"); 3.3方法三 InputStream inputStream = this.getClass().getResourceAsStream("/templates/jumppage.html"); 3.4方法四 File file = ResourceUtils.getFile("classpath:templates/jumppage.html"); InputStream inputStream = new FileInputStream(file); SpringBoot打包后资源文件读取问题springboot项目打包之后,将所有依赖都打入jar包,同时也将系统中要使用的一些资源文件也会打进来,之后运行这个jar包,里面包含的资源文件不能再像文件系统那样直接在classpath下就可以使用了。 如下所示,这段代码在idea中运行,可以按照预期,正确访问到资源文件hello.txt。 package com.xxx.springresourcedemo; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.core.io.ClassPathResource; import java.io.File; import java.io.InputStream; @SpringBootApplication public class SpringresourcedemoApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(SpringresourcedemoApplication.class, args); } @Override public void run(String... args) throws Exception { try { String path = new ClassPathResource("hello.txt").getURL().getPath(); File file = new File(path); System.out.println(file.getPath()+" exists -> "+file.exists()); }catch (Exception e){ System.out.println("exception -> "+e.getMessage()); } } }在 idea中运行程序,打印信息如下: 但是如果我们打包,直接在windows下或者在linux下运行,这个代码的结果就发生了改变: 我们可以通过反编译工具看jar包的内容,hello.txt文件确实在BOOT-INF\classes目录下: 打包之后运行的结果为什么会出现这个问题?其实仔细想想,jar包内的文件路径发生了改变,当然就不能再像文件系统那样使用这个文件了。 那么问题来了,静态文件怎么加载,springboot又是如何加载application.yml或者其他配置文件的呢?其实它是通过读取流的方式来加载资源文件的。 有了这个思路,我们改变代码,通过InputStream流来读取文件,看看结果怎样? package com.xxx.springresourcedemo; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.core.io.ClassPathResource; import java.io.File; import java.io.InputStream; @SpringBootApplication public class SpringresourcedemoApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(SpringresourcedemoApplication.class, args); } @Override public void run(String... args) throws Exception { try{ InputStream in = new ClassPathResource("hello.txt").getInputStream(); byte[] data = new byte[1024]; int len; String content = ""; while((len=in.read(data))!=-1){ content += new String(data,0,len); } in.close(); System.out.println("file content -> "+content); }catch (Exception e){ System.out.println("exception -> "+e.getMessage()); } } }这个代码,无论实在idea中运行,还是打包之后运行,结果都一样: 打包之后运行: 这样,我们大概就知道了,通过流的方式可以读取resources资源文件。 如果你使用了流的方式读取资源文件,发现还是不能读取,那么问题就是打包的时候资源文件被过滤了,这个时候就需要考虑打包配置了。可以参考如下pom.xml: src/main/resources **/*.yml **/*.txt true src/main/java **/*.xml true org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-resources-plugin 3.0.1 txt,yml我们可以看看springboot启动时加载application.properties的代码: 加载application.properties文件时用到了OriginTrackedPropertiesLoader类的load()方法,这个方法里面的内容如下: 断点的位置就开始通过reader读取了,而这里的CharacterReader内部类的构造器代码如下: CharacterReader(Resource resource) throws IOException { this.reader = new LineNumberReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.ISO_8859_1)); }这里通过resource.getInputStream()流来封装InputStreamReader,最后封装为LineNumberReader,至此,springboot加载配置文件的思路也就是通过InputStream流来读取我们就清楚了。还有其他的配置文件的加载方法,比如spring.factories加载方法,其实也是通过InputStream流的方式来读取的。 springboot打包之后,资源文件不能直接通过路径的方式来作为文件使用,但是可以通过流的方式读取,这里配置文件,我们只需要知道内容,无需写出来,但是比如图片,我们需要在别的地方使用的,那么就需要通过InputStream,OutputStream流将资源文件读出来保存到一个可以访问的文件中,那么我们就可以正常使用了。 |
CopyRight 2018-2019 实验室设备网 版权所有 |