【Servlet篇4】cookie和session

在这一篇文章当中,我们提到了什么是cookiesession

【网络原理8】HTTP请求篇_革凡成圣211的博客-CSDN博客HTTP的常见属性,URL,User-Agent,Refer,get 和post的区别https://blog.csdn.net/weixin_56738054/article/details/129180661?spm=1001.2014.3001.5502它们分别是客户端会话技术和服务端会话技术。

分别把用户的信息保存在客户端磁盘服务端,二者一般是相互配合使用的。


       当用户访问一个网站之后,这个网站会把用户的关键信息(例如身份标识符)存储到cookie当中,也就是用户的本地磁盘当中。

       当后续用户再次访问这个网站的时候,就会携带这个cookie,然后在服务器当中根据这个cookie来获取这个用户的其他信息。

       一般请求下,服务器只要不重启,同一个客户请求同一个网站的情况下,用户的cookie当中的身份标识符不会改变。

下面,就来聊一下session和cookie的常见api

目录

HttpSession session=req.getSession();

 当传入参数为true的时候:

当传入参数为false的时候:

当调用getSession()方法的时候,会做什么事情

步骤1:创建会话

步骤2:获取会话

HttpSession对象

setAttribute()和getAttribute()

session设置最大时间 

Cookie[] getCookies方法

resp.addCookie()方法

实现登录-跳转页面的案例

第一步:约定登录前后端交互的格式

登录接口的请求方式:

登录接口的响应方式:

第二步:约定如何获取主页的交互

获取主页的请求方式:

响应的格式:

第三步:编写登录的接口,并且把用户登录的信息保存在session当中

第四步:编写访问index页面的servlet

实现一个用户访问页面的次数的功能

 如果在其中一个浏览器登录了,可以在另外一个浏览器直接访问登录页面吗?

总结:cookie和session的区别


HttpSession session=req.getSession();

这一个方法,既可以用于获取到服务器上面的会话,又可以用于创建会话。

但是,这一个方法在HttpServletRequest当中是存在多态的。

 当传入参数为true的时候:

会话存在,则获取;会话不存在,则创建


当传入参数为false的时候:

会话存在,则获取;会话不存在,则返回null


当调用getSession()方法的时候,会做什么事情

步骤1:创建会话

首先先获取到HTTP请求头当中cookie这个属性里面的sessionId字段

接着,判断这一个sessionId是否在当前的服务器当中存在。

如果不存在,那么就进入创建会话的逻辑。

       第一步:首先创建一个HttpSession对象,并且生成一个sessionId(用16进制来表示);

       第二步:把sessionId作为key,这一个session对象作为value。保存到服务器的一个类似于"哈希表"的结构当中。(这个数据是保存到内存当中的,并不是持久化的)

       第三步:服务器返回一个HTTP响应,把sessionId通过Set-cookie字段返回给浏览器。

也就是返回给用户

       然后用户下次再次访问的时候,就可以通过这个cookie字段来获取了。 

下面,图解一下创建会话的流程:


步骤2:获取会话

先获取到请求的cookie里面的sessionId字段。

然后判断这个sessionId是否在当前的服务器上面存在(也就是是否在这个哈希表当中存在)

如果有,那么直接返回这个sessionId对应的对象。


HttpSession对象

每一个HttpSession对象都是通过键值对的形式来存储数据的。

当存储数据的时候,需要调用session.setAttribute(k,v)的方式来存储。

key是String的类型,value是Object的类型

看上去有点绕,怎么出现了套娃呢...那就画个图来解释一下吧~:

 一个服务器当中可以有多个session对象,每一个session对象都拥有一个sessionId

一个session对象都对应多个键值对


setAttribute()和getAttribute()

这两个方法,左边的那个是拥有设置key-value的。右边那个是通过key来获取value的。

当调用setAttribute之后,就相当于往已经创建的session对象当中存放key和value


session设置最大时间 

session.setMaxInactiveInterval()这个方法可以设置当前session对象的存活时间


Cookie[] getCookies方法

        通过调用req.getCookies方法,可以获取到用户提交的HTTP请求头当中的cookie字段对应哪些键值对:代码实现

@WebServlet("/servlet4")
public class Servlet4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       Cookie[] cookies= req.getCookies();

       for(int i=0;i<cookies.length;i++){
           Cookie cookie=cookies[i];
           System.out.println(cookie.getName()+"...."+cookie.getValue());
       }
    }
}

 运行结果:

 使用Fidller抓包:

可以看到,此时服务器就获取到了两个cookie对象。


resp.addCookie()方法

       此处传入的是一个Cookie类型的数据,Cookie也是由键值对组成的结构。键和值都是String类型的数据。

Cookie cookie=new Cookie("hello","hi");
Cookie cookie1=new Cookie("hello","hi");
resp.addCookie(cookie);
resp.addCookie(cookie1);

       这个addCookie方法,其实就相当于给客户端浏览器发送一个cookie类型的键值对。

       然后,可以在HTTP响应报头的set-cookie字段当中看到这一个字段。

   


下面,通过一个网页登录的案例来体会一下cookie和session。

实现登录-跳转页面的案例

第一步:约定登录前后端交互的格式

登录接口的请求方式:

协议版本:HTTP/1.1

请求方法:POST;

请求路径:/Servlet;

接收方式(Content-type)application/x-www.form-urlencoded

(也就是userName="***"&password="***")这样的格式


登录接口的响应方式:

响应行:HTTP/1.1 302(需要重定向);

重定向:Location: index。(重定向到index这个路径)


第二步:约定如何获取主页的交互

获取主页的请求方式:

HTTP版本:HTTP/1.1

请求方法:GET;

请求路径:/index;

没有参数需要提交


响应的格式:

HTTP版本:1.1;

状态码:200;

响应格式:Content-Type: text/html(返回一个html页面)


第三步:编写登录的接口,并且把用户登录的信息保存在session当中

 登录的时候,通过req.getSession()来创建一个session对象

并且把userName存放到session域当中。 

约定需要跳转的路径(/index)

     @WebServlet("/login")
public class Servlet5 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        //处理用户请求
        String userName=req.getParameter("userName");
        String password=req.getParameter("password");
        //此处简单模拟一下登录成功的情况
        if("张三".equals(userName)&& "123".equals(password)){
            //往会话当中存储键值对:用于保存用户登录的信息
            //此处指定的参数为true,那么:需要此时会创建一个sesion对象
            HttpSession session=req.getSession(true);
            //把用户名存入session当中,代表用户已经登录成功了
            session.setAttribute("userName",userName);
            resp.sendRedirect("index");
        }else{
            //登录失败
            resp.getWriter().write("login faild");
        }
    }
}

第四步:编写访问index页面的servlet

       再次调用req.getSession方法,但是此处需要指定参数为false

       因为此处的session就是为了验证用户登录与否,无需再次创建新的会话。

       此处的session对象和第三步当中的session期待是同一个session对象。

       因为期待是同一个会话。

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到用户名
        //此处getSession参数为false,原因:此处已经创建过会话了
        HttpSession session =req.getSession(false);
        resp.setCharacterEncoding("utf-8");
        //根据key来获取value
        String userName= (String) session.getAttribute("userName");
        //返回一个主页
        resp.getWriter().write("<h3>欢迎你!"+userName);
    }
}


实现一个用户访问页面的次数的功能

无需太大的改动。只需在用户登录的时候,设置一个count统计用户登录的次数。这一个count需要使用session保存。

然后在页面(index)处,每一次用户取出来数据,都要+1。

代码实现:

登录页面

@WebServlet("/login")
public class Servlet5 extends HttpServlet {
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         req.setCharacterEncoding("utf-8");
        //处理用户请求
        String userName=req.getParameter("userName");
        String password=req.getParameter("password");

        //此处简单模拟一下登录成功的情况
         System.out.println(userName+"..."+password);
        if("张三".equals(userName)&& "123".equals(password)){
            //往会话当中存储键值对:用于保存用户登录的信息
            //此处指定的参数为true,那么:需要此时会创建一个sesion对象
            HttpSession session=req.getSession(true);
            //把用户名存入session当中,代表用户已经登录成功了
            session.setAttribute("userName",userName);
            //登录成功,默认初始的值为0
            session.setAttribute("count",0);
            resp.sendRedirect("index");
        }else{
            //登录失败
            resp.getWriter().write("login faild");
        }
    }
}

index页面

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到用户名
        //此处getSession参数为false,原因:此处已经创建过会话了
        HttpSession session =req.getSession(false);
        //根据key来获取value
        String userName= (String) session.getAttribute("userName");
        resp.setCharacterEncoding("utf-8");
        //获取一个count的值
        Integer count= (Integer) session.getAttribute("count");
        Integer newCount=count+1;
        //在session当中保存自增过后的count
        session.setAttribute("count",newCount);
        //返回一个主页
        resp.getWriter().write("<h3>欢迎你!"+userName+"您访问此页面的次数为:"+newCount);
    }
}

 如果在其中一个浏览器登录了,可以在另外一个浏览器直接访问登录页面吗?

 不行的。来做个实验看一下:

 首先,启动Tomcat,默认在360安全浏览器打开页面。

然后登录(登录的接口跟上面的是一样的,都是/login),同时使用Fidler抓包

然后,再抓一下访问index页面的URL的包:


换一个浏览器,再次访问index页面的URL

       可以看到,换了一个浏览器,因为cookie当中包含的sessionID不一样了,也就没有办法保存原来sessionid当中的值,那么就无法获取到在原来的浏览器保存的session信息了。

        (每一个浏览器都会有自己的cookie,也就意味着不同的浏览器有不同的sessionId)


总结:cookie和session的区别

使用对象 数据类型 安全性 存储大小 存储位置
cookie

针对网站:

每一个网站都会被分配一组cookie

(String,String) 比较低,容易丢失、篡改 较小;一个cookie不超过3K 保存在客户端浏览器(磁盘)
session

针对用户:

只有客户端才可以访问。

程序为客户端添加一个sessionId.

一个sessionId对应一个HttpSession对象

(String,Object) 比较高 可以存储任意大的数据 保存在服务端

       

猜你喜欢

转载自blog.csdn.net/weixin_56738054/article/details/129334764