会话追踪技术详解


会话追踪技术

1.session机制

什么是会话?

一次会话:用户打开浏览器,进行一系列操作,然后最终将浏览器关闭,整个过程叫做一次会话。会话在服务器端也有一个对象,这个对象叫做session对象。

一次请求:用户打开浏览器,进行点击等操作的时候,然后到页面上停下来,可以认为是一次请求。请求对应的服务器端的java对象是request,一次会话对应n次请求,n∈[1,...]

package javax.servlet.http;
public interface HttpSession {}

Session是B/S结构的一部分,Session对象的最主要的功能就是保存会话状态信息。

原因:这是因为http协议是无状态(连接)协议。请求的时候B和S是连接的,但是请求结束之后连接就断掉了,这样的设计能够降低服务器的压力和占用带宽。但是这种设计的缺陷就是无法保存会话的状态。

一个例子:当你访问百度首页的时候,这时候你会向百度的服务器发起一次连接请求,当你收到一个response的时候,这时候连接管道就会被断开,那你上次连接做的操作,存的数据就都没有了。具体体现在requestreponse对象被销毁掉了
一些网站设计的安全退出按钮和直接点叉叉关闭有什么区别?

首先由于服务器是不知道你退出了浏览器的,这时候服务器会保存你的session,你点了安全退出,就相当于告诉服务器你要退出了,这时候就会为你删除掉session

为什么不使用request对象来保存状态?ServletContext呢?

关于request:request对象的生命周期太短,在一次请求和响应中就已经被销毁了,无法保存服务端和浏览器端的会话状态。

关于ServletContext:这个对象在服务器启动的时候就被创建,在关闭的时候就被销毁,这个ServletContext就只有一个,那么这个对象对于保存会话状态来说就太大了,而且涉及到多个用户共同访问的并发问题,不适合。

  • HttpServlet:请求域
  • HttpSession:会话域
  • application:应用域

2. Session实现原理

Session是如何获取的?

HttpSession session = request.getSession();
HttpSession session = request.getSession(false);
//加false这个参数是:从服务器获取session,如果获取不到session,那么就不会新建,返回null

如果服务器端没有这个Session,那么就会新建这个Session并且保存到服务器端。

为什么能够拿到属于自己的Session?

web服务器中有一个如上的session列表,key是session的key,value是session的对象

当用户发送第一次请求的时候,服务器会创建新的session对象,然后将session的id发送给浏览器,然后浏览器会将id进行缓存。

当用户发送第二次请求的时候,会自动将缓存中的sessionId发送给web服务器,然后就能查找到对应的session对象。

为什么关了浏览器就会导致session失效?

缓存问题:当你关闭了浏览器的时候,缓存失效,也就是说sessionId不在缓存中了,这时候就相当于一次新的会话

那么一次会话可以解释成SessionId生成到Session对象找不到了

Session对象找不到了有两种情况

  • 浏览器端找不到了,这种情况是缓存中的sessionId找不到了,清掉了
  • 服务器端根据sessionId找不到对应的对象,清掉了

关于销毁的问题

  • 超时销毁
<session-config>
    <!--设置超时时间-->
    <session-timeout>30</session-timeout>
</session-config>
  • 手动销毁
session.invalidate();

浏览器端向服务端发送的Session的形式是以Cookie的形式传回去的,是放在Http协议的Header的,Session关联的Cookie不是放在磁盘中的,而是放在浏览器的内存中的。

因此关闭浏览器的时候,缓存消失,Cookie消失,因此它就找不到Session了

如果禁用了Cookie,会发生什么?

Cookie禁用:表示服务器正常发送Cookie给浏览器,但是浏览器拒收了Cookie,从而导致浏览器中无法缓存SessionId。

在这种情况下每次都会生成一个新的Session对象,尽管浏览器端Cookie没有缓存你的SessionId,但是服务器端的底层依然会在不断生成Session对象,而这些Session在等待超时销毁。

解决办法

可以使用URL的重写机制

也就是在URL后加一个;JsessionId = ID,这样的话也可以获得同一个Session对象

这样的要求是在请求路径后总要加一个JsessionId作为参数

3. Cookie理论基础

Session的实现原理中,每一个Session对象都会关联一个SessionId,比如说JSessionId = xxx,这个ID是通过Cookie技术缓存到浏览器的运行内存中的。服务器根据这个值来找到这个对象。

Cookie案例

  • 存储本地状态:在未登录的情况下,向购物车中放几件商品,然后关闭商城,访问京东商城的时候,购物车内的东西还有,这是怎么做到的?实际上这是一种Cookie的应用手段,后台服务器将这些商品的ID存储到了Cookie中,然后保存到了我们的磁盘当中。这样即使关闭浏览器,下次到网站的时候,这时候会自动读取磁盘中的Cookie,拿到商品编号,然后展示购物车中的商品,Cookie可能是这样的CookieId = xxx,yyy,zzz
  • 十天内免登录:保存Cookie到本地的磁盘文件中。 登录成功后,浏览器客户端会保存一个cookie中保存了用户名和密码等信息,这个cookie保存在硬盘文件当中的,十天内有效,在十天内用户再次访问126的时候,浏览器自动提交126关联的cookie给服务器,服务器接收到cookie之后,获取用户名和密码,验证,通过之后,自动登录成功。

Cookie保存在什么地方?

Cookie最终保存在浏览器客户端上,可以保存在运行内存中(浏览器关闭则消失),也可以保存在硬盘文件(永久保存)中

Cookie作用

将会话状态保存在浏览器客户端上,与之相对的有保存在浏览器服务端上的session

Cookie格式

任何一个cookie都是由namevalue组成的,都是字符串

public class Cookie implements Cloneable {}
public Cookie(String name, String value) {}
//构建Cookie(name,value) 
public void setPath(String uri) {this.path = uri; }
//这个方法决定了Cookie将提交给哪个web服务站点,只有对应上了path才会发送对应的cookie
public void setMaxAge(int expiry) {this.maxAge = expiry;}
//设置Cookie的有效期为0,表示该Cookie被删除。删除浏览器上的同名Cookie
//只要这个数值大于0,就会保存在磁盘。
//如果设置为负数,那么就表示该cookie不会被存储到硬盘文件中,但是会被放到浏览器的运行内存中。
//和不调用maxAge()这个方法的效果是一样的。

服务端在生成session的时候,会将对应的cookie传递给客户端,那么是怎么实现这个操作的呢,是通过服务端中的一个方法:

void addCookie(Cookie var1);

这个接口方法实现,它会将JVM底层生成的Cookie对象通过reponse对象发送给浏览器客户端,然后给了客户端之后,浏览器根据存活时间选择保存策略,要么是通过运行时内存保存,要么是通过磁盘保存。甚至根据用户选择的Cookie保存选项来确定是否接收Cookie

关于Cookie关联的路径

假设现在发送的请求路径是localhost:8080/servlet13/cookie/genarate生成的cookie,如果cookie没有设置path,那么关联的路径就是这个请求路径以及它的下级路径localhost:8080/servlet13/cookie/%xxx

public void setPath(String path){}
//这里提交的路径是localhost:8080以后加的东西
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
    System.out.println(cookie);
}
//服务端使用cookie,要注意细节,这个方法有可能会返回null,如果没有提交cookie,那么将会返回null,而不是一个长度为0的数组

Cookie的基本设计是键值对,因此可以通过getName()getValue()的方式来得到相关的数据。


文章作者: 穿山甲
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 穿山甲 !
  目录