
Spring Framework 4.1 – 处理静态web资源
Spring Framework 4.1 的release已经有一阵子了,今天终于有点时间,看了下新特性中对于静态资源的灵活处理和转换,同时基于这种处理也提供了一种体验更好的开发方式,让我觉得非常兴奋。 先来看下对于这个新特性中的核心功能, ResourceResolvers 和 ResourceTransformers 。
- ResourceResolvers用来将内部的URL解析为用户能够访问的外部公共的URL(ResourceResolver接口定义的是双向的解析)。
- ResourceTransformers用来修改资源的内容。
这两个功能相结合,不禁让我想起了Rails的Sprockets。Sprockets主要进行三项工作,资源文件的合并,压缩,以及对高级语言的预编译(coffeescript,sass)。那么Spring的这个特性是另外一个pipeline吗? 官方博客给出的解释是这样的,
在Spring Framework 4.1中,我们使用依赖于优化的路径,这种优化在构件时使用最好的外部工具,在运行时使用Resolvers 和和Transformers 。
比如说,我们可以用yeoman,grunt,bower搭建一个面向前端开发者的项目,在开发阶段,利用ResourceResolvers直接引用工程源代码的资源路径。在生产环境,再引用经过其他工具优化过的构建完成的资源。正式通过这种方式带给了我们一种全新的开发体验。 Spring为这两个类提供了一些默认的实现类。
| 类名 | 目标 |
|---|---|
| CssLinkResourceTransformer | 修改CSS文件中得链接来匹配应该暴露给客户端的公共URL |
| CachingResourceTransformer | 缓存transformations的结果或者代理给下一个Transformer |
| AppCacheManifestTransfomer | 帮助处理HTML5离线应用的AppCache清单内的文件 |
帮助处理HTML5离线应用的AppCache清单内的文件
最后来看点例子。 首先是目录结构, Spring Resource Handling showcase application:
bash
spring-app/|- build.gradle|- client/| |- src/| | |- css/| | |- js/| | |- main.js| |- test/| |- build.gradle| |- gulpfile.js|- server/| |- src/main/java/| |– build.gradle
这样的项目结构有两个好处,
- 更好的开发体验,因为在开发阶段引用的是源代码。
- 生产环境中优化的性能,静态资源通过构建得以优化并且打包为webJar。
配置实例
- 注册Resolver和Transformer
bash
AppCacheManifestTransformer appCacheTransformer = new AppCacheManifestTransformer();VersionResourceResolver versionResolver = new VersionResourceResolver().addFixedVersionStrategy(version, "/**/*.js").addContentVersionStrategy("/**");registry.addResourceHandler("/**").addResourceLocations(location).setCachePeriod(cachePeriod).resourceChain(useResourceCache).addResolver(versionResolver).addTransformer(appCacheTransformer);
- 手动解析
bash
ResourceUrlProvider.getForLookupPath()
- 注册
ResourceUrlEncodingFilter,调用Response的encodeURL进行解析
bash
@Beanpublic ResourceUrlEncodingFilter resourceUrlEncodingFilter() {ResourceUrlEncodingFilter filter = new ResourceUrlEncodingFilter();return filter;}
ResourceUrlEncodingFilter是一个包装HttpServletResponse的过滤器,它覆盖了{HttpServletResponse#encodeURL(String) encodeUR} 方法,将内部URL转换为外部的公共URL。其内部也是使用了ResourceUrlProvider来进行转换的。
ResourceUrlProvider是获取外部URL路径的转换的核心组件,其内部定了Map<String, ResourceHttpRequestHandler> handlerMap用来进行链式的解析。
ResourceHttpRequestHandler是<mvc:resource /> 标签的具体实现,4.1版本ResourceHttpRequestHandler内部使用ResourceResolver以及ResourceTransformer来进行解析处理。
