Spring Boot 入门之路(5)--- Spring Boot 中静态资源的处理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Geffin/article/details/99719377

在 Spring Boot 中,默认已经提供了静态资源处理,我们可以使用 WebMvcConfigurer 进行配置。个人建议大家还是使用 Spring Boot 默认的配置方式比较好,如果有特殊情况,通过配置进行修改即可。

1 静态资源的默认映射

Spring Boot 默认可以直接访问四个目录(目录处于 src/main/resources 资源目录下)下的文件:

  1. classpath:/META-INF/resources
  2. classpath:/resources
  3. classpath:/static
  4. classpath:/public

目录的先后顺序为静态资源的查找顺序。 若出现了多个同名的静态资源,以前面找到的为准。

需要注意:

  • 默认配置的 /** 会映射到 classpath:/META-INF/resources 等四个目录
  • 默认配置的 /webjars/** 会映射到 classpath:/META-INF/resources/webjars/
    在这里插入图片描述
    若我们想访问 img.jpg ,请求地址应该为 http://localhost:8080/img.jpg 。

2 静态资源的自定义映射

上面我们示例的资源是打包在 jar 包之中的,但实际上,有部分资源是在需要动态维护的,不可能放在程序包中。对于这种随意指定目录的资源,应该如何访问?

由于需求,现在我们需要增加从 /test/* 到 classpath:/test/* 的映射
在这里插入图片描述
正常来说,直接输入地址 http://localhost:8080/test/img.jpg ,根本无法访问
在这里插入图片描述

此时,我们需要通过代码来自定义目录映射,只需要实现 WebMvcConfigurer 接口并实现 addResourceHandlers 方法即可。代码如下

@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/test/**").addResourceLocations("classpath:/test/");
    }
	
}

此时直接输入地址 http://localhost:8080/test/img.jpg 便可访问
直接输入地址 http://localhost:8080/test/img.jpg
注意,我们的自定义目录映射是不会影响默认映射的,它们可以同时使用。

覆盖自动映射

若我们将 /* 修改为映射到 /test/* ,则会覆盖系统的配置,我们可以多次使用 addResourceLocations 添加目录,优先级先添加的高于后添加的。

registry.addResourceHandler("/**").addResourceLocations("classpath:/test/").addResourceLocations("classpath:/static/");

访问 test 根目录下的 img.jpg 的 URL为 http://localhost:8080/img.jpg (/** 会覆盖系统默认的配置)

外部目录的使用

若我们需要使用绝对路径的文件夹,写法如下即可:

@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/test/**").addResourceLocations("file:D:/test/");
    }
	
}

注意指定磁盘绝对路径时需要加上 file 。

配置文件配置静态资源的映射

其实我们可以在 application.properties 配置映射,代码如下:

# 默认值为 /**
spring.mvc.static-path-pattern =
# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ 
spring.resources.static-locations = 这里设置要指向的路径,多个使用英文逗号隔开,
  1. spring.mvc.static-path-pattern 可以重新定义 pattern,如修改为 /test/** ,则访问 static 等目录下的 img.jpg 文件应该为 localhost:8080/test/img.jpg ,修改之前为localhost:8080/img.jpg 。注意,spring.mvc.static-path-pattern 只可以定义一个
  2. 使用 spring.resources.static-locations 可以重新定义 pattern 所指向的路径。

3 WebJars

对于 web 开发而言,对静态资源版本管理是比较混乱的,以 Jquery,Bootstrap举例,可能各个前端框架所依赖的各个组件的版本都不尽相同,一不注意就可能引起不同版本的冲突问题。所以,是否有一种像后端管理 jar 包一样的解决方案呢?答案当然是有的,这就是我们要讲到的 WebJars。

WebJars 的工作原理

WebJars 是将 web 前端资源打成 jar 包文件。借助版本管理工具(例如 Maven )进行版本管理,保证这些 web 资源的版本唯一性,避免文件混乱、版本不一致等问题。

实际上 WebJars 就是将资源文件放到 classpath:/META-INF/resources/webjars/ 中,然后打包成 jar 发布到 maven 仓库中。

WebJars 的应用

在 Spring Boot 中默认将 /webjars/** 映射到 classpath:/META-INF/resources/webjars/ ,因此,在 JSP 页面中引入 jquery.js 的方法为:

<script type="text/javascript" src="${pageContext.request.contextPath }/webjars/jquery/2.1.4/jquery.js"></script>

同时需要在 pom.xml 文件中添加 jquery 的 WebJars 依赖

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>2.1.4</version>
</dependency>

版本号统一管理

在实际开发中,也许我们会遇到升级版本号的情况,若有上千的页面,全部页面都按上面引入了 jquery.js ,那么如果有一天需要把版本号升级为 3.0.0,岂不累死?显然不能一个一个页面地去修改。

下面提供一个进行版本号统一管理的方法

在pom.xml 中添加依赖:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
</dependency>

增加一个WebJarsController:

@Controller
public class WebJarsController {

     private final WebJarAssetLocator assetLocator = new WebJarAssetLocator();

    @ResponseBody
    @RequestMapping("/webjarslocator/{webjar}/**")
    public ResponseEntity<Object> locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) {
        try {
            String mvcPrefix = "/webjarslocator/" + webjar + "/"; // This prefix must match the mapping path!
            String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
            String fullPath = assetLocator.getFullPath(webjar, mvcPath.substring(mvcPrefix.length()));
            return new ResponseEntity<>(new ClassPathResource(fullPath), HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }
}

在页面中使用的方式:

<script type="text/javascript" src="${pageContext.request.contextPath }/webjarslocator/jquery/jquery.js"></script>

4 对静态资源的版本管理

当资源内容发生改变时,由于浏览器缓存,用户本地的资源还是旧资源,为了防止这种情况发生。我们可能会选择在资源文件后面加上参数“版本号”或其他方式。

使用版本号参数的例子:

<script type="text/javascript" src="${pageContext.request.contextPath }/js/common.js?v=1.0.1"></script>

当文件修改后,手工修改版本号来达到 URL 文件不被浏览器缓存的目的。同样也存在很多文件都需要修改的问题。

Spring 为解决这个问题提供了 资源名称md5方式 的方法。

首先我们需要修改 application.properties 配置文件

spring.resources.chain.strategy.content.enabled = true
spring.resources.chain.strategy.content.paths = /**

所有 /** 请求的静态资源都会被处理。

然后创建 ResourceUrlProviderController 文件:

//处理静态资源URL
@ControllerAdvice
public class ResourceUrlProviderController {

    @Autowired
    private ResourceUrlProvider resourceUrlProvider;

    @ModelAttribute("urls")
    public ResourceUrlProvider urls() {
        return this.resourceUrlProvider;
    }
}

那在页面中使用的写法:

<script type="text/javascript" src="${pageContext.request.contextPath }${urls.getForLookupPath('/js/common.js') }"></script>

而当访问页面后,HTML 中实际生成的代码为:

<script type="text/javascript" src="/test/js/common-c6b7da8fffc9be141b48c073e39c7340.js"></script>

注意,在使用 md5 文件名方式的时候,Spring 是有缓存机制的,即在服务不重启的情况下,变动修改这些资源文件,其文件名的 md5 值并不会改变,只有重启服务再次访问才会生效。

5 对 Spring Boot 中静态资源处理的总结

  1. 对于第三方库,由于在项目开发中变动频率很小,即便是变动也是版本号的修改。 所以我建议使用 WebJars 的方式,并通过动态版本号( webjars-locator 的方式)来使用。
  2. 对于我们自己存放的静态资源文件(自己写的 js,css 文件等),由于改动频繁,所以我建议使用 md5 资源文件名的方式来使用。
  3. 对于项目素材文件,建议放到 classpath:/static 目录下。

参考:Spring Boot 静态资源处理

猜你喜欢

转载自blog.csdn.net/Geffin/article/details/99719377