黑马程序员Javaweb学习笔记04

该博客主要记录在学习黑马程序员Javaweb过程的一些笔记,方便复习以及加强记忆


系列文章

JavaWeb学习笔记01 BS架构 Maven Tomcat Servlet

JavaWeb学习笔记02 request和response

JavaWeb学习笔记03 JSP MVC
JavaWeb学习笔记04 待完善

文章目录

  • 一、会话跟踪技术
  • 二、Cookies
    • 2.1 cookies的基本使用
    • 2.2 cookies的基本使用2
  • 三、Session
    • 3.1 Session的基本使用
    • 3.2 Session的基本使用2
  • 四、总结
  • 五、案例的部分代码及注意事项
    • 5.1 登录注册
    • 5.2 记住我功能
  • 总结


一、会话跟踪技术

首先、会话是什么?

A和B在聊天,便是一次会话,不过我们这里的会话指的是浏览器和服务器之间的会话

当用户打开浏览器访问服务器之后,会话建立,一次会话之间包括多次请求和响应,比如用户点击删除按钮,便是一次请求,服务器响应删除后的html界面,便是一次响应,当浏览器或服务器其中一方关闭后,此次会话便结束

会话跟踪是什么?有什么用?

服务器会收到多个请求,这多个请求可能来自多个浏览器、服务器需要用来识别请求是否来自同一个浏览器,服务器用来识别浏览器请求的过程,这个过程就是会话跟踪
服务器识别浏览器后就可以在同一个会话中多次请求之间来共享数据

为什么要共享数据呢?
我们知道HTTP请求是无响应的,不会携带数据,因为这样快捷。
假如我们有这样一个场景,我在浏览京东,看见了一个不错的商品,点击加入购物车,这是一次请求,再点击进入购物车结算,这又是一次请求,进入购物车后就可以看见我刚刚选中的商品,购物车里面的商品是怎么来的呢?就是第一次请求共享带来的数据
其实这样子的功能可以去操作数据库实现,比如当我点击加入购物车后,把商品数据状态下来,而后在第二次请求时查询数据库,不过这样子的做法会给数据库带来很大压力

又比如,平时我们进行登录界面的时候会看见一个【记住我】的功能,在你第一次登录并勾选了【记住我】后,第二次登录就有账号密码数据,这两次登录作为两次请求,第二次登录【记住】了第一次登录的数据,其实这也是数据共享的效果

一次会话对应的是一个浏览器和一个服务器 下图中共有三次会话
黑马程序员Javaweb学习笔记04_第1张图片

如何实现

HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求

服务器要做的是
识别不同的浏览器(知道接收的请求是来自哪个浏览器)和
实现在同一个浏览器内数据共享


那么要怎么实现会话跟踪技术呢?

  1. 客户端会话跟踪技术:Cookie

  2. 服务端会话跟踪技术:Session

这两个技术都可以实现会话跟踪,它们最大的区别是:
Cookie是将数据存储在浏览器端而Session是存储在服务器端


二、Cookies

2.1 cookies的基本使用

正常流程如下图右:以中间的浏览器为例,在发送请求的时候,服务端会创建一个cookie返回给浏览器,浏览器发送请求2时就会带上这个cookie去访问服务器

黑马程序员Javaweb学习笔记04_第2张图片

代码例子:
我们创建一个名为ServletCookies的HttpServlet,用于创建cookie并发送
【这里我们发送一个cookie键值对,键是username,值是“张三”】

package com.web;

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

@WebServlet(value = "/ServletCookies")
public class ServletCookies extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cook = new Cookie("username","张三");

        response.addCookie(cook);
    }

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

创建一个名为ServletCookies2的HttpServlet,用于获取cookie


package com.web;

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(value = "/ServletCookies2")
public class ServletCookies2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie[] cooks = request.getCookies();
        response.setCharacterEncoding("UTF-8");
        for (Cookie co : cooks)
        {
            String name = co.getName();
            if(name.equals("username")){
                System.out.println(co.getValue());
                break;
            }
        }

    }

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

当我们去访问http://localhost:8080/web04_war/ServletCookies时,服务器便把cookie发送给浏览器,在浏览器中我们可以看见如下:

黑马程序员Javaweb学习笔记04_第3张图片

而后访问 http://localhost:8080/web04_war/ServletCookies2 结果如下:
黑马程序员Javaweb学习笔记04_第4张图片

cookies的基本原理

  • 前面的案例中已经能够实现,ServletCookies 给前端发送Cookie,ServletCookies2 从request中获取Cookie的功能
  • 对于ServletCookies 响应数据的时候,Tomcat服务器都是基于HTTP协议来响应数据
  • 当Tomcat发现后端要返回的是一个Cookie对象之后,Tomcat就会在响应头中添加一行数据Set-Cookie:username=张三
  • 浏览器获取到响应结果后,从响应头中就可以获取到Set-Cookie对应值username=张三,并将数据存储在浏览器的内存中
  • 浏览器再次发送请求给ServletCookies2 的时候,浏览器会自动在请求头中添加Cookie: username=张三 发送给服务端ServletCookies2
  • Request对象会把请求头中cookie对应的值封装成一个个Cookie对象,最终形成一个数组
  • ServletCookies2 通过Request对象获取到Cookie[]后,就可以从中获取自己需要的数据

2.2 cookies的基本使用2

默认情况下,cookie保存在浏览器内存中,关闭浏览器cookie自动销毁,我们如何设置时间呢


黑马程序员Javaweb学习笔记04_第5张图片

这里我们创建一个 /ServletCookies3,设置时间为三天

代码如下:

package com.web;

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

@WebServlet(value = "/ServletCookies3")
public class ServletCookies3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        Cookie cook = new Cookie("name","hello");

        cook.setMaxAge(60*60*24*3);     //设置三天时间

        res.addCookie(cook);

    }

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

访问后可在浏览器中查看到该cookie的时间,如下~
黑马程序员Javaweb学习笔记04_第6张图片
Cooke存储中文报错解决:

tomcat有些版本不支持中文的cookie存储,我们可以把cookie编一次码,获取cookie之后再解码,如下:
黑马程序员Javaweb学习笔记04_第7张图片
黑马程序员Javaweb学习笔记04_第8张图片

三、Session

3.1 Session的基本使用

上文说到,session和cookie的最大区别就是存储数据的位置不一样,一个是存储在客户端(浏览器),一个是存储在服务端(服务器),都能实现一次会话间多次请求中数据共享的问题
如下图,请求一和请求二和如何共享数据呢?当浏览器第一次请求时,服务器创建session对象,并存储好数据,放在一个域中,在第二次请求时,服务器可以在域中读取到上一次请求存储的数据,实现了数据共享
黑马程序员Javaweb学习笔记04_第9张图片
具体应用:
黑马程序员Javaweb学习笔记04_第10张图片

我们创建两个servlet类,命名为a,b,在a中获取session对象,并存入数据,b中也获取session,然后根据a中设置的键来获取值
代码如下:

//        存储数据
        HttpSession hs = req.getSession();

        hs.setAttribute("name2","李四");
//        获取数据
        HttpSession hs = req.getSession();

        Object name2 = hs.getAttribute("name2");
        System.out.println(name2);

我们依次访问a,b,控制台输出:
这里注意:如果访问a后关闭浏览器再访问b,控制台会输出null,因为会话结束,session销毁
黑马程序员Javaweb学习笔记04_第11张图片


3.2 Session的基本使用2

在上一个代码例子中,我们两次获取的session,如何保证第二次获取的session和第一次的session是同一个对象呢?当别的浏览器来访问时,session是不是还是这个对象呢?
验证方法直接在a和b中输出session对象,查看地址是不是一样即可

原理当别的浏览器来访问时,session不是同一个对象,其实session是基于cookie实现的,如下图:当下面的浏览器来访问时,session会设置一个id,如id-10,然后发送cookie返回给下面的浏览器,cookie中携带着session-id,下次下面的浏览器请求数据时,会带着id-10的cookie去访问服务器,服务器就可以根据cookie中的id去找对应的session。当上面的浏览器来访问服务器时,session自动新创建一个,并设置好值为id-11,防止不同的浏览器用相同的session


黑马程序员Javaweb学习笔记04_第12张图片


当服务器正常关闭的时候,session中的数据会保存到一个文件中,下次服务器开启时,便会把文件加载到session中,也就是说session不会因为服务器关闭而删除,但是浏览器关闭后,会话结束,session就销毁了,如果想要长期存储会话数据还是需要cookie~

session也可以自己销毁,比如登录游戏无操作30分钟时,session会自动销毁,并告诉你长时间没操作请重新登陆~
黑马程序员Javaweb学习笔记04_第13张图片
设置100分钟后销毁session,代码写在web.xml中

    <session-config>
        <session-timeout>100session-timeout>
    session-config>

四、总结

黑马程序员Javaweb学习笔记04_第14张图片

Cookie 是将数据存储在客户端,Session 将数据存储在服务端。关闭浏览器,cookie看setMaxAge设置的时间,session销毁。关闭服务器后两者都依然存在没销毁。

应用场景:

  购物车:使用Cookie来存储,因为要长期存储,且数据不敏感。

  已登录用户的个人信息展示:使用Session来存储,因为数据敏感

  记住我功能:使用Cookie来存储,因为要长期存储,牺牲安全提升体验

  验证码:使用session来存储,因为安全重要。发验证码请求和提交验证码请求的验证码只需要短期存储、且安全。

此处引用博客的内容

五、案例的部分代码及注意事项

5.1 登录注册

黑马程序员Javaweb学习笔记04_第15张图片
这里需要实现的是登录失败跳转回登录界面【跟前两章步骤类似】

三层架构如下:
黑马程序员Javaweb学习笔记04_第16张图片
注意事项:

登录成功显示xxx,欢迎你【这里可以在验证账号密码查询不为空后用session把账号(用户名)存在session中】注意el表达式中是可以获取session的数据

登录失败显示-账号或用户名有误,这个信息可以用req的请求转发去显示,当登录成功的话,就不请求转发,登录失败,设置键值对转发,用el表达式去获取。

所以登录界面代码中加入:

<div id="error">${msg}div>

servlet代码:

package com.web;

import com.mysql.cj.Session;
import com.pojo.user;
import com.service.UserService;

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

@WebServlet(value = "/servletLogin")
public class servletLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String name = req.getParameter("name");
        String password = req.getParameter("password");

        UserService us = new UserService();

        user u = us.login(name, password);
        System.out.println(name);
        System.out.println(password);
        if(u!=null)
        {
            //登录成功-重定向,因为这里没有数据共享,同时练习使用会话跟踪

            HttpSession session = req.getSession();
            session.setAttribute("user",u);


            String contextPath = req.getContextPath();//获取虚拟路径
            res.sendRedirect(contextPath+"/servletSelectAll");
        }else
        {
            //失败
            req.setAttribute("msg","用户名或密码错误");
            req.getRequestDispatcher("/login.jsp").forward(req,res);
        }

    }

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

5.2 记住我功能

登录成功并勾选了【记住我】后,创建cookie保存数据
黑马程序员Javaweb学习笔记04_第17张图片

获取cookie
黑马程序员Javaweb学习笔记04_第18张图片
servlet加入逻辑代码:


        String remember = req.getParameter("remember");	//获取【记住我】

        if(u!=null)	//账号密码不为空
        {
            if("1".equals(remember)){	//判断【记住我】是否选中,1为选中
                //创建cookie
                Cookie cook = new Cookie("name",name);
                Cookie cook2 = new Cookie("password",password);

                cook.setMaxAge(60 * 60 * 24 * 7);		//设置7天时间销毁
                cook2.setMaxAge(60 * 60 * 24 * 7);

                res.addCookie(cook);
                res.addCookie(cook2);
            }

登录界面部分代码:

 <p>账号 <input type="text" name="name" value="${cookie.name.value}">p>
    <p>密码 <input type="password" name="password" value="${cookie.password.value}">p>

注册功能类似,这里不一一讲解


总结

这一章主要讲解了cookie和session的基础概念和使用
代码将存放在码云中
未完待续…

你可能感兴趣的:(学习,服务器,数据库)