session内置对象简介
session是较常用的内置对象之一,与 request对象相比其作用范围更大。
session在网络中被称为会话。由于HTTP协议是一种无状态协议,也就是当一个客户向服务器发出请求,服务器接收请求,并返回响应后,该连接就结束了,而服务器并不保存相关的信息。为了弥补这一缺点,HTTP协议提供了session。通过session可以在应用程序的Web页面间进行跳转时,保存用户的状态,使整个用户会话一直存在下去,直到关闭浏览器。但是,如果在一个会话中,客户端长时间不向服务器发出请求, session对象就会自动消失。这个时间取决于服务器,例如, Tomcat服务器默认为30分钟。不过这个时间可以通过编写程序进行修改。
- session表示客户端与服务器的一次会话
- Web中的 session指的是用户在浏览某个网站时,从进入网站到
浏览器关闭
所经过的这段时间
,也就是用户浏览这个网站所花费的时间
- 从上述定义中可以看到, session实际上是一个特定的时间概念
- session保存在服务器的内存中,每一个客户都对应一个session。
session对象
session对象是一个JSP内置对象,是 Httpsession类的实例。
session对象在第一次访问JSP页面的时候被自动创建,用来完成客户端与服务器的一次会话管理。
当一个客户访问一个服务器时,可能会在几个页面之间切换,使用session就能知道这几个界面是都是同一个客户访问的。
session会话对象,一般用来保存帐户信息,一般购物车的实现也是用session完成
session对象常用方法
方法 |
描述 |
long getCreation Time() |
返回 session的创建时间 |
public String getId() |
返回session创建时JSP引擎为它设的唯一ID号 |
String[] getValueNames() |
返回一个包含此session中所有可用属性的数组 |
属性方法
通过session对象可以存储或读取客户相关的信息。例如,用户名或购物信息等。这可以通过 session对象的 setAttribute()
方法和getAttribute()
方法实现。
对于存储在 session会话中的对象,如果想将其从 session会话中移除,可以使用 session对象的removeAttributr()
方法,该方法的语法格式如下:
方法 |
描述 |
void setAttribute(String name, Object value) |
设置属性 |
Object getAttribute(String name) |
取得属性名称对应的属性值,没有该属性则返回null |
Enumeration<String> getAttributeNames() |
取得session中所有属性名称的枚举 |
void removeAttribute(String name) |
移除属性名为name的属性 |
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <%@page import="java.util.Enumeration"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% session.setAttribute("user", "小明"); session.setAttribute("password", "123456"); session.setAttribute("sex", "男"); session.removeAttribute("sex"); Enumeration<String> attrNames = session.getAttributeNames(); String name; while (attrNames.hasMoreElements()) { name = attrNames.nextElement(); out.print(name+"="+session.getAttribute(name)+"<br>"); } %> </body> </html>
|
session有效时间方法
在应用 session对象时应该注意 session的生命周期。一般来说, session的生命周期在20~30分钟之间。当用户首次访问时将产生一个新的会话,以后服务器就可以记住这个会话状态,当会话生命周期超时时,或者服务器端强制使会话失效时,这个 session就不能使用了。在开发程序时应该考虑到用户访问网站时可能发生的各种情况,例如用户登录网站后在 session的有效期外进行相应操作,用户会看到一张错误页面。这样的现象是不允许发生的。为了避免这种情况的发生,在开发系统时应该对session的有效性进行判断。
在 session对象中提供了设置会话生命周期的方法,分别介绍如下。
方法 |
描述 |
void setMaxInactiveInterval(int interval) |
以秒为单位设置 session的有效时间。 |
int getMaxInactiveInterval() |
以秒为单位返回一个会话内两个请求最大时间间隔(session的最大存活时间)。默认是1800秒。如果超过这个时间没有客户没有继续请求服务器,则该session对象被销毁 |
long getLastAccessedTime() |
返回客户端最后一次与会话相关联的请求时间,单位毫秒。 |
设置session生存时间实例
通过session.setMaxInactiveInterval(int seconds);
可以设置session的生存时间,当超时候,当前的session会被销毁。如果再新打开一个页面,则此时的session为新建的session对象,与原来旧的session无关。
修改上述的session.jsp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); session.setAttribute("user", "admin"); session.setAttribute("password", "123456"); session.setMaxInactiveInterval(2); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> <a href="http://localhost:8080/HelloWorld/session2.jsp" target="_blank">跳转到session2</a> </body> </html>
|
修改session2.jsp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session2</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> </body> </html>
|
打开session.jsp,然后稍微等待2秒钟,然后点击超链接,打开session2.jsp。可以看到两者的session id不一样,创建时间也不一样。
这说明之前的session对象已经过期了。session2.jsp中的session对象为新建的session对象。这两个页面不属于同一个会话
实例
下面创建两个jsp文件:session.jsp,session2.jsp。session.jsp中设置了两个属性。session2.jsp不设置属性,直接获取属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@page import="java.util.Enumeration"%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session2</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); session.setAttribute("user", "admin"); session.setAttribute("password", "123456"); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> <hr> 遍历session中的属性/属性值对: <br> <% Enumeration<String> enu = session.getAttributeNames(); String attr = null; while (enu.hasMoreElements()) { attr = enu.nextElement(); out.println(" " + attr + "=" + session.getAttribute(attr) + "<br>"); } %> <hr> session最大存活时间:<%=session.getMaxInactiveInterval() %>秒=<%=session.getMaxInactiveInterval()/60 %>分钟<br> </body> </html>
|
session2.jsp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@page import="java.util.Enumeration"%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session2</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> <hr> 遍历session中的属性/属性值对: <br> <% Enumeration<String> enu = session.getAttributeNames(); String attr = null; while (enu.hasMoreElements()) { attr = enu.nextElement(); out.println(" " + attr + "=" + session.getAttribute(attr) + "<br>"); } %> <hr> session最大存活时间:<%=session.getMaxInactiveInterval() %>秒=<%=session.getMaxInactiveInterval()/60 %>分钟<br> </body> </html>
|
运行结果:
session.jsp访问效果:
session2.jsp访问效果:
可以看到这虽然是两个不同的界面,但是他们的输出结果都是一模一样的。这是因为这两个页面除以相同的会话之中。共享一个session对象。这里session对象还是理解的不够通透,后续再深入,我先往前面吃。
session生命周期
创建
当客户端第一次访问某个jsp或者 Servlet时候,服务器会为当前会话创建一个SessionId每次客户端向服务端发送请求时,都会将此 SessionId携带过去,服务端会对此 Session进行校验。
活动
- 1 某次会话中通过超链接打开的新页面属于同一次会话。
- 2 只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。
- 3 除非本次会话的所有页面都关闭(关闭所有相关浏览器窗口)后再重新访问某个JSP或者servlet将会创建新的会话。
- 注意:
原有会话还存在
,只是这个旧的 Session仍然存在于服务端,只不过再也没有客户端会携带它然后交予服务端校验
,除非旧的会话超时了,旧的会话才结束。
验证说法1
修改session.jsp,session2.jsp如下:
session.jsp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@page import="java.util.Enumeration"%> <%-- <%@page import="java.util.Enumeration"%> --%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); session.setAttribute("user", "admin"); session.setAttribute("password", "123456"); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> <hr> 遍历session中的属性/属性值对: <br> <% Enumeration<String> enu = session.getAttributeNames(); String attr = null; while (enu.hasMoreElements()) { attr = enu.nextElement(); out.println(" " + attr + "=" + session.getAttribute(attr) + "<br>"); } %> <hr> <a href="http://localhost:8080/HelloWorld/session2.jsp" target="_blank">跳转到session2</a> </body> </html>
|
session2.jsp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@page import="java.util.Enumeration"%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session2</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> <hr> 遍历session中的属性/属性值对: <br> <% Enumeration<String> enu = session.getAttributeNames(); String attr = null; while (enu.hasMoreElements()) { attr = enu.nextElement(); out.println(" " + attr + "=" + session.getAttribute(attr) + "<br>"); } %> <hr> </body> </html>
|
打开ssession.jsp,显示如下:
然后通过下面的超链接打开session2.jsp:
可以看到两者的session id一样,所以某次会话中通过超链接打开的新页面属于同一次会话。
这句话得到验证。
验证说法2
不要关闭当前浏览器窗口,再打开一个浏览器窗口,访问ssession2.jsp:
可以看到新浏览器窗口中的session2.jsp中session id(BE58A27556C3883C7DA49083CDC6D4BD
)依然和旧浏览器窗口中的session2.jsp的session id一样。这说明第二点只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。
是正确的。
关闭新的浏览器窗口,旧的浏览器窗口中关闭掉全部Helloworld项目中的页面。
我的观察结果
验证过程中,我发现即使在浏览器中关闭了所有HelloWorld项目打开的标签页。但是只要没有关闭当前浏览器窗口。该session就还是有效的。
例如:在浏览器窗口中打开的session.jsp,session2.jsp和一个无关的页面:其中session.jsp中的session id为:790B84D02E1ED3D7CB3FBB1910C33343
现在我关闭掉session.jsp,session2.jsp,只留了一个无关的页面:
然后我输入session.jsp的地址,进行访问,如下图:
可以发现session id还是790B84D02E1ED3D7CB3FBB1910C33343
,然后点击超链接打开session2.jsp:
打开一个新的浏览器窗口,访问session.jsp:
可以发现session id还是790B84D02E1ED3D7CB3FBB1910C33343
。所以只要我旧的浏览器窗口没有关闭,这个session就会一直有效(不超时的情况下)。
所以我的结论是:在不超时的情况下,即使你关闭了在一个Web项目中打开的所有页面,只要不关闭当前的浏览器窗口,等你下次访问该项目的时候,新标签页或者是新窗口中的session对象还是原来的session对象
。
关闭所有的浏览器,然后重新打开浏览器,访问session.jsp:
可以看到这次的sesion id已经变成了:60F84C6ED79AD13DA8CD8BA12E8D4129
而不是原来的790B84D02E1ED3D7CB3FBB1910C33343
。这说明原来的session已经不再使用了。
tomcat中查看一个项目的所有session
进入tomcat首页http://localhost:8080/,然后点击Manager App
:
输入用户和密码,如果不知道用户和密码的话先设置。
进入之后就可以看到tomcat中的项目表:同时在表中的Session列中,可以看到每个项目中有多少个session,例如现在HelloWorld这个项目就有2个session:
点击这个数字可以查看项目中的Session列表:
可以看到这里有两个session:790B84D02E1ED3D7CB3FBB1910C33343
和60F84C6ED79AD13DA8CD8BA12E8D4129
,而790B84D02E1ED3D7CB3FBB1910C33343
这个session已经不再使用了,处于等死状态中,不过还没有被销毁,还在服务器内存中苟活,等到剩余的时间为0后,才会从服务器内存中被销毁。60F84C6ED79AD13DA8CD8BA12E8D4129
这个session是目前正在使用的session。我们肯继续访问HelloWorld项目,来为当前的session续命:
而以前的session就只有等死的份了,剩余时间会一直减少,直到为0后被销毁掉:
销毁
Session的销毁只有三种方式:
- 调用了
session.invalidate()
方法
- Session过期(超时)
- 服务器重新启动
虽然当客户端长时间不向服务器发送请求后, session对象会自动消失,但对于某些实时统计在线人数的网站(例如聊天室),每次都等 session过期后,才能统计出准确的人数,这是远远不够的。所以还需要手动销毁 session。通过 session对象的 invalidate方法可以销毁 session,其语法格式如下:
session对象被销毁后,将不可以再使用该 session对象了。如果在 session被销毁后,再调用 session对象的任何方法,都将报出 Session already invalidated
异常。
使用invalidate方法直接销毁
修改session.jsp如下,输出完信息后,就关闭当前的session:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.Date"%> <%@page import="java.util.Enumeration"%> <%-- <%@page import="java.util.Enumeration"%> --%> <%@ page language="java" contentType="text/html; charset=utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>session</title> </head> <body> <h2>session内置对象</h2> <% Date date = new Date(session.getCreationTime()); SimpleDateFormat format = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss"); session.setAttribute("user", "admin"); session.setAttribute("password", "123456"); %> session对象的创建时间: <%=format.format(date)%><br> session对象的ID:<%=session.getId()%><br> <hr> 遍历session中的属性/属性值对: <br> <% Enumeration<String> enu = session.getAttributeNames(); String attr = null; while (enu.hasMoreElements()) { attr = enu.nextElement(); out.println(" " + attr + "=" + session.getAttribute(attr) + "<br>"); } session.invalidate(); %> <hr> <a href="http://localhost:8080/HelloWorld/session2.jsp" target="_blank">跳转到session2</a> </body> </html>
|
如下所示:
访问完毕后,当前session就已经销毁掉了,可以打开管理页面http://localhost:8080/manager/html查看:
可以看到当前没有session,说明上面的session对象确实用完就被销毁掉了。我们每次访问后,都会是一个新的session:
超时销毁
这里有两种方式:
- 一种是通过
session.setMaxInactiveInterval(int seconds);
方法设置session的生存时间。
- 另一种是在
web.xml
中跟标签下进行配置:
1 2 3 4
| <session-config> <session-timeout>60</session-timeout> </session-config>
|
可以进入tomcat后天管理查看当前会话的活动时间已经被设置为60分钟了,而不是默认的30分钟:
参考链接
JSP Session
https://wenku.baidu.com/view/08dd8ef3f90f76c661371a0d.html?sxts=1544369585905