1. 程式人生 > >java應用清快取方式一

java應用清快取方式一

快取機制在頁面效能優化中是非常重要的,快取可以使頁面儘可能快載入,具有減輕頻寬,降低服務負荷,提高使用者體驗等;我們說了這麼多快取好處,為什麼現在要說清快取機制;因為在一個專案在開發中不穩定,頻繁釋出過程中我們就會發現快取不是那麼好,因為快取的存在經常會使我們釋出的功能不能實現,使用者體驗非常差;所以在開發階段,頻繁上線釋出階段我們清楚快取還是有必要的;

快取清除一版有:每個頁面加http頭部,載入每個頁面加版本號,使用打包的方式載入版本號相當於每次打包釋出的專案頁面都是不同的頁面;

1.給頁面加頭部:

<HEAD> 
<META HTTP-EQUIV="Pragma" CONTENT="no-cache"> 
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> 
<META HTTP-EQUIV="Expires" CONTENT="0"> 
</HEAD>

http頭部資訊:"Expires"和"Cache-Control"為應用程式伺服器提供了一個控制瀏覽器和代理伺服器上快取機制 。http頭資訊Expires告訴代理伺服器快取頁面過期時間。http1.1規範中新定義的頭部資訊Cache-Control可以通知瀏覽器不快取任何頁面,每次瀏覽器重新訪問伺服器獲取頁面;

no-cache:強制快取從伺服器上獲取新頁面

no-store:在任何環境下快取不儲存任何頁面

2.給每個url加引數:

在需要開啟的url後面增加一個隨機數:random():這樣每次請求url後面引數不一樣,相當於請求的是不同多的頁面,用這種方式也是可以達到我們的要求:只要為了達到目標不擇手段嗎;

我們主要是看看怎麼通過java程式碼來控制快取;畢竟上面兩種方式還是有缺陷的,每個頁面載入,這樣在我們後面專案穩定後如果還是使用的話,就會影響程式給使用者帶來的體驗了;

1.使用filter載入http頭:

 public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
		//response物件
		HttpServletResponse res = (HttpServletResponse) response;
		// 設定網頁的到期時間,一旦過期則必須到伺服器上重新呼叫
		res.setDateHeader("Expires", -1);
		// Cache-Control 指定請求和響應應遵循的快取機制 no-cache指示請求或響應訊息是不能快取的
		res.setHeader("Cache-Control", "no-cache");
		// 用於設定禁止瀏覽器從本地快取中呼叫頁面內容,設定後一旦離開頁面就無法從Cache中再調出
		res.setHeader("Pragma", "no-cache");
		// 放行
		chain.doFilter(request, res);
	}

2.是使用filter給url加引數;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

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.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EmsCacheCleanFilter implements Filter {

	private static Logger log = LoggerFactory
			.getLogger(EmsCacheCleanFilter.class);
	private static final String STATIC_TAIL = "__xxxx_t=";

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;

		// 1.獲取request請求的url訪問路徑
		String reqeustURL = req.getRequestURL().toString();
		String queryStr = req.getQueryString();

		// 2.通過給靜態資源新增時間戳,去避免快取問題
		// 當訪問的靜態資源是以*.js,*.css,*.html結尾時才給其加上時間戳
		if (reqeustURL != null) {
			if (checkURL(reqeustURL)) {
				String newURL = null;
				// 日期型別時間戳
				// String date = DateUtil.date2String(new Date(), "yyyyMMdd");
				// 毫秒值風格時間戳
				String date = new Date().getTime() + "";
				// 如果?後面有引數
				if (StringUtils.isNotBlank(queryStr)
						&& queryStr.trim().indexOf(STATIC_TAIL) == -1) {
					newURL = reqeustURL + "?" + queryStr + "&" + STATIC_TAIL
							+ date;
					newURL = newURL.replaceAll("\\n\\r", "");
					resp.setHeader("content-type",
							"text/application;charset=UTF-8");
					resp.sendRedirect(newURL);
				}
				// 如果?後面沒有引數
				if (StringUtils.isBlank(queryStr)) {
					newURL = reqeustURL + "?" + STATIC_TAIL + date;
					newURL = newURL.replaceAll("\\n\\r", "");
					resp.setHeader("content-type",
							"text/application;charset=UTF-8");
					resp.sendRedirect(newURL);
				}
			}
			try {
				// 只要請求url不為空放行
				chain.doFilter(request, response);
			} catch (Exception e) {
				e.printStackTrace();
				log.info("[http請求出現異常,檢查網路是否正常,或者再嘗試一次![exception:]"
						+ e);
			}
		}
	}
	/**
	 * @description:判斷url中是否包含這些字尾名
	 * @param url
	 *            訪問的url路徑
	 * @return
	 */
	public Boolean checkURL(String url) {
		String[] checks = { ".js", ".css", ".jsp",".html" };
		for (int i = 0; i < checks.length; i++) {
			if (url.endsWith(checks[i])) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @description:解決302問題未解決)
	 * @param
	 * @param response
	 */
	public void fixResponse(HttpServletResponse response) {
		response.setCharacterEncoding("UTF-8");
		response.setHeader("content-type", "text/application;charset=UTF-8");
		response.setStatus(200);
		try {
			PrintWriter out = response.getWriter();
			out.write("<html lang='zh-CN'>"
					+ "<head><meta http-equiv='content-type' content='text/html;charset=UTF-8'/></head></html>");
		} catch (IOException e) {
			e.printStackTrace();
			log.info("[瀏覽器或系統出現異常,請重新訪問]-[zengwei]");
		}
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}

	public void destroy() {
	}
}

配置filter生效:web.xml

<filter>
	<filter-name>emsCacheCleanFilter</filter-name>
	<filter-class>com.telegnosis.iframework.filter.EmsCacheCleanFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>emsCacheCleanFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
這些都是在載入的時候處理快取;下一篇我們將通過打包的方式來處理快取,就是每次打包都給頁面載入一個(版本號),這樣就是每次打包的靜態資源都是不一樣的;所以可以起到清楚快取的效果;