1、浏览器的加载与页面性能优化
http://www.baiduux.com/blog/2011/02/15/browser-loading/
2、iframe异步加载技术及性能
3、西红柿爱番茄 Blog
HTTP Caching 用好了,可以极大的减小服务器负载和减少网络带宽。十分有必要深入了解下 http 的 caching 协议。
先来看下请求/响应过程:
http 请求/响应
1、用 Last-Modified 头
在第一次请求的响应头返回 Last-Modified 内容,时间格式如:Wed, 22 Jul 2009 07:08:07 GMT。是零时区的 GMT 时间,servlet 中可以用 response.addDateHeader ("Last-Modified", date.getTime ()); 加入响应头。如图:
last-modified 和 If-Modified-Since
Last-Modified 与 If-Modified-Since 对应的,前者是响应头,后者是请求头。服务器要处理 If-Modified-Since 请求头与 Last-Modified 对比看是否有更新,如果没有更新就返回 304 响应,否则按正常请求处理。如果要在动态内容中使用它们,那就要程序来处理了。
ps:servlet 取 If-Modified-Since 可以用 long last = requst.getDateHeader ("If-Modified-Since");
2、用 Etag 头
很多时间可能不能用时间来确定内容是否有更新。那可以用 Etag 头,etag 是以内容计算一个标识。计算的方式可以自己决定,比如可以用 crc32、md5等。
Etag 和 If-None-Match
Etag 与 If-None-Match 是对应的,前者是响应头,后者是请求头。服务器要判断请求内容计算得到的 etag 是否与请求头 If-None-Match 是否一致,如果一致就表示没有更新,返回 304 就可,否则按正常请求处理。可以参考:用 HttpServletResponseWrapper 实现 Etag 过滤器
3、用 Expires 头,过期时间
当请求的内容有 Expires 头的时候,浏览器会在这个时间内不去下载这个请求的内容(这个行为对 F5 或 Ctrl+F2 无效,用 IE7,Firefox 3.5 试了,有效的比如:在地址输入后回车)。
expires 过期时间
在 servlet 中可以用 response.addDateHeader ("Expires", date.getTime ()); 添加过期内容。
ps:在 httpwatch 中可以看到 Result 为 (Cached) 状态的。
4、用 max-age 的 Cache-Control 头
max-age 的值表示,多少秒后失效,在失效之前,浏览器不会去下载请求的内容(当然,这个行为对 F5 或 Ctrl+F2 无效)。比如:服务器写 max-age 响应:response.addHeader ("Cache-Control", "max-age=10");
ps:如果你还要加一些 Cache-Control 的内容,比如:private,最好不要写两个 addHeader,而是一个 response.addHeader ("Cache-Control", "private, max-age=10"); 否则 ie 可能对 max-age 无效,原因它只读第一个 Cache-Control 头。
小结:
Last-Modified 与 Etag 头(即是方式 1 和2)还是要请求服务器的,只是仅返回 304 头,不返回内容。所以浏览怎么 F5 ,304 都是有效的。但用 Ctrl+F5 是全新请求的(这是浏览器行为,不发送缓存相关的头)。
Expires 头与 max-age 缓存是不需要请求服务器的,直接从本地缓存中取。但 F5 会忽视缓存(所以使用 httpwatch 之类的 http 协议监察工具时,不要 F5 误认为 Expires 和 max-age 是无效的)。
http 协议监察工具:
Firebox:httpfox、live http header
IE:httpwatch、iehttpheader
转载:http://kb.cnblogs.com/page/124879/
-----------------------------------华丽的分割线---------------------------------------
设置静态文件的过期时间
1、如果你有Http服务器,这个问题就很简单了,只需要配置服务器文件就可以搞定。
2、如果你的应用服务在内网中使用,没有HTTP服务器;只是使用了tomcat等,可以通过过滤器 (Filter)来缓存文件。
实现方式如下:
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
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;
/**
* 缓存所有图片、CSS、JS等静态元素Filter
*
* @author WY
*
*/
public class StaticFileCacheFilter implements Filter {
private FilterConfig config = null;
private Map<String, Integer> expiresMap = new HashMap<String, Integer>();
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
this.config = filterConfig;
expiresMap.clear();
Enumeration<?> names = config.getInitParameterNames();
while (names.hasMoreElements()) {
try {
String name = (String) names.nextElement();
String value = config.getInitParameter(name);
Integer expire = Integer.valueOf(value);
expiresMap.put(name, expire);
} catch (Exception ex) {
}
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
String fileType = null;
int isExist = uri.lastIndexOf(".");
if (isExist != -1) {
fileType = uri.substring(isExist + 1);
}
setResponseHeader(res, uri, fileType);
chain.doFilter(request, response);
}
/**
* 设置响应头信息
* @param response
* @param uri
* @param fileType
*/
private void setResponseHeader(HttpServletResponse response, String uri,
String fileType) {
if (fileType!= null && fileType.length() > 0) {
Integer expires = (Integer) expiresMap.get(fileType);
if (expires != null) {
if (expires.intValue() > 0) {
response.setHeader("Cache-Control",
"max-age=" + expires.intValue()); // HTTP 1.1
} else {
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache"); // HTTP 1.0
response.setDateHeader("Expires", 120);
}
}
}
}
protected FilterConfig getFilterConfig() {
return (config);
}
public void destroy() {
// TODO Auto-generated method stub
config = null;
}
}
此过滤器在web.xml中的配置:
<filter>
<filter-name>staticFileCacheFilter</filter-name> <filter-class>bc.pms.utils.StaticFileCacheFilter</filter-class> <init-param> <param-name>gif</param-name> <param-value>604800</param-value> </init-param> <init-param> <param-name>jpg</param-name> <param-value>604800</param-value> </init-param> <init-param> <param-name>js</param-name> <param-value>604800</param-value> </init-param> <init-param> <param-name>css</param-name> <param-value>604800</param-value> </init-param> </filter> <filter-mapping> <filter-name>staticFileCacheFilter</filter-name> <url-pattern>*.gif</url-pattern> </filter-mapping> <filter-mapping> <filter-name>staticFileCacheFilter</filter-name> <url-pattern>*.jpg</url-pattern> </filter-mapping> <filter-mapping> <filter-name>staticFileCacheFilter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <filter-mapping> <filter-name>staticFileCacheFilter</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping>