Spring4.1新特性——静态资源处理增强

2023-11-04

Spring 4.1对静态资源处理进行了细化,ResourceHttpRequestHandler细分为两大部分:ResourceResolver和ResourceTransformer。

Java代码   收藏代码
  1. public interface ResourceResolver {  
  2.   Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations,  
  3.             ResourceResolverChain chain);  
  4.   String resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain);  
  5. }    

 

resolveResource用于把当前请求路径解析到一个在locations中存在的Resource,即相对于locations目录,这个要看实际实现,比如PathResourceResolver就是相对目录;

resolveUrlPath用于把资源路径解析为向外暴露的URL路径形式,比如VersionResourceResolver实现就是在资源路径上加上版本号。 

Java代码   收藏代码
  1. public interface ResourceTransformer {  
  2.     Resource transform(HttpServletRequest request, Resource resource, ResourceTransformerChain transformerChain)  
  3.             throws IOException;  
  4. }  

用于把资源从一种形式转换为另一种形式,比如对css文件中的url进行过滤并修改。 

 

ResourceResolver和ResourceTransformer实现和Filter机制类似,就不多阐述了。

 

ResourceHttpRequestHandler核心实现:

Java代码   收藏代码
  1. protected Resource getResource(HttpServletRequest request) throws IOException{  
  2.     String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);  
  3.     if (path == null) {  
  4.         throw new IllegalStateException("Required request attribute '" +  
  5.                 HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");  
  6.     }  
  7.     if (!StringUtils.hasText(path) || isInvalidPath(path)) {  
  8.         if (logger.isTraceEnabled()) {  
  9.             logger.trace("Ignoring invalid resource path [" + path + "]");  
  10.         }  
  11.         return null;  
  12.     }  
  13.     ResourceResolverChain resolveChain = new DefaultResourceResolverChain(getResourceResolvers());  
  14.     Resource resource = resolveChain.resolveResource(request, path, getLocations()); //先进行ResourceResolver  
  15.     if (resource == null || getResourceTransformers().isEmpty()) {  
  16.         return resource;  
  17.     }  
  18.     ResourceTransformerChain transformChain = new DefaultResourceTransformerChain(resolveChain, getResourceTransformers());//然后进行ResourceTransformer  
  19.     resource = transformChain.transform(request, resource);  
  20.     return resource;  
  21. }  

 

交互流程是:

request(/static/js/jquery-版本.js)

        |

       V 

GzipResourceResolver(如果需要Gzip压缩,进行Gzip压缩)

        |

       V 

CacheResolver(缓存中如果找到了,直接返回)

        |

       V 

VersionResourceResolver(去掉版本号,然后查找资源)

        |

       V 

PathResourceResolver(如直接到底层文件系统找)

        |

       V

CachingResourceTransformer(判断是否有已经转换好的缓存)

        |

       V

CssLinkResourceTransformer(CSS链接替换,如加版本号,其会调用ResourceResolver的resolveUrlPath得到新的UrlPath)

        |

       V

response

 

对应的Spring配置文件

Java代码   收藏代码
  1. <mvc:resources mapping="/static/**" location="/WEB-INF/static/">  
  2.     <mvc:resolvers>  
  3.         <bean class="org.springframework.web.servlet.resource.GzipResourceResolver"/>  
  4.         <bean class="org.springframework.web.servlet.resource.CachingResourceResolver">  
  5.             <constructor-arg ref="cache"/>  
  6.         </bean>  
  7.         <bean class="org.springframework.web.servlet.resource.VersionResourceResolver">  
  8.             <property name="strategyMap">  
  9.                 <map>  
  10.                     <entry key="/**">  
  11.                         <bean class="org.springframework.web.servlet.resource.ContentVersionStrategy"/>  
  12.                     </entry>  
  13.                 </map>  
  14.             </property>  
  15.         </bean>  
  16.         <bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>  
  17.     </mvc:resolvers>  
  18.     <mvc:transformers>  
  19.         <bean class="org.springframework.web.servlet.resource.CachingResourceTransformer">  
  20.             <constructor-arg ref="cache"/>  
  21.         </bean>  
  22.         <bean class="org.springframework.web.servlet.resource.CssLinkResourceTransformer"/>  
  23.     </mvc:transformers>  
  24. </mvc:resources>  

其中版本机制是使用ContentBasedVersionStrategy,其通过MD5内容生成版本。

 

如果配置文件是如下形式,其默认会自动注册一个PathResourceResolver。

Java代码   收藏代码
  1. <mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>  

 

如果想在页面中也完成同样的事情,可以首先注册一个拦截器:

Java代码   收藏代码
  1. <mvc:interceptors>  
  2.     <mvc:interceptor>  
  3.         <mvc:mapping path="/**"/>  
  4.         <bean class="org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor">  
  5.             <constructor-arg>  
  6.                     <bean class="org.springframework.web.servlet.resource.ResourceUrlProvider"/>  
  7.             </constructor-arg>  
  8.         </bean>  
  9.     </mvc:interceptor>  
  10. </mvc:interceptors>  

然后在页面中使用如下代码完成相应的功能:

Java代码   收藏代码
  1. <%=((ResourceUrlProvider)request.getAttribute("org.springframework.web.servlet.resource.ResourceUrlProvider"))  
  2.         .getForLookupPath("/static/css/style.css")%>  

 

另外ResourceUrlProvider目前实现是有问题的,没有考虑使用mvc:resources标签注册ResourceHttpRequestHandler的情况;我们需要修改下其源码:

Java代码   收藏代码
  1. Object handler = hm.getUrlMap().get(pattern);  
  2. if(handler instanceof String) {//如果是字符串,那么接着去获取Bean才对  
  3.     handler = hm.getApplicationContext().getBean((String)handler);  
  4. }  
  5. if (handler instanceof ResourceHttpRequestHandler) {  

 

上边的使用还是很麻烦,大家可以自己实现一个jstl function来简化使用。

 

也可以使用ResourceUrlEncodingFilter过滤器,其会对Response进行包装,当调用encodeURL时会对url进行resolver。 

 

 

当我们访问localhost:8080/test时会看到响应内容带着版本号:hello /static/css/style-23f8024fc04a067828dded9083ceab4f.css,而style.css中会变成:

@import url('other-a18c41dc0df32e9856c5c08914284553.css');

 

@import url('../css2/css2-ad02c833411bcdc09669b1464001c5e4.css');

 

当other-a18c41dc0df32e9856c5c08914284553.css请求到服务端后,会使用VersionStrategy去提取版本并进行版本的匹配,如果版本变了,而客户端没有感知到,那么将报404,这个是无法忍受的,即版本化不是持久化的。

转自 http://jinnianshilongnian.iteye.com/blog/2108894

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring4.1新特性——静态资源处理增强 的相关文章

随机推荐

  • 深度学习------卷积(conv2D)底层

    卷积是深度学习的核心基础 充分理解卷积计算原理 二维卷积计算底层编程 代码按下列要求完成 lt 1 gt 定义图像image和核函数kernel矩阵 lt 2 gt 打印输出图像image和核函数的维度 lt 3 gt 定义函数comput
  • [转]npm查看一个包的版本信息

    我们npm install安装一个包之后 怎么查看这个包的版本信息呢 过一段时间之后 如何查看这个包最新的版本信息呢 下面将做一个全面的总结 1 查看项目中安装的所有的包 npm list 结果如下 vue2 0 test 0 1 0 C
  • 数字带通传输系统matlab仿真实验,基于MATLAB的数字带通传输系统设计

    基于MATLAB的数字带通传输系统设计 基于MATLAB的数字带通传输系统设计 通信原理课程实验 做了一晚上头脑异常清晰 写下来和大家分享下 程序有点问题 但可以基本实现要求 话不多说 上干货 软件环境是MATLAB2019B 大家如果找到
  • 机器学习(四):基于KNN算法对鸢尾花类别进行分类预测

    文章目录 专栏导读 1 KNN算法原理 2 实战案例 对鸢尾花类别分类预测 2 1确定特征和类别 2 2对特征进行处理 2 3对模型调参 选择最优参数 2 4使用分类模型进行预测 2 5评估模型 检验模型效果 3 完整代码及结果 专栏导读
  • idea导入maven项目问题

    问题产生原因 idea加载maven项目 如果网络不通畅 会在maven仓库中产生一个文件 如下图所示 当网络通畅时 在下载就会因为此文件导致无法下载正确的maven依赖 解决方案 打开maven仓库的根目录 搜索 pom lastUpda
  • 四张图,读懂 BIO、NIO、AIO、多路复用 IO 的区别

    作者 扛麻袋的少年 blog csdn net lzb348110175 article details 98941378 学习之前 我们先来了解一下IO模型 同步阻塞IO Blocking IO 即传统的IO模型 同步非阻塞IO Non
  • 智能工厂的指挥中心:APS排程系统

    从中国制造2025发布开始 我们就算正式进入数字信息化制造时代了 这就代表着很多的企业面临工业化转型 处理传统式的制造形式 版本升级为智能制造形式 APS指的是高级计划与排程均衡供应链与生产过程中各种资源 在不同的供应链与生产瓶颈阶段给出最
  • elasticsearch 脚本排序

    elasticsearch 脚本排序主要用于复杂场景的综合排序 脚本语言有 java painless groovy 目前调研的为painless kibana 脚本创建mapping DELETE ksc metadata PUT ksc
  • nacos支持配置文件热部署(@RefreshScope注解)

    nacos支持配置文件热部署 1 原理 RefreshScope注解实现的原理 是刷新bean 2 定义的变量 在代码中用变量来接 直接在代码块里面使用 示例 1 在配置文件定义一个share config的属性 share config
  • Ajax简单异步上传图片并回显

    前台代码 上传图片按钮 a href 选择图片 a 隐藏的文件选择器
  • C语言内功修炼---指针详讲(初阶)

    前言 都说会用一门语言几个礼拜就可以了 这句话我不敢苟同 至少在我学习C语言指针之后就不这么觉得了 不信 来上才艺 代码1 void 0 代码2 void signal int void int int 这两行代码出自 C陷阱和缺陷 我相信
  • react ant-design Select组件下拉框map不显示问题

    问题描述 在使用Select Option下拉组件时 map遍历后不显示下拉框 错误写法 dataList dataList map item gt
  • 洛谷P1010 [NOIP1998 普及组] 幂次方题解

    数论递归 题目描述 任何一个正整数都可以用2的幂次方表示 例如137 27 23 20 同时约定方次用括号来表示 即ab可表示为 a b 由此可知 137可表示为2 7 2 3 2 0 进一步 7 22 2 20 21用2表示 并且3 2
  • idea快捷键和leetCode快捷键

    idea替换字符串快捷键 Ctrl r idea批量重命名 shift F6 project structure F4打开 构造方法 重写方法快捷键 Alt insert 设置字体 File settings editor font Ctr
  • Python网络爬虫:50行代码爬取CSDN博客文章列表 并将点赞评论等数据存储到Excel表格

    hello 大家好 我是wangzirui32 今天我们来学习如何爬取CSDN博客文章列表 并将数据存储到Excel里 开始学习吧 Tips 本节课有点复杂 请耐心学习 学习目录 前言 1 网页代码分析 2 编写代码 写在最后 前言 最近
  • Yolov5项目在RK3588s设备上的部署(RMYC2023技术分享)

    前言 跟作者比赛有关 可以选择略过 在RMYC以往的赛季当中大多数队伍使用到的视觉技术都依赖于RoboMaster官方给的AI人工智能教育套件 但是随着比赛难度的增加 比赛对各种技术的要求AI教育套件可能已经无法满足 同时因AI教育套件的价
  • Laravel利用redis和定时任务实现活跃用户统计

    最近在Summer的 Laravel教程 Web开发实战进阶 学到很多东西 以前只会看文档 大概了解Laravel的内容而在实际运用中确不知道该怎样做 碰到一个需求不会立马联想到 这个东西可以用 实现 不是有句话 实践是检验真理的唯一标准
  • PCB设计中电容电阻的基本常识

    目录 电容的单位换算 电容上标的含义 电阻的单位换算 电阻上标的含义 常用的贴片封装 封装后面字母的含义 电容的单位换算 电容的常见单位有 f mf uf nf pf 1f 1000mf 1mf 1000uf 电容上标的含义 eg1 104
  • background-position 实现背景定位 ie用属性background-position-x

    实现背景图片的定位 如下图分别取各个银行的图标 HTML代码及CSS样式 添加背景图
  • Spring4.1新特性——静态资源处理增强

    Spring 4 1对静态资源处理进行了细化 ResourceHttpRequestHandler细分为两大部分 ResourceResolver和ResourceTransformer Java代码 public interface Re