🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!欢迎志同道合的朋友一起加油喔🤺🤺🤺
目录
客户端与服务器之间的通信流程
理解当前案例的前后端交互流程编辑
表白墙的交互接口
纯前端的表白墙 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) 步骤
服务器 解析请求、根据请求计算响应的步骤:
- 首先,Tomcat 服务器自动为我们实现了读取请求的逻辑。
- 其次,通过 jackson API 来将 Java 对象中的字符串解析成 json 格式的数据,并写在 HTTP 响应的 正文body 中。
- 最后,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 请求、获取响应、显示响应结果的步骤:
- 首先,从 HTTP 响应中的正文 body 中获取 json 格式的内容。
- 其次,从 客户端获取到 HTTP响应 的时候,响应中的 正文body 已然从 json 格式自动转换成了 数组形式,我们就可以遍历这个数组获取每个对象,将对象的属性拼接成字符串返回。
- 最后,将 数组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 请求、获取响应、显示响应结果的步骤:
- 首先,它创建一个名为
body
的JavaScript对象,此对象包含三个属性:from
、to
和message
,这些属性的值分别由变量from
、to
和msg
提供,分别代表消息的来源,消息的接收者,以及消息内容。 - 然后,它将
body
对象转换成JSON格式的字符串,存储在strBody
变量中。这是因为在HTTP请求中,数据需要以字符串的形式发送。 - 接着,它打印出
strBody
的内容。这通常是为了进行调试,或者在控制台确认发送的数据。 - 最后,它使用jQuery的
ajax
函数发送一个HTTP POST请求。此请求的目标URL为message
,发送的数据为strBody
,并声明其内容类型(Content-Type)为JSON格式,字符编码为UTF-8。 - 在请求成功后,它会执行一个回调函数,打印出"数据发布成功"的消息,表示数据已经成功发送。
(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) 步骤
服务器 解析请求、根据请求计算响应的步骤:
- 首先,Tomcat 服务器自动为我们实现了读取请求的逻辑。
- 其次,通过 jackson API 来将 json 格式的数据解析成 Java 对象,最终以键值对的形式呈现出来,再将整个对象放入顺序表中,暂时存起来。
- 接着,我们手动设置 HTTP 响应的 header 头、响应正文 body…
- 最后,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类,这个类是一个工具类,主要用于处理数据库连接和断开的操作
- 为类定义了一个静态的
DataSource
成员,用于存储数据源。因为它是静态的,所以这个成员在整个进程中只有一个实例。 - 使用静态代码块来初始化
dataSource
。这个代码块会在类加载时执行,并且只会执行一次。这个代码块中设置了连接数据库的URL、用户名和密码。 - 提供一个静态方法
getConnection()
,用于获取数据库连接。它调用dataSource.getConnection()
方法获取一个数据库连接并返回。 - 提供一个静态方法
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。我将会按照这个顺序分别描述每个方法的执行过程。
- doGet 方法: 当客户端发送一个 GET 请求到 /message 这个 URL 的时候,doGet 方法会被调用。它首先设置 HTTP 响应的内容类型为 application/json;charset=utf8,然后调用 load 方法从数据库获取所有的消息,得到一个包含所有消息的 List<Message> 对象。然后,这个列表被转换为 JSON 格式的字符串,写入 HTTP 响应的正文中。这样,客户端就可以获取到所有的消息。
- doPost 方法: 当客户端发送一个 POST 请求到 /message 这个 URL 的时候,doPost 方法会被调用。它首先从 HTTP 请求的主体中读取数据,这些数据是 JSON 格式的,然后将这些数据解析为一个 Message 对象。然后,这个 Message 对象被传递给 save 方法,保存到数据库。最后,设置 HTTP 响应的状态码为 200,表示请求处理成功。
- save 方法: 这个方法接收一个 Message 对象,然后将这个对象保存到数据库。它首先获取一个数据库连接,然后创建一个 SQL INSERT 语句,将 Message 对象的 from,to,和 message 字段的值插入到数据库的 message 表中。然后,执行这个 SQL 语句,将数据保存到数据库。最后,关闭数据库连接和 SQL 语句对象,释放资源。
- 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的使用可以看在以下两处:
- 在doGet方法中,objectMapper.writeValue(resp.getWriter(),messageList);。这里使用ObjectMapper将Java对象(messageList)转换为JSON格式的字符串,并将其写入HTTP响应。
- 在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. 第二个交互接口:客户端从服务器拿数据。
当页面加载(刷新页面)的时候,客户端就需要给服务器发送一个请求,,把之前已经保存在服务器上的信息,获取下来,展示到浏览器的页面上。