Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。有关使用 Session 对象的详细信息,请参阅“ASP 应用程序”部分的“管理会话”。注意 会话状态仅在支持 cookie 的浏览器中保留。
在系统登录后,都会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动退出登录,销毁session。
具体设置很简单,方法有三种:
- 在主页面或者公共页面中加入:session.setMaxInactiveInterval(900);参数900单位是秒,即在没有活动15分钟后,session将失效。这里要注意这个session设置的时间是根据服务器来计算的,而不是客户端。所以如果是在调试程序,应该是修改服务器端时间来测试,而不是客户端。
-
也是比较通用的设置session失效时间的方法,就是在项目的web.xml中设置
<!-- 设置session失效,单位分 --> <session-config> <session-timeout>1</session-timeout> </session-config>
- 直接在应用服务器中设置,如果是tomcat,可以在tomcat目录下conf/web.xml中找到<session-config>元素,tomcat默认设置是30分钟,只要修改这个值就可以了。
需要注意的是如果上述三个地方如果都设置了,有个优先级的问题,从高到低:(1)>(2)>(3)
在一般系统中,也可能需要在session失效后做一些操作,
(1)控制用户数,当session失效后,系统的用户数减少一个等,控制用户数在一定范围内,确保系统的性能。
(2)控制一个用户多次登录,当session有效时,如果相同用户登录,就提示已经登录了,当session失效后,就可以不用提示,直接登录了。
那么如何在session失效后,进行一系列的操作呢?
这里就需要用到监听器了,即当session因为各种原因失效后,监听器就可以监听到,然后执行监听器中定义好的程序就可以了。
监听器类为:HttpSessionListener类,有sessionCreated和sessionDestroyed两个方法
自己可以继承这个类,然后分别实现。
sessionCreated指在session创建时执行的方法
sessionDestroyed指在session失效时执行的方法
给一个简单的例子:
public class SessionListener implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent event) {
HttpSession ses = event.getSession();
String id=ses.getId()+ses.getCreationTime();
SummerConstant.UserMap.put(id, Boolean.TRUE); //添加用户
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession ses = event.getSession();
String id=ses.getId()+ses.getCreationTime();
synchronized (this) {
SummerConstant.USERNUM--; //用户数减一
SummerConstant.UserMap.remove(id); //从用户组中移除掉,用户组为一个map
}
}
}
然后只需要把这个监听器在web.xml中声明就可以了
<listener>
<listener-class>
com.demo.SessionListener
</listener-class>
</listener>
解决php项目中session失效的方法
今天下班坐班车,快到站的时候,上家公司的leader发了个qq给我,意思是救火,下车后回来在电脑上详细问了下,leader的描述如下
这个地址 你帮我看下 为啥上传完试卷发布任务 设置答题卡的时候 session就没了
因为这个项目一开始后台都是我一人开发的,因此很快就找到了问题所在。流程为:用户通过js组件上传试卷,在上传试卷的方法中通过session存储刚刚上传的试卷详细信息,如名称、后缀、存入资源表的ID等,上传成功后,再点击页面上的其他选项,如学校、年级、难易度等,最后点击提交,在提交处理的方法里,一开始便判断刚刚上传的session值是否存在,不存在便跳到试卷首页。我在此方法中打印了$_SESSION,没有值,奇怪了,以前还是好好的。于是我问了下,啥时候开始的,leader说下午快下班时,老师打电话说上传试卷设置答题卡不成功,老跳转。接着又问了下,动服务器环境了么,leader说没有。
既然出现了问题,那就解决问题呗。正好这段时间在看《PHP核心技术与最佳实践》一书,里面就对session和cookie有详细的描述,同时也加深了我对二者的理解。于是我先打开php的配置文件,找到session相关的配置项,发现session.save_path为/data2/session,我记得以前都是设置为/data1/session的,怎么变了。于是我退出来去看看此路径,一开始我以为是该目录权限不够,后来一看,压根就没有该目录,难怪每个session不会跨页面。于是新建文件,设置权限,再上传,一切又恢复正常了。
写到这,我也想再唠叨下session相关的技术点。session是存储在服务器端的,默认是以文件方式存储的(session.save_handler = files)。那session是如何产生的呢?session是通过session_start()函数产生的 ,当此函数运行时,在session存储的目录里生成一个文件和唯一一个与之对应的session id,通过session id可以取出该session文件的数据。由于每次运行session_start()都会产生新的seession文件,那么如何利用到以前生成session文件呢,只需session_start($session_id),那么便不会新产生session文件了,而会去读session id对应的session文件。session id在默认情况下都是使用在客户端(浏览器)的cookie来保存session id(在chrome浏览器上按F12键,点击Resources-cookies,可以看到),使用$_COOKIE['PHPSESSID']可以获取。那个PHPSESSID是session id的默认名称,在php.ini里可以通过session.name来设置,在脚本中用session_name()来获取session id的名称。每次浏览器和服务器对话时,浏览器都会把session id传给服务器的,服务器会依据传递过来的session id找到相应的session文件获取相应信息进行相关操作。而一旦客户端(浏览器)禁用了cookie,那么服务器端变不会接收到session id,此时需要显示传递session id了。两种方法:手动通过URL传递session id;隐藏表单传递session id。上述两种方法需要服务端的php环境中session.use_trans_sid 值为 1。
啰嗦了那么多,最后还是linus那句话,“talk is cheap,show me the code”。
<?php
session_start();
$_SESSION['arr'] = array('name' => 'molaifeng', 'hobby' => 'php');
?>
<a href="testSession.php?<?php echo session_name(); ?>=<?php echo session_id()?>">testSession</a>
<?php
session_start($_REQUEST[session_name()]);
print_r($_SESSION);
代码都看懂的吧,就不解释了。
最后总结下吧,一般情况下出现跨页面session失效,基本上是上述列出的几点。1、session.save_path有误,如权限不够,或是目录不存在;2、服务器php配置中的session.use_trans_sid值为0;3、客户端禁用了cookie。不过我觉得第一种情况出现的频率应该挺高的。