Tomcat内嵌JSP中图片Cache-Control异常问题求助
问题分析与解决方案
环境信息
Environment : java : oracle 8 Spring4 xml config eclipse version: 2020-06(4.16.0) was-server: tomcat 8.5 servlet: web-app_3_1.xsd version=3.1 jsp: 2.1
问题现象
- 首页
landing.jsp中的图片aaa响应头Cache-Control为max-age=0,符合预期 - 内嵌JSP
/WEB-INF/jsp/usr/common/curation.jsp中的图片响应头始终是no-cache, no-store, must-revalidate,导致每次都从Tomcat重新下载 - 未主动设置过缓存头,Tomcat自动应用该策略
- 自定义Filter尝试覆盖缓存头,但未生效
为什么Filter没生效
你当前的Filter是在chain.doFilter(request, response)之后设置Cache-Control头,此时响应可能已经被提交(committed)——比如内嵌JSP或处理图片的Servlet已经输出了内容并刷新了响应,这时候再修改响应头会被Tomcat忽略,无法生效。
解决方案
方案1:调整Filter逻辑,强制覆盖响应头
修改Filter,使用HttpServletResponseWrapper拦截所有响应头设置操作,确保Cache-Control最终被设置为max-age=0:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ HttpServletResponse resp = (HttpServletResponse) response; HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(resp) { @Override public void setHeader(String name, String value) { if ("Cache-Control".equalsIgnoreCase(name)) { super.setHeader(name, "max-age=0"); } else { super.setHeader(name, value); } } @Override public void addHeader(String name, String value) { if ("Cache-Control".equalsIgnoreCase(name)) { super.setHeader(name, "max-age=0"); } else { super.addHeader(name, value); } } }; chain.doFilter(request, wrapper); }
方案2:修改Tomcat静态资源缓存配置
如果这些图片是静态资源(如放在webapp/images目录下),Tomcat的DefaultServlet默认会对静态资源设置缓存策略。可以在项目的web.xml中覆盖全局配置:
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>cacheControl</param-name> <param-value>max-age=0</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
方案3:检查动态资源的缓存头设置
如果内嵌JSP中的图片是通过动态Servlet/JSP/控制器生成的(比如通过Spring MVC输出图片流),需要找到对应的处理代码,检查是否主动设置了no-cache头。例如:
// 找到类似代码并修改 response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 替换为 response.setHeader("Cache-Control", "max-age=0");
方案4:调整Filter的映射顺序
如果项目中有其他Filter(如编码Filter、安全Filter),可能先于你的testFilter执行并修改了响应头。需要确保你的Filter在web.xml中最先被映射:
<!-- 确保testFilter是第一个filter-mapping --> <filter-mapping> <filter-name>testFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 其他Filter映射放在后面 --> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
验证方法
修改后重启Tomcat,打开Chrome开发者工具的网络面板,刷新页面,查看对应图片的响应头,确认Cache-Control是否变为max-age=0。
内容的提问来源于stack exchange,提问作者jijonbo
相关产品推荐
相关产品推荐

