zoukankan      html  css  js  c++  java
  • 深入Session2

    一、分布式环境Session的处理方法

    分布式环境下要保持会话跟踪最简单的方式是只依靠客户端Cookie保存,不过大多数情况下还需要用到Session,一般的处理方式如下:

    1、Session复制

    每个web服务器有新session时都传递复制到其它的web服务器,所有的web服务器上都保留有所有的Session信息。此方法简单、能保证可靠性,但会增大网络带宽压力,如果session数量大,也会占用Web服务器资源。

    2、Session绑定或粘性Session

    用户初次访问某个web服务器产生session后,只在该web服务器中保存session,后面所有该用户的访问都定向到这台服务器上。此方法也简单,不会占用多余带宽和web服务器资源,但一旦某台web服务器故障,就会导致它上面的所有用户session数据丢失。

    3、Session集中存储

    所有Web服务器的session的数据统一保存在数据库、共享文件或分布式存储中,一般多是保存在分布式存储中,所有web服务器都集中存取Session。此方法可解决上面两种方法的缺点,但实现稍复杂,读写Session 数据引入了网络操作,这相对于本机的数据读取来说,存在时延和不稳定性,不过我们的通信基本都是发生在内网,问题不大。如果集中存储Session 的机器或者集群有问题,就会影响我们的应用。

    二、Session实现基于Cookie或Url重写

    第一次请求时web服务端会同时做url重写和Cookie写入SessionId操作(Java类服务器会如此处理),下次请求时会优先从Cookie中获取sesseionID,若存在后面请求就不会再做url重写。

    我们都知道session的实现主要两种方式:cookie与url重写,而cookie是首选(默认)的方式,因为各种现代浏览器都默认开通cookie功能,但是每种浏览器也都有允许cookie失效的设置。
    由于浏览器默认启动cookie功能,而且普通客户一般都不会取消cookie功能。久而久之,我们写代码的时候,也就不会在意session的具体实现,其实这里面还是有很多值得注意的地方,尤其在用户取消cookie功能的情况下。
    一 servlet session实现与接口简要介绍:
    servlet规范规定实现session的cookie名称强制为jsessionid(在servlet 3.0 可以自定义了),在浏览器第一次请求的时候,服务器产生一个唯一的id,并把这个id设置给一个名为jsessionid的cookie,然后再通过reponse的addcookie,输出到浏览器端。其实这些东西我们都可以通过debug模式下的去查看服务器,来验证这些内容;或者用http协议拦截器来查看,因为servlet的所有接口也都是基于http协议的
    由于服务器没发现浏览器没提供任何cookie,服务器不知道是浏览器未提供cookie的原因:可能是cookie功能取消了,也可能是第一次访问。所以服务器生成一个名为jsessionid的cookie,用Set-Cookie来把cookie推给浏览器;并且,服务器的servlet在生成html页面的时候需要用reponse.encodeURL方法来编码url,该方法其实就是用来实现url重写功能的,这是因为浏览器可能是因为取消cookie功能,而未提供cookie的。服务器为了确保下次提交成功,必须确保生成给浏览器端的url带有jsessionid。
    若cookie功能没取消,则浏览器浏览器第二次请求:
    POST /cxt/login.do;jsessionid=3EF0AEC40F2C6C30A0580844C0E6B2E8 HTTP/1.1
    Cookie: JSESSIONID=3EF0AEC40F2C6C30A0580844C0E6B2E8;
    ...
    浏览器的下一次请求的时候用http的Cookie属性把当前domain的Cookie都推给服务器,来表明自己的身份。这次,服务器知道浏览器支持cookie功能,servlet不需要再使用reponse.encodeURL来编码url了
    1.既然浏览器可能被取消cookie功能,那么我们输出给客户端的代码中必须要支持url重写功能,分几种情况解释
    假如纯粹用jsp/servlet来写,那么我们必须手动用reponse.encodeURL来编码每一个url,包括<a>的href,form的action,或者其他href
    2.使用其它web框架的话,最好消息使用框架提供的输出href功能,否则会有匪夷所思的结果。
    比如用struts,若struts单独提供了一个tag来实现html:rewrite,比如<html:rewrite action='logout'/>,在没有jsessionid cookie的情况下,最后会生成http://localhost:8080/ctx/logout.do;jsessionid=0916FB057C169069;若有jsessionid cookie,则会生成http://localhost:8080/ctx/logout.do。但是我们还注意到html:rewrite还有一个href属性,假如我们用href属性的话,则struts不会生成带有jsessionid参数。
    struts中提供url重写的功能的还有html:link与html:form,比如<html:link action="logout">logout</html:link>,这个tag功能与html:rewrite相似,也有href属性,生成带有<a>标签的html内容。<html:form action="/Login"></html:form>,html:form没有href属性,只有action属性。
    3.假若没有使用任何框架,则可以使用jstl提供的url重写功能
    jstl提供了标签来实现c:url,比如<c:url value="logout.do" />,这个也会根据浏览器是否支持cookie,来生成带有jsessionid属性的url。
    相信通过上面的总结,是我们对怎么使用session与cookie有更深入的认识。记住,在用jsp/servlet实现系统的时候,尽量不要自己写<a>标签,最好使用系统框架自带的标签来实现,否则浏览器取消cookie功能的话,系统不支持url重写功能。
    http://3237526.blog.51cto.com/3227526/1641971

    在Spring MVC当使用RedirectView或者"redirect:"前缀来做重定向时,Spring MVC最后会调用:
    response.sendRedirect(response.encodeRedirectURL(url));

    对于IE来说,打开一个新的浏览器窗口,第一次访问服务器时,encodeRedirectURL()会在url后面附加上一段jsessionid,如果初始的url为"http://www.sina.com.cn",最终得到的url为"http://www.sina.com.cn;jsessionid=2jcligmgi6fh"。

    这是典型的Java做事的方式,其他语言的服务器端平台并不会这样做。这个jsessionid很多时候会引起严重的问题,例如,如果你使用上述带有jsessionid的url直接访问新浪的网站,IE会向你报告:找不到服务器。

    解决方法:
    1. 不通过Spring MVC做重定向,自己直接调用:
    response.sendRedirect(url);
    return null; //告诉Spring MVC我已经完成了处理

    2. 修改Spring MVC的代码,将:
    response.sendRedirect(response.encodeRedirectURL(url));
    改为:
    response.sendRedirect(url);

    3. encodeRedirectURL()仅在无法确定浏览器是否支持cookie的时候才会在url后面附加上jsessionid,如果它能找到一个jsessionid的cookie,它就认为浏览器是支持cookie的。因此可以自己创建一个jsessionid的cookie来欺骗encodeRedirectURL()。
    Cookie cookie = new Cookie("jsessionid", "2jcligmgi6fh");
    cookie.setMaxAge(Integer.MAX_VALUE);
    response.addCookie(cookie);
    然后再调用Spring MVC的重定向功能就没有问题了:
    return new ModelAndView("redirect:"+url);
    http://blog.csdn.net/tototuzuoquan/article/details/46971843

    response.encodeURL()和response.encodeRedirectURL()。
    这2个方法会判断cookie是否可用,如果禁用了会解析出url中的jsessionid,并连接到指定的url后面,如果没有找到jessionid会自动帮我们生成一个。如果没禁用,则不做处理。
    至于为什么要有2个方法?这2个方法有什么不同?google了一下,说是这2个方法在判断是否要包含jsessionid的逻辑上会稍有不同。
    在调用HttpServletResponse.sendRedirect前,应该先调用encodeRedirectURL()方法,否则可能会丢失Sesssion信息。
    这2个方法的使用方法如:response.sendRedirect(response.encodeURL("/myapp/input.jsp"));。
    如果cookie没有禁用,我们在浏览器地址栏中看到的地址是这样的:/myapp/input.jsp,如果禁用了cookie,我们会看到:/myapp/input.jsp;jsessionid=73E6B2470C91A433A6698C7681FD44F4。
    所以,我们在写web应用的时候,为了保险起见,应该在程序里的每一个跳转url上都使用这2个方法,来保证session的可用性。
    http://www.cnblogs.com/huzi007/p/4137045.html

  • 相关阅读:
    《Linux系统编程(第2版)》
    《深入网站开发和运维》
    《软件定义网络:SDN与OpenFlow解析》
    《大话重构》
    《程序员的修炼——从优秀到卓越》
    《Web性能权威指南》
    自定义项目脚手架- Maven Archetypes
    Intellij修改archetype Plugin配置
    ng-template寄宿方式
    ThoughtWorks持续集成平台GO开源了
  • 原文地址:https://www.cnblogs.com/doit8791/p/7599914.html
Copyright © 2011-2022 走看看