Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
一天,客服反饋,說用戶購買某一產(chǎn)品時(shí),提交訂單失敗,并發(fā)來用戶的接口提示。我一看,這不是昨天晚上升級(jí)之前的頁面嗎?昨天驗(yàn)證過沒有問題呢。為什么用戶看到的是老的頁面?應(yīng)該是緩存的原因。回客服,讓客戶多刷新下頁面,重新購買就可以了。
問題倒是解決了,但是客戶體驗(yàn)非常不好,不能讓老客戶進(jìn)來都重多次刷新頁面吧!有沒有方法可以解jsp、html或者js的緩存問題呢?
前言
解決前端緩存問題,就需要頁面加載的時(shí)候,不去讀取瀏覽器的緩存,而是從Web服務(wù)器上重新獲取頁面。
一、方法講解
服務(wù)端方法
response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", -10);
Pragma頭域用來包含實(shí)現(xiàn)特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1協(xié)議中,它的含義和Cache- Control:no-cache相同。
Cache -Control指定請(qǐng)求和響應(yīng)遵循的緩存機(jī)制,no-cache指示請(qǐng)求或響應(yīng)消息不能緩存。
Expires 響應(yīng)頭包含日期/時(shí)間, 即在此時(shí)候之后,響應(yīng)過期,無效的日期,比如 -10, 代表著過去的日期,即該資源已經(jīng)過期。
客戶端方法
meta 是用來在HTML文檔中模擬HTTP協(xié)議的響應(yīng)頭報(bào)文。meta 標(biāo)簽用于網(wǎng)頁的<head>與</head>中,meta 標(biāo)簽的用處很多。meta 的屬性有兩種:name和http-equiv。name屬性主要用于描述網(wǎng)頁,對(duì)應(yīng)于content(網(wǎng)頁內(nèi)容),以便于搜索引擎機(jī)器人查找、分類(目 前幾乎所有的搜索引擎都使用網(wǎng)上機(jī)器人自動(dòng)查找meta值來給網(wǎng)頁分類)。這其中最重要的是description(站點(diǎn)在搜索引擎上的描述)和 keywords(分類關(guān)鍵詞),所以應(yīng)該給每頁加一個(gè)meta值。比較常用的有以下幾個(gè):
name 屬性
1、<meta name="Generator" contect="">用以說明生成工具(如Microsoft FrontPage 4.0)等;
2、<meta name="KEYWords" contect="">向搜索引擎說明你的網(wǎng)頁的關(guān)鍵詞;
3、<meta name="DEscription" contect="">告訴搜索引擎你的站點(diǎn)的主要內(nèi)容;
4、<meta name="Author" contect="你的姓名">告訴搜索引擎你的站點(diǎn)的制作的作者;
5、<meta name="Robots" contect="all|none|index|noindex|follow|nofollow">
http-equiv屬性
1、<meta http-equiv="Content-Type" contect="text/html";charset=gb_2312-80"> 和 <meta http-equiv="Content-Language" contect="zh-CN">用以說明主頁制作所使用的文字以及語言;又如英文是ISO-8859-1字符集,還有BIG5、utf-8、 shift-Jis、Euc、Koi8-2等字符集;
2、<meta http-equiv="Refresh" contect="n;url=http://yourlink">定時(shí)讓網(wǎng)頁在指定的時(shí)間n內(nèi),跳轉(zhuǎn)到頁面http;//yourlink;
3、<meta http-equiv="Expires" contect="Mon,12 May 2001 00:20:00 GMT">可以用于設(shè)定網(wǎng)頁的到期時(shí)間,一旦過期則必須到服務(wù)器上重新調(diào)用。需要注意的是必須使用GMT時(shí)間格式;
4、<meta http-equiv="Pragma" contect="no-cache">是用于設(shè)定禁止瀏覽器從本地機(jī)的緩存中調(diào)閱頁面內(nèi)容,設(shè)定后一旦離開網(wǎng)頁就無法從Cache中再調(diào)出;
5、<meta http-equiv="set-cookie" contect="Mon,12 May 2001 00:20:00 GMT">cookie設(shè)定,如果網(wǎng)頁過期,存盤的cookie將被刪除。需要注意的也是必須使用GMT時(shí)間格式;
6、<meta http-equiv="Pics-label" contect="">網(wǎng)頁等級(jí)評(píng)定,在IE的internet選項(xiàng)中有一項(xiàng)內(nèi)容設(shè)置,可以防止瀏覽一些受限制的網(wǎng)站,而網(wǎng)站的限制級(jí)別就是通過meta屬性來設(shè)置的;
7、<meta http-equiv="windows-Target" contect="_top">強(qiáng)制頁面在當(dāng)前窗口中以獨(dú)立頁面顯示,可以防止自己的網(wǎng)頁被別人當(dāng)作一個(gè)frame頁調(diào)用;
8、<meta http-equiv="Page-Enter" contect="revealTrans(duration=10,transtion= 50)">和<meta http-equiv="Page-Exit" contect="revealTrans(duration=20,transtion =6)">設(shè)定進(jìn)入和離開頁面時(shí)的特殊效果,這個(gè)功能即FrontPage中的“格式/網(wǎng)頁過渡”,不過所加的頁面不能夠是一個(gè)frame頁面。
二、Jsp、html緩存的解決
前端頁面處理方法
禁止客戶端緩存要在<head>中加入類似如下內(nèi)容:
<meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0">
不設(shè)置超時(shí)時(shí)間
<% response.setHeader("Cache-Control","no-store"); response.setHeader("Pragrma","no-cache"); response.setDateHeader("Expires",0); %>
設(shè)置超時(shí)時(shí)間10分鐘
<% int minutes = 10; Date d = new Date(); String modDate = d.toGMTString(); String expDate = null; expDate = (new Date(d.getTime() + minutes * 60000)).toGMTString(); response.setHeader("Last-Modified", modDate); response.setHeader("Expires", expDate); response.setHeader("Cache-Control", "public"); // HTTP/1.1 response.setHeader("Pragma", "Pragma"); // HTTP/1.0 %>
后端處理方法
public class CacheJiejue extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //指定該頁面不緩存 response.setDateHeader("Expires",-1); //IE游覽器支持的 //保證兼容性 response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragme", "no-cache"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
三、Js、css緩存的解決
Js或者css會(huì)被瀏覽器緩存下來,只有瀏覽器重啟后才會(huì)刪除,甚至重啟都不會(huì)刪除。這樣用戶可能看到的就是緩存的頁面效果。會(huì)照成生產(chǎn)問題。怎么解決呢?
方法一
在js或者css地址后面添加時(shí)間戳或者隨機(jī)數(shù),這樣每次請(qǐng)求都是新的地址,可以騙過瀏覽器的緩存,每次去服務(wù)器獲取最新的代碼。但是每次都去請(qǐng)求服務(wù)器獲取新的代碼,會(huì)占用帶寬。
<link rel="stylesheet" href="/Resource/css/webapp_reset.css?s=<%=System.currentTimeMillis()%>"/> <script type="text/javascript" src="/Resource/js/mobiscroll.custom-2.16.1.min.js?s=<%=Math.random()%>" ></script>
方法二
可以添加版本號(hào),每次修改的話在地址后面生成新的版本號(hào),可以用系統(tǒng)時(shí)間作為當(dāng)前更新的版本號(hào)。
<script type="text/javascript" src="/Resource/js/mobiscroll.custom-2.16.1.min.js?version=20190908" ></script>
搞定!!喜歡的朋友可以關(guān)注下~
最近寫博客真的是太痛苦了,倒不是寫博客本身,而是寫完之后往多個(gè)平臺(tái)發(fā)布的過程,一不注意就是十多分鐘往上的時(shí)間消耗。
為了解決這個(gè)問題,之前立項(xiàng)的“解決自媒體一鍵多平臺(tái)發(fā)布”項(xiàng)目必須得立刻著手完善了,爭(zhēng)取早日讓自己從發(fā)布這件事情上解脫出來專心寫文章。
【hxsfx的JavaScript庫】這個(gè)系列基本上是為“一鍵多平臺(tái)發(fā)布”項(xiàng)目打基礎(chǔ)用的。之所以把各個(gè)功能模塊拆分出來,是為了盡量讓小伙伴能夠復(fù)制即用(在兼容性方面,因?yàn)閭€(gè)人能力的原因,幾乎只會(huì)兼容Chrome瀏覽器)。
AJAX 是異步的 JavaScript 和 XML(Asynchronous JavaScript And XML),開發(fā)hxsfx.ajax庫的主要目的就是希望通過異步加載HTML,從而盡量避免直接在js中寫HTML來刷新頁面內(nèi)容。
hxsfx.ajax這個(gè)庫與jquery的ajax功能基本一致,不過短時(shí)間內(nèi)應(yīng)該是寫不到人家那么完善的。哈哈~
各位小伙伴別問,為什么不用jquery的ajax而要自己再寫一個(gè)呢?
問就是,博主喜歡造輪子。開玩笑了~
其實(shí)原因是為了減少三方庫的依賴,達(dá)到對(duì)項(xiàng)目的全面掌控。
項(xiàng)目地址:https://github.com/hxsfx/hxsfx_web_tools
要自己開發(fā)一個(gè)ajax庫,需要借助Web API接口中的XMLHttpRequest(XHR)對(duì)象。
XMLHttpRequest(XHR)對(duì)象用于與服務(wù)器交互。通過 XMLHttpRequest 可以在不刷新頁面的情況下請(qǐng)求特定 URL,獲取數(shù)據(jù)。這允許網(wǎng)頁在不影響用戶操作的情況下,更新頁面的局部內(nèi)容。
//hxsfx.js
(function () {
window.hxsfx = {};
})();
//ajax.js
(function () {
window.hxsfx.ajax = {
};
})();
//ajax.js
(function () {
window.hxsfx.ajax = {
loadHTML: function (ele, url) {
}
};
})();
//ajax.js
(function () {
window.hxsfx.ajax = {
loadHTML: function (ele, url) {
const httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.onreadystatechange = function () {
//為了讓代碼更健壯,使用try...catch來捕獲返回狀態(tài)判斷和處理HTML代碼的異常
try {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
//在這處理返回的HTML
}
}
else {
console.log("【ajax.get(" + url + ")請(qǐng)求出錯(cuò)】");
}
}
}
catch (ex) {
console.log("【ajax.get(" + url + ")異常】" + ex.message);
}
};
httpRequest.send();
}
};
})();
//ajax.js
//時(shí)間戳用來解決加載頁面緩存的問題
var urlTimeStamp = "timeStamp=" + new Date().getTime();
url += ((url.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
//ajax.js
ele.innerHTML = httpRequest.responseText;
var scriptElements = ele.getElementsByTagName("script");
for (var i = 0; i < scriptElements.length; i++) {
var scriptElement = document.createElement("script");
scriptElement.setAttribute("type", "text/javascript");
var src = scriptElements[i].getAttribute("src");
if (src) {
//因?yàn)榧虞d的src路徑是之前相對(duì)加載HTML頁面的,需要修改為當(dāng)前頁面的引用路徑
src = url.substring(0, url.lastIndexOf('/') + 1) + src;
src += ((src.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
scriptElement.setAttribute("src", src);
}
var scriptContent = scriptElements[i].innerHTML;
if (scriptContent) {
scriptElement.innerHTML = scriptContent;
}
//用生成的script元素去替換html中的script標(biāo)簽,以此來激活script代碼
ele.replaceChild(scriptElement, scriptElements[i]);
}
//ajax.js
(function () {
window.hxsfx.ajax = {
loadHTML: function (ele, url) {
//時(shí)間戳用來解決加載頁面緩存的問題
var urlTimeStamp = "timeStamp=" + new Date().getTime();
url += ((url.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
const httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.onreadystatechange = function () {
//為了讓代碼更健壯,使用try...catch來捕獲返回狀態(tài)判斷和處理HTML代碼的異常
try {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
ele.innerHTML = httpRequest.responseText;
var scriptElements = ele.getElementsByTagName("script");
for (var i = 0; i < scriptElements.length; i++) {
var scriptElement = document.createElement("script");
scriptElement.setAttribute("type", "text/javascript");
var src = scriptElements[i].getAttribute("src");
if (src) {
//因?yàn)榧虞d的src路徑是之前相對(duì)加載HTML頁面的,需要修改為當(dāng)前頁
src = url.substring(0, url.lastIndexOf('/') + 1) + src;
src += ((src.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
scriptElement.setAttribute("src", src);
}
var scriptContent = scriptElements[i].innerHTML;
if (scriptContent) {
scriptElement.innerHTML = scriptContent;
}
//用生成的script元素去替換html中的script標(biāo)簽,以此來激活script代
ele.replaceChild(scriptElement, scriptElements[i]);
}
}
}
else {
console.log("【ajax.get(" + url + ")請(qǐng)求出錯(cuò)】");
}
}
}
catch (ex) {
console.log("【ajax.get(" + url + ")異常】" + ex.message);
}
};
httpRequest.send();
}
};
})();
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>js庫測(cè)試</title>
<script src="Scripts/hxsfx/hxsfx.js"></script>
<script src="Scripts/hxsfx/ajax.js"></script>
<script>
window.onload = function () {
//調(diào)用ajax中的loadHTML方法
window.hxsfx.ajax.loadHTML(document.getElementById("ContentContainer"), "Views/test/testPage.html");
};
</script>
</head>
<body>
<div id="ContentContainer"></div>
</body>
</html>
<style>
div#TestPageContainer {
height: 300px;
width: 300px;
background-color: #F0F0F0;
}
</style>
<script src="../../Scripts/hxsfx/test/test.js"></script>
<script>
function updateBackgroundColor() {
try {
var backgroundColor = '#' + (Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0'));
document.getElementById("TestPageContainer").style.backgroundColor = backgroundColor;
}
catch (ex) {
console.log(ex.message);
}
}
</script>
<div id="TestPageContainer">
<button onclick="updateBackgroundColor()">更改背景色</button>
<button onclick="modifyPFontColor()">更改下面一句話的字體顏色</button>
<p id="P">這兒是一句話。</p>
</div>
以上內(nèi)容只是hxsfx.ajax庫的開始,后續(xù)的內(nèi)容更新小伙伴可以通過訪問Github項(xiàng)目地址進(jìn)行獲取。
迎關(guān)注我的頭條號(hào):Wooola,專注于Java、Golang、微服務(wù)架構(gòu),致力于每天分享原創(chuàng)文章、快樂編碼和開源技術(shù)。
最近發(fā)版前端項(xiàng)目,用戶經(jīng)常反饋新添加功能在線上環(huán)境不好用,常出現(xiàn)新老頁面并存的狀況。經(jīng)前端同事排查法發(fā)現(xiàn),實(shí)際上只需要重新刷新一下頁面就沒事了。但是每次去通知用戶肯定不現(xiàn)實(shí),所以需要對(duì)前端的js和css等文件采取一定的緩存失效的措施,強(qiáng)制瀏覽器重新去服務(wù)器獲取新的js代碼以及css文件。
樓主經(jīng)過實(shí)際的項(xiàng)目情況反饋,總結(jié)以下兩點(diǎn)切實(shí)可行的辦法,分享給大家,希望對(duì)大家有幫助。
時(shí)間版本號(hào)
如果每次發(fā)布,針對(duì)修改過的js或者css文件路徑加上時(shí)間的版本號(hào),一般以年月日拼寫。
<script type="text/javascript" src="lib/common.js?v=20190719"></script> <link rel="stylesheet" type="text/css" href="assets/css/ie/ie8.css?v=20190719" />
如果發(fā)生緊急情況,需要在一天當(dāng)中對(duì)某些css或者js文件多次發(fā)版,可以把時(shí)間精確到時(shí)分秒。
目前樓主主推采用加版本號(hào)的方式,因?yàn)槲募啵荒茏鲈隽啃薷摹:锰幨菦]有做任何修改js或者css文件可以不用加版本號(hào)。
采用隨機(jī)數(shù)
document.write('<script src=\".lib/common.js?r=' + Math.random() + "\"" + '><\/script>');
一般不建議用隨機(jī)數(shù)的方式,因?yàn)槊看嗡⑿马撁妫S機(jī)數(shù)都會(huì)變化,那么瀏覽器認(rèn)為一個(gè)新的url需要重新請(qǐng)求服務(wù)端獲取js或css文件,不會(huì)在使用瀏覽器本地緩存。同時(shí)占用網(wǎng)絡(luò)帶寬,影響服務(wù)器響應(yīng)速度。
可以利用 gulp-rev或者webpack
entry: { main: './src/common.js', slove: './src/ie8.js' }, output: { filename: '[name].[hash].js', path: path.resolve(__dirname, 'dist') }
例如百度搜索首頁,就是利用hash給js和css文件重命名。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。