Spring4.1新特性——静态资源处理增强
2016-03-10 00:31
489 查看
Spring 4.1对静态资源处理进行了细化,ResourceHttpRequestHandler细分为两大部分:ResourceResolver和ResourceTransformer。
Java代码
public interface ResourceResolver {
Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations,
ResourceResolverChain chain);
String resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain);
}
resolveResource用于把当前请求路径解析到一个在locations中存在的Resource,即相对于locations目录,这个要看实际实现,比如PathResourceResolver就是相对目录;
resolveUrlPath用于把资源路径解析为向外暴露的URL路径形式,比如VersionResourceResolver实现就是在资源路径上加上版本号。
Java代码
public interface ResourceTransformer {
Resource transform(HttpServletRequest request, Resource resource, ResourceTransformerChain transformerChain)
throws IOException;
}
用于把资源从一种形式转换为另一种形式,比如对css文件中的url进行过滤并修改。
ResourceResolver和ResourceTransformer实现和Filter机制类似,就不多阐述了。
ResourceHttpRequestHandler核心实现:
Java代码
protected Resource getResource(HttpServletRequest request) throws IOException{
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
if (path == null) {
throw new IllegalStateException("Required request attribute '" +
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
}
if (!StringUtils.hasText(path) || isInvalidPath(path)) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring invalid resource path [" + path + "]");
}
return null;
}
ResourceResolverChain resolveChain = new DefaultResourceResolverChain(getResourceResolvers());
Resource resource = resolveChain.resolveResource(request, path, getLocations()); //先进行ResourceResolver
if (resource == null || getResourceTransformers().isEmpty()) {
return resource;
}
ResourceTransformerChain transformChain = new DefaultResourceTransformerChain(resolveChain, getResourceTransformers());//然后进行ResourceTransformer
resource = transformChain.transform(request, resource);
return resource;
}
交互流程是:
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代码
<mvc:resources mapping="/static/**" location="/WEB-INF/static/">
<mvc:resolvers>
<bean class="org.springframework.web.servlet.resource.GzipResourceResolver"/>
<bean class="org.springframework.web.servlet.resource.CachingResourceResolver">
<constructor-arg ref="cache"/>
</bean>
<bean class="org.springframework.web.servlet.resource.VersionResourceResolver">
<property name="strategyMap">
<map>
<entry key="/**">
<bean class="org.springframework.web.servlet.resource.ContentVersionStrategy"/>
</entry>
</map>
</property>
</bean>
<bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>
</mvc:resolvers>
<mvc:transformers>
<bean class="org.springframework.web.servlet.resource.CachingResourceTransformer">
<constructor-arg ref="cache"/>
</bean>
<bean class="org.springframework.web.servlet.resource.CssLinkResourceTransformer"/>
</mvc:transformers>
</mvc:resources>
其中版本机制是使用ContentBasedVersionStrategy,其通过MD5内容生成版本。
如果配置文件是如下形式,其默认会自动注册一个PathResourceResolver。
Java代码
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
如果想在页面中也完成同样的事情,可以首先注册一个拦截器:
Java代码
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor">
<constructor-arg>
<bean class="org.springframework.web.servlet.resource.ResourceUrlProvider"/>
</constructor-arg>
</bean>
</mvc:interceptor>
</mvc:interceptors>
然后在页面中使用如下代码完成相应的功能:
Java代码
<%=((ResourceUrlProvider)request.getAttribute("org.springframework.web.servlet.resource.ResourceUrlProvider"))
.getForLookupPath("/static/css/style.css")%>
另外ResourceUrlProvider目前实现是有问题的,没有考虑使用mvc:resources标签注册ResourceHttpRequestHandler的情况;我们需要修改下其源码:
Java代码
Object handler = hm.getUrlMap().get(pattern);
if(handler instanceof String) {//如果是字符串,那么接着去获取Bean才对
handler = hm.getApplicationContext().getBean((String)handler);
}
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,这个是无法忍受的,即版本化不是持久化的。
转自 /article/3734349.html
Java代码
public interface ResourceResolver {
Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations,
ResourceResolverChain chain);
String resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain);
}
resolveResource用于把当前请求路径解析到一个在locations中存在的Resource,即相对于locations目录,这个要看实际实现,比如PathResourceResolver就是相对目录;
resolveUrlPath用于把资源路径解析为向外暴露的URL路径形式,比如VersionResourceResolver实现就是在资源路径上加上版本号。
Java代码
public interface ResourceTransformer {
Resource transform(HttpServletRequest request, Resource resource, ResourceTransformerChain transformerChain)
throws IOException;
}
用于把资源从一种形式转换为另一种形式,比如对css文件中的url进行过滤并修改。
ResourceResolver和ResourceTransformer实现和Filter机制类似,就不多阐述了。
ResourceHttpRequestHandler核心实现:
Java代码
protected Resource getResource(HttpServletRequest request) throws IOException{
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
if (path == null) {
throw new IllegalStateException("Required request attribute '" +
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
}
if (!StringUtils.hasText(path) || isInvalidPath(path)) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring invalid resource path [" + path + "]");
}
return null;
}
ResourceResolverChain resolveChain = new DefaultResourceResolverChain(getResourceResolvers());
Resource resource = resolveChain.resolveResource(request, path, getLocations()); //先进行ResourceResolver
if (resource == null || getResourceTransformers().isEmpty()) {
return resource;
}
ResourceTransformerChain transformChain = new DefaultResourceTransformerChain(resolveChain, getResourceTransformers());//然后进行ResourceTransformer
resource = transformChain.transform(request, resource);
return resource;
}
交互流程是:
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代码
<mvc:resources mapping="/static/**" location="/WEB-INF/static/">
<mvc:resolvers>
<bean class="org.springframework.web.servlet.resource.GzipResourceResolver"/>
<bean class="org.springframework.web.servlet.resource.CachingResourceResolver">
<constructor-arg ref="cache"/>
</bean>
<bean class="org.springframework.web.servlet.resource.VersionResourceResolver">
<property name="strategyMap">
<map>
<entry key="/**">
<bean class="org.springframework.web.servlet.resource.ContentVersionStrategy"/>
</entry>
</map>
</property>
</bean>
<bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>
</mvc:resolvers>
<mvc:transformers>
<bean class="org.springframework.web.servlet.resource.CachingResourceTransformer">
<constructor-arg ref="cache"/>
</bean>
<bean class="org.springframework.web.servlet.resource.CssLinkResourceTransformer"/>
</mvc:transformers>
</mvc:resources>
其中版本机制是使用ContentBasedVersionStrategy,其通过MD5内容生成版本。
如果配置文件是如下形式,其默认会自动注册一个PathResourceResolver。
Java代码
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
如果想在页面中也完成同样的事情,可以首先注册一个拦截器:
Java代码
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor">
<constructor-arg>
<bean class="org.springframework.web.servlet.resource.ResourceUrlProvider"/>
</constructor-arg>
</bean>
</mvc:interceptor>
</mvc:interceptors>
然后在页面中使用如下代码完成相应的功能:
Java代码
<%=((ResourceUrlProvider)request.getAttribute("org.springframework.web.servlet.resource.ResourceUrlProvider"))
.getForLookupPath("/static/css/style.css")%>
另外ResourceUrlProvider目前实现是有问题的,没有考虑使用mvc:resources标签注册ResourceHttpRequestHandler的情况;我们需要修改下其源码:
Java代码
Object handler = hm.getUrlMap().get(pattern);
if(handler instanceof String) {//如果是字符串,那么接着去获取Bean才对
handler = hm.getApplicationContext().getBean((String)handler);
}
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,这个是无法忍受的,即版本化不是持久化的。
转自 /article/3734349.html
相关文章推荐
- Java四种引用详解
- 初识Java多线程
- EditPlus编写java的大括号自动补全
- Java基础之理解Annotation
- Spring IoC学习笔记(1):注解配置Bean
- java线程安全总结
- 学习java
- 基于Spring4.X和Hibernate4.x开发Restful风格WebService
- java 获取路径的
- java enum(枚举)使用详解 + 总结
- Java培训 Unit 1阶段项目总结 一 看书吧小说在线阅读器
- spring mvc
- spring mvc 2
- Hashtable HashMap ConcurrentHashMap 源码分析
- 那些年spring声明式事务@Transaction的坑
- Android Studio导入eclipse项目
- spring @service注解
- javassist报错javassist.util.poxy.Poxy
- Spring数据库失效sa'@'localhost'nied for user '
- spring 定时任务