0
点赞
收藏
分享

微信扫一扫

编辑器,编译器,IDE的区别

静悠 2024-04-28 阅读 21

文章目录

一、HTTPServlet

在我们写 Servlet 的相关代码时。在创建类时,都会继承 HTTPServlet 后重写其中的某些方法。

核心方法如下所示:
在这里插入图片描述

介绍其中的关键 三个方法

  • init 方法

在 HTTPServlet 实例化后就被调用一次。
也就是说 Tomcat 在首次收到和该类相关联的 请求 时就会返回 (类似于 “懒汉模式”)

实现 init 方法如下:
在这里插入图片描述

需要注意的是,实例化的进行只进行一次。

这里通过多次访问页面观察情况:
在这里插入图片描述
很显然,当后续在收到请求时,就不会重复进行实例化了。

  • destory 方法

当 HTTPServlet 实例不在使用时就会调用。
实现 destory 方法:
在这里插入图片描述

当关闭服务器时,就会调用这个方法:
在这里插入图片描述

  • 结合三者介绍 生命周期

所谓生命周期,就是一个事物,从什么时候开始,什么阶段做什么事,什么时候结束。。。

二、HTTPServletRequest(处理请求)

当 Tomcat 通过 SocketAPI 读取 HTTP 请求时,就会按照 HTTP 协议的格式将字符串解析为 HTTPServletRequest 的形式。

核心方法如下所示:
在这里插入图片描述

1.分块介绍方法作用

get 为前缀的方法

这些方法主要的作用就是 获取 HTTP 的内部格式信息,这里通过简单的代码进行演示:
在这里插入图片描述
运行结果展示:
在这里插入图片描述

字段中 含有 getParameter 字段 的方法(前后端交互):

用来获取 query string 的键值对结构,这些方法是 通过 key 来获取 Value
这些键值对内容是什么完全是由程序员自定义的

  • 在 GET 请求的情况下
    前端向后端传输信息时:
    这里创建出两个变量作为 key
    在这里插入图片描述
    我们在访问时,提供两个相应的值时,就会在前端展现出来 (此时,如果没有输入值返回值就是 null),如图:
    在这里插入图片描述
  • 在 POST 请求的情况下
    前端中为 from 表单的数据向后端传输 信息时:
    对于这种情况,后端使用的方法仍然是 getParameter
    同样的这里仍然使用上面的两个变量。
    在这里插入图片描述
    使用 from 表单构造一个前端页面和后端进行交互。在这里插入图片描述
    输入信息后点击 “提交”,此时使用 Fiddle 进行抓包就会获得的到下面的结果:
    在这里插入图片描述

字段中 含有 getHeader 字段 的方法:

就是获取 HTTP 请求中请求头的信息。
代码展示:
在这里插入图片描述
此时,在网页中进行访问,就会在页面上获取到下面的信息:
在这里插入图片描述
在这里,如果使用 Fiddle 抓包,也会获得相同的信息。

2.解释前后端的交互过程

这里始终记住一点,此时的前端文件是存放在 webapp 这个文件夹下的。其中的请求,是可以被后端的代码解析到的。
这里通过 from 表单构造的前端页面与后端页面的交互进行简单解释。

前端代码(构造出一个前端请求):

<body>
    <form action="postParameter" method="post">
        <input type="text" name="studentID">
        <input type="text" name="classID">
        <input type="submit" value="提交">
    </form>
</body>

后端代码:

//获取请求时的最后一级路径
@WebServlet("/postParameter")
public class PostParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String studentID = req.getParameter("studentID");
        String classID = req.getParameter("classID");
        //告诉前端页面,这里的 body 的类型格式是什么样的
        resp.setContentType("text/html");
        //将获取到的信息输出到前端页面
        resp.getWriter().write("studentID = " + studentID + "classID = " + classID);
    }
}

将这里的四部分信息进行简单整合,大致如下图:
在这里插入图片描述

  • 前端代码 ——> 前端页面
    通过 from 表单构造出一个 post 请求。

  • 前端页面 ——> 后端接收(Tomcat 服务器)
    Tomcat 通过前端的信息构造出 req 和 resp 对象。
    其中的值存储在 req 对象中,通过 HTTPServletRequest 中的 getParameter 方法调用其中的值。

  • 后端 ——> 前端(浏览器)
    最后通过 resp 编写响应,写回到 Tomcat 中,并返回给浏览器显示。

形象图解:
在这里插入图片描述

3.使用 json 格式创建键值对结构

首先 ,json 的数据格式如下图所示:
在这里插入图片描述
上面就是将 body 按照这个方式进行了组织。

前端,可以通过 ajax 的方式进行构造,但是在这里,方便起见就是使用 postman 直接构造。

后端代码:

@WebServlet("/postParameter2")
public class PostParameterServlet2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //这个方法来处理 body 为 json 格式的数据
        //直接将 req 中对象的 body 完整的读取出来
        int length = req.getContentLength();
        //将获取到的字符长度赋给这个数组
        byte[] buffer = new byte[length];
        //定义一个输入流,并且将数据存储下来
        InputStream inputStream = req.getInputStream();
        //读取字符串信息
        inputStream.read(buffer);
        //将这个字符数组构造成一个 String 类型的字符串,并打印在运行结果中
        String body = new String(buffer,0,length,"utf8");
        System.out.println("body: " + body);
        resp.getWriter().write(body);
    }

如图,使用 postman 构造一个 json 格式字符串:
在这里插入图片描述
发送 post 请求后,就会在运行结果中出现拼接后的字符串结果。
在这里插入图片描述

4.使用第三方库 Jackson 构建

对于上面的问题,使用 Jackson 就可以解决。

  • 通过 maven 引入第三方库
    搜索 Jackson 后,第一个应该就是我们需要使用的第三方库。
    在这里插入图片描述

  • 将找到的 .xml 片段复制到 pom.xml 中
    在这里插入图片描述

  • 通过代码实现 Jackson 操作
    这里的操作会简单很多,使用一行代码就可以完成。

事先准备:
这个代码的实现方式比较特殊,需要一个事先准备好的一个 class 类确定传输的 key 值

class Student{
    public int studentID;
    public int classID;
}

Jackson 实现数据读取

@WebServlet("/postParameter2")
public class PostParameterServlet2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //使用 Jackson 的方式实现代码
        ObjectMapper objectMapper = new ObjectMapper();
        //readValue 就是将一个 json 字符串转成一个 Java 对象
        Student student = objectMapper.readValue(req.getInputStream(),Student.class);
        System.out.println(student.studentID + ", " + student.classID);
    }
  • 运行结果展示
    在发送一个请求后,这里仍然会在运行窗口进行打印,如图:
    在这里插入图片描述
    很明显,这里就只是出现了单纯的 Value 值。

三、HTTPServletResponse(处理响应)

上面描述方法,就是根据请求计算响应。之后将响应传递给 Response 内的对象中

Tomcat 就会将这里 Response 对象按照 HTTP 协议的格式,转成字符串,通过 Socket 写回给浏览器。

核心方法
在这里插入图片描述
如上图所示,我将比较重要且相似的方法已经标记出来。

解释其中的部分方法

第一组

这一组的方法 都与 header 有关
两个不同的方法,针对添加 header 的键值对的原则不同。

第二组

  • 解释 setContentType
    这个方法在前面的代码中我们已经使用过了。
    其目的是,告诉浏览器这里的 body 是什么类型的文件,以什么形式进行展示。

  • 解释 setCharacterEncoding
    这个方法主要是告诉浏览器,这个页面的编码字符集是什么样的。
    这里通过代码来简单演示一下其作用:

未设置字符集

@WebServlet("/SetCharacter")
public class TestSetCharacterEncoding extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String studentID = req.getParameter("studentID");
        String classID = req.getParameter("classID");
        resp.setContentType("text/html");

        resp.getWriter().write("学生ID =" + studentID + "班级ID =" + classID);
    }

在这里插入图片描述
设置字符集

//添加设置字符集
resp.setCharacterEncoding("utf8");

在这里插入图片描述

sendRedirec 方法

这个方法是构造一个重定向响应。
也就是 3XX 的状态码,浏览器会自动跳转到指定的新地址

同样的,这里通过简单的代码进行验证:

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://www.baidu.com");
    }
}

使用 Fiddle 进行抓包操作,就会获得下面的信息,重定向实现了
在这里插入图片描述

四、再次阐述 cookie 和 session

这里的 cookie 在本人前面的文章 HTTP协议解释(上篇) 中已经有所简单解释。
在这里,本人会以更加详细的形式对这两个重点信息进行解释。

1、什么是 cookie 以及登录的基本流程

要了解什么是 cookie 首先,我们需要明白下面几个问题:

对于上面的文字解释是比较晦涩的,下面我通过一个最常用的例子来更加详细的解释 cookie 的工作过程:

对于 cookie ,最典型的应用就是标识用户的身份信息,也就是网站的登录功能
如图:
在这里插入图片描述
针对登录操作: QQ 的服务器会通过数据库来判断用户的身份信息。

登陆成功: 此时,服务器就会将身份信息保存一份。并且向客户端分配一个 唯一的 身份序号。 这个身份序号 就存储在 cookie 中。(这个唯一的身份序号就被称之为 sessionID)

session (会话): 服务器会像 hash 这样的表结构一样,将 序号 作为 key,身份信息 作为 value 存储

后续请求: 在客户端发出请求时,会同时将 cookie 中的身份序号发送给服务器。此时,服务器就会查询上述的 hash 表,判定用户的身份信息。

2、了解 cookie 和 session 的联系与区别

  • 联系: 在网站登录的功能中,两者需要共同的配合来使用。
  • 区别

(1)cookie 可以单独进行使用,不搭配 session (实现非登录的情况)

(2)session 也可以不搭配 cookie 使用。(例如手机 app 进行登录就需要 session 此时就没有 cookie 的概念)cookie 是 与浏览器强相关的。

(3)cookie 是 客户端 的存储机制,session 是 服务器 的存储机制。

(4)cookie 中可以存储各种键值对,session 则是专门用来保存用户的身份信息

(5)cookie 是 HTTP 协议中的一个部分。
session 则可以与 HTTP 协议无关。

3.使用代码简单解释 cookie 和 session 的工作原理

要解释这两个的工作原理,可以通过一个简单的 模拟登陆页面 进行解释。

流程图如下:
在这里插入图片描述

  • 编写前端登录页面

使用 from 表单就可以编写出一个登录请求页面。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username">
        <br>
        <input type="password" name="password">
        <br>
        <input type="submit" value="登陆">
    </form>
</body>
</html>

通过抓包我们可以获取到下面各个元素之间的联系:
在这里插入图片描述

  • 编写 LoginServlet 处理登录请求

简单思路如下:
(1)首先,我们通过前端的代码已经知道会发出一个 post 请求。用户的 信息 就存在于 post 请求的 body 中。
(2)对此,后端首先会获取前端 body 中的信息。在于后端中的信息核对(这里方便期间就先写死了数据
(3)最后会创建出一个新的 session 会话。将 用户名 信息进行保存,并重定向到主页面。

代码如下(详细解释已经在代码注释中):

package login;

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("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到前端页面 body 中的用户名以及密码信息
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 在获取到相应信息后,就需要对信息进行核对。
        // 正常情况下是需要数据库进行存储信息,此处为了方便就直接将用户信息写死
        // 这里约定用户有 zhangsan 和 lisi
        // 密码都为 123
        if(!username.equals("zhangsan") && !username.equals("lisi")){
            //登录失败
            //后端反馈登录失败信息
            System.out.println("登录失败,请重新登录");
            //进行页面的重定向,将页面返回到登录页
            resp.sendRedirect("login.html");
            return;
        }
        if(!password.equals("123")){
            //登录失败
            //后端反馈登录失败信息
            System.out.println("登录失败,请重新登录");
            //进行页面的重定向,将页面返回到登录页
            resp.sendRedirect("login.html");
            return;
        }
        //登陆成功
        // 1. 创建出一个会话
        // 这里设定的 true 是为了判读是否需要创建一个新的 会话
        HttpSession session = req.getSession(true);
        // 2,将当前用户的用户名保存到会话中
        session.setAttribute("username",username);
        // 3,重定向到主页面
        resp.sendRedirect("index");
    }
}
  • 编写 IndexServlet 生成主页

简单思路如下:
(1)首先获取当前用户的登录情况。
(2)获取到前面绘画中的 用户名 信息
(3)在页面中输出信息

代码如下:(同样的,详细解释已经在代码中注释出来

package login;

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("/index")
public class IndexServlet extends HttpServlet {
    //通过重定向,浏览器发送的会是一个 get 请求
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 首先判断用户的登录状态
        // 如果还没有登录,就请求先登录
        // 已经登录了,就根据当前会话中的用户名,显示到页面上

        //首先获取当的会话,并不创建新的会话
        // 如果会话存在,则表明当前的用户已经登录了
        // 如果会话不存在,则表名当前用户处于未登录状态
        HttpSession session = req.getSession(false);
        if(session == null){
            //服务器信息反馈
            System.out.println("用户未登录");
            // 此时进行重定向,定向到登录页面
            resp.sendRedirect("login.html");
            return;
        }
        // 从前面的会话中获取到用户信息
        String username = (String) session.getAttribute("username");
        // 构造一个页面
        // 设定页面输出的格式
        resp.setContentType("text/html;charset=utf8");
        // 在页面输出信息
        resp.getWriter().write("欢迎 "+ username + " 登录!");
    }
}

4.总结

对于上述的完整代码,本人已经放置到码云之中 cookie&Session

最后,我们通过抓包工具,就可以很明确的了解到整个代码的运行逻辑,如下图:
在这里插入图片描述
在完成一次登陆之后,后续多次请求服务器,都会带上这了 cookie 的值 (也就是 SessionID)

码子不易,您小小的点赞是对我最大的鼓励!!!

举报

相关推荐

0 条评论