springboot下静态资源的处理(转)

Easter79
• 阅读 796
在SpringBoot中有默认的静态资源文件相关配置,需要通过如下源码跟踪:
WebMvcAutoConfiguration-->configureResourceChain(method)-->ResourceProperties中配置了默认的静态资源路径:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
其默认的优先级:META/resources > resources > static > public 
下面通过案例实践验证静态资源的应用

章节要点
1、传统静态资源引入;
2、WebJar使用;
3、版本管理;
4、静态资源配置抽取;
5、WAR包常规容易部署;


1、传统静态资源文件的引入:
1.1、在默认的路径下添加jquery.js:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
1.2、修改原jsp目录下的home.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>JSP</title>
<script type="text/javascript" src="https://my.oschina.net/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var myDate = new Date();
$("#dateInput").val(myDate.toLocaleString());
});
function increase(){
var currentPage=$("#currentPage");
currentPage.val(Number(currentPage.val())+1);
alert($("#currentPage").val());
}
</script>
</head>
<body>
<h1>Hello ${name} from JSP!</h1>
<div>
<label id="showLab">进入页面时间</label>
<input type="text" id="dateInput" style="width: 200px"/>
<input type="text" id="currentPage" style="width: 200px" value=1>
<a href="#" onclick="increase()">增一</a>
</div>
</body>
</html>

1.3、此时我们直接访问请求页面:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
点击增一,执行js
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
系统默认配置验证完成,能够正常加载使用。

1.4、下面我们开始验证自定义静态资源文件目录实现,尝试两种不同的方案(1、仍然在classpath目录下,新建非static目录;2、在WEB-INF目录下新建static/js目录),根据之前的实践,我们仅需在实现WebMvcConfigurerAdapter接口的配置类中添加addResourceHandlers方法即可(优先级为先添加的高于后添加的)。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/mystatic/\*\*").addResourceLocations("classpath:/mystatic/");
registry.addResourceHandler("/static/js/\*\*").addResourceLocations("/WEB-INF/static/js/");
}

1.5、添加对应的静态文件目录以及文件:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
如上目前在3个不同的路径下均有对应的js文件。

1.6、在页面中添加js的加载:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
1.7、我们发出请求查看,通过F12查看开发者模式下请求状态:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)

3种不同的配置均能够生效,均能够找到目前文件。
综上:
1、可以发现通过重写addResourceHandlers的方式添加静态资源请求映射不会覆盖系统原有默认映射,能够叠加使用;
2、通过配置对应的请求规则,映射值不同的资源文件目录。但采用默认的资源路径时,请求地址无需加入static,如上/js/jquery/jquery-1.11.3.min.js系统自动至默认的路径(目前为classpath:/static/)下查找,如果/static/js/jquery/jquery-1.11.3.min.js则默认情况下会在classpath:/static/路径下继续查找static目录,显然是没有的(当然本案例中已经将/static/js/\*\*请求重新映射资源路径)。
3、如果需要将系统默认的/\*\*默认资源路径更改,需要添加registry.addResourceHandler("/\*\*").addResourceLocations("/WEB-INF/static/");即可,通常无需此设置。

2、在springboot中静态资源文件的引用,可以通过webjars加载,WebJars将我们常用的js打包成了jar包。WebJars:http://www.webjars.org/
2.1、首先在POM文件中添加相关依赖:
<!-- webjar依赖 -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>1.11.3</version>
</dependency>
2.2、在页面中添加js文件的加载:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
2.3、请求页面查看请求效果:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
能够如愿正常加载访问。
2.4、既然通过POM文件可以直接指定加载的目标js库的版本,那么如果我们修改版本,是不是可以不需要手动修改引入js的版本路径呢:
2.4.1、继续添加相关依赖:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
</dependency>
2.4.2、新建一个控制器,如下:
@Controller
public class WebJarController {
private final WebJarAssetLocator assetLocator = new WebJarAssetLocator();

@ResponseBody
@RequestMapping("/webjarslocator/{webjar}/\*\*")
public ResponseEntity locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) {
try {
String mvcPrefix = "/webjarslocator/" + webjar + "/";
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);
}
}
}
2.4.3、在页面中添加引入:
<script type="text/javascript" src="https://my.oschina.net/webjarslocator/jquery/jquery.js"></script>
2.4.5、请求页面验证:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)

springboot下静态资源的处理(转)
一切都很正常,仅仅在引入地址省去了版本路径。

3、版本管理
在项目中,当我们资源内容发生变化时,由于浏览器缓存,用户本地的静态资源还是旧的资源,为了防止这种情况导致的问题,我们可能会手动在请求url的时候加个版本号或者其他方式。
此时在springboot中,我们可以通过如下两种方式解决此问题。
3.1、资源名-md5 方式:
3.1.1、在application.properties文件中添加:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/\*\*
3.1.2、通过paths的设置,所有的请求将均被处理,转换为相应的版本话地址,那么我们在jsp页面中引入的url需要简单处理,首先添加
package com.shf.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
/\*\*
\* 主要作用于版本话管理静态资源
\* @author song
\*/
@ControllerAdvice
public class ControllerConfig {
@Autowired
ResourceUrlProvider resourceUrlProvider;
@ModelAttribute("urls")
public ResourceUrlProvider urls() {
return this.resourceUrlProvider;
}
}
然后引入js:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
将上述论证的引入js的多种模式均验证,验证结果如下:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
可以发现,仅默认请求的/\*\*查找classpath:static以及webjars两种默认资源映射能够实现MD5版本化,自定义的/static/js/\*\*方式能够正常加载,而采用通过webjarslocator资源定位的则无法获取资源文件。
3.2:采用版本号方式
3.2.1、在application.properties文件中配置:
#spring.resources.chain.strategy.content.enabled=true
#spring.resources.chain.strategy.content.paths=/\*\*
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/\*\*
spring.resources.chain.strategy.fixed.version=v1.0.0
3.2.2、再次请求验证查看验证结果:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
可以发现,效果与md5方式差不多,仅默认请求的/\*\*查找classpath:static以及webjars两种默认资源映射能够实现版本化。
综上:当请求的地址为md5方式时,会尝试url中的文件名中是否包含-,如果包含会去掉后面这部分,然后去映射的目录(如/static/)查找/js/common.js文件,如果能找到就返回。
当请求的地址为版本号方式时,会在url中判断是否存在/v1.0.0 ,如果存在,则先从URL中把 /v1.0.0 去掉,然后再去映射目录查找对应文件,找到就返回。


4、3中描述的版本话管理,其实在项目实际使用中,对于引入的第三方js相对还比较稳定,不会常有变化。版本化管理不一定是硬性需求,同时我们js引入通常抽取为公共的jsp页面,无需每个页面添加,修改也比较容易:
4.1、新建一个head.jsp页面:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
<%@ page contentType="text/html;charset=UTF-8" %>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<script type="text/javascript" src="https://my.oschina.net/mystatic/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://my.oschina.net/static/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://my.oschina.net/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://my.oschina.net/webjars/jquery/1.11.3/jquery.js"></script>
<script type="text/javascript" src="https://my.oschina.net/webjarslocator/jquery/jquery.js"></script>
<script type="text/javascript" src="${urls.getForLookupPath('/js/jquery/jquery-1.11.3.min.js')}"></script>
<script type="text/javascript" src="${urls.getForLookupPath('/static/js/jquery/jquery-1.11.3.min.js')}"></script>
<script type="text/javascript" src="${urls.getForLookupPath('/webjarslocator/jquery/jquery.js')}"></script>

4.2、在home.jsp中include:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
4.3、请求验证,与上述效果一致:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)

5、打成war部署自定义容易验证(jar模式启动无需验证,jar模式下无法读取WEB-INF目录):
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
此时部署非根路径部署,需要调整为如下:
5.1、抽取一个公共jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
5.2、在home.jsp中添加include:
<%@include file="/WEB-INF/jsp/include/taglib.jsp" %>
5.3、在head.jsp中修改原引入:
<%@ page contentType="text/html;charset=UTF-8" %>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<script type="text/javascript" src="${ctx }/mystatic/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="${ctx }/static/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="${ctx }/js/jquery/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="${ctx }/webjars/jquery/1.11.3/jquery.js"></script>
<script type="text/javascript" src="${ctx }/webjarslocator/jquery/jquery.js"></script>
<script type="text/javascript" src="${ctx }${urls.getForLookupPath('/js/jquery/jquery-1.11.3.min.js')}"></script>
<script type="text/javascript" src="${ctx }${urls.getForLookupPath('/static/js/jquery/jquery-1.11.3.min.js')}"></script>
<script type="text/javascript" src="${ctx }${urls.getForLookupPath('/webjarslocator/jquery/jquery.js')}"></script>
<script type="text/javascript" src="${ctx }${urls.getForLookupPath('/webjars/jquery/1.11.3/jquery.js')}"></script>
5.4、此时我们现在开发环境启动验证:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
5.5、部署war包验证:
springboot下静态资源的处理(转)
springboot下静态资源的处理(转)
此时可以发现两种环境下,JS的引入与之前的效果一致,仅webjarslocator无法正常加载。

总结
有这么多方式来管理我们的资源文件,然而在实际应用中虽然也都有可能用到(存在就有存在的道理嘛): 
1. 我们使用第三方的库时,建议使用webjars的方式,通过动态版本号(webjars-locator 的方式)来使用(因为第三方库在项目开发中变动频率很小,即便是变动也是版本号的修改)。 
2. 我们使用自己存放在静态资源映射目录中的资源的时候,建议使用md5 资源文件名的方式来使用(项目开发中一些css、js文件会经常修改)。 
3. 项目素材文件建议放到 classpath:/static (或其他)目录中,打包在项目中,通过CMS维护的一些图片和资源,我们使用配置引用到具体的磁盘绝对路径来使用。 
4. 注意使用md5文件名方式的时候,Spring 是有缓存机制的,也就是说,在服务不重启的情况下,你去变动修改这些资源文件,其文件名的md5值并不会改变,只有重启服务再次访问才会生效。如果需要每次都获取实际文件的md5值,需要重写相关类来实现,我们不建议这样做,因为一直去计算文件md5值是需要性能代价的。


点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
SpringBoot 使用yml配置 mybatis+pagehelper+druid+freemarker实例
<divid"article\_content"class"article\_contenttrackingad"datamod"popu\_307"datadsm"post"style"overflow:hidden;"<divclass"markdown\_views"<h2id"springboot使用ym
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
JAVA中this用法小结
<divid"article\_content"class"article\_contentcsdntrackingstatisticstrackingclick"datamod"popu\_519"datadsm"post"style"overflow:hidden;"<divclass"htmledit\_vi
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k