web项目一旦部署完毕,项目中的图片、CSS以及JS基本上很少发生变动,那么假如把这些组件缓存在浏览器客户端,而不再从服务器上获取,那么网站的访问者在首次访问网站后,后续的请求将会大量减轻服务器的请求压力。这一举动,带来的性能提升,可以称作完美!那么如何做呢?那就是为组件添加Expires(期限)头!

一、了解Expires头

起初,在读《高性能web建站指南》第三章“添加Expires头”时,感觉很有压力,因为不了解Expires头是做什么用的,所以就没有心思去实践该做法,就搁置了一段时间。然而今天心情很好,耐着性子在网上找一系列的资源,并且重读这篇文章,实践再三,终于搞定,特此分享,希望更多的朋友能够看到,实践到你的项目中,从而提升网站性能。

我提供几篇文章大家读一读:

  1. tomcat7官方doc中给出的Expires_Filter,可结合源码进行分析。
  2. 浏览器缓存详细解析
  3. HTTP1.1 协议
  4. 网站性能优化:cache-control设置详解

有了这几篇文章作为铺垫,我想你基本上就可以了解Expires头啦。

二、效果

对于一个添加了Expires头的css来说,其请求的信息如图,多了max-age,以及Expires,这两者之间的关系我也不再赘述,之前的文章中描述比较清楚。

三、实现方法

①、新建CacheControlFilter.java

package com.honzh.common.filter;import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;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;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class CacheControlFilter implements Filter {private FilterConfig config = null;private static final String CACHE_CONTROL_BY_TYPE = "Cache-Control";private static final String HEADER_EXPIRES = "Expires";private static final Log log = LogFactory.getLog(CacheControlFilter.class);public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException {if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {HttpServletResponse httpResponse = (HttpServletResponse) response;HttpServletRequest httpRequest = (HttpServletRequest) request;boolean cacheControlSet = false;for (Enumeration<String> names = config.getInitParameterNames(); names.hasMoreElements();) {String headerName = (String) names.nextElement();log.debug("参数名称:" + headerName);String value = config.getInitParameter(headerName);log.debug("参数值:" + value);// 说明包含了类型,此时要筛选符合条件的类型String type = headerName.substring(CACHE_CONTROL_BY_TYPE.length()).trim();log.debug("参数规定的类型:" + type);String contentType = httpRequest.getHeader("Accept");log.debug("请求内容类型为:" + contentType);if (contains(contentType, ";")) {// lookup content-type without charset match (e.g.// "text/html")String contentTypeWithoutCharset = substringBefore(contentType, ";").trim();if (contentTypeWithoutCharset.indexOf(type) != -1) {// 类型匹配,再看值是不是max-age,如果是,将max-age设置为当前时间+1个月Calendar calendar = Calendar.getInstance();calendar.setTime(new Date());calendar.add(Calendar.MONTH, 1);Date expirationDate = calendar.getTime();httpResponse.setDateHeader(HEADER_EXPIRES, expirationDate.getTime());String maxAgeDirective = "max-age="+ ((expirationDate.getTime() - System.currentTimeMillis()) / 1000);setControlHeader(httpResponse, "private," + maxAgeDirective);cacheControlSet = true;}}}if (!cacheControlSet) {setControlHeader(httpResponse, "private");}}chain.doFilter(request, response);// resp.setHeader("Expires", "Tue, 03 Jul 2001 06:00:00 GMT");// resp.setDateHeader("Last-Modified", new Date().getTime());// resp.setHeader("Cache-Control",// "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");// resp.setHeader("Cache-Control", "private");// resp.setHeader("Pragma", "no-cache");}private void setControlHeader(HttpServletResponse httpResponse, String cache_control) {String cacheControlHeader = httpResponse.getHeader(CACHE_CONTROL_BY_TYPE);String newCacheControlHeader = (cacheControlHeader == null) ? cache_control : cacheControlHeader + ", "+ cache_control;httpResponse.setHeader(CACHE_CONTROL_BY_TYPE, newCacheControlHeader);}@Overridepublic void destroy() {}@Overridepublic void init(FilterConfig config) throws ServletException {this.config = config;}protected static boolean contains(String str, String searchStr) {if (str == null || searchStr == null) {return false;}return str.indexOf(searchStr) >= 0;}protected static String substringBefore(String str, String separator) {if (str == null || str.isEmpty() || separator == null) {return null;}if (separator.isEmpty()) {return "";}int separatorIndex = str.indexOf(separator);if (separatorIndex == -1) {return str;}return str.substring(0, separatorIndex);}
}
  1. web.xml中我们为Expires设置了三种类型,分别为image、css、js,②中有详细参数,这样在filter中,我们将为这三种类型添加Expires、max-age。
  2. 至于类中提到的private,你可以关注我的另一篇文章gzip压缩tomcat服务器响应包,大幅提升web性能。
  3. 其他方面,代码不复杂,主要的是做法,我将做法提供给大家。

②、web.xml

<filter><filter-name>cacheControlFilter</filter-name><filter-class>com.honzh.common.filter.CacheControlFilter</filter-class><init-param><param-name>Cache-Control image</param-name><param-value>max-age</param-value></init-param><init-param><param-name>Cache-Control text/css</param-name><param-value>max-age</param-value></init-param><init-param><param-name>Cache-Control application/javascript</param-name><param-value>max-age</param-value></init-param></filter><filter-mapping><filter-name>cacheControlFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

以上,两个步骤(为组件添加Expires头)完成后,你的项目就又在性能上有了进一步的提升,感觉怎么样呢?

为组件添加Expires头,最大化利用浏览器缓存相关推荐

  1. 放在请求头目的_YSLOW性能测试前端调优23大规则(三)添加Expires头

    正常如果要访问的组件,都必须建立相对应的HTTP请求从服务器端查找所需要的组件,这样每次访问都得重新从服务器读取信息,为了提高性能我们想出一种方法,如果可以使用浏览器或代理的缓存来减少HTTP请求的数 ...

  2. 前端性能优化-HTTP添加Expires头和Cache-Control

    转载自:https://www.jianshu.com/p/f331d5f0b979 浏览器在第一次加载网页后会进行缓存,在第二次以及以后加载时会快一点.但是之后还需要向服务器进行请求,看这期间网页有 ...

  3. 前端学习(2012)vue之电商管理系统电商系统之手动为upload组件添加请求头

    目录结构 router.js import Vue from 'vue' import Router from 'vue-router' import Login from './components ...

  4. 添加Expires头

    今天看了<<高性能网站建设指南>>里边的规则3----添加Expires头,看完之后很受益,然后就试着动手去加,可是竟然不知道在哪加.在网上查了挺久,发现博客园里边的Micro ...

  5. 利用浏览器缓存抓取网络资源:【炉石传说】所有卡牌png图片地址

    有的时候我们在网络上看到很好的资源,想要抓取,却苦于没有好的手段.今天我就来介绍一下通过chrome浏览器缓存抓取的方法. 大家都知道,浏览器把网页展示给我们看的时候,会先将页面上的所有图片等资源下载 ...

  6. 浏览器缓存机制的研究分享

    源宝导读:互联网Web应用大行其道的今天,浏览器已经成为Web应用运行的重要平台.而Web应用对浏览器缓存机制的高效利用,可以大幅提升应用性能和用户体验.本文将对浏览器缓存机制进行系统化的梳理,分享我 ...

  7. 优化-浏览器缓存和压缩优化

    一.减少HTTP请求 1.图片地图: 假设导航栏上有五幅图片,点击每张图片都会进入一个链接,这样五张导航的图片在加载时会产生5个HTTP请求.然而,使用一个图片地图可以提高效率,这样就只需要一个HTT ...

  8. 浏览器缓存库设计总结(localStorage/indexedDB)

    前言 浏览器缓存设计一直是web性能优化中非常重要的一个环节,也是SPA应用盛行的今天不得不考虑的问题.作为一名优秀的前端工程师,为了让我们的应用更流畅,用户体验更好,我们有必要做好浏览器缓存策略. ...

  9. 浏览器缓存的简单介绍和实践

    前言 相对于以前的 html 开发阶段,现在的前端项目一般都会经过打包,然后再部署到服务器上,最后用户再访问.打包部署过程可玩性有很大提高,引入了前端工程管理的很多内容,比如多环境支持.动态配置.打包 ...

最新文章

  1. UIActivityViewController使用
  2. page 怎么把list 分页_自定义分页器的实现
  3. AAAI 2022 | 可解释和鲁棒的联合文本分类及证据提取
  4. JMM层面的内存屏障-HappenBefore
  5. Linux命令gitview,使用linux的gitview命令查看文件内容
  6. C++: find()函数的注意事项
  7. pyinstaller相关错误
  8. 关于React Native init 项目时候速度太慢的解决方法
  9. GetLastError错误码大全
  10. 2021-07-18
  11. cd linux 镜像,解开 CDLinux 的iso映像文件
  12. 坚定信念,雨后终会见彩虹
  13. 将r中的数据导出为excel文件
  14. 如何从iPhone的音乐应用程序中删除Apple Music
  15. Android逆向之旅---静态方式破解微信获取聊天记录和通讯录信息
  16. 激光雷达和相机的坐标转换以及联合标定
  17. Elaticsearch force merge操作
  18. Stata-Mata系列(一):Mata入门
  19. 多个输入框实现串联筛选
  20. iOS开发二维码生成(一)

热门文章

  1. <%=BASE_URL%>根目录
  2. hdu 1408 盐水的故事
  3. 淘口令效果及粘贴板攻击防护实现
  4. 14 模板的使用大全
  5. 股票交易就是在走台阶
  6. 记录NUC 12蝰蛇峡谷Ubuntu装机+外置egpu
  7. 计算机窗口老失去焦点,win7系统电脑使用优化软件后当前窗口失去焦点
  8. 利用AI+大数据的方式分析恶意样本(十八)
  9. 【腾讯云 Finops Crane 集训营】学习云原生成本优化
  10. Redis不是号称单线程效率也很高吗,为什么又采用多线程了?