第十五节:HttpContext五大核心对象的使用(Request、Response、Application、Server、Session)
一. 基本认识
1. 简介:HttpContext用于保持单个用户、单个请求的数据,并且数据只在该请求期间保持;
也可以用于保持需要在不同的HttpModules和HttpHandlers之间传递的值;
也可以用于保持某个完整请求的相应信息。
2. 五大核心对象包括:Response、Request、Application、Server、Session
3. 源码分析:在MVC框架中HttpContext对象来源于一个HttpContextBase类的一个实例,该类中包括以下几个重要属性:(非MVC框架中有一个单独HttpContext类)
①:HttpRequestBase Request
②:HttpResponseBase Response
③:HttpApplicationStateBase Application
④: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.测试Request对象
$("#btn1").click(function () {
$.ajax({
type: "Post",
url: "TestRequest",
data: {
"name": ""
},
success: function (data) {
if (data.status == "ok") {
alert("测试通过");
$("#s1").html(data.HttpMethod);
$("#s2").html(data.RawUrl);
$("#s3").html(data.UrlReferrer);
$("#s4").html(data.name);
}
if (data == "error") {
alert("测试未通过");
}
}
});
});
/// <summary>
/// 测试Request对象相关
/// </summary>
/// <returns></returns>
public ActionResult TestRequest()
{
var HttpMethod = Request.HttpMethod;
var RawUrl = Request.RawUrl;
var UrlReferrer = Request.UrlReferrer;
var name = Request["name"];
var data = new
{
status="ok",
HttpMethod=HttpMethod,
RawUrl= RawUrl,
UrlReferrer= UrlReferrer,
name= name
};
return Json(data);
}
测试结果:
2. Server对象
1. Server:一个辅助类 (已完成)
①.HtmlEncode方法:将html编码转换成对应的字符串
②.HtmlDecode方法:将字符串转换成Html编码
③.MapPath方法:获取该地址对应的物理路径
④.UrlEncode方法:将url编码转换成对应的字符串
⑤.UrlDecode方法:将对应的字符串转换成Url格式的编码
2. 代码测试
//2.测试Server对象
$("#btn2").click(function () {
$.ajax({
type: "Post",
url: "TestServer",
data: { },
success: function (data) {
if (data.status == "ok") {
alert("测试通过");
$("#s11").html(data.HtmlEncode);
$("#s22").html(data.HtmlDecode);
$("#s33").html(data.MapPath);
$("#s44").html(data.UrlEncode);
$("#s55").html(data.UrlDecode);
}
if (data == "error") {
alert("测试未通过");
}
}
});
});
public ActionResult TestServer()
{
string HtmlEncode = Server.HtmlEncode("<p>积极向上</p>");
string HtmlDecode = Server.HtmlDecode(HtmlEncode);
string MapPath = Server.MapPath("/home/index"); //只能做物理文件的映射
string UrlEncode = Server.UrlEncode("https://www.2345.com/");
string UrlDecode = Server.UrlDecode(UrlEncode);
var data = new
{
status = "ok",
HtmlEncode = HtmlEncode,
HtmlDecode = HtmlDecode,
MapPath = MapPath,
UrlEncode = UrlEncode,
UrlDecode = UrlDecode
};
return Json(data);
}
测试结果:
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下载文件
/// <summary>
/// 测试下载文件
/// </summary>
/// <param name="type">1代表图片 2代表Excel文件</param>
/// <returns></returns>
public ActionResult TestDownFile(string type)
{
if (type == "")
{
//需要下载的文件在服务器上的物理路径
string path = Server.MapPath("/Content/imageHandle/pipe1.jpg");
//需要下载的文件下载后保存到本地后的名字
string fileName = DateTime.Now.ToString("yyyyMMddHHmmssffffff") + ".jpg";
return File(path, "image/jpg", fileName);
}
if (type == "")
{
string path = Server.MapPath("/Content/myExcel/text.xlsx");
string fileName = DateTime.Now.ToString("yyyyMMddHHmmssffffff") + ".xlsx";
return File(path, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
return Content("");
}
//4. 测试下载文件
//4.1 下载图片
$("#btn5").click(function () {
window.location.href = "TestDownFile?type=1";
});
//4.2 下载Excel
$("#btn6").click(function () {
window.location.href = "TestDownFile?type=2";
});
结果:
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是一个集合,该集合中存放着用户需要的信息。
(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自动过期也是这种效果)
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
第十五节:HttpContext五大核心对象的使用(Request、Response、Application、Server、Session)的更多相关文章
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- 第三百八十五节,Django+Xadmin打造上线标准的在线教育平台—登录功能实现,回填数据以及错误提示html
第三百八十五节,Django+Xadmin打造上线标准的在线教育平台—登录功能实现 1,配置登录路由 from django.conf.urls import url, include # 导入dja ...
- 第三百七十五节,Django+Xadmin打造上线标准的在线教育平台—创建课程机构app,在models.py文件生成3张表,城市表、课程机构表、讲师表
第三百七十五节,Django+Xadmin打造上线标准的在线教育平台—创建课程机构app,在models.py文件生成3张表,城市表.课程机构表.讲师表 创建名称为app_organization的课 ...
- 第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解
第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解 信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行 ...
- 第三百二十五节,web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签
第三百二十五节,web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签 标签选择器对象 HtmlXPathSelector()创建标签选择器对象,参数接收response回调的html对象需 ...
- centos lamp/lnmp阶段复习 以后搬迁discuz论坛不需要重新安装,只需修改配置文件即可 安装wordpress 安装phpmyadmin 定时备份mysql两种方法 第二十五节课
centos lamp/lnmp阶段复习 以后搬迁discuz论坛不需要重新安装,只需修改配置文件即可 安装wordpress 安装phpmyadmin 定时备份mysql两种方法 第二十五节 ...
- centos Linux系统日常管理2 tcpdump,tshark,selinux,strings命令, iptables ,crontab,TCP,UDP,ICMP,FTP网络知识 第十五节课
centos Linux系统日常管理2 tcpdump,tshark,selinux,strings命令, iptables ,crontab,TCP,UDP,ICMP,FTP网络知识 第十五节课 ...
- 大白话5分钟带你走进人工智能-第十五节L1和L2正则几何解释和Ridge,Lasso,Elastic Net回归
第十五节L1和L2正则几何解释和Ridge,Lasso,Elastic Net回归 上一节中我们讲解了L1和L2正则的概念,知道了L1和L2都会使不重要的维度权重下降得多,重要的维度权重下降得少,引入 ...
- 第四百一十五节,python常用排序算法学习
第四百一十五节,python常用排序算法学习 常用排序 名称 复杂度 说明 备注 冒泡排序Bubble Sort O(N*N) 将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮 ...
随机推荐
- C# -- 使用委托 delegate 执行异步操作
C# -- 使用委托 delegate 执行异步操作 委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似. 与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的. 委托的 ...
- python 3.7 安装mysqlclient 错误解决
安装时出现的问题 >pip3.7 install mysqlclientCollecting mysqlclient Using cached https://files.pythonhost ...
- C#默认参数原理探究
起因 写这一篇的起因是想要通过新增默认参数来代替以前的方法,结果发现尽管在调用时写起来一样,实际上也没有被当做同样的方法,两个方法大致如下: // 先前的方法-删除 private static st ...
- HTML5存储技术Storage
前端存储技术localStorage是永久存储sessionStorage是一次会话存储 localStorage只支持string类型的存储 存进去的所有类型, 取出来之后都变成了string. 一 ...
- SQL UNIQUE 约束
SQL UNIQUE 约束 UNIQUE 约束唯一标识数据库表中的每条记录. UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证. PRIMARY KEY 拥有自动定义的 ...
- android开发学习 ------- 关于getSupportFragmentManager()不可用的问题
在Android开发中,少不了Fragment的运用. 目前在实际运用中,有v-4包下支持的Fragment以及app包下的Fragment,这两个包下的FragmentManager获取方式有点区别 ...
- ESP8266天线问题
http://www.icxbk.com/ask/detail/28832.html 目前市面上常见的外接天线包括 1.FPC天线,就是一小块柔性PCB,上面走一个铜线,下方不覆铜,然后一般带一个贴纸 ...
- dede 5.7 任意用户重置密码前台
返回了重置的链接,还要把&删除了,就可以重置密码了 结果只能改test的密码,进去过后,这个居然是admin的密码,有点头大,感觉这样就没有意思了 我是直接上传的一句话,用菜刀连才有乐趣 ...
- kubernete 本地持久化存储 kube-controller-manager的日志输出 + pvc pv 概念 -- storageclass 概念
1.mysql持久化存储 [root@pserver78 0415villa]# cat latestmysql.yaml |grep -v '^#' apiVersion: v1 kind: Ser ...
- BZOJ3709 Bohater 贪心
传送门 思路很妙-- 有个前提条件:血量无限,这样话肯定先打会回血的怪,再打会掉血的怪 对于会回血的怪,按照受到伤害的顺序从小往大打 对于会掉血的怪似乎并不是很好搞,考虑:将每一时刻的血量函数画出来, ...