Cookie和session入门到进阶

Cookie的快速入门

Cookie是客户端的传话技术,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问服务器时都会这小分据携带到服务器个人理解cookie是服务器第一次发送过来的仍后浏览器给保存上

相关的API

  • 创建一个Cookie 对象 (cookie只能保存字符串数据,且不能保存中文)

    new Cookie(String name,String value);

  • 把cookie写回浏览器

    ·response.addCookie(cookie);

  • 获取浏览器带过来的所有Cookie

request.getCookies();//得到所有的cookie对象,是一个数组,开发根据key等到目标cookie

  • cookie的API

    cookie.getName();//返回cookie中设置的key

    cookie.getValue;//返回cookie中设置的value

    入门代码

    package itheima.day24_Cookie_session_jsp;
    
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class TestDemo01 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("cookies:::来了一个请求");
            //获取cookis对象
            if (req.getCookies().length!=0){
                Cookie[] cookies = req.getCookies();
                for (Cookie cookie1 : cookies) {
                    //获取所有的cookie
                    if(cookie1.getName().equals("name")){
                        String value = cookie1.getValue();
                        System.out.println(value);
                    }
                }
            }
    
            //New 一个COokie创建一个新的cookie
            Cookie cookie = new Cookie("name","pyb");
            Cookie cookie2 = new Cookie("password","123");
            resp.addCookie(cookie2);
            //写入里浏览器里面去
            resp.addCookie(cookie);
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    

    4.小结

    1. cookie特点

      • Cookie保存在客户端(浏览器端的)
      • 第一次请求的时候, 没有Cookie的, 先由服务器写给浏览器.
      • Cookie里面只能保存字符串, 大小有限制
    2. cookie相关API

      • new Cookie(String name,String value); 创建Cookie
      • response.addCookie(cookie); 把Cookie写给浏览器
      • request.getCookies(); 获得所有的Cookie对象
      • cookie.getName() 获得Cookie的key
      • cookie.getValue() 获得Cookie的value

      Cookie本质是请求头,响应头

为了方便把获取想要的cookis抽出来工具类中

package itheima.beanUntils;

import javax.servlet.http.Cookie;

public class IfCookie {
    /**
     * 从cookie的数组里面查找出来我们想要的目标cookie
     * @param cookies  cookie的数组
     * @param key 想要获取的cookie的名字
     * @return  cookie的对象
     */
    public static String  getCookieUntil(Cookie[] cookies,String key){
        //cookies数组是否为空
        if(cookies!=null){
            for (Cookie cookie1 : cookies) {
                //获取所有的cookie
                if(cookie1.getName().equals("name")){
                    String value = cookie1.getValue();
                   return value;
                }
            }
        }
        return null;
        //如果没有找到就直接返回null
    }
}

知识点-cookis进阶

cookie的有效时长和路径分析
  • 会话级别临时性cookie默认

    在默认的情况下,当浏览器进程结束(浏览器关闭,会话结束)的时候,cookie就会消失。

  • 持久性cookie

    • 设置cookie.setMaxAge(int expiry) 时间是秒

-1:默认。代表Cookie数据存到浏览器关闭(保存在浏览器文件中)。

正整数:以秒为单位保存数据有有效时间(把缓存数据保存到磁盘中)

​  0:代表删除Cookie.如果要删除Cookie要确保路径一致。告诉浏览器,立即删除掉这个cookie .

代码

package itheima.day24_Cookie_session_jsp;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/Demo02")
public class ServletDmo02 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //一个会话进来了
        System.out.println("我进来了");
            //设置一个会话
        Cookie cookie = new Cookie("name", "pyb");
        //这个cookie不设置长度
        response.addCookie(cookie);
        Cookie cookie1 = new Cookie("key","username");
        //设置时间
        cookie1.setMaxAge(60*60*7);
        response.addCookie(cookie1); // 设置有效期,单位是秒   如果是谁知7天

    }

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

cookie有效路径(了解)

setPath(String url); 设置路径

  1. 保证不会携带别的网站/项目里面的cookie到我们自己的项目 不会吧其他servlet设置的cookie带到现在的这个servlet来。
  2. 如果路径不一样, cookie的key可以相同 , 在相同路径下,重复一样的cookie的key,他们的值会覆盖的。
  3. 保证自己的项目可以合理的利用自己项目的cookie
  • 默认路径,例如:

    • 访问http://localhost:8080/web18A_Cookie/demo01; cookie默认路径 /web18A_Cookie

    • 访问http://localhost:8080/web18A_Cookie/aaa/demo01; cookie默认路径 /web18A_Cookie/aaa

    • 访问http://localhost:8080/web18A_Cookie/aaa/bbb/demo01; cookie默认路径 /web18A_Cookie/aaa/bbb

  • 随带Cookie需要的条件: **只有当访问资源的url包含此cookie的有效path的时候,才会携带这个cookie;反之不会. **

  • cookie的路径通常设置 / 或者 /发布项目名设置的有效是 /day30a-cookie. 当前项目下的Servlet都可以使用该cookie. 一般这么设置: cookie.setPath(request.getContextPath());

    只要是当前项目里面的资源 路径必须包含项目名路径.

代码
package itheima.day24_Cookie_session_jsp;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/Demo02")
public class ServletDmo02 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //一个会话进来了
        System.out.println("我进来了");
            //设置一个会话
        Cookie cookie = new Cookie("name", "pyb");
        //这个cookie不设置长度
        response.addCookie(cookie);
        Cookie cookie1 = new Cookie("key","username");
        //设置时间
        cookie1.setMaxAge(60*60*7);
        response.addCookie(cookie1); // 设置有效期,单位是秒   如果是谁知7天

    }

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

cookie保存中文

cookie不能保存中文,但是可以把中文字符经过编码 之后保存后续再经过 解码还原成正常的中文即可

URLEncode.encode(value,"utf-8")//存入的时候通过utf-解码

URLDecode.decode(value,"uft-8")//取出通过utf-解码

代码
package itheima.day24_Cookie_session_jsp;

import itheima.beanUntils.IfCookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Base64;

@WebServlet("/ServletDemo04")
public class ServletDemo04 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //
        System.out.println("进来了一条数据");
        //获取数据 第一种数据方式
      /*  Cookie[] cookies = request.getCookies();
        String name = IfCookie.getCookieUntil(cookies, "name");
        if (name!=null){
            Base64.Decoder decoder = Base64.getDecoder();
            byte[] decode = decoder.decode(name);
            System.out.println(new String(decode));

        }*/
        //第二种方式
         Cookie[] cookies = request.getCookies();
        String name = IfCookie.getCookieUntil(cookies, "name");
        if (name!=null){
            String decode = URLDecoder.decode(name, "utf-8");
            System.out.println(decode);

        }

       /* //第一种方式利用BASe64编码
        Base64.Encoder urlEncoder = Base64.getUrlEncoder();
        String string = urlEncoder.encodeToString("hello".getBytes());
        Cookie cookie = new Cookie("name",string);
        response.addCookie(cookie);*/
       //第二种编码方式
        String en = URLEncoder.encode("你好李焕英", "UTF-8");
        Cookie cookie = new Cookie("name",en);
        response.addCookie(cookie);
    }

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

URLEncode.encode(value,"utf-8");//存入的时候(先通过utf-8编码)
URLDecode.decode(value,"utf-8");//取出 (通过utf-8解码)

接下来我们实现一个小案例,记录用户各自上次访问的时间

package itheima.day24_Cookie_session_jsp;

import itheima.beanUntils.IfCookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.Date;

@WebServlet("/sca")
public class ServletCookieAnli extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //获取值
        Cookie[] cookies = request.getCookies();
        String time = IfCookie.getCookieUntil(cookies, "time");
        if(time!=null){
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
           String value = dateFormat.format(new Date(Long.parseLong(time)));

            response.getWriter().write("<h2>您上一次访问的时间:"+value+"</h2>");
        }

        //完成上次访问时间的小案例
        //首先设置cookies存数据获取时间
        long timeMillis = System.currentTimeMillis();
        Cookie cookie = new Cookie("time",String.valueOf(timeMillis));
        //设置时间长度
            cookie.setMaxAge(60*60*7);
        //存好放入res
        response.addCookie(cookie);
    }

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

知识点-session概述

3.1session概述

​ session是服务器端的技术。服务器为每一个浏览器开辟一块内存空间,即session对象。由于session对象是每一个浏览器特有的,所有用户的记录可以存放在session对象中。同时,每一个session对象都对应一个sessionId,服务器把sessionId写到cookie中,再次访问的时候,浏览器把sessionId带过来,找到对应的session对象

session 是一种基于cookie的会话技术。

session是保存在服务器端的原则上大小是没有限制的,session可以存在基本数据类型,集合对象

入门案例
package itheima.project.colltion;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/demo08")
public class ServletSession extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            
        //获取session
        HttpSession session = request.getSession();
        //可以查看session的id 
        String id = session.getId();
        System.out.println(id);
    }

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

        doPost(request,response);
    }
}

我们不难发现cookies是从服务器拿的然后存到浏览器中和session是从request中拿的存到服务器中

4.小结

  1. session是服务器端的技术, 数据保存在服务器端的
  2. 只有在服务器端调用了requet.getSession()的时候, 才有session产生 ,才会开辟空间
  3. session基于cookie的
    • 创建session的同时 生成sessionId, 服务器自动通过Cookie的方式写给浏览器, 浏览器自己保存
    • 下次的话 浏览器携带cookie(SessionId)找到对应的session使用了

session 的API

  • request.getSession() 获得session(如果第一次调用的时候其实是创建session,第一次之后通过sessionId找到session进行使用)
  • object.getAttribute(String name);获取值
  • void setAttribute(String name, Object value) ;存储值
  • void removeAttribute(String name) ;移除
代码案例
package itheima.day24_Cookie_session_jsp;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取数据
        HttpSession session = request.getSession();
        //设置参数
        session.setAttribute("name","pyb");
        session.setAttribute("password","12344");
        //3. 取数据
        System.out.println("address=" + session.getAttribute("name"));
        System.out.println("className=" + session.getAttribute("password"));

        //4. 删除数据
        session.removeAttribute("name");

    }

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

4.小结

  1. Session基本使用: 作为域对象存取数据 范围: 一次会话(多次请求, 用户各自的) 不同的浏览器session不一样

    • Object getAttribute(String name) ;获取值
    • void setAttribute(String name, Object value) ;存储值 如果存值的话,已经存在了name, name后面一次操作的value值会覆盖前面的value值。
    • void removeAttribute(String name) ;移除
  2. 浏览器关闭了, session使用不了, 是session销毁了吗?

    ​ session没有销毁. 因为关闭浏览器是客户端的行为, session是服务器端里面的一块内存空间。关闭浏览器怎么会影响到session的销毁呢?

    ​ session基于cookie, sessionId保存到cookie里面的, 默认情况下cookie是会话级别,浏览器关闭了cookie就是消失了,也就是说sessionId消失了, 从而找不到对应的session对象了, 就不能使用了.

    ​ 解决: 自己获得sessionId, 自己写给浏览器 设置Cookie的有效时长, 这个Cookie的key必须: JSESSIONID

  3. session的生命周期

    1. 创建:

      ​ 第一次调用getSession()的时候创建

    2. 销毁:

      1. 超时了销毁(session默认有有效期(30分钟),过了有效期就销毁了。) 自动销毁
      2. 手动销毁, 调用方法: invalidate();
      3. 服务器异常关闭: 蓝屏,突然停电...
      4. 关闭服务器,会销毁session吗? 不会销毁里面的数据。下次再启动服务器还是能够拿到以前的数据的。
  4. 面试的问题:

    1. 浏览器关闭,session销毁了吗? 没有

    2. 那么为什么我们打开浏览器之后,访问不到以前的数据了呢? 因为cookie销毁了,cookie里面有session的ID

    3. 如果我希望打开浏览器重新访问之后,还能获取到以前的值,怎么办?

      需要手动设置cookie。

代码案例
package com.itheima.demo2_session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/session04")
public class DemoSession04 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("session04:::来了一个请求~~");


        //赋值然后取值。
        HttpSession session = req.getSession();
        session.setAttribute("username" , "张三");
        System.out.println("sesison04==="+session.getAttribute("username"));

        //如果希望一会关闭浏览器之后,再来访问session05 还能取到04 存的值,那么需要手动设置cookie
        //cookie的name不能乱写! 必须是固定写法!!!!
        Cookie cookie = new Cookie("JSESSIONID" , session.getId());
        cookie.setMaxAge(60*60*24*7);
        resp.addCookie(cookie);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

相信大家都cookies和session有很强的认知了

那我们看一个三个域对象比较、

域对象 创建 销毁 作用范围 应用场景
ServletContext 服务器启动 服务器正常关闭/项目从服务器移除 整个项目 记录访问次数,聊天室
HttpSession 没有session 调 用request.getSession()方法 session过期(默认30分钟)/调用invalidate()方法/服务器异常关闭 会话(多次请求) 验证码校验,保存用户登录状态等
HttpServletRequest 来了请求 响应这个请求(或者请求已经接收了) 一次请求 servletA和jsp(servletB)之间数据传递(转发的时候存数据)

想看钝化的文件的位置,请参考idea里面的日志输出:

Using CATALINA_BASE: "C:\Users\xiaomi\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_8_5_27_javaweb110_3"目录查看

  • 如果是正常关闭服务器,

    把session钝化到服务器磁盘上,再次启动,把磁盘上的文件活化到内存里面

    Session钝化:把内存中的session序列化到硬盘上
    
    Session活化:从硬盘上读取序列化的session到内存中
    

了解就好了

3.2三个域对象怎么选择?

三个域对象怎么选择?

​ 记住一个准则: 够用就好。

​ 一般情况下, 最小的可以解决就用最小的.

​ 但是需要根据情况(eg: 重定向, 多次请求, 会话范围, 用session; 如果是转发,一般选择request)

谢谢小伙伴们,欢迎留言哦

posted @ 2021-03-17 23:29  学海无芽  阅读(97)  评论(0)    收藏  举报