一. 基本認識javascript
1. 簡介:HttpContext用於保持單個用戶、單個請求的數據,而且數據只在該請求期間保持;html
也能夠用於保持須要在不一樣的HttpModules和HttpHandlers之間傳遞的值;java
也能夠用於保持某個完整請求的相應信息。ajax
2. 五大核心對象包括:Response、Request、Application、Server、Sessionjson
3. 源碼分析:在MVC框架中HttpContext對象來源於一個HttpContextBase類的一個實例,該類中包括如下幾個重要屬性:(非MVC框架中有一個單獨HttpContext類)瀏覽器
①:HttpRequestBase Request服務器
②:HttpResponseBase Responsecookie
③:HttpApplicationStateBase Applicationsession
④:HttpServerUtilityBase Server多線程
⑤:HttpSessionStateBase Session
即所謂的五大核心對象,因此在MVC框架中一般能夠這麼用: HttpContext.Request、HttpContext.Response、HttpContext.Application、 HttpContext.Server、HttpContext.Session .
但咱們也常常看到省略HttpContext對象,直接:Request、Response、Server、Session 來使用,隨意選中其中一個,點擊F12查看源碼可知,Controller類中也包含如下四個屬性:
①:HttpRequestBase Request
②:HttpResponseBase Response
③:HttpServerUtilityBase Server
④:HttpSessionStateBase Session
二. 逐個分析
1. Request對象
1. Request:接收處理客戶端發送過來的請求 (已完成)
①:HttpMethod屬性:獲取客戶端發送請求的類型
②:RawUrl屬性:獲取當前請求完整的URL
③:UrlReferrer屬性:獲取有關連接到當前 URL 的客戶端請求的 URL
④:Request["XX"]:獲取xx屬性值
2. 代碼測試
1 //1.測試Request對象 2 $("#btn1").click(function () { 3 $.ajax({ 4 type: "Post", 5 url: "TestRequest", 6 data: { 7 "name": "123" 8 }, 9 success: function (data) { 10 if (data.status == "ok") { 11 alert("測試經過"); 12 $("#s1").html(data.HttpMethod); 13 $("#s2").html(data.RawUrl); 14 $("#s3").html(data.UrlReferrer); 15 $("#s4").html(data.name); 16 } 17 if (data == "error") { 18 alert("測試未經過"); 19 } 20 } 21 }); 22 });
1 /// <summary> 2 /// 測試Request對象相關 3 /// </summary> 4 /// <returns></returns> 5 public ActionResult TestRequest() 6 { 7 var HttpMethod = Request.HttpMethod; 8 var RawUrl = Request.RawUrl; 9 var UrlReferrer = Request.UrlReferrer; 10 var name = Request["name"]; 11 var data = new 12 { 13 status="ok", 14 HttpMethod=HttpMethod, 15 RawUrl= RawUrl, 16 UrlReferrer= UrlReferrer, 17 name= name 18 }; 19 return Json(data); 20 }
測試結果:
2. Server對象
1. Server:一個輔助類 (已完成)
①.HtmlEncode方法:將html編碼轉換成對應的字符串
②.HtmlDecode方法:將字符串轉換成Html編碼
③.MapPath方法:獲取該地址對應的物理路徑
④.UrlEncode方法:將url編碼轉換成對應的字符串
⑤.UrlDecode方法:將對應的字符串轉換成Url格式的編碼
2. 代碼測試
1 //2.測試Server對象 2 $("#btn2").click(function () { 3 $.ajax({ 4 type: "Post", 5 url: "TestServer", 6 data: { 7 8 }, 9 success: function (data) { 10 if (data.status == "ok") { 11 alert("測試經過"); 12 $("#s11").html(data.HtmlEncode); 13 $("#s22").html(data.HtmlDecode); 14 $("#s33").html(data.MapPath); 15 $("#s44").html(data.UrlEncode); 16 $("#s55").html(data.UrlDecode); 17 } 18 if (data == "error") { 19 alert("測試未經過"); 20 } 21 } 22 }); 23 });
1 public ActionResult TestServer() 2 { 3 string HtmlEncode = Server.HtmlEncode("<p>積極向上</p>"); 4 string HtmlDecode = Server.HtmlDecode(HtmlEncode); 5 string MapPath = Server.MapPath("/home/index"); //只能作物理文件的映射 6 string UrlEncode = Server.UrlEncode("https://www.2345.com/"); 7 string UrlDecode = Server.UrlDecode(UrlEncode); 8 var data = new 9 { 10 status = "ok", 11 HtmlEncode = HtmlEncode, 12 HtmlDecode = HtmlDecode, 13 MapPath = MapPath, 14 UrlEncode = UrlEncode, 15 UrlDecode = UrlDecode 16 }; 17 return Json(data); 18 }
測試結果:
3. Application對象
1. Application: 用於在ASP.NET 應用程序內的多個會話和請求之間共享信息(案例:單點登陸)
①. Lock方法:鎖定對象的訪問
②. unLock方法:取消鎖定對象的訪問
③. Add和Set方法:向集合中添加一個新對象
④. Application[]和Get方法:獲取對象的值
⑤. Remove、RemoveAt、RemoveAll方法:用來刪除對象
補充一個單一對話: HttpContextBase context.Item[""] ; 是指是一個IDictionary類,有Add、Clear、Contains、Remove等方法(不作測試)
2. 測試:
①. 用不一樣的瀏覽器打開Index頁面,模擬多線程多個會話,發現name2的值是相同的。
4. Response對象
1. Response:用戶服務器端將信息返回給客戶端
①.ContentType屬性:獲取或設置當前響應的 HTTP MIME 類型 (很是重要!),下面補充幾個經常使用的類型(多用於下載)
a. Json格式: "application/json"
b. JavaScript格式:"application/x-javascript"
c. 普通文本格式:"text/plain"
d. Html格式:"text/html"
e. XML格式:"text/xml"
f. Excel格式:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
g. gif圖片格式:"image/gif"
②.Redirect方法:用於站內跳轉或站點間的跳轉
③.Write方法:能夠將字符、字符串、字節等寫入到Http響應輸出流 (MVC中的Content方法就是基於該方法進行擴展的)
④.WriteFile和TransmitFile方法:將指定文件寫入到Http相應輸出流 (MVC中的FileResult就是基於該方法封裝的,簡化了下載流程)
(原生的四種下載方法詳見:https://www.cnblogs.com/weixing/archive/2012/02/27/2369567.html (不作測試了))
2. 測試利用FileResult下載文件
1 /// <summary> 2 /// 測試下載文件 3 /// </summary> 4 /// <param name="type">1表明圖片 2表明Excel文件</param> 5 /// <returns></returns> 6 public ActionResult TestDownFile(string type) 7 { 8 if (type == "1") 9 { 10 //須要下載的文件在服務器上的物理路徑 11 string path = Server.MapPath("/Content/imageHandle/pipe1.jpg"); 12 //須要下載的文件下載後保存到本地後的名字 13 string fileName = DateTime.Now.ToString("yyyyMMddHHmmssffffff") + ".jpg"; 14 return File(path, "image/jpg", fileName); 15 } 16 if (type == "2") 17 { 18 string path = Server.MapPath("/Content/myExcel/text.xlsx"); 19 string fileName = DateTime.Now.ToString("yyyyMMddHHmmssffffff") + ".xlsx"; 20 return File(path, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName); 21 } 22 return Content(""); 23 } 24
1 //4. 測試下載文件 2 //4.1 下載圖片 3 $("#btn5").click(function () { 4 window.location.href = "TestDownFile?type=1"; 5 }); 6 //4.2 下載Excel 7 $("#btn6").click(function () { 8 window.location.href = "TestDownFile?type=2"; 9 });
結果:
5. Session對象
Session:存儲於服務器內存中key-value集合
(1).補充Cookie的概念:Cookie存儲於客戶端,經過瀏覽器的【Response Header】標頭下的Set-Cookie進行存儲,由瀏覽器進行創建、
保存、和到期刪除。Cookie默認的生命週期是瀏覽器的生命週期,瀏覽器關閉,cookie消失,固然也能夠顯式的設置Cookie的到期時間,瀏覽器會根據這個到期
時間,將Cookie存放到客戶端硬盤的。
注意:Cookie在瀏覽器能夠被看到,因此不適合存放敏感信息;Cookie能存儲的數據有限,最大4kb;Cookie是按照瀏覽器進行劃分的。
(2).Http的請求流程:
①:客戶端第一次訪問,沒有Cookie,沒有Session,服務器端會生成一個SessionId和一個空的Value,保存到服務器內存上。
②:客戶端第一次返回,經過瀏覽器的【Response Header】標頭下的Set-Cookie進行輸出。
③:客戶端第二次訪問,會帶上Cookie進行訪問,且Cookie中存放着SessionId,服務器端經過SessionMoudle解析獲得SessionId,獲取內存
中存放的數據,而且知道剛纔你來過。
④:接下來在Session沒有過時和不關閉的瀏覽器的狀況下,每次訪問服務器端,都會帶着同一個SessionId進行訪問。
圖解:
(3).深刻剖析Session
①:同一個瀏覽器在不關閉的狀況下(且服務器端Session沒有過時),不管訪問幾回服務器端,SessionId都是相同的,由於每次請求都會帶着Cookie中存儲的SessionId的。
②:關閉瀏覽器,再次請求服務器,由於【Request Header】表頭中,沒有提交剛纔的SessionId,服務器會認爲這是一個新的請求,服務器會分配給你一個新的
SessionId,這就解釋了原SessionId並無過時爲何服務器會從新分配給你一個SessionId的緣由了。
③:同一個瀏覽器登陸狀態下,長時間沒有任何操做(Session默認過時時間爲20分鐘),再次操做的時候,雖然Cookie中帶着SessionId進行
訪問服務器端,可是原Session已經被服務器端給清除了,只保留SessionId,原存放到Session中的內容均爲null。
④:Session不能跨進程訪問,只能由當前會話的用戶訪問,由於SessionId是以Cookie的形式存放在訪問者的客戶端瀏覽器中。
⑤:在同一個會話中,Session是能夠跨頁面進行全局使用的。
⑥:服務器上的Session保存的是一個SessionId和一個Value,而Value是一個集合,該集合中存放着當前用戶的Key
(4).平常開發Session的侷限性
在咱們開發管理系統中,一般登陸後會把該用戶的權限放到Session中(如:放到Session["user"]中),這時候,在同一個瀏覽器中登陸admin帳戶,
會把a、b、c權限放到Session["user"]中,在不關閉該瀏覽器的狀況下,登陸admin2帳戶,這時候同一個瀏覽器請求的【Request Header】表頭中
的cookie存放的SessionId是相同的,因此服務器端會認爲是同一個會話,admin2帳戶的c,d權限會把原先的Session["user"]中的a、b、c權限覆蓋,
致使admin帳戶操做系統的時候,發現本身沒有 a、b、c權限,而是有c、d權限。
(如何解決這個問題呢?可使用NoSQL來替代Session)
(5).Session的聲明和銷燬
①:從寫入開始,若是該頁面一直沒有操做,默認20分鐘,服務器會把session銷燬,但SessionId仍是存在的。
②:手動經過Abandon的方式取消當前會話
③:刪除客戶端的Cookie,會致使服務器端從新分配給客戶端一個SessionId,其實服務器端的原Session並無消失
(6).總結:
客戶端向服務器發請求,若是請求頭中沒有帶SessionId,服務器會分配一個SessionId給客戶端,並存放在客戶端的Cookie中;
客戶端向服務器發送請求,若是cookie中有值,會帶着該值一塊兒發送到服務器,若是沒有,則不帶。
(7).補充Session的幾個經常使用方法
①:Session[]:用於設置或讀取Session的值
②:Timeout屬性:設置Session過時時間
(補充經過配置文件的形式設置全局session過時:System.Web下添加 <sessionState mode="InProc" timeout="30"/> )
InProc表示進程內;timeout表示多少分鐘後Session失效。
③:SessionID屬性:每一個會話的惟一標識符
④:Remove方法:從會話集合中刪除一項;Clear方法:從會話集合中刪除全部的鍵和值;Abandon方法:取消當前會話
MVC中的TempData就是基於Session實現的,可是TempData只能讀取一次
(8). 測試:
①:測試同一個瀏覽器,不關閉狀況下SessionId相同,且同一個key的數據會被後面覆蓋
②:測試服務器端Session過時後,SessionId還存在,Session中的值均爲Null(銷燬也是這個效果)
③:經過F12 瀏覽器驗證http流程,並查看【Response Header】和【Request Header】中何時又SessionId
④:手動刪除客戶端的Cookie,再次請求服務器,會從新分配新的SessionId
先貼出來幾塊代碼:
a:打開該頁面,顯示SessionId和name的值,以下圖:
b:分析該頁面打開的請求,以下圖:印證Http請求第一次請求和第一次返回的請求流程
c. 點擊按鈕屢次,獲取SessionId和name的值,結果以下圖:SessionId和name的值都是相同的。(但刷新頁面,name值是變得,SessionID依舊不變)
d. 查看該按鈕對應的請求,以下圖:
e: 不關閉該瀏覽器的狀況下,從新在一個新的選項卡中打開Index頁面,SessionId沒有變,name從新賦值了。
f:回到第一次打開的頁面,從新點擊測試按鈕,獲取SessionId和name值,SessionId沒有變,可是name值被第二次打開的頁面的name值覆蓋了。(印證了管理系統中權限覆蓋的問題)
g:點擊銷燬Session,而後從新點擊測試按鈕,查看結果,SessionId依舊存在,可是Session的value集合變成null了(等待服務器session自動過時也是這種效果)
!