JS/CSS缓存失效求助:Mojarra JSF-2.2.12与PrimeFaces 6环境
针对你遇到的JS/CSS资源无法缓存、每次请求Date头都更新的问题,结合你的环境,咱们一步步排查和解决:
1. 先确认资源是否由JSF资源Servlet处理
JSF的资源缓存配置只对通过javax.faces.resource/*路径请求的资源生效,你需要检查页面渲染后的HTML里,<h:outputScript>生成的<script>标签src是否长这样:
/javax.faces.resource/js/ProcessSpecific-min.js.xhtml?ln=js&v=xxxxxx
- 如果没有
javax.faces.resource前缀,说明你的资源被容器(比如Tomcat)的默认Servlet直接处理了,JSF的缓存配置根本没起作用。这时候要确保你的资源放在webapp/resources目录下,这是JSF资源的默认存放位置。 - 如果没有
v=xxxxxx版本参数,说明资源版本化没开启,浏览器无法识别资源是否更新,会频繁发起请求。
2. 修正defaultResourceMaxAge的配置细节
你设置的3628800000毫秒对应的是42天,但注释写的是8小时,虽然数值本身合法,但容易混淆。8小时的正确毫秒值是28800000(8×60×60×1000)。更关键的是,要确认响应头里是否返回了正确的缓存控制字段:
- 正常情况下,响应头应该包含
Cache-Control: public, max-age=28800(这里的max-age是秒,对应8小时),以及Expires(当前时间+8小时)、ETag或Last-Modified字段。 - 如果这些字段缺失,说明JSF的资源缓存配置没生效,可能是
PROJECT_STAGE没正确设置为Production(你已经设置了,但可以再检查web.xml里的配置位置,确保没有被其他配置覆盖)。
3. 检查自定义过滤器是否干扰缓存
你提到创建了自定义过滤器,要确认它没有拦截JSF资源路径(/javax.faces.resource/*),也没有在响应头里强制设置Date、Cache-Control: no-cache这类会破坏缓存的字段。可以暂时禁用过滤器测试,如果缓存恢复正常,就调整过滤器的拦截规则或者修改它对响应头的处理逻辑。
4. 配置PrimeFaces的资源版本化
PrimeFaces 6自带资源版本化机制,需要明确开启才能让它的资源和你的自定义资源一起被正确缓存,在web.xml里添加:
<context-param> <param-name>primefaces.RESOURCE_VERSIONING</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>primefaces.RESOURCE_VERSION</param-name> <param-value>auto</param-value> <!-- 自动根据资源内容生成版本哈希 --> </context-param>
开启后,PrimeFaces会给所有资源URL加上版本参数,浏览器会根据版本号判断是否需要重新请求资源,而不是每次都刷新。
5. 验证容器的默认Servlet配置
如果你的容器(比如Tomcat)的默认Servlet设置了cacheMaxAge,可能会覆盖JSF的配置。可以检查容器的conf/web.xml里的default Servlet配置,确保它没有处理JSF资源路径,或者把它的cacheMaxAge设置得和JSF一致。
最终的web.xml配置示例
把上述正确配置整合后,你的web.xml相关部分应该是这样:
<context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Production</param-value> </context-param> <context-param> <param-name>com.sun.faces.defaultResourceMaxAge</param-name> <param-value>28800000</param-value> <!-- 8小时(毫秒) --> </context-param> <context-param> <param-name>primefaces.RESOURCE_VERSIONING</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>primefaces.RESOURCE_VERSION</param-name> <param-value>auto</param-value> </context-param>
按照这些步骤排查后,应该能解决资源每次都重新请求的问题,让浏览器正确读取缓存。
内容的提问来源于stack exchange,提问作者user12409995

