会话、Cookie、Session

目录

 

1 会话

2 Cookie

2.1 什么是Cookie

2.2 Cookie的作用

2.3 服务器生成Cookie对象发送给客户端

2.4 服务器获取浏览器在请求时所携带的Cookie

2.5 Cookie的携带路径

2.6 Cookie的生命周期

2.7 清除Cookie对象

2.8 Cookie记录上一次的访问时间

3 Session

3.1 Session对象的ID

3.2 Session对象的持久化

3.3 Session对象的销毁

3.4 Session对象的生命周期


1 会话

web会话:用户开一个浏览器,访问某一个web网站,在这个网站点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
注意:如果一个浏览器里面有多个选显卡,关闭其中一个,还剩下其他选项卡,则该会话不关闭,直到把整个浏览器关掉,会话才会结束。重新打开浏览器就是第二个会话。

2 Cookie

2.1 什么是Cookie

Cookie可以把服务器传递过来的一些数据记录在客户端浏览器中,解决会话从什么时候开始,到什么时候结束。
生成Cookie对象在服务器中完成,而往Cookie对象中存数据是在客户端浏览器中完成的。
在浏览器中Cookie是以文本的形式保存数据。

2.2 Cookie的作用

(1)判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须从新填写登录的相关信息。
(2)保存上次登录的时间等信息。
(3)保存上次查看的页面
(4)浏览计数。

2.3 服务器生成Cookie对象发送给客户端

服务器向客户端发送Cookie
Cookie对象是用来存储键值对数据的,Cookie对象的产生在服务器端,但是往Cookie对象中存数据是在客户端浏览器
Cookie类的构造方法:
Cookie(String name, String value) Cookie对象实际上就是一个存储键值对的容器,这个name可以理解为key
至于把来自于服务器端的Cookie传给客户端的方法,这就用到了服务器端的响应对象response
response对象中有个方法addCookie(),把来自于服务器端的Cookie返回给客户端(通过响应头)

/**
 * 服务器向客户端发送Cookie
 * Cookie对象是用来存储键值对数据的,Cookie对象的产生在服务器端,但是往Cookie对象中存数据是在客户端浏览器
 * Cookie类的构造方法:
 *  Cookie(String name, String value) Cookie对象实际上就是一个存储键值对的容器,这个name可以理解为key
 * 至于把来自于服务器端的Cookie传给客户端的方法,这就用到了服务器端的响应对象response
 * response对象中有个方法addCookie(),把来自于服务器端的Cookie返回给客户端(通过响应头)
 */
@WebServlet(urlPatterns = "/sendCookie")
public class SendCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建Cookie对象
        Cookie cookie = new Cookie("cookie_name", "cookie_value");
        //response对象将cookie返回给客户端
        response.addCookie(cookie);
    }

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

 

2.4 服务器获取浏览器在请求时所携带的Cookie

浏览器在访问服务器的时候, 会携带保存的Cookie数据, 服务器端可使用request对象获取Cookie数据; Cookie数据放在请求头。

/**
 * 在客户端浏览器获取来自服务器的Cookie对象
 * 客户端在访问服务器时,会生成Cookie数据,客户端浏览器会将Cookie数据放到http协议的请求头中
 * 通过request对象获取请求头数据(只拿cookie)方法:getCookies()
 */
@WebServlet(urlPatterns = "/getCookie")
public class GetCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通过request对象获取客户端的Cookie数据
        Cookie[] cookies = request.getCookies();
        //这里本应该判断一下cookies是不是null,否则如果浏览器中没有Cookie时会报空指针异常
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                System.out.println("key:" + cookie.getName() + "  value:" + cookie.getValue());
            }
        }
    }

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

 到这里我发现:一旦关闭整个浏览器(结束会话),之前生成的Cookie就消失了!所以说,Cookie的生命周期究竟是多久呢(详情见Cookie的生命周期)?

2.5 Cookie的携带路径

浏览器访问服务器,是否携带Cookie?答:默认情况下,Cookie在哪产生的,在哪里访问才携带!
接下来解释上面这句话:
如果我在/web03/pathCookie 路径下创建一个Cookie对象传给浏览器,浏览器如果要想在请求时带上这个Cookie,则浏览器的请求地址必须是/web03/*
如果我在/web03/aaa/pathCookie 路径下创建一个Cookie对象传给浏览器,浏览器如果要想在请求时带上这个Cookie,则浏览器的请求地址必须是/web03/aaa/*
如果我在/web03/aaa/pathCookie中创建一个Cookie,然后下一次访问的时候url是web03/bbb/* 那就肯定不会携带Cookie

但是在开发中,我们需要“只要访问的是web03这个web项目就要携带Cookie”而不是“在哪产生,在哪里访问才能携带”
完成上述要求的做法为:通过Cookie对象的setPath方法设置Cookie的携带路径

@WebServlet(urlPatterns = "/aaa/pathCookie")
public class PathCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("path", "cookiePath");

        //一旦设置了cookie的携带路径,那么即使在web03/aaa/bbb/ccc/* 产生的Cookie,在web03/下的任意路径下访问时都会携带有该Cookie
        cookie.setPath(request.getContextPath()); //写的是web应用程序的名称,这个名称不要写死,而是通过request对象的getContextPath方法获取
        //保存Cookie到服务器
        response.addCookie(cookie);
    }

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

2.6 Cookie的生命周期

Cookie是会话对象,它是有生命周期的,它的生命周期和会话有关,一旦关闭浏览器,Cookie对象也就消失了。
通过Cookie对象的setMaxAge方法可以设置Cookie的生命周期,可能由于浏览器的不同,导致即使设置了很长时间的cookie生存周期,但是一旦关闭浏览器Cookie就没了,这是浏览器本身的问题!

@WebServlet(urlPatterns = "/lifeCookie")
public class LifeCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("cookie_name3", "cookie_value3");
        cookie.setMaxAge(60); //60秒
        response.addCookie(cookie);
    }

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

2.7 清除Cookie对象

清除某个Cookie对象有两个方法:
(1)浏览器 ctrl + shift + delete 直接删除Cookie
(2)“覆盖”,要保证新Cookie和要被覆盖的Cookie的(键名,携带路径)是一样的,然后让新Cookie的携带时间为0 就能清除当前Cookie(但是这个方法似乎不好使,我测试不出来,也可能是浏览器本身的问题)

/**
 * 清除Cookie的方法:
 * (1)浏览器 ctrl + shift + delete 直接删除Cookie
 * (2)清除Cookie通过“覆盖”,要保证新Cookie和要被覆盖的Cookie的(键名,携带路径)是一样的,然后让新Cookie的携带时间为0 就能清除当前Cookie
 */
@WebServlet(urlPatterns = "/clearCookie")
public class ClearCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //新Cookie的名字和旧Cookie一样
        Cookie cookie = new Cookie("cookie_name3", "value");
        //让新Cookie的携带路径和旧Cookie一样
        cookie.setPath(request.getContextPath());
        //设置新Cookie的时间为0秒
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }

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

2.8 Cookie记录上一次的访问时间

记录客户端上一次访问的时间,并且在浏览器上响应上一次访问的时间。
这个时间存在Cookie里面,由服务器创建传给浏览器,浏览器每次访问服务器时,都会携带该时间Cookie
服务器获取到该Cookie,把这个时间打印到浏览器页面上。

实现思想:
1、获取客户端携带的Cookie
2、判断
  A: 客户端的请求中没有携带Cookie
        欢迎语打在浏览器
        创建Cookie,值是当前时间
        响应回客户端
  B: 客户端的请求中携带了Cookie
        获取Cookie中的键值对,值就是客户端上次访问的时间
        响应客户端(上一次访问的时间)
        创建Cookie,值是当前时间
        响应回客户端

@WebServlet(urlPatterns = "/lastTime")
public class LastTimeServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应,处理中文乱码
        response.setContentType("text/html;charset=utf-8");
        //1、获取客户端携带的Cookie数据
        Cookie[] cookies = request.getCookies();
        //2、判断Cookies数组是不是空,如果是空,则认为是客户端第一次访问服务器
        if (cookies == null) {
            //客户端第一次访问
            response.getWriter().write("欢迎首次访问");
            //Cookie记录现在的时间
            createCookie(request, response);
        } else {
            System.out.println(cookies.length);
            //客户端不是第一次访问,则取出Cookie中的键值对,在浏览器上显示“上一次的访问时间”
            for (Cookie cookie : cookies) { //cookies里面一直只有一个cookie,这个循环实际上没啥用
                String name = cookie.getName();
                String value = cookie.getValue(); //值是上一次的访问时间
                response.getWriter().write("上一次访问的时间是:" + value);
                //新创建一个Cookie,记录现在的时间
                createCookie(request, response);
            }

        }
    }

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

    //创建Cookie:该Cookie的值是一个日期,生存时间10分钟、所有访问web03项目的请求都会携带该Cookie
    public void createCookie(HttpServletRequest request, HttpServletResponse response){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); //Cookie不允许有空格和冒号,所以采用此种形式
        String format = simpleDateFormat.format(new Date());
        Cookie new_Cookie = new Cookie("time", format);
        new_Cookie.setMaxAge(60 * 10); //设置Cookie的生存时间(前提是不关闭浏览器)
        new_Cookie.setPath(request.getContextPath()); //设置Cookie的携带路径,让请求只要是访问web03项目的,则都会携带该Cookie
        response.addCookie(new_Cookie); //把Cookie回传给浏览器
    }
}

3 Session

3.1 Session对象的ID

session域对象的id值
session对象获取id的方法:getId
唯一性(在一个Tomcat服务器之中,开启了web项目还不能关闭,如果重启了web项目,session对象的id值就变了,详情见Session对象的生命周期)

其实,服务器创建、获取Session对象是这样的过程:
(1)浏览器访问服务器,会携带Cookie,如果没有用于存放Session_ID的Cookie,那么服务器就自己创建一个新的Session对象,该对象作用于该会话。
(2)但是这不意味着服务器中本来就没有Session对象,可能服务器中本来就有Session对象,但是由于没有用于保存Session_ID的Cookie(比如不小心删除了Cookie),所以服务器才只能创建新的Session对象。
(3)如果浏览器访问服务器时,携带的Cookie正好存了Session_ID,那就直接用服务器中现成的这个Session对象,而不去创建新对象了。

每次关闭浏览器后再打开,之前存在session对象中的数据就没了,这是为什么?
答:session对象以及存的数据是在服务器中的,并没消失,只不过关闭浏览器后,该session对象所对应的cookie(携带有session Id)没了
没了cookie就没了session ID,没了session ID自然就找不到之前存在session对象中的数据了(即:数据没丢,只是没了id所以找不到了)。
 而此时,由于新的浏览器访问,已经创建了新的session对象(服务器中旧的session对象可能仍然还在,这就要看session对象的生命周期了)

如果我想即便关掉浏览器后再打开,之前存在session对象中的数据不消失,怎么办?
答:延长用于存放session id 的Cookie的生存时间,不要让它一关闭浏览器就消失(这是默认情况,cookie的生命周期即为一次会话)

@WebServlet(urlPatterns = "/session3")
public class Session3Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getSession().getId();
        System.out.println(id); //只要浏览器不关闭,session对象的id值就不会变(沿用之前的session对象而不会创建新的session对象,所以id不变)
    }

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

3.2 Session对象的持久化

Session域对象的持久化,实际上是在持久化Cookie
客户端保存的Cookie(它的值是Session对象的id),如果要想持久化,就要保证即便关掉浏览器再打开,这个Cookie还是存在的。

@WebServlet(urlPatterns = "/session3")
public class Session3Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //拿到session对象的id
        String id = request.getSession().getId();
        System.out.println(id); //只要浏览器不关闭,session对象的id值就不会变(沿用之前的session对象而不会创建新的session对象,所以id不变)
        //往这个session对象中存储一些数据,看看一会儿重启浏览器后能不能再次访问到这个数据
        request.getSession().setAttribute("key","value");

        //创建cookie对象,存储当前session的id,设置Cookie的生存时间,把这个Cookie返回给浏览器
        Cookie cookie = new Cookie("JSESSIONID", id); //注意:此时的键必须是“JSESSIONID”
        //设置Cookie的生存时间
        cookie.setMaxAge(60 * 10);
        //设置Cookie携带路径
        cookie.setPath(request.getContextPath());
        //把cookie返回给客户端浏览器
        response.addCookie(cookie);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
//测试session对象是否被持久化:即使关闭浏览器,之前存到session对象中的数据仍然能被访问到
@WebServlet(urlPatterns = "/session4")
public class Session4Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //取出session3 中session域对象中的值
        Object value = request.getSession().getAttribute("key");
        System.out.println(value);
    }

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

3.3 Session对象的销毁

前面说了那么多,似乎忽略了一个问题:Session对象本身的生命周期,如果Session对象到时间被销毁了,即使Cookie里面存了它的ID也是无济于事的(类似于野指针吧···)

Session域对象的销毁:
方法1:Tomcat服务器默认30分钟后销毁Session对象(tomcat包中的conf文件下的web.xml配置文件中配置了这个时间)
但是不建议直接改tomcat配置文件,而是自己在项目的web.xml中进行配置
Session对象的生命周期,从它被创建出来开始,如果一直不去使用它(一旦使用则重新刷新时间),则默认30min后服务器会销毁该对象。
关于Session对象存活时间的设置,可以在项目中的web.xml文件中配置,如下图,而不是去修改Tomcat本身的配置文件。
方法2:调用session对象的invalidate()方法,如下下图。

 

@WebServlet(urlPatterns = "/session5")
public class Session5Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.invalidate();

        //测试一下这个session对象有没有被销毁(直接状态码500:空指针异常)
        Object value = session.getAttribute("key");
        System.out.println(value);
    }

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

3.4 Session对象的生命周期

Session对象的生命周期:

session创建时机
(1)这个浏览器在servlet中第一次使用session时候,通过getSession一旦被调用,会先去客户端请求中寻找键为“JSESSIONID”的Cookie,
如果没找到,就创建一个Session对象,如果找到了就去内存中查看是否真的有该对象,如果没有就还要重新创建。如果有则返回这个现成的对象。
(2)这个浏览器第一次访问jsp的时候,服务器也会为这个浏览器创建一个session对象;

session销毁时机
(1)程序员调用invalidate方法(立刻销毁)
(2)设置的存活时间到了(默认是30分钟)
(3)服务器非正常关闭(突然断电,然而正常关闭服务器后session对象是不会被销毁的,而是通过文件被的形式被序列化到电脑硬盘中,一旦重新打开服务器,该文件会被反序列化到内存中(文件随之消失),于是之前创建的session对象又出现了)。

注意:
正常关闭服务器,session不会销毁,而是直接序列化到硬盘上,下一次服务器启动的时候,会重新创建出来。
如果浏览器单方面关闭会话,服务器上对应的session不会死亡 ,但是会导致服务器给浏览器创建的JSESSIONID的cookie死亡,当cookie死亡后,会导致浏览器无法找到上一个session对象,会造成服务器中session死亡的假象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值