JavaWeb学习笔记(六)之Session

Session

1会话介绍

所谓会话,可以理解成两个人打电话,从电话接通,多次沟通,到电话挂断的过程。假如 A B 打电话, A 看做客户端, B 看做服务器,当电话接通后,会话开始,在接通后 A B 一问一答,代表客户端和服务器端的多次请求和响应,直到某一方挂断电话,这次会话结束。
JavaWeb 中,浏览器向服务器第一次请求开始,会话开始,浏览器进程关闭,会话结束。
会话:指的是在一段时间内,单个客户与Web应用的一连串相关的交互过程。在一个会话中,客户可能会多次请求访问Web应用的同一网页,也可能请求访问同一个Web应用中的多个网页。

2会话机制
HTTP是无状态的协议。每次客户端请求访问Web服务器端的一个网页时,都必须先与服务器建立一个连接(FTP连接),然后发送HTTP请求,等收到服务器端的HTTP响应,本次连接就被关闭。
如果有以下场景:
a)多个客户各自以合法的账号登陆到电子邮件系统,然后分别进行收信,写信和发信的操作。假如某客户请求查看收件箱,Web服务器必须能够判断发出请求的客户身份,才能返回与这个客户相对应的数据。
b)多个客户同时登陆淘宝购物,Web服务器必须为每个客户配置一个虚拟的购物车。当某个客户请求将一个商品放入购物车时,web服务器必须根据发出的请求客户的身份,找到该客户的购物车,才能将商品放入其中。
对于以上两种案例,要求服务器必须具备一种能辨识不同客户端的能力。又因为HTTP是无状态的,此时必须要有一种技术,用于跟踪客户状态信息。该技术就是会话机制。
会话机制:就是用于跟踪客户状态的一种解决方案(即:会话过程中产生一些数据,这些数据是每个用户独享,需要在服务器端找个地方存放,下次登录服务器能认识该用户,且能获得该用户保存的数据)。JavaWeb中,使用Session完成会话跟踪,Session底层依赖Cookie技术。
注意:Cookie是客户端技术,Session是服务器端技术。

3Cookie技术(回顾)
案例1Cookie键值为中文。
分析:
Cookienamevalue都不能使用中文。想使用中文,可以使用以前讲过的URL编码方式。


案例2Cookie显示上次访问时间。


案例3Cookie显示最近看过的电影记录。
youku, iqiyi等,最近看过的视频,会显示出来。


Session会话机制
Servlet规范制定了基于Java的会话具体运作机制:
Servlet API中定义了代表会话的javax.servlet.http.HttpSession接口,Servlet容器必须实现该接口。当一个会话开始时,Servlet容器将创建一个HttpSession对象,在该对象中可以存放表示客户状态的信息(会话内共享数据)Servlet容器为每个HttpSession对象分配一个唯一的Session ID

会话的运作流程:


细节分析:

以上是一个浏览器与服务器进行会话的过程。如果多个浏览器进程与同一个服务器会话,在服务器端,Servlet容器为每个会话分配一个HttpSession对象,服务器的Web应用把每个客户端的共享对象存放在与之对应的HttpSession对象中。在每个客户端存放了表示SessionIDCookie


Session会话分析:

JSP默认支持会话,可通过<%@ page session=”true” %>显式声明。
通过以上分析,一个Web组件支持会话,就表示
a)浏览器请求访问该Web组件时,Servlet容器会自动查找HTTP请求中Session IDCookie,以及向HTTP响应结果中添加表示Session IDCookie
b)Servlet容器会自动解析Cookie,如果不存在,则容器会创建新的HttpSession对象;如果存在,则寻找已经存在的与Session ID对应的HttpSession对象
c)Web组件可以访问代表当前会话的HttpSession对象。

2HttpSession的会话范围及生命周期 

会话范围是指浏览器与一个Web应用进行一次会话的过程。HttpSession对象的生命周期与会话范围一致。因此,Web组件只要共享同一个HttpSession对象,即可共享会话范围内的共享数据。
HttpSession接口方法:(JSP,Servlet组件可通过以下方法访问会话)
1getId()
     返回SessionID
2invalidate()
     销毁当前会话,Servlet容器会释放HttpSession对象占用的资源
3setAttribute(String name, Object object)
     将一对name/value属性保存在HttpSession对象中
4getAttribute(String name)
     根据name参数返回保存在HttpSession对象中的属性值
5getAttributeNames()
     返回HttpSession对象中所有的属性名
6removeAttribute(String name)
     HttpSession对象中删除name参数的指定属性
7isNew()
     判断是否是新建会话。是,返回true。否则返回false
8setMaxInactiveInterval(int interval)
     设定一个会话处于不活动状态的最长时间,以秒为单位。超过该时间,Servlet

容器会自动销毁会话。如果参数interval设置为负数,会话永远不会过期。

Tomcat为会话设定的默认的保持不活动状态的最长时间为1800秒(30分钟)

   tomcatweb.xml配置信息 
<session-config>

<session-timeout>30</session-timeout>

    </session-config>


9getMaxInactiveInterval()
     读取当前会话可以处于不活动状态的最长时间
10getServletContext()
     返回会话所属的Web应用的ServletContext对象。

Ø  HttpSession对象的创建
Servlet容器在以下情况,会创建一个新的HttpSession对象:
1
)一个浏览器进程第一次访问Web应用中支持会话的任意网页
2)浏览器进程与Web应用的一次会话已经被销毁后,浏览器进程再次访问  Web应用中支持会话的任意网页。

注意:
当浏览器进程与Web应用的一次会话被销毁后,服务器端的相应HttpSession对象结束生命周期。当浏览器进程再次访问Web应用中支持会话的任意网页时,在它的HTTP请求的Cookie中包含了已经被销毁的会话的SessionID, Servlet容器无法找到与该SessionID对应的HttpSession对象,此种情况下,Servlet容器会创建新的HttpSession对象,开始新会话

Ø  HttpSession对象的获得和使用
Web应用中,获得HttpSession对象,才能设置或得到存放在Session中的会话范围内的共享数据。
JSP
中,可以直接通过session内置对象获得HttpSession对象。在Servlet中,通过request对象中获得HttpSession对象:
1) HttpSession  request.getSession()
    
如果当前会话中已经有了session对象,则直接返回。如果当前会话中还

不存在会话,则创建session对象并返回。相当于下面方法flag=true

2)HttpSession   request.getSession(Boolean flag)
    
参数为true,与request.getSession()相同。参数为false,如果当前会

话中存在session则返回,不存在则返回null
获得HttpSession对象后,可通过setAttribute, getAttribute, removeAttribute, getAttributeNames操作会话范围内的共享数据。

Ø  HttpSession对象的销毁
Servlet容器在以下情况,会销毁HttpSession对象,并且会话范围内的共享数据也被销毁。
1
)浏览器进程终止
2)服务器端执行HttpSession对象的invalidate()方法
3)会话过期

会话过期是指当会话开始后,如果一段时间内,客户一直没有和Web应用交互即一直没有请求访问Web应用中的支持会话的任意一个网页,则Servlet容器会销毁该会话。
会话过期的意义:
首先,销毁长时间处于不活动状态的会话,可以及时释放无效的HttpSession对象占用的内存空间;其次防止未授权的用户访问会话,提高Web应用的安全性。如A登陆京东,因有急事,离开一段时间,这期间,其他人可能通过浏览器,进入京东。此时由于设置了会话过期,存放在会话范围内的用户名和密码信息不存在,Web应用要求用户重新登陆。

Ø  注意两种情况
1)当Tomcat中的Web应用被终止时,它的会话不会被销毁,而是被Tomcat持久化到永久存储设置中,当Web应用重启后,Tomcat会重新加载这些会话。
2)当一个会话开始后,如果浏览器进程突然关闭,Servlet容器端无法立即知道浏览器进程已经被关闭,因此Servlet容器端的HttpSession对象不会立即结束生命周期。但浏览器进程关闭后,这个会话就处于不活动状态,等到超过了setMaxInactiveInterval(int interval)方法设置的时间,会话就会因为过期而被Servlet容器销毁。

1         重写URL跟踪会话

如果浏览器支持CookieServlet容器就把SessionID作为作为Cookie保存在浏览器中;如果浏览器处于安全考虑,禁用Cookie,就不允许服务器向客户端存放Cookie,此时,就需要另一种机制-重写URL来跟踪会话。

URL重写就是在原有的URL地址基础上加上JSESSIONID
方式一:(了解)
超链接或表单提交地址:
   <a href=’/weburl/a.jsp;jsessionid=<%=session.getId()%>’>
   <form action=’/weburl/a.jsp;jsessionid=<%=session.getId()%>’>
请求重定向地址:
    response.sendRedirect(url;jsessionid=<%=session.getId()%>’)
方式二:推荐使用。本质上就是在URL后跟上的是  ;jsessionid=xxx
超链接或表单提交地址:
    String newURL = response.encodeURL("/weburl/a.jsp");
   <a href=”<%= newURL %>”>main</a>

<form action=”<%= newURL %>” method=”post”>
请求重定向地址:
    String newURL = response.encodeRedirectURL(url);
    response.sendRedirect(newURL);

运行流程:

mail案例为例。当客户端请求mailcheck.jsp ,执行到<a href =<%=response.encodeURL(“maillogin.jsp”)%>’>

1) 先判断 maillogin.jsp 是否支持会话,如果不支持会话,直接返回参数指定的 URL: maillogin.jsp ,此时该链接依然等同于 <a href=”maillogin.jsp”>
注意:不支持会话两种形式: JSP 文件声明了 <%@page session=”false”%>; JSP 文件中,调用了 session.invalidate() 方法的后续代码都不支持会话。

2)再判断浏览器是否支持Cookie,如果支持,就直接返回参数指定的URLmaillogin.jsp,此时maillogin.jsp的链接依然为<a href=”maillogin.jsp”>如果浏览器不支持Cookie,就在参数指定的URL中加入当前SessionID,然后返回修改后的URL,此时maillogin.jsp的链接形式如下:
<a href=”maillogin.jsp;jsessionid=xxxx”
也就是说:只有在当前Web组件支持会话,并且浏览器不支持Cookie的情况下,encodeURL(url)方法才会重写URL,否则直接返回参数指定的原始URL

           案例:
1- 禁用Cookie

2- 对上次案例进行修改。

2会话的持久化(了解)
会话的持久化:
将内存中HttpSession对象保存到文件系统或数据库中的过程。会话的持久化完全依赖于Servlet容器实现。
会话持久化好处:
   
 1)节约内存空间。一万个客户同时访问web应用,在Servlet容器中就会生    
       成一万个HttpSession对象。如果一直存放在内存中,会耗费大量内存资
         源。因此可以将处于不活动状态的对象保存到文件系统或数据库中.
   2)确保服务器重启或单个Web重启后,能恢复重启前的会话。比如淘宝购
         物,用户将购买物品放入购物车后,保存在session中,此时服务器突然因
         故终止前,将session持久化,待服务器重启后,恢复故障前持久化的
         session。此时用户购物车内的东西仍在。

会话持久化本质:HttpSession对象保存到文件系统或数据库的方法,采用了Java的对象序列化技术;而将HttpSession对象从文件系统或数据库中恢复到内存中,采用了Java的对象反序列化机制。此时需要保证session的属性对象所属的类实现了java.io.Serializable接口。

会话的两种状态:运行时状态和持久化状态

Ø  运行时状态:
主要特征是HttSession对象位于内存中。运行时状态还包括两个子状态,即活动状态和不活动状态。
活动状态:指在一段时间内,处于会话中的客户端频繁与Web应用交互。
不活动状态:在一段时间内,处于会话中的客户端一直没有向Web应用发 
                    出任何HTTP请求。

Ø  持久化状态:
主要特征是HttpSession对象位于永久性存储设备中。

会话两种状态之间转换:

Ø  搁置(持久化):运行时状态转变为持久化状态的过程.以下情况会搁置
1)当服务器终止或单个Web应用终止
2)会话处于不活动状态的时间太长,达到了特定的限制值
3)web应用处于运行时状态的会话数目太多,达到了特定的限制值,部分会话会被搁置。

Ø  激活(加载):持久化状态转变为运行时状态的过程.以下情况会激活
1)服务器重启或单个Web应用重启时,Web应用中会话被激活
2)处于会话中的客户端向Web应用发出HTTP请求,相应会话被激活

注意:会话的搁置和激活,对于客户端来说是透明的,感觉不到的。

Tomcat采用会话管理器管理会话,包括两种会话管理器:

Ø  org.apache.catalina.session.StandardManager:标准会话管理器
实现机制:tomcat服务器终止或单个Web应用被终止时,会对被终止的Web应用的HttpSession对象进行持久化,并将它们保存在默认的文件:
C:\tomcat7\work\Catalina\localhost\test06\ SESSIONS.ser中。
Tomcat服务器重启或者单个Web应用重启时,会激活已经被持久化的HttpSession对象。
案例:

Ø  org.apache.catalina.session.PersistentManager:持久化会话管理器
PersistentManager提供了比StandardManager更灵活的管理会话功能,它把存放HttpSession对象的永久性存储设备称为会话store。具有如下功能:
1)服务器或单个Web应用重启或关闭时,会将Web应用的HttpSession对象持久化到会话store中。
2)具有容错功能,及时把HttpSession对象备份到会话store中,一旦服务器意外关闭或重启,可从会话store中恢复
3)可灵活控制内存中的HttpSession对象数目,将部分转移到会话store

Tomcat的会话store接口为org.apache.catalina.Store,目前提供两个实现类。
1org.apache.catalina.FileStore:session对象保存到文件中
    FileStore保存文件的默认目录:
    C:\tomcat7\work\Catalina\localhost\test06\sessionid.session
    每个session都会对应一个sessionid.session的文件

配置步骤:
1- web应用创建文件,META-INF/context.xml

2- 配置信息:
<Context reloadable="true">

    <Manager className="org.apache.catalina.session.PersistentManager"

        saveOnRestart="true"

        maxActiveSessions="10"

        minIdleSwap="60"

        maxIdleSwap="120"

        maxIdleBackup="180"

        maxInactiveInterval="300"

        >

        <Store className="org.apache.catalina.session.FileStore"directory="mydir" />

    </Manager>

</Context>

className: 指定会话管理器的类名
saveOnRestarttrue,web应用终止时,将内存中所有session对象保
                          存到会话store中。应用重启时,加载这些会话对象。
maxActiveSessions:设定处于运行时状态会话的最大数目,超过该数,
                                tomcat会把一些session对象转移到会话store
                               -1,表示不限制运行时状态的会话数目

minIdleSwap:指定会话处于不活动状态的最短时间(秒),超过指定时间
                      tomcat可能将该session对象转移到会话store中。为-1
                      表示不限制会话处于不活动状态的最短时间
maxIdleSwap:指定会话不活动状态的最长时间,超过这一时间,tomcat
                       必须session对象转移到会话store中。为-1,表示不限
                       制会话处于不活动状态的最长时间。
maxIdleBackup:指定会话处于不活动状态的最长时间,超过这一时间,
                           tomcat将该session对象在会话store中进行备份。与
                        maxIdleSwap不同,该session对象仍然存在于内存中

maxInactiveInterval:指定会话处于不活动状态的最长时间,超过该时
间,tomcat会使该会话过期

案例:配置以上信息,并重启,查看。
2org.apache.catalina.JDBCStore:将对象保存到数据库的一张表中
注意:tomcatJDBCStore实现还不健壮,仅作实验性质的尝试。
该表的字段描述:

session_id:   表示sessionid

session_data:      HttpSession对象的序列化数据

app_name:   会话所属的web应用的名字

valid_session:     会话是否有效

session_inactive:会话可以处于不活动状态的最长时间

last_access:  最近一次访问会话的时间。
案例:

1-web应用的lib放入mysql驱动

2-创建数据库   create database  sessiondb;

3-使用sessiondb    usesessiondb;

4-创建session_table

create table tomcat_sessions(

 session_id varchar(100) not null primary key,

 valid_session char(1) not null,

 max_inactive int not null,

 last_access bigint not null,

 app_name varchar(255),

 session_data mediumblob,

);

5-web应用的  META-INF/context.xml

<Context reloadable="true">

    <Manager className="org.apache.catalina.session.PersistentManager"

        saveOnRestart="true"

        maxActiveSessions="10"

        minIdleSwap="60"

        maxIdleSwap="120"

        maxIdleBackup="180"

        maxInactiveInterval="300"

        >

        <Store className="org.apache.catalina.session.JDBCStore"

            driverName="com.mysql.jdbc.Driver"

            connectionURL="jdbc:mysql://localhost/sessionDB?user=root空格 password=root"    

            sessionTable="tomcat_sessions"

            sessionIdCol="session_id"

            sessionDataCol="session_data"

            sessionValidCol="valid_session"

            sessionMaxInactiveCol="max_inactive"

            sessionLastAccessedCol="last_access"

            sessionAppCol="app_name"

            checkInterval="60"/>

    </Manager>

</Context>

checkInterval:表示tomcat定期检查会话状态的时间间隔的字段名称。

 

3会话的监听
Servlet API中定义了4个用于监听会话中的各种时间的监听器接口。

a)HttpSessionListener接口:监听创建会话及销毁会话的事件。
sessionCreated(HttpSessionEvent event):Servlet容器创建一个会话后调用
sessionDestroyed(HttpSessionEvent event):容器将要销毁一个会话前调用

b)HttpSessionAttributeListener接口:监听向会话中添加,替换,删除属性事件
attributeAdded(HttpSessionBindingEvent event):web应用向一个会话中加入一个新属性时,Servlet容器调用此方法。
attributeRemoved(HttpSessionBindingEvent event):Web应用从会话中删除一个属性时,Servlet容器调用此方法
attributeReplaced(HttpSessionBindingEvent event):web应用替换了会话中的一个已经存在的属性的值时,Servlet容器会调用此方法。

c)HttpSessionBindingListener接口:监听一个会话与一个属性绑定或解除事件
valueBound(HttpSessionBindingEvent event):web应用把一个属性与会话绑定后,Servlet容器调用此方法。
valueUnbound(HttpSessionBindingEvent event):Web应用将要把一个属性与会话解除绑定钱,Servlet容器调用此方法。

d)HttpSessionActivationListener接口:监听会话被激活和被搁置的事件
sessionDidActivate(HttpSessionEvent event):Servlet容器把一个会话激活后,调用此方法
sessionWillPassivate(HttpSessionEvent event):Servlet容器把一个会话搁置前,调用此方法

注意:以上四个接口,HttpSessionListenerHttpSessionAttributeListener,使用前必须在web.xml文件中通过<listener>元素向Servlet容器注册。HttpSessionBindingListenerHttpSessionActivationListener,则有会话的属性类实现。
案例1:演示各种事件触发触发时机。


          案例2:用HttpSessionListener统计在线用户人数。

                很多论坛,都有统计在线人数功能。当一个用户登入一个web应用时,开启一个会话;当这个会话被销毁,意味着用户离开。因此,一个在线用户      
       对应一个会话,web应用的当前所有会话数,就等于在线用户数目。


案例3:用HttpSessionBindingListener统计在线用户人数 

                案例2实际上统计的是web应用的当前所有会话的数目,无法统计所有在线用户的具体名单。可使用HttpSessionBindingListener实现。

增加反射内容

 

猜你喜欢

转载自blog.csdn.net/zqq3436/article/details/80388176
今日推荐