javaweb入门(二)——Session和Cookie学习01

1.会话

会话:用户点开浏览器,访问了多个web资源,之后关闭浏览器,这一整个过程我们称之为会话。也就是说,一次会话是指从用户打开浏览器到完成使用关闭浏览器

会话分为有状态会话无状态会话
有状态会话:有状态Session则是一种将用户会话状态保存在持久化资源中的对象,例如数据库中。每次请求时,会从持久化资源中获取最新的会话状态,并将会话状态与客户端的Session对象进行关联。
无状态会话:无状态Session是一种不会持久保存用户会话状态的对象,每次请求结束都会重新创建一个Session对象,因此无状态Session的会话状态是临时的。

总而言之,有状态会话是指服务器会存储客户端的信息,以便下次客户端访问时识别。无状态会话不会存储客户端的信息。

2.保存会话的两种技术

保存会话主要有两种技术:cookiesession。保存会话的技术我们也称之为会话跟踪。(我们需要知道的是:Http是一种无状态的协议)

cookiesession的主要区别是:cookie是被存放在客户端(即浏览器)中的,session是存储在服务器之中的

session和cookie常见的应用:我们在bilibili中登录了一次之后,在我们关闭了浏览器结束会话后,下次我们打开bilibili时,不需要再次登录。

关于Cookie

案例:通过cookie获取客户端上次开始会话的时间

为了方便我们的理解,我们接下来针对cookie做一个简单的案例

在此案例中我们将使用cookie完成客户端在访问服务器的时候,服务器将客户端上次访问的日期返回给客户端。

在此案例中,我们做的servlet需要完成的功能:

  1. 获取客户端传来的cookie
  2. 如果客户端传来的cookie中有数据,那么获取cookie中数据,将其输出;如果客户端传来的cookie中没有数据,那么就提示用户是第一次访问。
  3. 将用户此次的访问时间封装到cookie当中
  4. cookie存放在response之中返回给客户端

案例代码:

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;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CookieDemo01 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
//        设置字符集
        req.setCharacterEncoding("UTF-8");
//        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
//        获取输出字符
        PrintWriter out = resp.getWriter();
//        1.获取cookie
        Cookie[] cookies = req.getCookies();
//        2.检查请求中的cookie中是否有数据
        boolean hasCookie = false;
        if (cookies != null){
    
    
            for (Cookie cookie : cookies){
    
    
                if ("loginTime".equals(cookie.getName())){
    
    
//                    cookie中如果有数据,那么就将数据输出
                    out.write("您上次访问的时间是:" + cookie.getValue());
                    hasCookie = true;
                }
            }
        }

        if (!hasCookie){
    
    
//            cookie中没有数据那么就提示用户第一次访问
            out.write("这是您第一次访问本网站!");
        }
//      3.将用户此刻访问的时间田间到cookie之中
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");//需要注意cookie字符串中不可存放空格和一些特殊字符
        String dateFormat = simpleDateFormat.format(date);
        Cookie cookie1 = new Cookie("loginTime",dateFormat);
//        设置cookie的最大存在时间,注意单位是秒
        cookie1.setMaxAge(24*60*60);
//        4.将cookie放入响应之中
        resp.addCookie(cookie1);

    }

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


实现结果:
第一次访问:
在这里插入图片描述
非第一次访问:
在这里插入图片描述
在此次案例之中我们需要注意:cookie中对它存放的字符有限制,其中的字符不可以有空格和方括号等一系列特殊字符

扫描二维码关注公众号,回复: 17811627 查看本文章

从上面这个案例中我们可以知道cookie是客户端传给服务器的,在服务器处理完客户端请求之后,再由客户端传送给服务器。因此,在请求中只有获取cookie的方法,在响应中只有设置cookie的方法。

cookie是保存在客户端本地的。一般是保存在客户端本地的AppData 目录下。

关于cookie的一些需要知道的知识

  1. 一个cookie只能保存一个信息(只能有一对键值对)
  2. 一个web站点可以向客户端发送多个cookie,一般来说客户端最多存放这个站点20个cookie (这个根据浏览器来设置),当存放的cookie超出浏览器限制,那么浏览器会将新的cookie来替换掉最老的cookie;有些浏览器会限制接受该站点的cookie数量,一般是300个。
  3. Cookie的大小有限制,最大为4kb(也就是4096个字节)

关于删除cookie的方法

一般来说我们删除cookie的方法是创建一个和我们要删除的cookie同名的cookie,并且将它的生存周期设置为0,这么一来,新建的cookie就会替代我想要删除的cookie,而新建的cookie在刚替换完之后就会因为生存周期为0而被删除
删除代码:

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 CookieDemo02 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
//        我们删除名字为loginTime的cookie
        Cookie cookie = new Cookie("loginTime","");
        cookie.setMaxAge(0);//设置生存周期为0
        resp.addCookie(cookie);//将cookie添加到响应之中
    }

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

关于Session

关于Session:服务器会给每个用户(浏览器)创建一个Session对象,一个Session独占一个会话,浏览器没有关闭(会话没有结束),Session就会一直存在。

SessionCookie

目前来说,Cookie我们可以把它理解为一个标记,服务器给客户端Cookie作为标记,方便以后的操作中服务器进行辨别。Session我们可以理解为一个数据结构,或者一个数据载体,它可以承载本次会话中需要用到的数据。
一般来说,Cookie中会带有一个Session ID,方便服务器根据传来的Cookie来找到对应的Session,以此来更加方便的辨认出用户。

SessionCookie的关系我们可以通过一个案例来理解:

我们可以用银行卡的例子来更加方便我们来理解。

我们可以把Cookie理解为银行卡,把客户端理解为客户,把服务器理解为银行,把Session理解为此张银行卡在银行中的金额等信息
当用户带着银行卡到银行中时,银行才可以通过银行卡来了解到这个用户的一些信息(比如信用情况,可以取出多少金额);同理,当客户端带着Cookie来访问服务器的时候,服务器才可以根据Cookie来得知客户端的在本网站的一些基本信息。

Session中常用的方法

1.在Session中存储以及读取数据
关于Session中存放数据,我们可以清楚Session不仅可以存放字符串(String)类型的数据同时也可以存放类(一般为实体类)
Session中存放String类型的代码:

package com.kuang.servlet;

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

public class SessionDemo01 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
//        在此条Demo中我们将会获取Session并且在其中存贮一个字符串
//        1.解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
//        2.获取Session
        HttpSession session = req.getSession();
//        3.在Session中写入信息
        session.setAttribute("name","一个写Bug的");
//        4.获取SessionID
        String id = session.getId();
//        5.判断Session是否是新生成的
        if (session.isNew()){
    
    
            resp.getWriter().write("这个Session是新生成的,ID : " + id);
        }else{
    
    
            resp.getWriter().write("这个Session不是新生成的,ID : " + id);
        }

    }

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

Session中存放类:
新建一个实体类User

package com.kuang.pojo;

public class User {
    
    
    private String name;
    private int age;

    public User(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    public User() {
    
    
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Session中存放此类

package com.kuang.servlet;

import com.kuang.pojo.User;

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

public class SessionDemo03 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
//        在本Demo中,我们将在Session中存储一个实体类
//        1.解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
//        2.获取Session
        HttpSession session = req.getSession();
//        3.创建实体类
        User user = new User("一个写Bug的", 23);
//        4.将实体类存入Session
        session.setAttribute("user",user);
//        5.提示用户已经完成
        resp.getWriter().write("已经将user类存入Session");
    }

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

关于读取的Session中的数据的方法也很简单,在我们获取Session之后,只需要使用getAttribute获取对应存储数据的名称即可。我们需要知道的是,Session之中存储的键值对类型是<String,Object>,也就是说在我们获取数据时,一般会同时将获取的数据进行一个类型转化。

package com.kuang.servlet;

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

public class SessionDemo02 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
//       本条Demo中,我们将获取Session中的数据并且将其输出
//        1.解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
//        2.获取Session,并且获取Session里面的数据
        HttpSession session = req.getSession();
        String name = (String) session.getAttribute("name");
//        3.将获取的数据输出
        resp.getWriter().write("获取到的数据为 : " + name);
    }

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

2.使Session失效
我们一般将Session失效的方法用两种,一种是在代码中直接使用invalidate()方法将Session失效,另外一种则是在web.xml中设置Session的过期时间。
使用invalidate()方法:

package com.kuang.servlet;

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

public class SessionDemo05 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
//        用来使Session失效
//        1.获取Session
        HttpSession session = req.getSession();
//        2.使Session中的数据失效
        session.removeAttribute("name");
        session.invalidate();
    }

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

在web.xml中设置Session的过期时间:

    <session-config>
<!--        以分钟来设置Session的失效时间,单位为分钟,也就是说此处设置Session会在15分钟之后失效-->
        <session-timeout>15</session-timeout>
    </session-config>

Session的使用场景

  • 保存用户的登录信息
  • 购物车信息
  • 在网站中会经常被使用到的信息,我们一般也会把它存储在Session之中

3.总结

我们现在已经学习了ServletContextCookie以及Session这三个在网络应用中常见的存放数据的技术。关于这三个技术之间的关系,我们可以用一张图直观的表述:
请添加图片描述