Java Cookie和Session

<!–/*! normalize.css v3.0.1 | MIT License | git.io/normalize *//** * 1. Set default font family to sans-serif. * 2. Prevent iOS text size adjust after orientation change, without disabling * user zoom. */html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */}/** * Remove default margin. */body { margin: 0;}/* HTML5 display definitions ========================================================================== *//** * Correct `block` display not defined for any HTML5 element in IE 8/9. * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. * Correct `block` display not defined for `main` in IE 11. */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary { display: block;}/** * 1. Correct `inline-block` display not defined in IE 8/9. * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */audio,canvas,progress,video { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */}/** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */audio:not([controls]) { display: none; height: 0;}/** * Address `[hidden]` styling not present in IE 8/9/10. * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. */[hidden],template { display: none;}/* Links ========================================================================== *//** * Remove the gray background color from active links in IE 10. */a { background: transparent;}/** * Improve readability when focused and also mouse hovered in all browsers. */a:active,a:hover { outline: 0;}/* Text-level semantics ========================================================================== *//** * Address styling not present in IE 8/9/10/11, Safari, and Chrome. */abbr[title] { border-bottom: 1px dotted;}/** * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. */b,strong { font-weight: bold;}/** * Address styling not present in Safari and Chrome. */dfn { font-style: italic;}/** * Address variable `h1` font-size and margin within `section` and `article` * contexts in Firefox 4+, Safari, and Chrome. */h1 { font-size: 2em; margin: 0.67em 0;}/** * Address styling not present in IE 8/9. */mark { background: #ff0; color: #000;}/** * Address inconsistent and variable font size in all browsers. */small { font-size: 80%;}/** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */sub,sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline;}sup { top: -0.5em;}sub { bottom: -0.25em;}/* Embedded content ========================================================================== *//** * Remove border when inside `a` element in IE 8/9/10. */img { border: 0;}/** * Correct overflow not hidden in IE 9/10/11. */svg:not(:root) { overflow: hidden;}/* Grouping content ========================================================================== *//** * Address margin not present in IE 8/9 and Safari. */figure { margin: 1em 40px;}/** * Address differences between Firefox and other browsers. */hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0;}/** * Contain overflow in all browsers. */pre { overflow: auto;}/** * Address odd `em`-unit font size rendering in all browsers. */code,kbd,pre,samp { font-family: monospace, monospace; font-size: 1em;}/* Forms ========================================================================== *//** * Known limitation: by default, Chrome and Safari on OS X allow very limited * styling of `select`, unless a `border` property is set. *//** * 1. Correct color not being inherited. * Known issue: affects color of disabled elements. * 2. Correct font properties not being inherited. * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. */button,input,optgroup,select,textarea { color: inherit; /* 1 */ font: inherit; /* 2 */ margin: 0; /* 3 */}/** * Address `overflow` set to `hidden` in IE 8/9/10/11. */button { overflow: visible;}/** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. * Correct `select` style inheritance in Firefox. */button,select { text-transform: none;}/** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */button,html input[type="button"], /* 1 */input[type="reset"],input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */}/** * Re-set default cursor for disabled elements. */button[disabled],html input[disabled] { cursor: default;}/** * Remove inner padding and border in Firefox 4+. */button::-moz-focus-inner,input::-moz-focus-inner { border: 0; padding: 0;}/** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */input { line-height: normal;}/** * It's recommended that you don't attempt to style these elements. * Firefox's implementation doesn't respect box-sizing, padding, or width. * * 1. Address box sizing set to `content-box` in IE 8/9/10. * 2. Remove excess padding in IE 8/9/10. */input[type="checkbox"],input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */}/** * Fix the cursor style for Chrome's increment/decrement buttons. For certain * `font-size` values of the `input`, it causes the cursor style of the * decrement button to change from `default` to `text`. */input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button { height: auto;}/** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari and Chrome * (include `-moz` to future-proof). */input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box;}/** * Remove inner padding and search cancel button in Safari and Chrome on OS X. * Safari (but not Chrome) clips the cancel button when the search input has * padding (and `textfield` appearance). */input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration { -webkit-appearance: none;}/** * Define consistent border, margin, and padding. */fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em;}/** * 1. Correct `color` not being inherited in IE 8/9/10/11. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */legend { border: 0; /* 1 */ padding: 0; /* 2 */}/** * Remove default vertical scrollbar in IE 8/9/10/11. */textarea { overflow: auto;}/** * Don't inherit the `font-weight` (applied by a rule above). * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */optgroup { font-weight: bold;}/* Tables ========================================================================== *//** * Remove most spacing between table cells. */table { border-collapse: collapse; border-spacing: 0;}td,th { padding: 0;}/* mscore */* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}*:before,*:after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}html { font-size: 62.5%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);}body { /*font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;*/ font-family: 'Helvetica Neue', Helvetica, Arial, 'Microsoft Yahei', sans-serif; font-size: 14px; line-height: 1.42857143; color: #333333;}input,button,select,textarea { font-family: inherit; font-size: inherit; line-height: inherit;}a { color: #428bca; text-decoration: none;}a:hover,a:focus { color: #2a6496; text-decoration: underline;}a:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px;}figure { margin: 0;}img { vertical-align: middle;}/*github.com style (c) Vasily Polovnyov */.hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8;}.hljs-comment,.hljs-template_comment,.diff .hljs-header,.hljs-javadoc { color: #998; font-style: italic;}.hljs-keyword,.css .rule .hljs-keyword,.hljs-winutils,.javascript .hljs-title,.nginx .hljs-title,.hljs-subst,.hljs-request,.hljs-status { color: #333; font-weight: bold;}.hljs-number,.hljs-hexcolor,.ruby .hljs-constant { color: #099;}.hljs-string,.hljs-tag .hljs-value,.hljs-phpdoc,.tex .hljs-formula { color: #d14;}.hljs-title,.hljs-id,.coffeescript .hljs-params,.scss .hljs-preprocessor { color: #900; font-weight: bold;}.javascript .hljs-title,.lisp .hljs-title,.clojure .hljs-title,.hljs-subst { font-weight: normal;}.hljs-class .hljs-title,.haskell .hljs-type,.vhdl .hljs-literal,.tex .hljs-command { color: #458; font-weight: bold;}.hljs-tag,.hljs-tag .hljs-title,.hljs-rules .hljs-property,.django .hljs-tag .hljs-keyword { color: #000080; font-weight: normal;}.hljs-attribute,.hljs-variable,.lisp .hljs-body { color: #008080;}.hljs-regexp { color: #009926;}.hljs-symbol,.ruby .hljs-symbol .hljs-string,.lisp .hljs-keyword,.tex .hljs-special,.hljs-prompt { color: #990073;}.hljs-built_in,.lisp .hljs-title,.clojure .hljs-built_in { color: #0086b3;}.hljs-preprocessor,.hljs-pragma,.hljs-pi,.hljs-doctype,.hljs-shebang,.hljs-cdata { color: #999; font-weight: bold;}.hljs-deletion { background: #fdd;}.hljs-addition { background: #dfd;}.diff .hljs-change { background: #0086b3;}.hljs-chunk { color: #aaa;}#container { padding: 15px;}pre { border: 1px solid #ccc; border-radius: 4px; display: block; background-color: #f8f8f8;}pre code { white-space: pre-wrap;}.hljs,code { font-family: Monaco, Menlo, Consolas, ‘Courier New’, monospace;}:not(pre) > code { padding: 2px 4px; font-size: 90%; color: #c7254e; background-color: #f9f2f4; white-space: nowrap; border-radius: 4px;}–>1.会话技术简介

http协议是无状态的,因此对于服务端来说,当它接收到客户端的http请求时,无法识别这个请求来源于哪个客户端。无状态的协议有优点也有缺点,但对于需要识别客户端甚至是需要记住客户端的业务来说,应当要让http协议”有状态”。

需要记住客户端的业务种类非常多。例如登陆系统,在一个页面登录后,新打开一个该网站页面,应当也保持登录状态。再例如购物车系统,某用户添加商品1后应当保证他还能继续添加商品2,在结算时能够读取购物车中的所有商品。

如何让服务端记住客户端?目前使用最多的是cookie和session两种会话技术。

1.Cookie:数据存储在客户端本地,减少服务器端的存储的压力,安全性不好,客户端可以清除cookie。2.Session:将数据存储到服务器端,安全性相对好,会增加服务器的压力。2.Cookie技术

Cookie技术是将用户的数据存储到客户端的技术,它的作用是为了让服务端根据每个客户端持有的cookie来区分不同客户端。

cookie由cookie name、具有唯一性的cookie value以及一些属性(path、expires、domain等)构成,其中value是区分客户端的唯一依据。

Cookie的原理为:服务端在接收到客户端首次发送的请求后,服务端在响应首部中加入”set-cookie”字段发送给客户端;客户端接收响应后,将cookie信息存储到内存中(如果设置了MaxAge属性,则存储到磁盘中);因为cookie数据在浏览器的内存中,因此无论是哪个页面,客户端再次向服务端发送请求时都能获取该cookie信息,并在请求首部中加入”cookie”字段发送给服务端;服务端借此就可以识别客户端,并从cookie中找到该客户端的信息。

使用Cookie需要解决的两个问题:

(1).服务端怎样将一个Cookie发送到客户端。(2).服务端怎样接受客户端携带的Cookie。2.1 服务器端向客户端发送Cookie

设置Cookie涉及的几个常用方法为:

Cookie(String cookie_name,String cookie_value):构造一个Cookie对象。setPath(uri):当访问属于该uri下的路径(包括子路径)时,该cookie都生效,例如setPath("/Cookie"),当本机使用http://localhost/Cookie/servlet1http://localhost/Cookie/servlet2访问时,都拥有该Cookie。setMaxAge(int second):设置该属性时,cookie将持久化保存到客户端的磁盘中,保存时间为second秒。如果cookie不具有该属性,则cookie只会存放在内存中。setDomain(String domain):设置Cookie生效的域范围,例如cookie.setDomain(".foo.com");,这将对foo.com域下的所有主机都生效(如www.foo.com),但不包括子域(www.abc.foo.com)。

设置好Cookie后,需要使用response的方法addCookie(Cookie cookie)将cookie加入到响应首部中发送给客户端。

例如,以下是名为CooikeDemo工程的一个servlet,该servlet的uri路径为”/cookieservlet”。

import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class CookieServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        Cookie cookie = new Cookie("username","zhangsan");  //构造cookie对象        cookie.setPath("/CookieDemo");       //设置cookie生效的uri范围        cookie.setMaxAge(10*60);             //设置cookie持久到磁盘的时间为10分钟        response.addCookie(cookie);          //在响应首部中加入set-cookie字段并发送给客户端    }protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    doGet(request, response);}

该cookie将会在响应首部加入set-cookie字段发送给客户端:

当客户端再次请求时,将在请求首部中加入cookie字段。

需要注意的几点:

(1).Cookie中不能存储中文。 (2).如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭时cookie信息销毁,这是会话级的cookie。如果设置持久化时间,cookie信息会被持久化到磁盘中,这是持久级别的cookie。持久化后的cookie不会随浏览器关闭而失效,而是在有效时间内都有效。 (3).setPath()设置的生效路径为目录时,则cookie对该目录和子目录下的资源都生效,如果生效路径为文件时,则只对该文件有效。例如:

cookie.setPath("/webapp");  //代表访问webapp应用中的任何资源都携带cookiecookie.setPath("/webapp/cookieservlet");  //代表访问webapp中的cookieservlet时才携带cookie信息

(4).如果想要删除当前还有效的cookie信息,可以使用同名同路径的持久化时间为0的cookie进行覆盖。这样一来,每次客户端接收到响应后cookie就立即失效,也就无法携带cookie请求服务端。例如删除上面示例的cookie信息

Cookie cookie = new Cookie("username","zhangsan");cookie.setPath("/CookieDemo");cookie.setMaxAge(0);response.addCookie(cookie);

2.2 服务器端接受客户端携带的Cookie

如前面的图中所示,客户端的cookie信息是以请求头的方式发送到服务器端的。因此服务端要获取cookie信息,需要使用request对象中的方法getCookies()。这时唯一的获取cookie的方法,它返回的是Cookie数组集合,因此需要遍历该数组才能获取指定名称的cookie。

例如,获取cookie name为”username”的cookie。

Cookie[] cookies = request.getCookies();if(cookies != null) {    for (Cookie coo : cookies) {        String cookie_name = coo.getName();        if (cookie_name.equals("username")) {            String cookie_value = coo.getValue();            System.out.println(cookie_name+":"+cookie_value);        }    }}

3.Session技术

从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程(释放浏览器内存),成为一次会话。除了Cookie技术可以让服务端在一次会话过程中记住客户端,Session技术也可以达到这样的目的。

Session技术将数据存储在服务器端,它会为每个客户端都创建一块内存空间存储客户端数据,并为客户端分配一个存储在cookie中的JSESSIONID,客户端需要每次都携带一个这个ID,服务器通过这个ID可以找到属于该客户端的内存空间。由于这个标识ID是借助Cookie存储的唯一性标识JSESSIONID,因此Session是基于Cookie来实现的。

Session的原理:服务端接收到某客户端首次发送的请求后,为此客户端生成一个session,并分配一段属于该session的缓冲区,同时将该session配对的标识号JSESSIONID作为cookie的name添加到响应首部中返回给客户端;客户端下次访问时,请求首部中将携带该JSESSIONID,服务端将根据该JSESSIONID寻找与之配对的session,如果能找到对应的session,则直接操作该session资源,否则将重新为此JSESSIONID分配一个session和对应的缓冲区。

使用Session技术需要解决如下三个问题:

(1).怎样获得属于某客户端的session对象(内存区域)?(2).怎样向session中存取数据?(3).session对象的生命周期?3.1 获得Session对象

服务端通过客户端发送cookie中的JSESSIONID区分客户端,可以通过请求包中的这个信息来获取该客户端相关的session信息。

HttpSession session = request.getSession();

此方法有两个作用:

(1).从cookie中获取JSESSIONID,并寻找是否存在该ID对应的session对象。如果存在,则获取该session对象。(2).如果该客户端没有发送JSESSIONID或JSESSIONID和服务端记录的ID值不匹配,则为该JSESSIONID重新分配一个session对象。

实际上就是根据JSESSIONID判断该客户端是否在服务器上已经存在session了,有则用之,无则分配之。

3.2 向session中存取数据(session也是一个域对象)

session也是一个域对象,session域的作用范围是整个session,可以对客户端的多次请求生效。该范围小于context域(即application域),大于request域(只在一次请求内有效)。

作为域对象,session对象也同样具有如下三个方法:

session.setAttribute(String name,Object obj);session.getAttribute(String name);session.removeAttribute(String name);

此外,可以通过session对象的getId()方法获取到该session的JSESSIONID值。

3.3 Session对象的生命周期创建:第一次执行request.getSession()时创建。当客户端访问带有getSession()方法的servlet时会执行该方法并创建session,访问jsp页面也会,因为jsp默认设置session=true会创建session。但访问静态资源(html/pic)等不会,因为输出这些静态数据的默认servlet不执行getSession()。销毁:1.服务器(非正常)关闭时。2.session过期/失效(默认30分钟,这个默认时间可以在web.xml中修改)。

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

需要注意的是失效时间的起算点,即从何时开始计算30分钟?从不操作服务器端的资源开始计时(即从最近一次读取session数据开始)。3.手动销毁session:session.invalidate();

也就是说,客户端在一次会话中任何资源都共用一个session对象。

问题:浏览器关闭,session就销毁了吗?不对,session存储在服务端,和客户端没多大关系,只要客户端没有操作session,等一段时间后,session自动销毁。但是,关闭浏览器后,cookie中的JSESSIONID就丢失了,也就无法再找到对应的session数据。可以在发送session给客户端前将jsessionid当成cookie的属性并配置cookie的持久化时间持久化到客户端磁盘,这样再次打开浏览器时jsessionid就不会丢失。代码大致如下:

HttpSession session = request.getSession();session.setAttribute("username","Tom");String id = session.getId();                  //获取JSESSIONID值Cookie cookie = new Cookie("JSESSIONID",id);  //"JSESSIONID"为固定值cookie.setPath("/CookieDemo");cookie.setMaxAge(12*60*60);   //JSESSIONID持久化保存12小时response.addCookie(cookie);response.getWriter().write("JSESSIONID:"+id);System.out.println(session.getAttribute("username"));

注:若您觉得这篇文章还不错请点击右下角推荐,您的支持能激发作者更大的写作热情,非常感谢!

但我自信,我能点亮心烛,化解心灵的困惑。

Java Cookie和Session

相关文章:

你感兴趣的文章:

标签云: