【问题标题】:How to disable caching of static assets like .css and .js in JSF2?如何在 JSF2 中禁用 .css 和 .js 等静态资产的缓存?
【发布时间】:2012-06-06 22:41:10
【问题描述】:

我正在尝试设置一个不缓存静态资产 .css 和 .js 的项目。对于某些人来说,我们似乎遇到了一些内部缓存问题,我希望这能解决问题。

我有一个相位监听器,基本上是这个http://turbomanage.wordpress.com/2006/08/08/disable-browser-caching-in-jsf/的略微修改版本

我的班级:

package com.ods.common.jsf.phaselistener;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletResponse;

public class CacheControlPhaseListener implements PhaseListener
{
public PhaseId getPhaseId()
{
    return PhaseId.RENDER_RESPONSE;
}

public void afterPhase(PhaseEvent event)
{
}

public void beforePhase(PhaseEvent event)
{
    FacesContext facesContext = event.getFacesContext();
    HttpServletResponse response = (HttpServletResponse) facesContext
            .getExternalContext().getResponse();
    response.setHeader("Cache-control", "no-cache"); // HTTP 1.1
    response.setHeader("Cache-control", "no-store"); // HTTP 1.1
    response.setHeader("Cache-control", "must-revalidate"); // HTTP 1.1
    // response.setHeader("Pragma","no-cache"); //HTTP 1.0
    response.setHeader("Allow", "GET"); // Allowing GET Method only
    response.setHeader("Allow", "POST");// Allowing POST Method only
    response.setDateHeader("Expires", -1); // prevent caching at the proxy server

            /*what I've added*/
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Content-type", "x-javascript");
            //below are the content types I'm seeing for the css/js assets via Firebug
    response.setHeader("Content-type", "application/x-javascript");
    response.setHeader("Content-type", "text/css");
}
}

我对 faces-config.xml 的补充:

<lifecycle>
    <phase-listener id="nocache">com.ods.common.jsf.phaselistener.CacheControlPhaseListener</phase-listener>
</lifecycle>

我的 .xhtml 页面在过去获得了过期标头:

Expires Thu, 01 Jan 1970 00:00:00 GMT

所以这似乎有点工作......我假设这个日期来自 Expires -1(将其设置为 unix 纪元)。

如您所见,我已尝试为一些 javascript 和 css 设置适当的内容类型标头,但这些资产的到期日期是未来一周后。

有人有什么想法吗?另外,我是前端开发人员,而不是后端 Java 人。我可以乱用 Java,但我绝对不是 Java 开发人员。这也是我在 JSF 的第一份工作,所以尽可能地低调一点就好:)

【问题讨论】:

    标签: javascript css jsf websphere browser-cache


    【解决方案1】:

    使用setHeader(),您将覆盖任何先前设置的标头。而是使用addHeader(),或者只是将所有以逗号分隔的值作为标头值。这是完整的集合:

    response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
    response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
    response.setDateHeader("Expires", 0); // Proxies.
    

    您的另一个错误是PhaseListener 不是最好的地方。它只在 JSF 页面请求上调用,而不是在由 webbrowser 独立调用的静态资源请求上调用。换句话说,只有 JSF 页面本身禁用了缓存,但所有 &lt;script&gt;&lt;link&gt;&lt;img&gt; 等都会生成不会调用 PhaseListener 的新请求,因为这些不是 JSF 页面。

    宁可使用Filter

    @WebFilter("/*")
    public class NoCacheFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            response.setDateHeader("Expires", 0); // Proxies.
            chain.doFilter(req, res);
        }
    
        // ... (just keep init() and destroy() NO-OP)
    }
    

    如果您以 Servlet 3.0 容器(Tomcat 7、Glassfish 3 等)为目标,则无需注册 web.xml(或 faces-config.xml)。 @WebFilter("/*") 将自动注册它并将其映射到 /* 的 URL 模式上,从而涵盖 所有 请求。

    另见:


    与具体问题无关,完全禁用静态资产缓存并不是最好的主意。它不必要地消耗网络带宽。而是寻找不同的解决方案,例如在查询字符串中包含服务器启动时间戳。

    例如

    <script src="foo.js?#{startup.time}"></script>
    

    faces-config.xml

    <managed-bean>
        <managed-bean-name>startup</managed-bean-name>
        <managed-bean-class>java.util.Date</managed-bean-class>
        <managed-bean-scope>application</managed-bean-scope>
    </managed-bean>
    

    此示例将强制浏览器在服务器重新启动时重新加载资产。

    【讨论】:

    • 如果我只需要 .css 和 .js 文件,是否需要两个单独的过滤器? @WebFilter("/path/to/css") 和@WebFilter("/path/to/javascript")
    • 使用@WebFilter(urlPatterns={"*.js","*.css"})
    • 注意:对于 Servlet 2.5,您当然需要老式的web.xml 注册。具体示例参见stackoverflow.com/tags/servlet-filters/info
    • 在资源上设置标题并自定义它们的处理,实际上是javax.faces.application.Resource 的工作。我建议注册一个覆盖自定义 Resource 处理的 ResourceHandler。另请参阅 custom ResourceHandlerMojarra Implementation
    • @YoYo:并非所有静态资源都经过FacesServlet
    猜你喜欢
    • 2012-05-08
    • 1970-01-01
    • 2023-03-26
    • 2023-03-04
    • 2012-09-02
    • 2015-08-19
    • 1970-01-01
    • 2022-01-26
    • 2022-01-12
    相关资源
    最近更新 更多