最近在做项目的时候碰见了session过期的问题,然后就上网查了一些资料,我将我整理过的知识点梳理一下,顺便说一下我的使用方案。

Session存储在服务器端,一般为了防止在服务器的内存中(为了高速存取),Sessinon在用户访问第一次访问服务器时创建,需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session,可调用request.getSession(true)强制生成Session。

 一、关于Session的一些基础知识

  Session什么时候失效?

  1. 服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效。Tomcat中Session的默认失效时间为20分钟。

  2. 调用Session的invalidate方法。

  Session对浏览器的要求:

  虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。

  该Cookie为服务器自动生成的,它的maxAge属性一般为-1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。但是由浏览器窗口内的链接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,因此会共享一个Session。

  注意:新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择"在新窗口中打开"时,子窗口便可以访问父窗口的Session。

如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:URL地址重写。

  URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。HttpServletResponse类提供了encodeURL(String url)实现URL地址重写,该方法会自动判断客户端是否支持Cookie。如果客户端支持Cookie,会将URL原封不动地输出来。如果客户端不支持Cookie,则会将用户Session的id重写到URL中。

  注意:TOMCAT判断客户端浏览器是否支持Cookie的依据是请求中是否含有Cookie。尽管客户端可能会支持Cookie,但是由于第一次请求时不会携带任何Cookie(因为并无任何Cookie可以携带),URL地址重写后的地址中仍然会带有jsessionid。当第二次访问时服务器已经在浏览器中写入Cookie了,因此URL地址重写后的地址中就不会带有jsessionid了。

来源于:http://www.cnblogs.com/binger/archive/2013/03/19/2970171.html session的生命周期

 二、延长或控制Session的有效期的方法总结

如果访问者在Session的设定的失效时间内(比如默认的20分钟)没有任何动作,Session就会失效,这个就意味着与Session存贮相关的变量也会同时失效,不能再访问。有时候我们需要保持Session很长的时间来等待用户完成工作,比如博客,当用户在写完文章之后提交却发现Session已经失效,这是一件多么悲惨的事情。

很多人可能尝试这样做

<system.web>
      <authentication mode="Forms">
        <forms timeout="60"/>
      </authentication>

...
    </system.web>

尽管我们可以很简单的增加Session的过期时间,但是这并不是一个很好的方案。当用户真的离开的时候,它会让你的服务器系统浪费很多内存资源来保存一些完全没有意义的东西。如果这个网站的访问量非常大的时候,可能由于Session占用的内存太多,而使你的网站运行得很慢。解决方案我们可以采用客户端周期性请求服务器的方法来保持Session。很多大型网站都是采用这样的方法,例如网易,51博客和QQ在写邮件和发文章的时候。为了达到这样的效果,我们可以使用javascript,jquery,metarefresh和asp.net ajax几种方法来解决。

1.    用javascript来保持Session

Asp.net 仅仅会记住用户的最后一次请求,它不知道用户是否关闭了浏览器,或者是否在干别的事情。为了保住那些还开着我们的网页的用户的Session,我们可以使用JS的setInterval功能

<%--
In this example, image will be used to keep session alive,
By changing image's src parameter, we'll make periodical requests
to web server.
--%>
<img id="imgSessionAlive" width="1" height="1" /> <script type="text/javascript" >
// Helper variable used to prevent caching on some browsers
var counter;
counter = 0; function KeepSessionAlive() {
// Increase counter value, so we'll always get unique URL
counter++; // Gets reference of image
var img = document.getElementById("imgSessionAlive"); // Set new src value, which will cause request to server, so
// session will stay alive
img.src = "http://YourWebSiteUrl.com/RefreshSessionState.aspx?c=" + counter; // Schedule new call of KeepSessionAlive function after 60 seconds
setTimeout(KeepSessionAlive, 60000);
} // Run function for a first time
KeepSessionAlive();
</script>

代码

在这个例子里,RefreshSessionState.aspx这个页面将会每分钟被请求一次。我们通过操作SRC来请求服务器。当然这只是一个巧妙的方法,你可以使用Http Request.当然那更加的麻烦。如果你只是想保住Session的话你可以设置为19分钟(19*60*1000=1140000)。当访问的间隔很小时,比如例子的一分钟,这样做的好处是你可以准确的知道用户的离开时间,并且立即释放掉不需要使用的资源。你甚至可以把Session的过期时间定为2分钟。这样你的服务器就只会保存当前停留在你网站的用户的Session.

因为RefreshSessionState.aspx页面会被每分钟请求,所以我们可以使用ASP.NET服务器技术来追踪我们的用户,例如统计当前用户数,用户在看那一个页面等等详细信息,如果是做一个社区性质的网站的话,相信这些会让你的网站绽放光彩的。

2.      使用JQUERY 保持Session

我们可以使用Jquery框架来完成相同的任务。这里我们使用Post提交方式来保持我们的Session

<script language="javascript" type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script language="javascript" type="text/javascript"> function KeepSessionAlive() {
// 1. Make request to server
$.post("http://YourWebSiteUrl.com/RefreshSessionState.aspx"); // 2. Schedule new request after 60000 miliseconds (1 minute)
setInterval(KeepSessionAlive, );
} // Initial call of function
KeepSessionAlive(); Â
</script>

代码

Jquery的简洁性是不是让你眼红呢?

3.      使用Meta Refresh来保持Session

一般我们不会用refresh来定时刷新我们的整个页面,因为这会造成你的页面一闪一闪,这可不是一闪一闪亮晶晶,你要是一闪一闪的用户早跑了。所以我们一般使用一个Iframe来完成这个功能

<iframe height="0" width="0" src="RefreshSessionState.aspx" frameborder="0" />

此时RefreshSessionState.aspx如果你不要跟踪用户的话不需要服务器代码。我习惯于这样写

   <html>
<head>
<%
Response.Write(@"<meta http-equiv=""refresh"" content=""900;url=RefreshSessionState.aspx?x=" +
Server.UrlEncode(DateTime.Now.ToString()) + @""" />");
%>
</head>
<body> </body>
</html>

代码

参数x的作用是为了避免浏览器缓存整个页面导致我们需要的功能成为泡影,这样我们就通过了一个iframe来完成了我们需要的功能。

4.   使用asp.net ajax 来保持Session

Aspx页面的代码如下:

 <html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div> <asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" Interval="10000" ontick="Timer1_Tick">
</asp:Timer>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel> </div>
</form>
</body>
</html>

代码

Timer控件的Interval可是设置间隔时间但是是毫秒。服务器端的代码我们可以这样写:

using System;

    public partial class Ajax_Refresh : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Set session timeout to small value, in this case
// 2 minutes, to see quickly if Timer will keep session alive
Session.Timeout = ;
// Set some value in session
Session["Testing"] = "session is alive";
} // Timer will make request to server in regular time intervals
protected void Timer1_Tick(object sender, EventArgs e)
{
// Write current session value into label
Label1.Text = (string)Session["Testing"];
Label1.Text += "<br /> Last request at " + DateTime.Now.ToString();
}
}

代码

实际上在许多公司使用asp.netajax的比较少,但是如果是一些要求快速开发的项目来说,asp.net ajax也不愧为一个很好的选择。

以上就是保持延长Session的四种解决方案,希望对你有些帮助。

由于我们当前项目使用率不是太高,至于内存效率什么的都不在考虑范围之内,我直接用的就是最开始修改  <forms timeout="60"/>来解决session过期的问题的。

关于session的一些问题的更多相关文章

  1. session实现购物车

    为实现简单的购物功能(购物车添加.账户查看.购物车商品删除.实时的购物商品数量及价格的计算显示.购物车商品数量可手动输入等),用session实现了一简单的以php语言为基础.连接MySQL数据库的购 ...

  2. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  3. 懒加载session 无法打开 no session or session was closed 解决办法(完美解决)

           首先说明一下,hibernate的延迟加载特性(lazy).所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作.因为hibernate当中支持实体对象,外键会与实体对象关联起来.如 ...

  4. 探索ASP.NET MVC5系列之~~~6.Session篇(进程外Session)

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  5. Nhibernate的Session管理

    参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...

  6. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  7. zookeeper源码分析之六session机制

    zookeeper中session意味着一个物理连接,客户端连接服务器成功之后,会发送一个连接型请求,此时就会有session 产生. session由sessionTracker产生的,sessio ...

  8. [转载]Cookie/Session的机制与安全

    Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道.本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题. 因 ...

  9. 修改session垃圾回收几率

    <?php //修改session垃圾回收几率 ini_set('session.gc_probability','1'); ini_set('session.gc_divisor','2'); ...

  10. Nginx反向代理,负载均衡,redis session共享,keepalived高可用

    相关知识自行搜索,直接上干货... 使用的资源: nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换. tomcat服务器两台,由nginx进行反向代理和负载均衡,此 ...

随机推荐

  1. HDU-2594-Simpsons' Hidden Talents(kmp, 扩展kmp)

    链接: https://vjudge.net/problem/HDU-2594#author=0 题意: 求S1的前缀和S2的后缀的<最大>匹配 思路: kmp方法: 将s1, s2首尾连 ...

  2. 2017"百度之星"程序设计大赛 - 初赛(A) [ hdu 6108 小C的倍数问题 ] [ hdu 6109 数据分割 ] [ hdu 6110 路径交 ] [ hdu 6112 今夕何夕 ] [ hdu 6113 度度熊的01世界 ]

    这套题体验极差. PROBLEM 1001 - 小C的倍数问题 题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6108 (2017"百度之星 ...

  3. BZOJ1968: [Ahoi2005]COMMON 约数研究 线性筛

    按照积性函数的定义筛一下这个积性函数即可. #include <cstdio> #include <algorithm> #define N 1000004 #define s ...

  4. Number Of Permutations

    Number Of Permutations 思路:利用容斥,首先所有可能的排列肯定是fac[n],然后可能会有三种 bad 的情况: ①第一个元素的排列是非递减 ②第二种是第二个元素的排列是非递减 ...

  5. js 原型链、构造函数、原型与实例之间的关系

    面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针, ...

  6. Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

    2019-07-24 11:09:15.231+08:00 LISA.Common.Utilities.LogUtil - System.ObjectDisposedException: Instan ...

  7. linu逻辑分区动态调整大小

    注意: 这个动态调整的方法是有丢数据风险的,要确保调整的源分区没有使用或者使用率很低.源分区中如果有重要的文件最好先备份 在centos 6.5上操作过 lvdisplay 查看已有的分区的大小 lv ...

  8. 一、基础篇--1.2Java集合-HashMap和ConcurrentHashMap的区别【转】

    http://www.importnew.com/28263.html 今天发一篇”水文”,可能很多读者都会表示不理解,不过我想把它作为并发序列文章中不可缺少的一块来介绍.本来以为花不了多少时间的,不 ...

  9. php执行方式对比:mod_php&php-fpm

    mod_php 1.是apache的附属包,apache死掉后php也会死掉 2.稳定性差,php出错服务器进程也会受影响 php-fpm       1.和nginx是两个独立的个体. 2.php- ...

  10. 浅析java中的四种线程池

      1.使用线程池的好处 2.JUC中几种常用的线程池 java.util.concurrent包下的Executors工厂类,提供了一系列的线程池的创建方法,其构造方法如下: public Thre ...