Javaweb之cookie和session

    xiaoxiao2022-06-29  63

    一、会话的概念

      会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。   有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾经来过,这称之为有状态会话。

    二、会话过程中要解决的一些问题

      每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。

    三、保存会话数据的两种技术

    3.1、Cookie机制

      Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

    3.2、Session机制

      session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

      当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否包含了一个session标识-称为sessionID(这个sessionID一般以cookie的形式存储在浏览器中,用户每次请求的时候都会带上,除非是第一次访问),如果已经包含一个session id则说明以前已经为这个客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。

    如果客户请求不包含session id,则服务器会为这个客户创建一个session并且生成一个与此session相关联的session id,这个session id将在本次响应中返回给客户端保存。

    3.3、Cookie机制和Session机制的区别

    1、从存取方式上比较 Cookie中只能保存ASCII字符串,如果需要存取Unicode字符或者二进制数据,需要进行UTF-8GBK或者BASE64等方式的编码。Cookie中也不能直接存取Java对象。若要存储稍微复杂的信息,使用Cookie是比较困难的。 而Session中可以存取任何类型的数据,包括而不限于String、Integer、List、Map等。Session中也可以直接保存Java Bean乃至任何Java类,对象等,使用起来非常方便。可以把Session看做是一个Java容器类。 2、从隐私安全上比较 Cookie存储在客户端浏览器中,对客户端是可见的,客户端的一些程序可能会窥探、复制甚至修改Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的危险。 如果选用Cookie,比较好的办法是,敏感的信息如账号密码等尽量不要写到Cookie中。或者是像Google、Baidu那样将Cookie信息加密,提交到服务器后再进行解密,保证Cookie中的信息只有自己能读得懂。而如果选择Session就省事多了,反正是放在服务器上,Session里任何隐私都可以。 3、从有效期上比较 Cookie能实现信息永久的保存只需要设置CookiemaxAge属性为一个很大很大的数字或者Integer.MAX_VALUE就可以了。如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。

    如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。

    存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。 使用Session理论上也能实现这种效果。只要调用方法setMaxInactiveInterval(Integer. MAX_VALUE)不就可以了么。但是由于Session依赖于名为JSESSIONID的Cookie,而Cookie JSESSIONID的maxAge默认为-1,只要关闭了浏览器该Session就会失效,因此Session不能实现信息永久有效的效果。使用URL地址重写也不能实现。 而且如果设置Session的超时时间过长,服务器累计的Session就会越多,越容易导致内存溢出。 4、从对服务器的负担上比较 Session是保存在服务器端的,每个用户都会产生一个Session。如果并发访问的用户非常多,会产生非常多的Session,消耗大量的内存。因此像GoogleBaiduSina这样并发访问量极高的网站,是不太可能使用Session来追踪客户会话的。他们一般都用加密的cookie来存储用户会话信息。 5、从浏览器支持上比较 Cookie是需要客户端浏览器支持的。如果客户端禁用了Cookie,或者不支持Cookie,则会话跟踪会失效。对于WAP上的应用,常规的Cookie就派不上用场了。 如果客户端浏览器不支持Cookie,需要使用Session以及URL地址重写。需要注意的是所有的用到Session程序的URL都要使用response.encodeURL(String URL)或者response.encodeRedirectURL(String URL)进行URL地址重写,否则导致Session会话跟踪失败。对于WAP应用来说,Session+URL地址重写也许是它唯一的选择。 如果客户端支持Cookie,则Cookie既可以设为本浏览器窗口以及子窗口内有效(把maxAge设为-1),也可以设为所有浏览器窗口内有效(把maxAge设为某个大于0的整数)。但Session只能在本浏览器窗口以及其子窗口内有效。如果两个浏览器窗口互不相干,它们将使用两个不同的Session。 6、从跨域名上比较 Cookie支持跨域名访问,例如将domain属性设置为".helloweenvsfei.com",则以".helloweenvsfei.com"为后缀的所有域名均可以访问该Cookie。跨域名Cookie现在被广泛用在网络中,例如GoogleBaiduSina等。而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。

    四、Cookie使用范例

    4.1、使用cookie记录用户上一次访问的时间

    package com.servlet.study; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * cookie实例:获取用户上一次访问的时间 */ public classCookieDemo1 extends HttpServlet { publicvoiddoGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置服务器端以UTF-8编码进行输出 response.setCharacterEncoding("UTF-8"); //设置浏览器以UTF-8编码进行接收,解决中文乱码问题 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //获取浏览器访问服务器时传递过来的cookie数组 Cookie[] cookies =request.getCookies(); //如果用户是第一次访问,那么得到的cookies将是null if (cookies!=null) { out.write("您上次访问的时间是:"); for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; if (cookie.getName().equals("lastAccessTime")){ Long lastAccessTime =Long.parseLong(cookie.getValue()); Date date = new Date(lastAccessTime); out.write(date.toLocaleString()); } } }else { out.write("这是您第一次访问本站!"); } //用户访问过之后重新设置用户的访问时间,存储到cookie中,然后发送到客户端浏览器 Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");//创建一个cookie,cookie的名字是lastAccessTime //将cookie对象添加到response对象中,这样服务器在输出response对象中的内容时就会把cookie也输出到客户端浏览器 response.addCookie(cookie); } publicvoiddoPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

    第一次访问时这个Servlet时会提示这是您第一次访问本网站,点击浏览器的刷新按钮,进行第二次访问,此时就服务器就可以通过cookie获取浏览器上一次访问的时间了。

       在上面的例子中,在程序代码中并没有使用setMaxAge方法设置cookie的有效期,所以当关闭浏览器之后,cookie就失效了,要想在关闭了浏览器之后,cookie依然有效,那么在创建cookie时,就要为cookie设置一个有效期。如下所示:

    //用户访问过之后重新设置用户的访问时间,存储到cookie中,然后发送到客户端浏览器

    Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");//创建一个cookie,cookie的名字是lastAccessTime

     //设置Cookie的有效期为1天

     cookie.setMaxAge(24*60*60);

     //将cookie对象添加到response对象中,这样服务器在输出response对象中的内容时就会把cookie也输出到客户端浏览器

     response.addCookie(cookie);

      用户第一次访问时,服务器发送给浏览器的cookie就存储到了硬盘上,这样即使关闭了浏览器,下次再访问时,也依然可以通过cookie获取用户上一次访问的时间。

    五、Cookie注意细节

    一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。 如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie

     5.1、Cookie中存取中文

    要想在cookie中存储中文,那么必须使用URLEncoder类里面的encode(String s, String enc)方法进行中文转码,例如:

    Cookie cookie = newCookie("userName", URLEncoder.encode("Cookie测试","UTF-8"));

    response.addCookie(cookie);

    在获取cookie中的中文数据时,再使用URLDecoder类里面的decode(String s, String enc)进行解码,例如:

    URLDecoder.decode(cookies[i].getValue(),"UTF-8")

    六、session使用范例

    6.1、服务器是如何实现一个session为一个用户浏览器服务的?

       服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。可以用如下的代码证明:

    package com.servlet.study; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public classSessionDemo1 extends HttpServlet { publicvoiddoGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF=8"); response.setContentType("text/html;charset=UTF-8"); //使用request对象的getSession()获取session,如果session不存在则创建一个 HttpSession session = request.getSession(); //将数据存储到session中 session.setAttribute("data","Session测试"); //获取session的Id String sessionId = session.getId(); //判断session是不是新创建的 if (session.isNew()) { response.getWriter().print("session创建成功,session的id是:"+sessionId); }else { response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId); } } publicvoiddoPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

    第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了

    6.2、session对象的销毁时机

      session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:

    <?xmlversion="1.0" encoding="UTF-8"?> <web-appversion="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 设置Session的有效时间:以分钟为单位--> <session-config> <session-timeout>15</session-timeout> </session-config> </web-app>

    当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。

    HttpSession session = request.getSession(); //手工调用session.invalidate方法,摧毁session session.invalidate();

     

    转载请注明原文地址: https://ju.6miu.com/read-1125073.html

    最新回复(0)