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

news2024/10/7 12:24:11

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

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


目录

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

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

表白墙的交互接口

纯前端的表白墙 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/574651.html

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

相关文章

【短信业务】阿里云可以发送带变量的链接短信

阿里云配置短信业务1.在账号管理中的 Accesskey管理中申请accessKeyId和accessKeySecret2.进入短信服务管理3.进入快速学习和测试申请签名&#xff1a;按照要求填写信息&#xff0c;审核一般两三个小时左右申请模板 &#xff1a;按照要求填写信息&#xff0c;审核一般两三个小时…

python+django高校就业求职招聘信息服务系统_8ryq3

本文论述了高校就业信息服务系统的设计和实现&#xff0c;该网站从实际运用的角度出发&#xff0c;运用了计算机网站设计、数据库等相关知识&#xff0c;基于系统管理和Mysql数据库设计来实现的&#xff0c;网站主要包括用户、企业、人才库、面试邀请、岗位分类、招聘信息、应聘…

【IM群发推内容参考iMessage苹果推】下面的 mailto、news 和 isbn URI 都是 URN 的示例。

要实现APNs认证以用于iMessage推送&#xff0c;以下是一样平常的步调&#xff1a; 建立苹果开发者账户&#xff1a;确保你具有苹果开发者账户。若是没有&#xff0c;请注册一个开发者账户。 登录到苹果开发者中间&#xff1a;利用你的开发者账户登录到苹果开发者中心&#xf…

凭据收集工具 Legion 瞄准额外的云服务

黑客在受感染的 Web 服务器上部署的名为 Legion 的商业恶意软件工具最近已更新&#xff0c;可以提取额外云服务的凭据以通过 SSH 进行身份验证。 这个基于 Python 的脚本的主要目标是获取存储在电子邮件提供商、云服务提供商、服务器管理系统、数据库和支付系统的配置文件中的…

【Python】循环语句 ③ ( while 嵌套循环案例 - 打印乘法表 | print 不换行打印 | tab 制表符 )

文章目录 一、print 不换行打印二、tab 制表符三、while 嵌套循环案例 - 打印乘法表 一、print 不换行打印 使用 print 函数打印字符串 , 会进行自动换行 ; Python 中的 print 函数原型如下 : def print(self, *args, sep , end\n, fileNone): 默认情况下 , print 打印字符串…

MVC模式和三层架构(附综合案例增删改查)

MVC模式和三层架构 MVC模式 MVC 是一种分层开发的模式&#xff0c;其中&#xff1a; M&#xff1a;Model&#xff0c;业务模型&#xff0c;处理业务 V&#xff1a;View&#xff0c;视图&#xff0c;界面展示 C&#xff1a;Controller&#xff0c;控制器&#xff0c;处理请求…

【ISO14229_UDS刷写】-5-$38诊断服务RequestFileTransfer理论部分

总目录&#xff1a;&#xff08;单击下方链接皆可跳转至专栏总目录&#xff09; 《UDS/OBD诊断需求编辑工具》总目录https://blog.csdn.net/qfmzhu/article/details/123697014 目录 1 $0x38 RequestFileTransfer诊断服务描述 2 0x38服务请求消息 2.1 0x38服务请求消息定义…

MongoDB window安装教程

官网下载 MongoDB&#xff1a;https://www.mongodb.com/try/download/community MongoDB shell脚本&#xff1a;https://www.mongodb.com/try/download/shell&#xff0c;下载后解压到MongoDB安装目录创建数据库文件的存放位置 在data文件夹下创建 db 文件夹&#xff08;启动 …

【composer】如何在本地开发、调试Composer包

1、准备工作 创建两个空文件夹 |- TestProject # 用于composer引入测试 |- TestPackage # composer的自定义扩展包1.1 初始化 在TestProject和TestPackage分别执行&#xff1a; composer init一路默认或者自己按需修改引导中的参数完成composer初始化 例如&#xff1a; Pa…

C++11常用的一部分新特性

C11 统一的列表初始化&#xff5b;&#xff5d;初始化std::initializer_list 声明autodecltypenullptr STL中一些变化新容器已有容器的新接口 右值引用和移动语义左值引用和右值引用右值引用使用场景和意义右值引用引用左值及其一些更深入的使用场景分析完美转发 新的类功能默认…

【ISO14229_UDS刷写】-4-$37诊断服务RequestTransferExit理论部分

总目录&#xff1a;&#xff08;单击下方链接皆可跳转至专栏总目录&#xff09; 《UDS/OBD诊断需求编辑工具》总目录https://blog.csdn.net/qfmzhu/article/details/123697014 目录 1 $0x37 RequestTransferExit诊断服务描述 2 0x37服务请求消息 2.1 0x37服务请求消息定义…

经典 SQL 数据库笔试题及答案整理

马上又是金三银四啦&#xff0c;有蛮多小伙伴在跳槽找工作&#xff0c;但对于年限稍短的软件测试工程师&#xff0c;难免会需要进行笔试&#xff0c;而在笔试中&#xff0c;基本都会碰到一道关于数据库的大题&#xff0c;今天这篇文章呢&#xff0c;就收录了下最近学员反馈上来…

PLX31-EIP-MBTCP 以太网/IP到Modbus TCP/IP

PLX31-EIP-MBTCP ProSoft Technology的EtherNet/IP to Modbus TCP/IP通信网关允许在支持EtherNet/IP的控制器或设备与Modbus TCP/IP控制器或设备之间进行高速双向数据传输。 我们的Modbus TCP/IP驱动程序具有多种客户端和服务器功能&#xff0c;可实现更快的数据传输。此外&a…

策略路由+静态路由+ip link+healthcheck检测外网物理链路提高网络的可靠性

一、适用环境 1、外网链路有防火墙Firewall出口&#xff0c;外网也有路由器Router出口。 2、用户量大需要多条外网链路负载均衡&#xff0c;多条链路也可以互为主备。 3、有ip专线网络&#xff08;上下行对称&#xff09;与拨号光纤&#xff08;上下行非对称&#xff09;网络配…

PFEA112-65 3BSE050091R65 满足正确的机械和电气安装

力传感器的工作原理对其性能有很大影响。它还影响整个称重传感器的刚性和无振动程度&#xff0c;以及其稳健性和过载耐受性。所有这些因素都会影响卷筒纸加工机械。ABB的Pressductor传感器技术由于当称重传感器受到机械力时的电磁场。 这是一个操作起源于冶金现象的原理力改变…

AI:探究下前端组件化设计的实现方法及其重要性

文章目录 1. 什么是前端组件化设计1.1 定义前端组件1.2 什么是组件化设计 2. 组件化设计的重要性2.1 提高开发效率2.2 降低维护成本2.3 促进代码复用 3. 组件化设计的原则和模式3.1 单一职责原则3.2 可复用性原则3.3 可拆分性原则3.4 可扩展性原则3.5 微型模式3.6 组件库模式3.…

Chat-GPT 聚合平台 Poe:集成多个 AI 聊天机器人

Chat-GPT 聚合平台 Poe&#xff1a;集成多个 AI 聊天机器人 介绍 Poe 是知名问答社区 Quora 推出的 AI 平台——开放探索平台 (Platform for Open Exploration, Poe)。Poe 集成了多个基于大型语言模型的聊天机器人&#xff0c;包括 ChatGPT&#xff0c;以及 Sage、Claude、Dr…

代码随想录算法训练营15期 Day 3 | 203.移除链表元素 、707.设计链表 、206.反转链表

今日任务 链表理论基础 203.移除链表元素 707.设计链表 206.反转链表 链表理论基础 链表是一种通过指针串联在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个节点的指针&#xff09;&#xff0c;最后…

代码随想录算法训练营第五十三天 | 子序列系列2

1143.最长公共子序列 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;动态规划子序列问题经典题目 | LeetCode&#xff1a;1143.最长公共子序列_哔哩哔哩_bilibili 状态&#xff1a;dp定义想不到&#xff0c;看了dp定义能写出后面部分。 思路 动规…

ab压力测试工具使用

AB测试工具使用 参考网址&#xff1a; https://pdai.tech/md/devops/linux/linux-ab-test.html 推荐 java 体系学习网址 https://pdai.tech/ 安装 基于 Linux 操作系统 &#xff0c; 在 centos7 中安装 ab 测试工具 yum -y install httpd-tools测试安装是否成功&#xff1a;…