json session cookie介绍和使用

Session和Cookie的作用都是为了保持访问用户与后台服务器的交互状态。

但它们各有优缺点:
使用Cookie传递信息时,随着Cookie的个数的增多和访问量的增大,它占用的带宽也很大。所以有大的访问量时,都希望用Session,但Session的弱点在于不易在多台服务器之间共享。这也限制了Session的使用。


 

Cookie的介绍和使用:

cookie的作用是当用户通过http访问一个服务器时,这个服务器会将一些key/value键值对返回给客户端浏览器,并给这些数据加上限制条件,在条件符合时用户下次访问服务器时,数据又被完整地带回服务器。

当初W3C在设计 Cookie时实际上考虑的是为了记录用户在一段时间内访问web应用的行为路径。由于Http协议是一种无状态协议,当用户的一次访问请求结束后,后端服务器就无法知道下一次来访问的还是不是上次访问的用户,在设计应用程序时,我们很容易想到两次访问是同一人访问与不同的两个人访向对程序设计和性能来说有很大的不同。例如,在一个很短的时闻内,如果与用户相关的数据被频繁访问,可以针对这个数据做缓存,这样可以大大提高数据的访问性能。 Cookie的作用正是在此,由于是同一个客户端发出的请求,每次发出的请求都会带有第一次访问时服务端设置的信息,这样服务端就可以根据 Cookie值来划分访问的用户了。

Cookie的两个版本:version0 和 version1:

以上两个版本的 Cookie中设置的Head的标识符是不同的,我们常用的是Set-Cookie: userName=“ junshan”;Domain=“xulingbo.net”,这是 Version 0的形式,针对 Set-Cookie2是这样设置的: SetCookie2:userNames=“ junshan"; Domain=“ xulingbo.net”;Max-Age=1000。但是在 Java Web的Servlet规范中并不支持 Set- Cookie2响应头,在实际应用中 Set-Cookie2的一些属性项却可以设置在 Set-Cookie中,如这样设置: Set-Cookie:userName=“ junshan”; Version=“1”;Domain=“xulingbo net ”; Max-Age=1000。

cookie怎么工作:

  当我们用下方式创建cookie时:

cookie是怎样加到http的header中的,看看tomcat创建响应头的时序图:

  从图10-1中可以看出,真正构建 Cookie是在 org.apache.catalina.connector. Response

类中完成的,调用 generateCookieString方法将cookie对象构造成一个字符串;构造的字

符串的格式如 userName=“ junshan"; Version=“1”; Domain=“ xulingbo. net"; Max-Age=1000。

然后将这个字符串命名为 Set- Cookie添加到 MimeHeaders中。

  在这里有几点需要注意:

  • 创建的 Cookie的NAME不能和 Set-Cookie或者 Set-Cookie2的属性项值一样,如果一样会抛 IllegalArgument Exception异常。
  • 创建 Cookie的NAME和 VALUE的值不能设置成非ASSIC字符,如果要使用中文,可以通过 URLEncoder将其编码,否则将会抛 llIegalArgumentException异常。
  • 当NAME和 VALUE的值出现一些 TOKEN字符(如“\”、“,”等)时,构建返回头会将该 Cookie的 Version自动设置为1
  • 当该 Cookie的属性项中出现 Version为1的属性项时,构建HTTP响应头同样会将 Version设置为1。

  当我们通过 response.addCookie创建多个 Cookie时,这些 Cookie最终是在一个 Header项中还是以独立的 Header存在的,通俗地说也就是我们每次创建 Cookie时是否都是创建一个以NAME为 Set-Cookie的 Mimeheaders?答案是肯定的,从上面的时序图中可以看出每次调用 addCookie的时候,最终都会创建一个Header,但是我们还不知道最终在请求返回时构造HTTP响应头是否将相同Header标识的set- Cookie值进行合并。

  Tomcat构造的Http响应头代码,这段代码位于org.apache.coyote.http11.Http11Processor类的propareResponse的方法中,如下所示:

  可以看出在构建Http返回字节流是将Header中所有的项顺序地写出,而没有进行任何修改。所以浏览器在接收HTTP协议返回的数据时是分别解析每一个Header项的。

使用cookie的限制:


 

Session的介绍和使用:

  前面己经介绍了 Cookie可以让服务端程序跟踪每个客户端的访问,但是每次客户端

的访问都必须传回这些 Cookie,如果Cookie很多,这无形地增加了客户端与服务端的数

据传输量,而 Session的出现正是为了解决这个问题。

  同一个客户端每次和服务端交互时,不需要每次都传回所有的 Cookie值,而是只要传回一个ID,这个ID是客户端第一次访问服务器的时候生成的,而且每个客户端是唯一的。这样每个客户端就有了一个唯一的ID,客户端只要传回这个ID就行了,这个ID通常是NANE为 JSESIONID的一个 Cookie。

session与cookie

  下面详讲Session如何基于cookie来工作,实际上有三种方式能可以让 Session正常工作:

  • 基于 URL Path Parameter,默认支持。
  • 基于Cookie如果没有修改 Context容器的 cookies标识,默认也是支持的。
  • 基于SSL,默认不支持,只有connector.getAttribute("SSLEnabled")为TRUE时才支持

  第一种情况下,当浏览器不支持cookie功能时,浏览器会将用户的 SessionCookieName重写到用户请求的URL参数中,它的传送格式如 /path/Servlet;name =value;name2-value2.Name3=value3,其中“ Servlet:”后面的K-V就是要传递的 Path Parameters,,服务器会从这个 Path Parameters中拿到用户配置的 SessioncookieName,关于这个 SessioncookieName,

如果在 web.xml中配置 session-config 配置项,其 cookie-config下的name属性就是这个SessionCookieName值。如果没有配置了session-config配置项,默认的 SessionCookieName就是大家熟悉的“ JSESSIONID”。需要说明的一点是,与 Session关联的 Cookie与其他Cookie没有什么不同。接着 Reques根据这个 SessionCookieName到 Parameters中拿到Session ID并设置到 request.setRequestedSessionld 中。

  请注意,如果客户端也支持 Cookie,Tomcat仍然会解析Cookie的 Session ID,并会覆盖URL中的Session ID

  如果是第三种情况,將会根据 javax.servlet,request.ssl_session属性值设置 Session Id

Session如何工作:

  有了 Session id服务端就可以创建HTTPSession对象了,第一次触发通过request. getSession()方法,如果当前的 Session ID没有对应的 Httpsession对象,那么就创建一个新的,并将这个对象加载到org.apache.catalina.Manager的 Sessions容器中保存。Manager类将管理所有 Session生命周期,Session过期将被回收,服务器关闭, Session将被序列化到磁盘等,只要这个HttpSession对象存在,用户就可以根据 Session ID来获取这个对象,也就达到了状态的保持。

Session相关类图如图所示:

  • Session工作的时序图:

  可以看到从Request中获得的Session对象保存在org.apache.catalina.Manager类中,它的实现类是rg.apache.catalina.session.StandarManager,通过requestedSessionId从StandarManager的session集合中取出StandardSession对象。由于一个requestedSessionId对应一个访问的客户端,所以一个客户端就对应一个StandaSession对象,正是我们保存创建的Session值的。

 

 

   StandardManager类负责 Servlet容器中所有的 StandardSession对象的生命周期管理。当 Servlet容器重启或关闭时 StandardManager负责持久化没有过期的StandardSession对象,它会将所有的 StandardSession对象持化到一个以 "SESSIONS.ser"为文件名的文件中,到 Servlet容器重启时,也就是 StandardManager初始化时,会重新读取这个文件解析出所有 Session对象,重新保存在 StandardManager的sessions集合中。 

  当 Servlet容器关闭时 StandardManager类会调用 unload方法将 sessions集合中的StandardSession对象写到“ SESSIONS.ser”文件中,然后在启动时再按照主面的状态图重新恢复,注意要持久化保存 Servlet容器中的 Session对象,必须调用 Servlet容器的stop和 start命令,而不能直接结束( kill) Servlet容器的进程,因为直接结束进程, Servlet容器没有机会调用 unload方法来持久化这些 Session对象。另外, StandardManager中的 sessions集合中的 StandardSession对象并不是永远保存的,否则 Servlet容器的内存将很容易被消耗尽,所以必须给每全 Session对象定义一个有效时间,超过这个时间 Session对象将被清除,在 Tomcat中这个有效时间是60( maxInactiveInterval属性控制)秒,超过60秒该 Session将会过期。检查每个 Session是否失效是在 Tomcat的一个后合线程中完成的 backgroundProcessO方法中)。

  除了后台进程检查 Session是否失效外,当调用 request.getSession()时也会检查该Session是否过期,值得注意的是, request.getSession()法调用的 StandardSession永远都会存在,即使与这个客户端关联的Session对象已经过期。如果过期,又会重新创建一个全新的 StandardSession对象,但是以前设置的Session值将会丢失。如果你取到了Session对象但是通过 Session.getAttribute取不到前面设置的Session值,请不要奇怪,因为很可能它已经失效了,请检查一下 <Manager pathname” maxInactiveInterval="60"/>中maxlnactiveInterval 的配置项的值,如果不想让Session过期可以设置为-1,但是你要仔细评估一下,网站的访问量和设置的 Session的大小,防止将你的 Servlet容器内存撑爆。如果不想自动创建 Session对象,也可以通过 reques.getSession( boolean create)方法来判断该客户端关联的 Session对象是否存在。


 

 参考:

深入分析JavaWeb(修订版)   _许令波著

posted @ 2019-04-05 14:34  小小宣  阅读(1099)  评论(0编辑  收藏  举报