15

我如何编写一个过滤器,该过滤器将按照 Google 的建议(https://developers.google.com/speed/docs/best-practices/caching)适当地缓存静态资源。

创建一个将上次修改日期设置为某个静态日期的过滤器是否足够(每次服务器重新启动时都会更改)?

为所有可缓存资源指定 Expires 或 Cache-Control max-age 之一以及 Last-Modified 或 ETag 之一非常重要。同时指定 Expires 和 Cache-Control: max-age 或同时指定 Last-Modified 和 ETag 是多余的。

上面的链接似乎建议您需要指定 Expires 或 Cache-Control。为什么这是必要的?

4

3 回答 3

27

如何编写一个过滤器,以按照 Google 的建议适当缓存静态资源

如果您的意思是 JSF 资源文件/resources夹中的文件完全由 JSF 内置资源处理程序处理(因此所有文件都通过<h:outputStylesheet>, <h:outputScript>,引用<h:graphicImage>#{resource}因此不是通过纯 HTML 方式),那么您不需要为工作。要满足 Google 的建议,您唯一需要做的就是将Expires日期设置得更远一些。它默认为 7 天(604800000 毫秒),而 Google Page Speed 和 Yahoo YSlow 等性能测试工具建议至少 30 天(2592000000 毫秒)。

在 Mojarra 中,您可以使用以下上下文参数设置它web.xml

<context-param>
    <param-name>com.sun.faces.defaultResourceMaxAge</param-name>
    <param-value>2592000000</param-value> <!-- 30 days -->  
</context-param>

在 MyFaces 中使用以下内容:

<context-param>
    <param-name>org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES</param-name>
    <param-value>2592000000</param-value> <!-- 30 days -->  
</context-param>

创建一个将上次修改日期设置为某个静态日期的过滤器是否足够(每次服务器重新启动时都会更改)?

您不需要也不应该设置Last-Modified. JSF 资源处理程序已经自动执行此操作。如果您因为更改了资源而想强制重新加载资源,请使用资源库版本控制。另请参阅JSF 资源库的用途是什么以及应该如何使用它?

请注意,每次服务器重新启动时更改它是没有意义的,因为Expires标头仍会一直告诉浏览器仅在一段时间后重新测试缓存的有效性。在浏览器真正请求资源之前,浏览器永远不会注意到Last-Modified资源的变化。唯一迫使浏览器难以完全重新请求资源的是 URL 的更改,通常通过更改查询字符串参数值来实现。JSF 资源库版本控制正是这样做的。

另请注意,OmniFacesCombinedResourceHandler使用资源的最后修改时间戳作为查询字符串中的“资源版本”,而不是资源库版本。因此,如果您使用它,则不一定需要资源库版本控制机制。


上面的链接似乎建议您需要指定 Expires 或 Cache-Control。为什么这是必要的?

Expires头告诉浏览器何时通过条件 GET 请求重新测试缓存资源的有效性。所以,在那之前浏览器不会这样做,并且会继续使用缓存中的那个。Cache-Control告诉浏览器使用哪种缓存策略。请注意,当它设置为 egno-cache而不是 时publicExpires标题将不起作用。另请注意,没有Cache-Control标头意味着public(正如 JSF 资源所做的那样)。

于 2013-02-25T12:05:35.317 回答
5

这是我编写缓存过滤器的方式。奇迹般有效。

编写缓存过滤器以提高 JSF/Servlet 屏幕静态内容的性能

在您的 web.xml 中添加以下内容

<filter>
    <filter-name>cache</filter-name>
    <filter-class>au.com.webapp.config.CacheFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>cache</filter-name>
    <url-pattern>*.xhtml</url-pattern>
</filter-mapping>

在您的 au.com.webapp.config 包中创建一个类 CacheFilter,如下所示:

package au.com.webapp.config;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CacheFilter implements Filter {
    private static long maxAge = 86400 * 30; // 30 days in seconds

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        String uri = ((HttpServletRequest) request).getRequestURI();
        if (uri.contains(".js") || uri.contains(".css") || uri.contains(".svg") || uri.contains(".gif")
                || uri.contains(".woff") || uri.contains(".png")) {
            httpResponse.setHeader("Cache-Control", "max-age=" + maxAge);
        }
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Cache Filter started: ");

    }

    @Override
    public void destroy() {
    }
}

如何验证我的屏幕是否正在使用缓存

要查看您的内容是否已经使用 gzip 和缓存,请在Google Chrome浏览器中 -> 右键单击​​屏幕 -> 检查 -> 单击网络选项卡 -> 刷新屏幕。单击图像、图标、样式表,看看您是否在响应标题中看到以下内容

Cache-Control:max-age=2592000

此外,当您刷新页面时,如果元素的状态是 304 而不是 200(来自缓存),那么您就完成了。

其他性能改进,例如 gzip

有关可以显着改变您的 web 应用程序或网站性能的其他简单性能改进,请参阅以下链接,例如 gzip 或 JQuery UI 组件。 https://stackoverflow.com/a/35567464/5076414

于 2016-02-23T02:10:23.797 回答
-1

无需编写过滤器,Tomcat 7 已经有 ExpiryFilter,它将 Cache-Control 添加到您的资源中。它可以基于修改或访问时间。请参阅此博客:

http://kahimyang.info/kauswagan/howto_blogs/1574-improving_page_load_with_mod_expires_and_expiresfilter_in_jsf_applications

于 2013-06-24T16:40:42.197 回答