最近在做项目的时候碰见了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功能
class="code_img_closed" src="/Upload/Images/2013121818/0015B68B3C38AA5B.gif" alt="" />
<%-- 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, 60000); } // 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 = 2; // 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过期的问题的。