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);}@Overridepublic 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中运行程序,打印信息如下:

img

但是如果我们打包,直接在windows下或者在linux下运行,这个代码的结果就发生了改变:

img

我们可以通过反编译工具看jar包的内容,hello.txt文件确实在BOOT-INF\classes目录下:

img

打包之后运行的结果为什么会出现这个问题?其实仔细想想,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);}@Overridepublic 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中运行,还是打包之后运行,结果都一样:

img

打包之后运行:

img

这样,我们大概就知道了,通过流的方式可以读取resources资源文件。

如果你使用了流的方式读取资源文件,发现还是不能读取,那么问题就是打包的时候资源文件被过滤了,这个时候就需要考虑打包配置了。可以参考如下pom.xml:

<build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.yml</include><include>**/*.txt</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>3.0.1</version><configuration><nonFilteredFileExtensions><nonFilteredFileExtension>txt,yml</nonFilteredFileExtension></nonFilteredFileExtensions></configuration></plugin></plugins>
</build>

我们可以看看springboot启动时加载application.properties的代码:

img

加载application.properties文件时用到了OriginTrackedPropertiesLoader类的load()方法,这个方法里面的内容如下:

img

断点的位置就开始通过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流将资源文件读出来保存到一个可以访问的文件中,那么我们就可以正常使用了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554996.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于使用this.getClass().getResource(“/“)获取文件时遇到的坑_ClassPathResource加载资源文件用法

最近在工作中遇到需要读取配置文件&#xff0c;然后第一想法就是将文件放到项目的resources目录下, 然后使用&#xff1a; String fileName "config/zh.md" String path this.getClass().getResource("/").getPath() fileName; System.out.println(p…

Objects.requireNonNull( )方法说明

Objects.requireNonNull( )方法在java.util.Objects中 作用就是判断一个对象是否为空 底层源码&#xff1a; /* param obj 需要检测是否为空的对象* param <T> 对象类型* return 对象不为空则返回该对象* throws 对象为空则报NullPointerException异常*/public static …

数据模型 同比 环比_同比和环比计算公式?

一、同比增长计算公式&#xff1a; 1、同比增长率(本期数&#xff0d;同期数)同期数100% 例子&#xff1a;比如说去年3月的产32313133353236313431303231363533e4b893e5b19e31333365666237值100万&#xff0c;本年3月的产值300万&#xff0c;同比增长率是多少&#xff1f; 本…

SimpleDateFormat的线程不安全问题

一、前言 日期的转换与格式化在项目中应该是比较常用的了 一个问题&#xff1a;项目中的日期转换怎么用的&#xff1f;SimpleDateFormat 用过吗&#xff1f;能说一下 SimpleDateFormat 线程安全问题吗&#xff0c;以及如何解决&#xff1f; 回答&#xff1a;平时就是在全局定…

JVM——System.gc、内存溢出、内存泄漏、STW、安全点、安全区域、强软弱虚引用

文章目录①. System.gc()的理解②. 内存溢出(out of Memory)③. 内存泄漏(Memory Leak)④. Stop The World⑤. 多线程中的并行与并发⑥. 垃圾回收的并行、串行、并发⑦. 安全点(Safepoint)⑧. 安全区域(Safe Region)⑨. 引用①. 强引用:不回收②. 软引用: 内存不足即回收③. 弱…

Java——ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法

文章目录①. ThreadLocal简介①. ThreadLocal是什么②. api介绍③. 永远的helloword④. 通过上面代码总结②. 从阿里ThreadLocal规范开始①. 非线程安全的SimpleDateFormat②. 将SimpleDateFormat定义成局部变量(方案一)③. ThreadLocal 解决日期格式乱码问题④. 阿里规范怎么说…

JPA入门

文章目录JPA概述JPASpring Data JPAJPA注解基础注解EntityTableIdEnumeratedTransientColumnTemporal联合主键注解IdClassEmbeddable和EmbeddedId注解实体之间关联关系注解OneToOneManyToOne和OneToManyRepositoryJPA查询方式DQM&#xff08;定义查询方法&#xff09;使用实例D…

Java8——Stream流操作List排序_List集合中每个对象元素按时间顺序排序

一个学生类的实体类 Data public class Student {private Long id;private String name;private int age;private Double height;public Student(Long id, String name, int age, Double height) {this.id id;this.name name;this.age age;this.height height;}然后我们测…

java线程初始方法三种_Java 多线程 三种实现方式

Java多线程实现方式主要有三种&#xff1a;继承Thread类、实现Runnable接 口、使用ExecutorService、Callable 实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值&#xff0c;只有最后一种Callable是带返回值的&#xff0c;返回结果可以从Future中取出来关于Exe…

java控制层创建websocket_用Java构建一个简单的WebSocket聊天室

前言首先对于一个简单的聊天室&#xff0c;大家应该都有一定的概念了&#xff0c;这里我们省略用户模块的讲解&#xff0c;而是单纯的先说说聊天室的几个功能&#xff1a;自我对话、好友交流、群聊、离线消息等。今天我们要做的demo就能帮我们做到这一点啦&#xff01;&#xf…

Java中Date与 LocalDateTime ,LocalDate之间的转换

Date与LocalDateTime和LocalDate互相转换思路 Date转LocalDateTime和LocalDate都可以通过Date先转换成Instant然后再转换成LocalDateTime和LocalDate&#xff0c;可以按照下图的方式进行转换。LocalDateTime和LocalDate转换成Date也是以Instant为中介来进行转换的。 1&#xff…

Spring-data-jpa入门(一)

啥是JPA 我这个小白没有听说过&#xff0c;全英文名叫Java Persistence API&#xff0c;就是java持久化api&#xff0c;是SUN公司推出的一套基于ORM的规范。 持久化想必如雷贯耳&#xff0c;都2022年了&#xff0c;谁还不用个持久化框架啊&#xff0c;举起mybatis。 ORM呢&a…

struts单例模式 java_Java单例设计模式详细介绍

Java单例设计模式教程中包含了单例模式的定义、特点以及线路安全等问题。单例模式定义&#xff1a;单例模式确保某个类只有一个实例&#xff0c;而且自行实例化并向整个系统提供这个实例。在计算机系统中&#xff0c;线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对…

NetBeans、Eclipse 和 IDEA,哪个才是最优秀的Java IDE?

NetBeans、Eclipse 和 IDEA&#xff0c;哪个才是最优秀的Java IDE? 本文将向您介绍三种流行的Java IDE的基本特点&#xff0c;并比较它们的优缺点。 众所周知&#xff0c;集成开发环境(IDE)能够让程序员的日常编程过程&#xff0c;比起直接在文本编辑器上编写代码要容易得多。…

Spring-data-jpa入门(二)

前言 上一节我们讲解了spring-data-jpa最基础的架构和最简单的增删查改的实现&#xff0c;可以发现spring-data-jpa在简单增删查改的实现是非常友好的&#xff0c;甚至根本见不着sql语句的存在&#xff0c;让人直呼NB。 还记得上一节埋的几个坑吗&#xff0c;这一节就先把坑填…

JavaWeb学习笔记——详细

一、HTTP协议简介 1、什么是http协议 概述&#xff1a; HTTP是Hyper Text Transfer Protocol的缩写&#xff0c;即超文本传输协议。它是一种请求/响应式的协议&#xff0c;客户端在与服务器端建立连接后就可以向服务器端发送请求&#xff0c;这种请求被称作HTTP请求&#xf…

基本数据类型和包装类的区别,编程中如何选择?

问题&#xff1a;基本数据类型和包装类有什么区别吧&#xff0c;什么时候用包装类什么时候用基本数据类型&#xff1f; 最本质的区别&#xff1a;基本数据类型不是对象&#xff0c;包装类型是对象存储位置不同&#xff1a;基本类型是直接将变量值存储在栈中&#xff0c;而包装…

java怎么获取控制台内容的类型_java 怎么获取控制台的数据并且输出到GUI上

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼以前做过&#xff0c;给个参考。为防止格式错乱&#xff0c;以下代码用base64解码一下得到格式良好的代码。aW1wb3J0IG9yZy5qdW5pdC5UZXN0OwoKaW1wb3J0IGphdmEuaW8uKjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0a…

描述一下JAVA的加载过程_JVM源码分析之Java类的加载过程

简书 占小狼转载请注明原创出处&#xff0c;谢谢&#xff01;趁着年轻&#xff0c;多学习背景最近对Java细节的底层实现比较感兴趣&#xff0c;比如Java类文件是如何加载到虚拟机的&#xff0c;类对象和方法是以什么数据结构存在于虚拟机中&#xff1f;虚方法、实例方法和静态方…

MongoDB 官方云端使用方法

MongoDB介绍 MongoDB是一种面向文档型的非关系型数据库&#xff08;NoSQL&#xff09;&#xff0c;由C编写。非关系数据库中是以键值对存储&#xff0c;结构不固定&#xff0c;易存储&#xff0c;减少时间和空间的开销。文档型数据库通常是以JSON或XML格式存储数据&#xff0c…