美文网首页
Servlet学习5 -- cookie和session

Servlet学习5 -- cookie和session

作者: 张氏小毛驴 | 来源:发表于2022-04-13 15:03 被阅读0次

一.会话技术

  1. 基本概念

    会话就类似于正常生活中的双方打电话,有一方拿起手机,拨号,另一方接听,然后进行通话,最后结束电话,在web端,就是客户端(浏览器)发出请求,服务器收到请求,发回响应,最后关闭浏览器,在这段时间内产生的多次请求和响应,合起来就叫做浏览器和服务器之间的一次会话

  2. 功能

    在一次会话中的多次请求间共享数据。

    比如记录用户登陆信息,有些网站在用户第一次登陆时会显示“欢迎来到本网站”,当第二次登入时,则会显示“欢迎回来”,为什么服务器能知道用户已经登录过该页面?原因就是在于服务器会话时保存了一些数据,服务器通过这些数据来判断是否登陆过,从而做出不同的响应。

  3. 分类

    • 客户端会话技术:Cookie
    • 服务器端会话技术:Session

二.Cookie

  1. 概述

    Cookie技术是一种会话数据管理技术,是把会话数据保存在客户端的

    可以简单理解为是服务器存储在浏览器的一些数据,比如访问某一个网站时会记住用户名,当下一次访问同一个网站时候,服务器会主动去查询这个cookie,如果存在则做相关操作,比如记住密码等。

  2. 工作原理

    Cookie的工作原理分为几步:

    • 首先浏览器会向服务器发出请求
    • 服务器会根据需要生成一个Cookie对象,将数据保存在该对象中。
    • 然后服务器将这个Cookie对象放在响应头中,发送给浏览器
    • 浏览器收到服务器响应后,将该Cookie保存在浏览器端
    • 当浏览器下一次访问那个服务器时,就会把这个Cookie作为请求头一并发给服务器
    • 服务器从请求头中提取出Cookie,判断里面的数据,再做相应的处理。
  3. Cookie的快速使用

    • 使用步骤

      1. 创建Cookie对象,绑定数据。使用new Cookie(String name,String value)
  4. 发送Cookie对象。使用response.addCookie(Cookie cookie)

    1. 服务器获取Cookie,拿到数据。使用Cookie[] request.getCookies()

首先,服务器创建Cookie,并发送给客户端

@WebServlet("/CookieServlet")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建Cookie对象
        Cookie cookie = new Cookie("name", "zhangsan");
        // 发送Cookie
        response.addCookie(cookie);
    }
}

使用浏览器访问CookieServlet,查看响应头,此时cookie作为一个响应头发送了过来,如下图

然后接着用浏览器再次访问服务器,查看请求头,如下图

可见,浏览器会将cookie作为请求头发送给服务器,这时服务器可以接收cookie,再做相应处理,下面加上相关代码

@WebServlet("/CookieServlet")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建Cookie对象
        Cookie cookie = new Cookie("name", "zhangsan");
        // 发送Cookie
        response.addCookie(cookie);

        // 获取cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie c : cookies) {
            System.out.println(c.getName() + ":" + c.getValue());
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

服务器会打印出:name:zhangsan

  1. Cookie常用api

    • 创建Cookie对象

      Cookie(String name, String value)

    • 设置Cookie对象

      setPath(String url):设置cookie的有效路径,也就是指定该cookie访问哪个资源时会发送,其他资源不会发送。

      setMaxAge(int expiry):设置cookie的有效时长,单位为秒。

      setValue(String newValue):设置cookie的值。

    • 发送Cookie对象

      addCookie(Cookie cookie)

    • 接收浏览器的Cookie

      Cookie[] getCookies()

  1. Cookie一些细节

    • 一次可不可以发送多个Cookie?

      可以。创建多个cookie对象,多次使用addCookie发送即可。

    • cookie在浏览器的保存时间

      默认情况下,浏览器关闭后,cookie数据被销毁;

      要持久化存储,需要使用方法setAge(int expiry)

      1. 参数为正数:将Cookie数据写到硬盘的文件中,持久化存储,指定cookie的存货时间,时间到了,cookie文件会失效。
      2. 参数为负数:默认值,即浏览器关闭后,会销毁cookie。
      3. 参数为零:删除cookie数据。
    • cookie能否存储中文?

      1. 在tomcat 8 之前,cookie不能直接存储中文数据,需要将中文数据转码。(使用URL编码)
      2. 在tomcat 8 之后,cookie支持中文数据存储,但不支持特殊字符。

      建议还是使用URL编码存储,再用URL解码,避免发生错误。

    • cookie共享问题

      1. 假设在一个tomcat服务器中,部署了多个web项目,那这些web项目中cookie能不能共享?

        默认情况下是不能共享的。

        如果需要共享,可以设置cookie的获取范围,使用setPath(String path)

        如果要共享,可以将path设置为'/'

      2. 不同tomcat服务器间cookie的共享问题。

        可以使用setDomain(String path),设置域名,如果设置一级域名相同,那么多个服务器之间cookie可以共享。

        比如:setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com可以共享cookie。

  2. cookie的特点和作用

    • 特点
      1. cookie存储在客户端浏览器中。
      2. 浏览器对于单个cookie的大小有限制,最大为4kb。
      3. 同一域名下的总cookie数量有限制,最大为20个。
    • 作用
      1. 一般用于存储少量,不太敏感的数据。
      2. 可以完成对客户端的身份识别
  3. 小程序——记录上次访问的时间

    需求:访问一个servlet,如果是第一次访问,则提示"你好,欢迎来到本网站",如果不是第一次访问,则提示"欢迎回来,您上次访问时间为:xxxxx"

    @WebServlet("/CookieTest")
    public class CookieTest extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 设置编码
            response.setContentType("text/html;charset=utf-8");
            boolean flag = false;
            // 获取Cookie
            Cookie[] cookies = request.getCookies();
            if (cookies != null && cookies.length > 0) {
                for (Cookie c: cookies) {
                    if (c.getName().equals("lastTime")) {
                        flag = true;
                        // 不是第一次登录,设置当前时间,重新发送cookie
                        Date date = new Date();
                        SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                        String str_date = sf.format(date);
                        // URL编码,避免乱码
                        str_date = URLEncoder.encode(str_date, "utf-8");
                        c.setValue(str_date);
                        // 设置Cookie存活时间
                        c.setMaxAge(60 * 60 * 24 * 7); // 一周
                        // 发送cookie
                        response.addCookie(c);
    
                        // 响应部分
                        String value = c.getValue();
                        value = URLDecoder.decode(value, "utf-8");
                        response.getWriter().println("<h1>欢迎回来,上次访问时间为:" + value + "</h1>");
    
                        break;
                    }
                }
            }
            // 第一次访问
            if(cookies == null || cookies.length == 0 || flag == false) {
                // 设置Cookie
                Date date = new Date();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                String str_date = sf.format(date);
                // 编码
                str_date = URLEncoder.encode(str_date, "utf-8");
                Cookie cookie = new Cookie("lastTime", str_date);
                // 设置存活时间
                cookie.setMaxAge(60*60*24*7);
                response.addCookie(cookie);
                // 响应
                response.getWriter().println("<h1>您好,欢迎首次访问</h1>");
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    

执行结果如下:

第一次访问时:

第二次访问:

三.Session

  1. 概述

    Session是另一种会话管理技术,Session将数据保存在服务器端

    Session和Cookie同样是会话管理技术,但一般使用Session,主要是Cookie存在以下局限性:

    • Cookie的数据类型是String的,而且大小由限制
    • Cookie不适合存储敏感数据

    而Session可以解决以下两个问题。

  2. 工作原理

    Session的实现是依赖于Cookie的。

    Session工作分为以下几步:

    • 浏览器发送请求到服务器。
    • 服务器会根据需要生成Session对象,并且给这个对象一个ID,一个ID对应一个Session对象。
    • 服务器把数据封装到这个Session对象,然后把Session对象保存在服务器端。
    • 服务器将Session对象的ID,存放到Cookie中,作为响应发给浏览器
    • 浏览器接收到这个Cookie,会保存起来,下一次请求服务器时,会将这个Cookie作为请求头发给服务器。
    • 服务器拿到这个Cookie后,取出内容,就是Session对象的ID,然后通过这个ID找到Session对象,取出数据。
  3. Session的相关API

    • 获取HttpSession对象

      HttpSession session = request.getSession()

    • 使用HttpSession对象

      Object getAttribute(String name)

      void setAttribute(String name, Object value)

      void removeAttribute(String name)

    • 其他

      获取Session对象的ID:String getId()

      设置session对象的有效时间:void setMaxInactiveInterval(int interval)

      销毁session对象:void invalidate()

  4. Session的一些细节

    • 当客户端关闭后,服务器不关,两次获取的Session是否同一个?

      默认情况下不是同一个。

      如果需要是同一个,则可以通过创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化存储。

      因为session的实现是依赖于cookie的,并且cookie中保存的是session的id。

    • 客户端不关闭,服务器关闭后,两次获取的session是否同一个?

      不是同一个。

      但为了确保数据不丢失,tomcat会自动完成以下工作:

      • session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上
      • session的活化:在服务器启动之后,将session文件转化为内存中的session对象

      (IDEA不支持这种操作,因为每次用idea重启tomcat时候,会自动删除catalina_base中的work目录,这样session的序列化文件会被删除)

    • Session什么时候被销毁?

      1. 服务器关闭

      2. session对象调用invalidate()

      3. session默认失效时间:30分钟

        选择性配置修改web.xml

        <session-config>
            <session-timeout>30</session-timeout>
        </session-config>
        
  5. session的特点

    • session用于存储一次会话的多次请求的数据,数据保存在服务器端
    • session可以存储任意类型,任意大小的数据
  6. Session与Cookie的区别

    • session数据存储在服务器端,cookie数据存储在客户端
    • session没有数据大小限制,cookie有
    • session数据安全,cookie相对不安全
  7. Session小练习

    • 需求

      使用session实现记录上次访问的时间,需求与Cookie中的练习一致。

    • 代码实现

      @WebServlet("/SessionTest")
      public class SessionTest extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 设置编码
              response.setContentType("text/html;charset=utf-8");
      
              // 获取session
              HttpSession session = request.getSession();
              if (session != null && session.getAttribute("Last_Time") != null) {
                  // 不是第一次登录,设置当前时间,
                  Date date = new Date();
                  SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                  String str_date = sf.format(date);
                  // URL编码,避免乱码
                  str_date = URLEncoder.encode(str_date, "utf-8");
                  session.setAttribute("Last_Time",str_date);
      
                  // 响应
                  String value = (String)session.getAttribute("Last_Time");
                  value = URLDecoder.decode(value, "utf-8");
                  response.getWriter().println("<h1>欢迎回来,上次登录时间为:" + value + "</h1>");
              } else {
                  // 第一次登录
                  Date date = new Date();
                  SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                  String str_date = sf.format(date);
                  // URL编码,避免乱码
                  str_date = URLEncoder.encode(str_date, "utf-8");
                  session.setAttribute("Last_Time",str_date);
      
                  // 响应
                  String value = (String)session.getAttribute("Last_Time");
                  value = URLDecoder.decode(value, "utf-8");
                  response.getWriter().println("<h1>您好,欢迎首次登录</h1>");
              }
          }
      
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              doPost(request, response);
          }
      }
      

相关文章

网友评论

      本文标题:Servlet学习5 -- cookie和session

      本文链接:https://www.haomeiwen.com/subject/rnqsjrtx.html