一、Springboot中默认静态资源存放的位置
springboot项目结构
|———main |———java———代码 |———src | | | | | | | |———resources———静态资源配置 project | |———test |———pom.xml
打包成jar包后得结构如下
|———META-INF | |——lib project | | |———BOOT-INF| |——classes——(项目结构java下面的class文件和resources下面的文件)
SpringBoot默认资源文件的存放位置如下四个
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
classpath顾名思义,就是class的路径,打包前指的就是resources,打包后指的就是classes,
当我们想访问静态资源的时候会从上往下一个地址接一个地址的去找,找到即可返回
如:访问:localhost:8080/123.jpg时,访问顺序
src/main/resources/META-INF下/resoures/123.jpg
src/main/resources/resoures/123.jpg
src/main/resources/static/123.jpg
src/main/resources/public/123.jpg
直接通过浏览器访问上述路径下的文件时候有的是下载方式有的是直接预览,比如图片、txt、pdf、视频都是直接预览,而zip 、apk、docx、xlsx、ppt都是下载
二、手动配置资源存放的位置
1、把文件放在SpringBoot项目下的classpath中
方式1:配置类方式
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * 主动设置URL匹配路径 */ @Configuration public class MyURLPatternConfiguration extends WebMvcConfigurationSupport { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/fileData/**").addResourceLocations("classpath:/myFile/"); super.addResourceHandlers(registry); } }
此时:访问IP地址:端口号/fileData/时,就相当于到了src/main/resources/myFile文件夹中了,图示说明
注:此时默认的四个文件夹都失效了,如果想让默认的四个文件夹依然有效,那么可以在配置类中多次通 过.addResourceHandler添加指定那四个文件夹
方式2:配置文件方式
# 设置当URI为/fileData/**时,才进过静态资源 # 注:如果设置为/**,那么表示任何访问都会经过静态资源路径 spring.mvc.static-path-pattern=/fileData/** # 自定义路径 # 注:自定义路径时,默认的四个文件夹下中的“META-INF下的resoures文件夹”仍然有效,其他三个文件夹失效 # (此时:访问ip:端口号/fileData/时,相当于访问到了 “自定义的文件夹”和 “META-INF下的resoures文件夹”); # 注:搜索文件时,自定义的文件夹的优先级要高于默认的四个文件夹 spring.resources.static-locations=classpath:/myFile/ # 提示:如果我们显式地把自定义文件夹 和 默认的四个文件夹都写出来,那么都会有效(此时,优先级 从左至右 依次降低) #spring.resources.static-locations = classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/myFile/
2、把文件放在项目jar包之外的服务器磁盘中的某个文件夹中
方式1:通过配置类
/** * 添加一个静态资源路径的映射,不会覆盖默认的资源路径,以当前文件中的配置为例 * 映射完成后在项目中请求http://localhost:8080/image/xx.png就可以读取到所映射的绝对路径中的xx.png了 */ @Configuration public class OaFileConfig implements WebMvcConfigurer { private String windir = "E:/oaFile"; private String lindir = "/home/oa/oaFile/"; /** * 实现资源映射访问路径方法 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { /** * 资源映射路径 * addResourceHandler:访问映射路径 * addResourceLocations:资源绝对路径 */ // 获取对应的系统 String os = System.getProperty("os.name"); // 如果是window系统 if (os.toLowerCase().startsWith("win")) { registry.addResourceHandler("/fileData/**").addResourceLocations("file:" + windir); } else { registry.addResourceHandler("/fileData/**").addResourceLocations("file:" + lindir); } } }
此时:我们访问IP地址:端口号/fileData/时,就相当于到了服务器D盘下的myFile文件夹中了。
注:此时默认的四个文件夹都失效了,如果想让默认的四个文件夹依然有效,那么可以在配置类中通过.addResourceHandler多次添加四个文件夹。
方式2:通过配置文件
# 设置当URI为/fileData/**时,才进过静态资源 # 注:如果设置为/**,那么表示任何访问都会经过静态资源路径 spring.mvc.static-path-pattern=/fileData/** # 自定义路径 # 注:自定义路径时,默认的四个文件夹下中的“META-INF下的resoures文件夹”仍然有效,其他三个文件夹失效 # (此时:访问ip:端口号/fileData/时,相当于访问到了 “自定义的文件夹”和 “META-INF下的resoures文件夹”); # 注:搜索文件时,自定义的文件夹的优先级要高于默认的四个文件夹 spring.resources.static-locations=file:D:/myFile/ # 提示:如果我们显式地把自定义文件夹 和 默认的四个文件夹都写出来,那么都会有效(此时,优先级 从左至右 依次降低) #spring.resources.static-locations = classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:D:/myFile/
三、文件读取和下载
1、读取
方式1:使用项目内路径读取,该路径只在开发工具中显示,类似:src/main/resources/resource.properties。只能在开发工具中使用,部署之后无法读取
@Test public void testReadFile2() throws IOException { File file = new File("src/main/resources/resource.properties"); FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String data = null; while((data = br.readLine()) != null) { System.out.println(data); } br.close(); isr.close(); fis.close(); }
方式2:使用org.springframework.util.ResourceUtils,读取。在linux环境中无法读取。(不通用)因为ResourceUtils底层也是通过new File()方式读取的
@Test public void testReadFile3() throws IOException { File file = ResourceUtils.getFile("classpath:resource.properties"); FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String data = null; while((data = br.readLine()) != null) { System.out.println(data); } br.close(); isr.close(); fis.close(); }
方式3:使用org.springframework.core.io.ClassPathResource,各种环境都能读取。(通用,推荐使用)
@Test public void testReadFile() throws IOException { // ClassPathResource classPathResource = new ClassPathResource("resource.properties"); Resource resource = new ClassPathResource("resource.properties"); InputStream is = resource.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String data = null; while((data = br.readLine()) != null) { System.out.println(data); } br.close(); isr.close(); is.close(); }
方式4: 结合spring注解,使用org.springframework.core.io.ResourceLoader;类的注解。(通用)
@Autowired ResourceLoader resourceLoader; @Test public String demo1(HttpServletRequest request) throws IOException { Resource resource = resourceLoader.getResource("classpath:demo.txt"); InputStream is = resource.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String data = null; while((data = br.readLine()) != null) { System.out.println(data); } br.close(); isr.close(); is.close(); return "ok"; } }
方式5:通用
@Test public String demo1(HttpServletRequest request) throws IOException { InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("demo.txt"); InputStreamReader isr = new InputStreamReader(resourceAsStream); BufferedReader br = new BufferedReader(isr); String data = null; while((data = br.readLine()) != null) { System.out.println(data); } br.close(); isr.close(); resourceAsStream.close(); return "ok"; }
方式6:通用
@Test public String demo1(HttpServletRequest request) throws IOException { InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("demo.txt"); InputStreamReader isr = new InputStreamReader(resourceAsStream); BufferedReader br = new BufferedReader(isr); String data = null; while((data = br.readLine()) != null) { System.out.println(data); } br.close(); isr.close(); resourceAsStream.close(); return "ok"; }
2、下载
直接通过浏览器访问上述默认四个路径下的文件或者自定义路径下文件时有的是下载方式有的是直接预览,比如图片、txt、pdf、视频是直接打开预览,而zip 、apk、docx、xlsx、ppt都是下载
如何解决直接预览改为下载文件
@GetMapping("/download") public void download(HttpServletResponse response) { String fileName = "测试.txt"; ClassPathResource resource = new ClassPathResource(fileName); InputStream is = null; try { is = resource.getInputStream(); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) + "\""); OutputStream os = response.getOutputStream(); FileCopyUtils.copy(is, os); } catch (IOException e) { e.printStackTrace(); } }
原生
@GetMapping("/download") public void download(HttpServletResponse response) { String fileName = "测试.txt"; ClassPathResource resource = new ClassPathResource(fileName); InputStream is = null; try { is = resource.getInputStream(); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) + "\""); byte[] buffer = new byte[1024]; OutputStream os = response.getOutputStream(); int len; while ((len = is.read(buffer)) != -1) { os.write(buffer, 0, len); } response.flushBuffer(); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException ignored) { } } } }
四、文件上传和回显
前面已经讲过如果访问资源、文件上传建议将其上传到特定的文件服务器,直接通过文件路径访问,或者jar包外指定的路径。然后通过配置映射访问
https://blog.csdn.net/qq_34491508/article/details/111618431
五、访问WebJar资源
使用Springboot进行web开发时,boot底层实际用的就是springmvc,项目中加入spring-boot-starter-web依赖,就会提供嵌入的tomcat以及mvc依赖,可以查看依赖树
Web前端使用了越来越多的JS或CSS,如jQuery, Backbone.js 和Bootstrap。一般情况下,我们是将这些Web资源拷贝到Java的目录下,通过手工进行管理,这种通方式容易导致文件混乱、版本不一致等问题。
WebJars是将这些通用的Web前端资源打包成Java的Jar包,然后借助Maven工具对其管理,保证这些Web资源版本唯一性,升级也比较容易。关于webjars资源,有一个专门的网站https://www.webjars.org/,我们可以到这个网站上找到自己需要的资源,在自己的工程中添加入maven依赖,即可直接使用这些资源了。
原理过程:查看引入的jar包
SpringBoot将对/webjars/**
的访问重定向到classpath:/META-INF/resources/webjars/**
源码如下
public void addResourceHandlers(ResourceHandlerRegistry registry) { if(!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); } else { Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl(); if(!registry.hasMappingForPattern("/webjars/**")) { this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); } String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if(!registry.hasMappingForPattern(staticPathPattern)) { this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); } } }
所以可使用目录 localhost:8080/webjars/jquery/3.3.1/jquery.js访问静态资源
六、favicon.ico图标
如果在配置的静态资源目录中有favicon.ico文件,SpringBoot会自动将其设置为应用图标。
在Spring Boot的配置文件application.properites中可以添加配置项spring.mvc.favicon.enabled=false关闭默认的favicon,
七.欢迎页面
SpringBoot支持静态和模板欢迎页,它首先在静态资源目录查看index.html文件做为首页,被/**映射
参考地址SpringBoot资源文件的存放位置设置_justry_deng的博客-CSDN博客_springboot 文件路径