【一个简单的前后端交互页面】

news2024/11/22 15:18:35

🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!

欢迎志同道合的朋友一起加油喔🤺🤺🤺


目录

客户端与服务器之间的通信流程 

理解当前案例的前后端交互流程​编辑

表白墙的交互接口

纯前端的表白墙 html 页面代码

第一个交互接口:客户端从服务器拿数据

1. 通过 Servlet 构造 GET 响应

(1) 步骤

(2) 代码

2. 通过 ajax 构造 GET 请求

(1) 步骤

(2) 代码

第二个交互接口:从客户端往服务器提交数据

1. 通过 ajax 构造 POST 请求

(1) 步骤

 (2) 代码

2. 通过 Servlet 构造 POST 响应

(1) 步骤

(2) 代码

前后端完全分离的总代码

1. ajax 代码

2. Servlet 代码

3. 展示结果

(1) 提交数据展示

(2) 浏览器展示结果: ​

4. 提出问题

解决方案

将数据写入数据库

(1) 定义了一个DUBtil类,这个类是一个工具类,主要用于处理数据库连接和断开的操作

(2)实现从数据库获取所有的消息和保存一个新的消息

(3) ObjectMapper类的使用

(4) 展示写入数据库

总结



客户端与服务器之间的通信流程 

理解当前案例的前后端交互流程

表白墙的交互接口

在当前表白墙的案例中,我的需求主要是为了实现服务器来保存用户提交的留言。

第一个交互接口:客户端从服务器拿数据。

当页面加载(刷新页面)的时候,客户端就需要给服务器发送一个请求,把之前已经保存在服务器上的信息,获取下来,展示到浏览器的页面上。

第二个交互接口:从客户端往服务器提交数据。

当浏览器页面的用户点击提交的时候,就要给服务器发送一个请求,把这次留言的信息传给服务器。

纯前端的表白墙 html 页面代码

下面代码是【纯前端的表白墙 html 页面代码】,也就是【不涉及前后端交互的一个简单 html 实现的页面】,在下面的内容中,我们需要对这里的代码进行修改。最重要的是,我们应该理解,html 代码在什么场景下,修改了哪些部分。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表白墙</title>
    <style>
 
        * {
            /* 消除浏览器默认样式 */
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        .container {
            width: 600px;
            margin: 20px auto;
        }
 
        h1 {
            text-align: center;
        }
 
        p {
            text-align: center;
            color: #666;
            margin: 20px auto;
        }
 
        .row {
            /* 开启弹性布局 */
            display: flex;
            height: 40px;
            /* 水平方向居中 */
            justify-content: center;
            /* 竖直方向居中 */
            align-items: center;
        }
        .row span {
            width: 80px;
        }
        .row input {
            width: 200px;
            height: 30px;
        }
 
        .row button {
            width: 280px;
            height: 30px;
            color: white;
            background-color: orange;
            /* 去掉默认边框 */
            border: none;
            border-radius: 3px;
        }
 
        .row button:active {
            background-color: gray;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>表白墙</h1>
        <p>输入内容后点击提交,信息将显示到下方表格</p>
        <div class="row">
            <span>谁: </span>
            <input type="text">
        </div>
        <div class="row">
            <span>对谁: </span>
            <input type="text">
        </div>
        <div class="row">
            <span>说: </span>
            <input type="text">
        </div>
        <div class="row">
            <button>提交</button>
        </div>
        <div class="row">
            <button id="revert">撤销</button>
        </div>
    </div>
 
    <script>
        // 实现将提交的内容呈现在页面显示
        let containerDiv = document.querySelector('.container');
        let inputs = document.querySelectorAll('input');
        let button = document.querySelector('button');
        button.onclick = function() {
            //分别获取三个输入框的内容
            let from = inputs[0].value;
            let to = inputs[1].value;
            let msg = inputs[2].value;
            if(from == '' || to == '' || msg == '') {
                return;
            }
            //构建一个新的div
            let rowDiv = document.createElement('div');
            //此处class属性名不构造row防止撤销把自己删除了
            rowDiv.className = 'row message';
            rowDiv.innerHTML = from + ' 对 ' + to + ' 说 ' + msg;
            containerDiv.appendChild(rowDiv);
            // 完成提交后 清空输入框内的内容
            for(let input of inputs) {
                input.value = '';
            }
            let revertButton =document.querySelector('#revert');
            revertButton.onclick = function() {
                //删除最后一条消息
                //选中所有的row message,找出最后一个row message,然后进行删除
                let rows = document.querySelectorAll('.message');
                //如果没有数据就不删了
                if(rows == null || rows.length == 0) {
                    return;
                }
                containerDiv.removeChild(rows[rows.length-1]);
            }
        }
    </script>
</body>
</html>

第一个交互接口:客户端从服务器拿数据

1. 通过 Servlet 构造 GET 响应

(1) 步骤

服务器 解析请求、根据请求计算响应的步骤:

  1. 首先,Tomcat 服务器自动为我们实现了读取请求的逻辑。
  2. 其次,通过 jackson API 来将 Java 对象中的字符串解析成 json 格式的数据,并写在 HTTP 响应的 正文body 中。
  3. 最后,Tomcat 服务器自动为我们实现了返回响应的逻辑。

(2) 代码

//从服务器获取数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //显示的告诉浏览器,数据是json格式的,字符集是utf8的
    resp.setContentType("application/json;charSet=utf8");
    //writeValue方法只是把messageList转成json格式的字符串
    //并写在HTTP响应的正文body中
    objectMapper.writeValue(resp.getWriter(),messageList);
}

2. 通过 ajax 构造 GET 请求

首先,我们必须明确,GET 请求在当前案例的逻辑是什么?
答:GET 请求:点击浏览器刷新按钮,将服务器的数据展示在浏览器上。

怎么展示?
答:先要获取 HTTP 响应中正文 body 的内容,再展示前端页面上。

(1) 步骤

客户端 构造 GET 请求、获取响应、显示响应结果的步骤:

  1. 首先,从 HTTP 响应中的正文 body 中获取 json 格式的内容。
  2. 其次,从 客户端获取到 HTTP响应 的时候,响应中的 正文body 已然从 json 格式自动转换成了 数组形式,我们就可以遍历这个数组获取每个对象,将对象的属性拼接成字符串返回。
  3. 最后,将 数组body中的 from, to, message 的三个值挂在 DOM 树的末尾,这样一来,就可以在浏览器上显示出来了。

(2) 代码

// [新增] 在页面加载的时候, 使用jQuery的ajax方法发送HTTP GET请求 
//从服务器获取到数据并添加到页面中
$.ajax({
    type: 'get', // 设定请求类型为GET
    url: 'message', // 设定目标URL为"message"
    success: function(body) { // 定义请求成功时的回调函数
        // 此处拿到的 body 就是一个 js 的对象数组了. 
        // 本来服务器返回的是一个 json 格式的字符串, 但是 jquery 的 ajax 能够自动识别
        // 自动帮我们把 json 字符串转成 js 对象数组
        // 查找类名为'container'的div元素
        let containerDiv = document.querySelector('.container');
        // 接下来遍历这个body数组, 把元素取出来, 构造到页面中即可,此处相当于增强for循环
        for (let message of body) {
            // 对于body数组中的每个元素,创建一个新的div元素
            let rowDiv = document.createElement('div');
            // 为新创建的div元素设置类名为'row message'
            rowDiv.className = 'row message';
            // 设置新创建的div元素的HTML内容。这里将每个消息的"from", "to", 和 "message"字段拼接成一段文字。
            rowDiv.innerHTML = message.from + ' 对 ' + message.to + ' 说: ' + message.message;
            // 将新创建的div元素添加到containerDiv元素的子节点列表的末尾,从而将其显示在页面上
            containerDiv.appendChild(rowDiv);
        }
    }
});

第二个交互接口:从客户端往服务器提交数据

1. 通过 ajax 构造 POST 请求

首先,我们必须明确,POST 请求在当前案例的逻辑是什么?
答:POST请求:点击提交按钮,将客户端的数据提交到服务器上。

怎么提交?
答:客户端先将内容写在 HTTP 请求中的正文 body 中,服务器接收到 HTTP请求后,读取请求中的正文 body 内容,并以顺序表这个数据结构保存起来。

(1) 步骤

客户端 构造 POST 请求、获取响应、显示响应结果的步骤:

  1. 首先,它创建一个名为body的JavaScript对象,此对象包含三个属性:fromtomessage,这些属性的值分别由变量fromtomsg提供,分别代表消息的来源,消息的接收者,以及消息内容。
  2. 然后,它将body对象转换成JSON格式的字符串,存储在strBody变量中。这是因为在HTTP请求中,数据需要以字符串的形式发送。
  3. 接着,它打印出strBody的内容。这通常是为了进行调试,或者在控制台确认发送的数据。
  4. 最后,它使用jQuery的ajax函数发送一个HTTP POST请求。此请求的目标URL为message,发送的数据为strBody,并声明其内容类型(Content-Type)为JSON格式,字符编码为UTF-8。
  5. 在请求成功后,它会执行一个回调函数,打印出"数据发布成功"的消息,表示数据已经成功发送。

 (2) 代码

// 4. [新增] 给服务器发起 post 请求, 把上述数据提交到服务器这边
            // 定义一个JSON对象,用于包含要发送的消息
            let body = {
                "from": from, 
                "to": to, 
                "message": msg 
            };
            // 使用JSON.stringify方法将上述对象转换成字符串,以便能够作为HTTP请求体发送
            let strBody = JSON.stringify(body);

            // 使用console.log函数输出strBody的值,主要用于调试
            console.log("strBody: " + strBody);

            // 使用jQuery的ajax方法发送HTTP POST请求
            $.ajax({
                type: 'post', // 设定请求类型为POST
                url: 'message', // 设定目标URL为"message"
                data: strBody, // 设定请求体的内容为之前定义的字符串strBody
                contentType: "application/json; charset=utf8", // 设定请求头部的Content-Type为"application/json; charset=utf8",告诉服务器发送的数据是JSON格式且字符编码为UTF-8
                success: function(body) { // 定义请求成功时的回调函数
                    console.log("数据发布成功"); // 请求成功时,使用console.log函数输出一段信息,表示数据发布成功
                }
            });

2. 通过 Servlet 构造 POST 响应

(1) 步骤

服务器 解析请求、根据请求计算响应的步骤:

  1. 首先,Tomcat 服务器自动为我们实现了读取请求的逻辑。
  2. 其次,通过 jackson API 来将 json 格式的数据解析成 Java 对象,最终以键值对的形式呈现出来,再将整个对象放入顺序表中,暂时存起来。
  3. 接着,我们手动设置 HTTP 响应的 header 头、响应正文 body…
  4. 最后,Tomcat 服务器自动为我们实现了返回响应的逻辑。

(2) 代码

//向服务器提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //把body中的数据读取出来了,然后解析成Message对象
        Message message =  objectMapper.readValue(req.getInputStream(),Message.class);
        //此处用简单粗暴的方式来保存数据,将数据存入messageList这个顺序表中
        messageList.add(message);
        //此处的状态码可以省略.默认也是200
        resp.setStatus(200);
    }

前后端完全分离的总代码

1. ajax 代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表白墙</title>
    <style>
        /* * 通配符选择器, 是选中页面所有元素 */
        * {
            /* 消除浏览器的默认样式. */
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .container {
            width: 600px;
            margin: 20px auto;
        }

        h1 {
            text-align: center;
        }

        p {
            text-align: center;
            color: #666;
            margin: 20px 0;
        }

        .row {
            /* 开启弹性布局 */
            display: flex;
            height: 40px;
            /* 水平方向居中 */
            justify-content: center;
            /* 垂直方向居中 */
            align-items: center;
        }

        .row span {
            width: 80px;
        }

        .row input {
            width: 200px;
            height: 30px;
        }

        .row button {
            width: 280px;
            height: 30px;
            color: white;
            background-color: orange;
            /* 去掉边框 */
            border: none;
            border-radius: 5px;
        }

        /* 点击的时候有个反馈 */
        .row button:active {
            background-color: grey;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>表白墙</h1>
        <p>输入内容后点击提交, 信息会显示到下方表格中</p>
        <div class="row">
            <span>谁: </span>
            <input type="text">
        </div>
        <div class="row">
            <span>对谁: </span>
            <input type="text">
        </div>
        <div class="row">
            <span>说: </span>
            <input type="text">
        </div>
        <div class="row">
            <button id="submit">提交</button>
        </div>
        <div class="row">
            <button id="revert">撤销</button>
        </div>
        <!-- <div class="row">
            xxx 对 xx 说 xxxx
        </div> -->
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        // 实现提交操作. 点击提交按钮, 就能够把用户输入的内容提交到页面上显示. 
        // 点击的时候, 获取到三个输入框中的文本内容
        // 创建一个新的 div.row 把内容构造到这个 div 中即可. 
        let containerDiv = document.querySelector('.container');
        let inputs = document.querySelectorAll('input');
        let button = document.querySelector('#submit');
        button.onclick = function() {
            // 1. 获取到三个输入框的内容
            let from = inputs[0].value;
            let to = inputs[1].value;
            let msg = inputs[2].value;
            if (from == '' || to == '' || msg == '') {
                return;
            }
            // 2. 构造新 div
            let rowDiv = document.createElement('div');
            rowDiv.className = 'row message';
            rowDiv.innerHTML = from + ' 对 ' + to + ' 说: ' + msg;
            containerDiv.appendChild(rowDiv);
            // 3. 清空之前的输入框内容
            for (let input of inputs) {
                input.value = '';
            }

            // 4. [新增] 给服务器发起 post 请求, 把上述数据提交到服务器这边
            // 定义一个JSON对象,用于包含要发送的消息
            let body = {
                "from": from, 
                "to": to, 
                "message": msg 
            };
            // 使用JSON.stringify方法将上述对象转换成字符串,以便能够作为HTTP请求体发送
            let strBody = JSON.stringify(body);

            // 使用console.log函数输出strBody的值,主要用于调试
            console.log("strBody: " + strBody);

            // 使用jQuery的ajax方法发送HTTP POST请求
            $.ajax({
                type: 'post', // 设定请求类型为POST
                url: 'message', // 设定目标URL为"message"
                data: strBody, // 设定请求体的内容为之前定义的字符串strBody
                contentType: "application/json; charset=utf8", // 设定请求头部的Content-Type为"application/json; charset=utf8",告诉服务器发送的数据是JSON格式且字符编码为UTF-8
                success: function(body) { // 定义请求成功时的回调函数
                    console.log("数据发布成功"); // 请求成功时,使用console.log函数输出一段信息,表示数据发布成功
                }
            });

        }
        let revertButton = document.querySelector('#revert');
        revertButton.onclick = function() {
            // 删除最后一条消息. 
            // 选中所有的 row, 找出最后一个 row, 然后进行删除
            let rows = document.querySelectorAll('.message');
            if (rows == null || rows.length == 0) {
                return;
            }
            containerDiv.removeChild(rows[rows.length - 1]);
        }


        // [新增] 在页面加载的时候, 使用jQuery的ajax方法发送HTTP GET请求 
        //从服务器获取到数据并添加到页面中
        $.ajax({
            type: 'get', // 设定请求类型为GET
            url: 'message', // 设定目标URL为"message"
            success: function(body) { // 定义请求成功时的回调函数
                // 此处拿到的 body 就是一个 js 的对象数组了. 
                // 本来服务器返回的是一个 json 格式的字符串, 但是 jquery 的 ajax 能够自动识别
                // 自动帮我们把 json 字符串转成 js 对象数组

                //此次在控制台打印body,用于观察body的数据格式
                console.log(body);
                // 查找类名为'container'的div元素
                let containerDiv = document.querySelector('.container');
                // 接下来遍历这个body数组, 把元素取出来, 构造到页面中即可,此处相当于增强for循环
                for (let message of body) {
                    // 对于body数组中的每个元素,创建一个新的div元素
                    let rowDiv = document.createElement('div');
                    // 为新创建的div元素设置类名为'row message'
                    rowDiv.className = 'row message';
                    // 设置新创建的div元素的HTML内容。这里将每个消息的"from", "to", 和 "message"字段拼接成一段文字。
                    rowDiv.innerHTML = message.from + ' 对 ' + message.to + ' 说: ' + message.message;
                    // 将新创建的div元素添加到containerDiv元素的子节点列表的末尾,从而将其显示在页面上
                    containerDiv.appendChild(rowDiv);
                }
            }
        });

    </script>
</body>
</html>

2. Servlet 代码

class Message {
    public String from;
    public String to;
    public String message;
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    //使用这个List来保存所有消息
    private List<Message> messageList = new ArrayList<Message>();
    private ObjectMapper objectMapper = new ObjectMapper();
    //从服务器获取数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //显示的告诉浏览器,数据是json格式的,字符集是utf8的
        resp.setContentType("application/json;charSet=utf8");
        //writeValue方法只是把messageList转成json格式的字符串
        //并写在HTTP响应的正文body中
        objectMapper.writeValue(resp.getWriter(),messageList);
    }

    //向服务器提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //把body中的数据读取出来了,然后解析成Message对象
        Message message =  objectMapper.readValue(req.getInputStream(),Message.class);
        //此处用简单粗暴的方式来保存数据,将数据存入messageList这个顺序表中
        messageList.add(message);
        //此处的状态码可以省略.默认也是200
        resp.setStatus(200);
    }
}

3. 展示结果

(1) 提交数据展示

POST 请求与GET请求的抓包结果:

(2) 浏览器展示结果: 

4. 提出问题

在上面的客户端与服务器交互的过程中,从客户端往服务器提交数据,这一过程并没有什么问题,但客户端从服务器拿数据时,就出现了问题。

在我们使用 GET 请求与响应的时候,重启 Tomcat 服务器,然后刷新浏览器页面,之前客户端往服务器提交数据,就加载不出来了。这是为什么呢?

答:当前服务器把数据保存到了 messageList 变量,其实也就是将数据放到是内存中了,此时,一旦程序重启 ( 服务器重启 ),内存中的东西就没了。

private List<LovelyMessage> messageList = new ArrayList<>();

解决方案

从上面的存储方式看,我们从客户端发给服务器的数据,只是一份 “临时文件”,然而,那么,如何做到服务器重启后,数据也不丢失呢?

答:内存存储的是一份临时数据,那么,什么才能够持久化存储呢?一定就是硬盘了!如何写硬盘呢?

(1) 直接写到文件中
(2) 保存到数据库中

由于客户端发给服务器的数据,在服务器端没有做到持久化存储,所以,客户端这里的代码不需要改变,只需要改变服务器端的这边代码即可。

将数据写入数据库

(1) 定义了一个DUBtil类,这个类是一个工具类,主要用于处理数据库连接和断开的操作

  1. 为类定义了一个静态的 DataSource 成员,用于存储数据源。因为它是静态的,所以这个成员在整个进程中只有一个实例。
  2. 使用静态代码块来初始化 dataSource。这个代码块会在类加载时执行,并且只会执行一次。这个代码块中设置了连接数据库的URL、用户名和密码。
  3. 提供一个静态方法 getConnection(),用于获取数据库连接。它调用 dataSource.getConnection() 方法获取一个数据库连接并返回。
  4. 提供一个静态方法 close(),用于断开数据库连接和关闭资源。这个方法接收一个 Connection 对象、一个 PreparedStatement 对象和一个 ResultSet 对象作为参数,并尝试关闭它们。
//通过这个类,把数据库连接过程封装一下
//此处把 DBUtil 作为一个工具类,提供 static 方法供其他代码使用
public class DBUtil {
    //静态成员跟随对象的,类对象在整个进程中只有唯一一份
    //静态成员相当于也是唯一的实例(单例模式,饿汉模式)
    private static DataSource dataSource = new MysqlDataSource();
    static  {
        //使用静态代码块,针对dataSource进行初始化操作
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("1111");
    }
    //通过这个方法建立连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    //通过这个方法断开连接,释放资源
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        if(resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

(2)实现从数据库获取所有的消息和保存一个新的消息

class Message {
    public String from;
    public String to;
    public String message;
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    //从服务器获取数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //显示的告诉浏览器,数据是json格式的,字符集是utf8的
        resp.setContentType("application/json;charSet=utf8");
        //顺序表接收从数据库读取到的所有message对象
        List<Message> messageList = load();
        //writeValue方法只是把messageList转成json格式的字符串
        //并写在HTTP响应的正文body中
        objectMapper.writeValue(resp.getWriter(),messageList);
    }

    //向服务器提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //把body中的数据读取出来了,然后解析成Message对象
        Message message =  objectMapper.readValue(req.getInputStream(),Message.class);
        //将message对象存入数据库
        save(message);
        //此处的状态码可以省略.默认也是200
        resp.setStatus(200);
    }

    //提供一对方法
    //往数据库中存一条消息
    private void save(Message message) {
        //JDBC操作
        Connection connection = null;
        PreparedStatement statement = null;
        //1.建立连接
        try {
            connection = DBUtil.getConnection();
            //2.构造sql语句
            String sql = "insert into message values(?,?,?)";
            statement = connection.prepareStatement(sql);
            statement.setString(1,message.from);
            statement.setString(2,message.to);
            statement.setString(3,message.message);
            //3.执行sql
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //4,关闭连接
            DBUtil.close(connection,statement,null);
        }
    }

    //从数据库取所有消息
    private List<Message> load() {
        List<Message> messageList = new ArrayList<>();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            //1.和数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造sql
            String sql = "select * from message";
            statement = connection.prepareStatement(sql);
            //3.执行sql
            resultSet = statement.executeQuery();
            //遍历结果集合
            while (resultSet.next()) {
                Message message = new Message();
                message.from = resultSet.getString("from");
                message.to = resultSet.getString("to");
                message.message = resultSet.getString("message");
                messageList.add(message);
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源,断开连接
            DBUtil.close(connection,statement,resultSet);
        }
        return messageList;
    }
}

这个 MessageServlet 类主要包含四个方法:doGet,doPost,save,和 load。我将会按照这个顺序分别描述每个方法的执行过程。

  1. doGet 方法: 当客户端发送一个 GET 请求到 /message 这个 URL 的时候,doGet 方法会被调用。它首先设置 HTTP 响应的内容类型为 application/json;charset=utf8,然后调用 load 方法从数据库获取所有的消息,得到一个包含所有消息的 List<Message> 对象。然后,这个列表被转换为 JSON 格式的字符串,写入 HTTP 响应的正文中。这样,客户端就可以获取到所有的消息。
  2. doPost 方法: 当客户端发送一个 POST 请求到 /message 这个 URL 的时候,doPost 方法会被调用。它首先从 HTTP 请求的主体中读取数据,这些数据是 JSON 格式的,然后将这些数据解析为一个 Message 对象。然后,这个 Message 对象被传递给 save 方法,保存到数据库。最后,设置 HTTP 响应的状态码为 200,表示请求处理成功。
  3. save 方法: 这个方法接收一个 Message 对象,然后将这个对象保存到数据库。它首先获取一个数据库连接,然后创建一个 SQL INSERT 语句,将 Message 对象的 from,to,和 message 字段的值插入到数据库的 message 表中。然后,执行这个 SQL 语句,将数据保存到数据库。最后,关闭数据库连接和 SQL 语句对象,释放资源。
  4. load 方法: 这个方法从数据库加载所有的消息。它首先获取一个数据库连接,然后创建一个 SQL SELECT 语句,从 message 表中选择所有的记录。然后,执行这个 SQL 语句,获取结果集。遍历结果集,对于每一条记录,创建一个 Message 对象,将记录的 from,to,和 message 字段的值设置到 Message 对象中,然后将 Message 对象添加到列表中。最后,关闭数据库连接、SQL 语句对象、和结果集,释放资源。返回这个包含所有消息的列表。

(3) ObjectMapper类的使用

ObjectMapper是Jackson库中的一个核心类,它提供了一些功能来将Java对象转换为JSON表示,以及将JSON字符串转换为Java对象。这个过程通常被称为序列化和反序列化。

  • 序列化是将Java对象转换为JSON格式的过程
  • 反序列化则是将JSON格式转换为Java对象的过程。

在上面的代码中,ObjectMapper的使用可以看在以下两处:

  1. 在doGet方法中,objectMapper.writeValue(resp.getWriter(),messageList);。这里使用ObjectMapper将Java对象(messageList)转换为JSON格式的字符串,并将其写入HTTP响应。
  2. 在doPost方法中,Message message = objectMapper.readValue(req.getInputStream(),Message.class);。这里使用ObjectMapper从HTTP请求的输入流中读取JSON格式的字符串,然后将其转换为Message对象。

(4) 展示写入数据库

总结

  • 基于 HTTP 协议,客户端与服务器通信流程的本质上就是:一发一收。
  • 一发一收指的并不是只有一个客户端发送,一个服务器接收。一般情况下,一个服务器在同一时刻可以与许许多多的客户端交互。
  • 可以联想到:我们通过百度查资料,同一时刻,可能就是成千上万的人同时向百度服务器发出查询请求。
  • 然而,不同的客户端在与同一个服务器进行交互的时候,它们之间的约定是不一样的。( 比如:客户端 访问 / 接收路径,访问 / 接收数据… )

所以说,一发指的是客户端发一条指令,一收指的是服务器收到指令就会处理响应。

理解一发一收,对于 Web 开发是相当重要的。

在客户端发送请求之后,接着,服务器接收请求了,那么,服务器如何构造响应,选择在什么样的时刻处理请求,选择以什么样的格式返回响应等等…这些都是需要基于 “一发一收” 这样的规则。

综上所述,在写案例的时候,就需要先约定好:( 页面和服务器之间,要按照什么样的方式来交互),页面给服务器发送什么样的请求,服务器返回什么样的响应,这个是 Web 开发中最关键的,也是最难的步骤。
由于 前端负责构造发送请求,后端负责接收并解析请求;前端负责接收并解析响应,后端负责构造发送响应。如果不事先约定好,那么,就会造成无法正常沟通的状况。

比如:约定 HTTP请求 到底是 GET 还是 PUT ?约定 HTTP响应 到底是 json 格式 还是类似于 query string 的格式 ?约定 两者交互时的共同路径是什么 ?

同时,这也就是属于 Web程序 【设计】的一部分,这个和技术关系不大,主要是得理清楚业务流程。而业务流程取决于你的需求,这也就是你设计的初衷。

在当前表白墙的案例中,我的需求主要是为了实现服务器来保存用户提交的留言。

1. 第一个交互接口:从客户端往服务器提交数据。

当浏览器页面的用户点击提交的时候,就要给服务器发送一个请求,把这次留言的信息传给服务器。

2. 第二个交互接口:客户端从服务器拿数据。

当页面加载(刷新页面)的时候,客户端就需要给服务器发送一个请求,,把之前已经保存在服务器上的信息,获取下来,展示到浏览器的页面上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/575551.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python文件拆分技巧详解

Python 文件拆分技巧详解 随着数据量的不断增大&#xff0c;我们经常需要处理非常大的数据文件&#xff0c;这时候就需要用到文件拆分技巧。在Python中&#xff0c;文件拆分可以帮助我们提高数据处理的效率&#xff0c;这是一个非常实用的技巧。在本篇文章中&#xff0c;我们将…

奇巴布Feed流性能优化

01 项目背景 “爱奇艺奇巴布”是爱奇艺为0-8岁孩子和家长定制化设计的寓教于乐平台&#xff0c;为儿童量身打造精致的观看体验&#xff0c;精彩内容解锁寓教于乐新方式。为儿童提供优质动画内容的同时&#xff0c;我们更关注APP用户体验。在产品交互设计上我们立足儿童视角&…

抖音SEO矩阵系统开发分享及搭建流程

目录 产品功能亮点 产品介绍及开发背景 开发要求及实现流程 产品功能亮点 1. 支持多账号多平台一键 授权管理 2.支持矩阵视频批量剪辑&#xff0c;批量发布 3. 多平台关键词布局&#xff0c;提升企业及产品曝光 4. 评论区关键词自动回复&#xff0c;意向线索智能挖掘 5…

RTOS专栏(一) —— rt-thread简单介绍和qemu使用

本期主题&#xff1a; 简单介绍rt-thread介绍qemu和rt-thread怎么配合使用qemu的简单例子 rt-thread & qemu 1.rt-thread介绍2.qemu介绍3.搭建rt-thread和qemu开发环境4.简单例子 1.rt-thread介绍 RT-Thread 是一款完全由国内团队开发维护的嵌入式实时操作系统&#xff0…

《操作系统》期末主观题梳理

操作系统简答题 文章目录 操作系统简答题第一章第二章第三章第四章第五章第六章第七章第八章第九章 第一章 在计算机系统上配置OS(operating system, 操作系统)的目标是什么?作用主要表现在哪几个方面? 在计算机系统上配置OS, 主要目标是实现&#xff1a;方便性、有效性、可…

Error: Flash Download failed - Target DLL has been cancelled

文章目录 背景参考 背景 在使用keilv5进行STM32开发时&#xff0c;配置用JLink进行文件烧录&#xff0c;出现如下错误&#xff1a; 查阅资料&#xff0c;是因为Keil未识别烧录工具&#xff0c;需要进行下面的操作&#xff1a; 1.打开工程配置窗口&#xff0c;点开Debug选项卡…

并查集专题

⭐️前言⭐️ 本篇文章主要介绍与并查集相关的题目。 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题可以在评论区留言 &#x1f349;博客中涉及源码及博主…

阿里「通义千问」内测详细使用体验

名人说&#xff1a;一花独放不是春&#xff0c;百花齐放花满园。——《增广贤文》 作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、简要介绍二、分类问题测试0️⃣自我介绍1️⃣生成内容2️⃣回答问题3️⃣对话协…

springboot+vue大学生租房系统(java项目源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的大学生租房系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌…

太稳了,支付系统就该这么设计

支付中心系统对内为各个业务线提供统一的支付、退款等服务&#xff0c;对外对接三方支付或银行服务实现资金的流转。如下图&#xff1a; 大部分公司基本都是这样的架构&#xff0c;主要有以下几方面的优点&#xff1a; 形成统一支付服务&#xff0c;降低业务线接入成本及重复研…

数据结构-树,森连,二叉树之间的转换

树》二叉树 1.给兄弟加线 2.给出长子外的孩子去线 3.层次调整 &#xff08;整体向左偏移45&#xff09; eg&#xff1a; 1.给兄弟加线&#xff1a; 2.给处长紫外的孩子去线 3.层次调整&#xff0c;整体向左偏移45 &#xff08;由兄弟转化来的孩子都是右节点&#xff0c…

DJ6-5 目录管理

目录 6.5.1 文件控制块和索引结点 1、文件控制块 FCB 2、索引节点 6.5.2 简单文件目录 1、单级目录结构 2、二级目录结构 3、树形目录结构 6.5.3 目录查询技术 1、线性检索法 2、Hash 方法 文件目录&#xff1a;是指由文件说明索引组成的用于文件检索的特殊文件…

chatgpt赋能python:Python文件复制到指定文件夹——实现简单又高效的文件操作

Python 文件复制到指定文件夹——实现简单又高效的文件操作 如今&#xff0c;人们对于数据的需求越来越多&#xff0c;因此在编程过程中&#xff0c;对于文件的操作也变得越来越重要。而Python作为一种高效而简洁的编程语言&#xff0c;其文件操作也是十分出色的。本文将会带领…

C/C++ ---- 内存管理

目录 C/C内存分布 常见区域介绍 经典习题&#xff08;读代码回答问题&#xff09; 选择题 填空题 C语言内存管理方式 malloc/free calloc realloc C内存管理方式 new和delete操作内置类型 new和delete操作自定义类型 operator new和operator delete函数 new和dele…

Linux环境变量总结

Linux是一个多用户的操作系统。多用户意味着每个用户登录系统后&#xff0c;都有自己专用的运行环境。而这个环境是由一组变量所定义,这组变量被称为环境变量。用户可以对自己的环境变量进行修改以达到对环境的要求。 设置环境变量的方法 对所有用户生效的永久性变量 这类变…

K8s进阶6——pod安全上下文、Linux Capabilities、OPA Gatekeeper、gvisor

文章目录 一、Pod安全上下文1.1 配置参数1.2 案例11.2.1 dockerfile方式1.2.2 pod安全上下文方式 1.3 案例21.4 Linux Capabilities方案案例1案例2 二、pod安全策略2.1 PSP&#xff08;已废弃&#xff09;2.1.1 安全策略限制维度 2.2 OPA Gatekeeper方案2.2.1 安装Gatekeeper2.…

百度搜索迎来奇点 大模型掀起代际变革

每一轮技术革命掀起的浪潮&#xff0c;大部多数人还没来得及思考或者布局&#xff0c;已经消失于海浪中。机会是给有准备的人的&#xff0c;要发现新兴技术的亮点&#xff0c;并立足自身去积极拥抱它&#xff0c;最后转化为自身前进的动力&#xff0c;跨越周期&#xff0c;迎来…

网站出现403 Forbidden错误的原因以及怎么解决的方法

这几天刚接手一批新做的网站&#xff0c;在访问网站的时候&#xff0c;会时不时的出现403 Forbidden错误&#xff0c;浏览器会给出403 Forbidden错误提示&#xff0c;在打开Access Error中列出的URL之后, 出现以下错误&#xff1a; 403 Forbidden Access to this resource on…

SAP工具箱 批量下载指定表数据到EXCEL

点击蓝字 关注我们 一 前言 下载指定表内容到指定的EXCEL是一个比较简单的程序.但仔细考虑这个程序,还是可以在细节上找出一些关注点 多表内容同时下载,每个表生成一个文件多表选择时,先查看表的记录数大表下载时,拆分下载拆分到不同的文件中拆分到同一个文件中的不同的工作表下…

windows server 2016 ftp搭建详细教程

一.什么是FTP&#xff1f; FTP(File Transfer Protocol)是TCP/IP网络上两台计算机传送文件的协议&#xff0c;使得主机间可以共享文件。 接下来我给大家分享快速搭建FTP服务器的方法。 二.安装FTP服务器 1.进入服务器系统打开“服务器管理器”&#xff0c;点击“添加角色和功…