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

简介: <p>Spring 4.1对静态资源处理进行了细化,ResourceHttpRequestHandler细分为两大部分:ResourceResolver和ResourceTransformer。</p> <div id="" class="dp-highlighter"> <div class="bar"> <div class="tools">Java代码  <a target="

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

目录
相关文章
|
8月前
|
Java 数据库 Spring
Spring事务的传播机制(行为、特性)
Spring事务的传播机制(行为、特性)
142 0
|
3月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
63 4
|
3月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
57 0
|
5月前
|
安全 前端开发 Java
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择。依赖注入使对象管理交由Spring容器处理,实现低耦合高内聚;AOP则分离横切关注点如事务管理,增强代码模块化。Spring还提供MVC、Data、Security等模块满足多样需求,并通过Spring Boot简化配置与部署,加速微服务架构构建。掌握这些核心概念与工具,开发者能更从容应对挑战,打造卓越应用。
49 1
|
2月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
35 0
|
8月前
|
设计模式 前端开发 Java
玩转Spring—Spring5新特性之Reactive响应式编程实战
玩转Spring—Spring5新特性之Reactive响应式编程实战
276 0
|
8月前
|
XML 监控 安全
Spring特性之一——AOP面向切面编程
Spring特性之一——AOP面向切面编程
83 1
|
4月前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
287 6
|
8月前
|
安全 Java 程序员
Spring框架的核心特性是什么?
【4月更文挑战第30天】Spring 的特性
436 0
|
5月前
|
存储 Java 开发者
使用Spring Boot 3.3全新特性CDS,启动速度狂飙100%!
【8月更文挑战第30天】在快速迭代的软件开发周期中,应用的启动速度是开发者不可忽视的一个重要指标。它不仅影响着开发效率,还直接关系到用户体验。随着Spring Boot 3.3的发布,其中引入的Class Data Sharing(CDS)技术为应用的启动速度带来了革命性的提升。本文将围绕这一全新特性,深入探讨其原理、使用方法以及带来的实际效益,为开发者们带来一场技术盛宴。
307 2