Spring Security中实现ResourceUrlEncodingFilter及旧版本静态资源版本化问题
嘿,我明白你的困扰——Spring 4.3+那套便捷的静态资源版本化组件在3.2.x里完全没有,直接照搬高版本的配置肯定失效。下面给你一套适配这个旧版本技术栈的可行方案:
核心思路
Spring 3.x没有ResourceUrlEncodingFilter和ResourceUrlProvider这类自动处理URL版本的工具,所以我们得用原生支持的方式,手动控制版本标识+资源映射,同时配合Spring Security的放行配置。
具体实现步骤
1. 配置静态资源的版本化映射
先在你的Spring MVC配置文件(比如spring-servlet.xml)里,给静态资源加上版本前缀的映射:
<mvc:resources mapping="/v1/**" location="/static/" />
这里的/v1/就是版本标识,后续更新资源时,只要把这个前缀改成/v2/,就能强制浏览器加载新资源(因为URL变了,缓存失效)。
2. 手动生成带版本的资源URL
既然没有自动替换的过滤器,我们可以写个简单的工具类来统一生成带版本的资源路径:
public class ResourceVersionHelper { // 可以把版本号放到配置文件里,方便后续修改 private static final String RESOURCE_VERSION = "v1"; public static String getVersionedUrl(String resourcePath) { return "/" + RESOURCE_VERSION + resourcePath; } }
在JSP页面里,就可以用EL表达式调用这个方法:
<script src="${resourceVersionHelper.getVersionedUrl('/js/main.js')}"></script> <link href="${resourceVersionHelper.getVersionedUrl('/css/style.css')}" rel="stylesheet">
3. 让Spring Security放行静态资源
因为你用了Spring Security,必须确保带版本前缀的静态资源不会被拦截。在Spring Security配置文件里添加:
<security:http pattern="/v1/**" security="none" />
如果是在web.xml里配置Spring Security过滤器,也要注意不要让过滤器拦截这些路径,或者调整过滤器的映射顺序,确保静态资源请求先被处理。
4. 进阶:基于文件哈希的动态版本(可选)
如果不想手动改版本号,可以自己实现一个工具类,在应用启动时计算静态资源的哈希值,用哈希值作为版本标识,这样文件内容变了版本号自动更新:
public class ResourceHashUtil { public static String getFileHash(String filePath) throws IOException { try { MessageDigest md = MessageDigest.getInstance("MD5"); File file = new File(filePath); try (InputStream is = new FileInputStream(file)) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { md.update(buffer, 0, bytesRead); } return DatatypeConverter.printHexBinary(md.digest()).toLowerCase(); } } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Failed to calculate file hash", e); } } }
启动时把哈希值存入全局配置,生成URL时替换版本前缀即可。
关于你提到的web.xml片段
你说的resourceUrlEncod...过滤器是Spring 4.x才引入的,Spring 3.2.x里根本没有这个类,所以配置了也会报错,直接换成上面的方案就好。
内容的提问来源于stack exchange,提问作者Kumar

