Spring Boot War包部署后无法读取resources/static下文件求助
我之前也碰到过一模一样的坑,本地用内嵌Tomcat跑完全正常,一部署到公司服务器就报文件找不到,核心原因其实是War包部署后,资源文件是打包在War内部的,并非服务器文件系统上的独立实体文件,你用File类去访问肯定会失败——因为File只能识别真实的文件系统路径,没办法直接读取War包里面的资源。
先把路径问题纠正过来
你一直用的src\main\resources\static\sql_collection\configure_SQL_Descriptions.txt是开发阶段的项目路径,打包后这个路径根本不存在!正确的类路径应该从classpath根目录开始写,也就是static/sql_collection/configure_SQL_Descriptions.txt——因为src/main/resources下的所有文件,最终都会被打包到War包的WEB-INF/classes目录下,而这个目录就是classpath的根目录。
正确的读取方式:用InputStream代替File
下面给你两种靠谱的实现方案,都是通过流来读取War包内的资源:
方式1:用Spring的ResourceLoader(推荐,适合Spring管理的Bean)
如果你的类是Spring的Bean(比如Controller、Service),可以直接注入ResourceLoader来获取资源流:
@Autowired private ResourceLoader resourceLoader; public void readSQLDescriptionFile() throws IOException { // 注意路径用正斜杠,别用反斜杠 Resource resource = resourceLoader.getResource("classpath:static/sql_collection/configure_SQL_Descriptions.txt"); // 用try-with-resources自动关闭流,避免资源泄漏 try (InputStream inputStream = resource.getInputStream()) { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String lineContent; while ((lineContent = reader.readLine()) != null) { // 这里处理每一行内容,比如打印、解析等 System.out.println(lineContent); } } }
方式2:用ClassLoader直接获取流(适合非Spring管理的类)
如果你的类不是Spring Bean,可以用当前类的ClassLoader来获取流:
public void readSQLDescriptionFile() throws IOException { String resourcePath = "static/sql_collection/configure_SQL_Descriptions.txt"; InputStream inputStream = getClass().getClassLoader().getResourceAsStream(resourcePath); if (inputStream == null) { throw new FileNotFoundException("未找到资源文件,请检查路径是否正确"); } try (inputStream) { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String lineContent; while ((lineContent = reader.readLine()) != null) { // 处理内容 } } }
为什么你之前的方法会失败?
你用classLoader.getResource("fileName").getFile()得到的路径是类似file:/opt/tomcat/webapps/your-app.war!/WEB-INF/classes!/static/...的字符串,这是War包内部的虚拟路径,File类根本识别不了,自然会抛出NoSuchFileException。而本地用内嵌Tomcat运行时,Spring Boot会把资源解压到临时目录,所以File能访问到,但部署到外部Tomcat时,War包可能不会被完全解压(或者解压路径你无法直接访问),这种方式就失效了。
额外检查点
- 确保文件被正确打包:可以手动解压你的War包,查看
WEB-INF/classes/static/sql_collection/下是否存在configure_SQL_Descriptions.txt。如果没有,检查你的Maven/Gradle配置,确保src/main/resources下的文件都被复制到打包后的classes目录中。 - 路径分隔符用正斜杠:Java类路径的分隔符是
/,别用Windows的反斜杠\,避免跨平台问题。
内容的提问来源于stack exchange,提问作者user3668556

