表白墙 -- 前后端代码详解

news/2024/11/20 4:20:54/

表白墙 -- 前后端代码详解

  • 一、前端
  • 二、后端实现
    • 2.1 需求
    • 2.2 创建项目及初始化
    • 2.3 实现提交数据 (存档)
      • 2.3.1 实现 doPost
      • 2.3.2 构造请求 (修改 html 文件)
      • 2.3.3 验证
    • 2.4 实现获取数据 (读档)
      • 2.4.1 实现 doGet
      • 2.4.2 构造请求 (修改 html 文件)
      • 2.4.3 验证
  • 三、JDBC 版本 (MySQL)
    • 3.1 引入 JDBC 驱动包
    • 3.2 设计数据库表结构
    • 3.3 修改代码
    • 3.4 验证

一、前端

先提供一个之前写过的表白墙的前端代码:

<!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>
</head>
<body><style>.container {width: 400px;/* margin 外边距. 第一个数字上下外边距, 第二个数字表示水平外边距. 如果水平设置成 auto 表示元素就水平居中~~ */margin: 0 auto;}h1 {text-align: center;}p {text-align: center;color: #666;}.row {height: 40px;display: flex;/* 水平居中 */justify-content: center;/* 垂直居中 */align-items: center;}.row span {width: 100px;}.row input {width: 200px;height: 30px;}.row button {width: 306px;height: 40px;color: white;background: orange;border: none;}.row button:active {background-color: #666;}</style><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><script>let container = document.querySelector('.container');let button = document.querySelector('button');button.onclick = function() {// 1. 获取到输入框的内容let inputs = document.querySelectorAll('input');let from = inputs[0].value;let to = inputs[1].value;let message = inputs[2].value;if (from == '' || to == '' || message == '') {alert('当前输入框内容为空!');return;}console.log(from + ", " + to + ", " + message);// 2. 能够构造出新的 div, 用来保存用户提交的内容let rowDiv = document.createElement('div');rowDiv.className = 'row';rowDiv.innerHTML = from + " 对 " + to + " 说: " + message;container.appendChild(rowDiv);// 3. 提交完之后, 清空输入框的内容for (let i = 0; i < inputs.length; i++) {inputs[i].value = '';}}</script>
</body>
</html>

形如:
在这里插入图片描述

二、后端实现

2.1 需求

当我们输入一些内容:
在这里插入图片描述
但是一旦刷新后,所有数据都没了!
因为当前的数据只是在内存中存储的!关了再开,内存中原来的数据就没了 ~~
这样显然不能达到我们的预期。解决方案:
需要让用户留言的数据能够在服务器这边保存,就可以保证即使页面关闭,数据也不会丢失!!!

  • 点击提交,希望数据能够在服务器这里保存,势必要把数据发给服务器 (存档)
    在这里插入图片描述

  • 当关闭页面再打开的时候,就需要从服务器获取到之前保存过的数据,在页面上显示出来 (读档)
    在这里插入图片描述

2.2 创建项目及初始化

参考博客:https://blog.csdn.net/yyhgo_/article/details/128468738?spm=1001.2014.3001.5501
创建一个新的 Maven 项目!(引入 Servlet 依赖Jackson 依赖)

把之前实现的表白墙前端页面文件拷贝到 webapp 目录中!

2.3 实现提交数据 (存档)

在这里插入图片描述

2.3.1 实现 doPost

首先创建一个 Message 类:

public class Message {private String from;private String to;private String message;public String getFrom() {return from;}public void setFrom(String from) {this.from = from;}public String getTo() {return to;}public void setTo(String to) {this.to = to;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

MessageServlet 类:

import com.fasterxml.jackson.databind.ObjectMapper;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;@WebServlet("/message")
public class MessageServlet extends HttpServlet {// 这个对象在多个方法中都需要使用private ObjectMapper objectMapper = new ObjectMapper();private List<Message> messageList = new ArrayList<>();// 负责让页面获取到数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}// 提交数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取到 body 中的数据并解析Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 把这个 message 保存一下. 简单的办法就是保存在内存中.messageList.add(message);resp.setStatus(200);System.out.println("提交数据成功: from=" + message.getFrom()+ ", to=" + message.getTo() + ", message=" + message.getMessage());}}

2.3.2 构造请求 (修改 html 文件)

补充 第4步
点击发送按钮,给服务器发个 post 请求 ~~

<!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>
</head>
<body><style>.container {width: 400px;/* margin 外边距. 第一个数字上下外边距, 第二个数字表示水平外边距. 如果水平设置成 auto 表示元素就水平居中~~ */margin: 0 auto;}h1 {text-align: center;}p {text-align: center;color: #666;}.row {height: 40px;display: flex;/* 水平居中 */justify-content: center;/* 垂直居中 */align-items: center;}.row span {width: 100px;}.row input {width: 200px;height: 30px;}.row button {width: 306px;height: 40px;color: white;background: orange;border: none;}.row button:active {background-color: #666;}</style><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">黑猫 对 白猫 说: 喵</div> --></div><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script><script>let container = document.querySelector('.container');let button = document.querySelector('button');button.onclick = function() {// 1. 获取到输入框的内容let inputs = document.querySelectorAll('input');let from = inputs[0].value;let to = inputs[1].value;let message = inputs[2].value;if (from == '' || to == '' || message == '') {alert('当前输入框内容为空!');return;}console.log(from + ", " + to + ", " + message);// 2. 能够构造出新的 div, 用来保存用户提交的内容let rowDiv = document.createElement('div');rowDiv.className = 'row';rowDiv.innerHTML = from + " 对 " + to + " 说: " + message;container.appendChild(rowDiv);// 3. 提交完之后, 清空输入框的内容for (let i = 0; i < inputs.length; i++) {inputs[i].value = '';}// 4. 点击发送按钮, 给服务器发个 post 请求. let data = {from: from,to: to,message: message};$.ajax({type: 'post',url: 'message',// url: '/java105/message',// 这里放的是 body 的内容data: JSON.stringify(data),contentType: "application/json; charset=utf8",success: function(body) {console.log("提交数据成功");}});}</script>
</body>
</html>

细节:
在这里插入图片描述
在这里插入图片描述

2.3.3 验证

1)启动 tomcat 服务器
在这里插入图片描述

2)通过 表白墙.html 发送请求

访问 http://127.0.0.1:8080/MessageWall/表白墙.html:

在这里插入图片描述

过程中使用 Fiddler 抓包:
请求:
在这里插入图片描述
服务器解析结果:
在这里插入图片描述
响应:
在这里插入图片描述

2.4 实现获取数据 (读档)

在这里插入图片描述

2.4.1 实现 doGet

MessageServlet 类:

import com.fasterxml.jackson.databind.ObjectMapper;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;@WebServlet("/message")
public class MessageServlet extends HttpServlet {// 这个对象在多个方法中都需要使用private ObjectMapper objectMapper = new ObjectMapper();private List<Message> messageList = new ArrayList<>();// 负责让页面获取到数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// body 就是响应的 body 内容 (json 数组).// jquery 非常智能的帮我们把 json 数组给解析成了 js 对象数组// 但是有个前提条件, 就是响应的 Content-Type 得是 application/jsonresp.setContentType("application/json; charset=utf8");// 把 messageList 转成 json 字符串,并且返回给页面就行了.resp.getWriter().write(objectMapper.writeValueAsString(messageList));}// 提交数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取到 body 中的数据并解析Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 把这个 message 保存一下. 简单的办法就是保存在内存中.messageList.add(message);resp.setStatus(200);System.out.println("提交数据成功: from=" + message.getFrom()+ ", to=" + message.getTo() + ", message=" + message.getMessage());}}

2.4.2 构造请求 (修改 html 文件)

什么时候来发这个请求呢?
页面加载的时候,我们就希望进行读档操作!
==================================================================================
在 html 文件中,哪里是页面加载的时候呢?
直接写在 script 标签里的代码,都是在页面加载的时候执行的!

<!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>
</head>
<body><style>.container {width: 400px;/* margin 外边距. 第一个数字上下外边距, 第二个数字表示水平外边距. 如果水平设置成 auto 表示元素就水平居中~~ */margin: 0 auto;}h1 {text-align: center;}p {text-align: center;color: #666;}.row {height: 40px;display: flex;/* 水平居中 */justify-content: center;/* 垂直居中 */align-items: center;}.row span {width: 100px;}.row input {width: 200px;height: 30px;}.row button {width: 306px;height: 40px;color: white;background: orange;border: none;}.row button:active {background-color: #666;}</style><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">黑猫 对 白猫 说: 喵</div> --></div><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script><script>let container = document.querySelector('.container');let button = document.querySelector('button');button.onclick = function() {// 1. 获取到输入框的内容let inputs = document.querySelectorAll('input');let from = inputs[0].value;let to = inputs[1].value;let message = inputs[2].value;if (from == '' || to == '' || message == '') {alert('当前输入框内容为空!');return;}console.log(from + ", " + to + ", " + message);// 2. 能够构造出新的 div, 用来保存用户提交的内容let rowDiv = document.createElement('div');rowDiv.className = 'row';rowDiv.innerHTML = from + " 对 " + to + " 说: " + message;container.appendChild(rowDiv);// 3. 提交完之后, 清空输入框的内容for (let i = 0; i < inputs.length; i++) {inputs[i].value = '';}// 4. 点击发送按钮, 给服务器发个 post 请求. let data = {from: from,to: to,message: message};$.ajax({type: 'post',url: 'message',// url: '/java105/message',// 这里放的是 body 的内容data: JSON.stringify(data),contentType: "application/json; charset=utf8",success: function(body) {console.log("提交数据成功");}});}// 直接写在 script 标签里的代码, 都是在页面加载的时候执行的. // 来获取服务器的数据function getMessages() {$.ajax({type: 'get' ,url: 'message',success: function(body) {// body 就是响应的 body 内容 (json 数组). // jquery 非常智能的帮我们把 json 数组给解析成了 js 对象数组// 但是有个前提条件, 就是响应的 Content-Type 得是 application/jsonlet container = document.querySelector('.container');// 观察 html, .row 都是在 .container 中存放的,所以获取到.container,把新的 .row 都加进去!  for (let i = 0; i < body.length; i++) {let message = body[i];// 根据这个元素构造一个 div.row, 来容纳数据// <div class="row">//     黑猫 对 白猫 说: 喵// </div>let row = document.createElement('div');row.className = 'row';row.innerHTML = message.from + " 对 " + message.to + " 说: " + message.message;container.appendChild(row);}}});}getMessages();</script>
</body>
</html>

function 中的参数 body 就是响应的 body 内容 (json 数组)!
jquery 非常智能地帮我们把 json 数组给解析成了 js 对象数组!但是有个前提条件,就是响应的 Content-Type 得是 application/json 格式!
在这里插入图片描述
如果 jquery 没做这个事情,就需要使用 JSON.parse 来完成 ~~

2.4.3 验证

1)重新启动 tomcat 服务器
在这里插入图片描述

2)访问 http://127.0.0.1:8080/MessageWall/表白墙.html

此时提交数据后,无论怎样刷新,数据仍然保留!!!成功 ~

在这里插入图片描述

服务器重启,原有的数据就没了 ~~

页面刷新过程中使用 Fiddler 抓包:
请求:
在这里插入图片描述
响应:
在这里插入图片描述

三、JDBC 版本 (MySQL)

我们这个程序目前最大的问题就是:数据在内存中,服务器一旦重启就没了。我们需要让数据在数据库中持久化保存!JDBC!!!

3.1 引入 JDBC 驱动包

中央仓库中搜索 mysql,选择:
在这里插入图片描述

这里选择 5.1.49:
在这里插入图片描述

将代码拷贝到 pom.xml 中:
在这里插入图片描述
在这里插入图片描述

3.2 设计数据库表结构

设计有几张表,表里有什么 ~~

1.message 表;
2.三个列:from、to、message

在这里插入图片描述

注意: from 等关键字,需要加上反引号 `` !!!

在这里插入图片描述

3.3 修改代码

Java的JDBC编程 博客链接:https://blog.csdn.net/yyhgo_/article/details/128061324?spm=1001.2014.3001.5501

通过数据库来 存 / 读 数据,就不再需要 ArrayList 了 ~~
主要是两个方法:

  • private void save(Message message) :把数据保存到数据库中
  • private List<Message> load() :从数据库查询数据

完整代码:

public class Message {private String from;private String to;private String message;public String getFrom() {return from;}public void setFrom(String from) {this.from = from;}public String getTo() {return to;}public void setTo(String to) {this.to = to;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;// 使用这个类来封装 DataSource 的单例
public class DBUtil {private static volatile DataSource dataSource = null;private DBUtil() {}public static DataSource getDataSource() {if (dataSource == null) {synchronized (DBUtil.class) {if (dataSource == null) {dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java105?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");// 数据库密码.((MysqlDataSource)dataSource).setPassword("632yyh..");}}}return dataSource;}}
import com.fasterxml.jackson.databind.ObjectMapper;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.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;@WebServlet("/message")
public class MessageServlet extends HttpServlet {// 这个对象在多个方法中都需要使用private ObjectMapper objectMapper = new ObjectMapper();// 负责让页面获取到数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 显式声明当前的响应数据格式 不要让客户端去猜!!!resp.setContentType("application/json; charset=utf8");// 把 messageList 转成 json 字符串, 并且返回给页面就行了.List<Message> messageList = null;try {messageList = load();} catch (SQLException e) {e.printStackTrace();}resp.getWriter().write(objectMapper.writeValueAsString(messageList));}// 提交数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取到 body 中的数据并解析Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 把这个 message 保存一下. 简单的办法就是保存在内存中.// messageList.add(message);try {save(message);} catch (SQLException e) {e.printStackTrace();}resp.setStatus(200);System.out.println("提交数据成功: from=" + message.getFrom()+ ", to=" + message.getTo() + ", message=" + message.getMessage());}private void save(Message message) throws SQLException {// 把数据保存到数据库中// 1. 先有一个数据源DataSource dataSource = DBUtil.getDataSource();// 2. 建立连接Connection connection = dataSource.getConnection();// 3. 构造 SQLString sql = "insert into message values(?, ?, ?)";PreparedStatement statement = connection.prepareStatement(sql);statement.setString(1, message.getFrom());statement.setString(2, message.getTo());statement.setString(3, message.getMessage());// 4. 执行 SQLint ret = statement.executeUpdate();System.out.println("ret = " + ret);// 5. 关闭连接statement.close();connection.close();}private List<Message> load() throws SQLException {// 从数据库查询数据// 1. 先有一个数据源DataSource dataSource = DBUtil.getDataSource();// 2. 建立连接Connection connection = dataSource.getConnection();// 3. 构造 SQLString sql = "select * from message";PreparedStatement statement = connection.prepareStatement(sql);// 4. 执行 SQLResultSet resultSet = statement.executeQuery();// 5. 遍历结果集合List<Message> messageList = new ArrayList<>();while (resultSet.next()) {Message message = new Message();message.setFrom(resultSet.getString("from"));message.setTo(resultSet.getString("to"));message.setMessage(resultSet.getString("message"));messageList.add(message);}// 6. 关闭连接statement.close();connection.close();return messageList;}}

细节:
数据源不需要创建多份,因此可以使用单例模式:单独构造一个 类DBUtil !

Servlet 代码中是否涉及到 多线程/线程安全 的问题呢?
Servlet 写的是一个服务器。同一时刻,可能要处理多个客户端的请求!
一旦同时有多个客户端都发来请求,服务器势必就需要同时处理多个请求。Tomcat 内部正是使用了多线程的方式来处理的 ~~

3.4 验证

1)重新启动 tomcat 服务器
在这里插入图片描述

2)访问 http://127.0.0.1:8080/MessageWall/表白墙.html

此时提交数据后,无论怎样刷新,还是重新启动服务器,数据仍然保留!!!成功 ~

在这里插入图片描述

此时查看数据库中 message 表的数据:
在这里插入图片描述


完!提前祝大家 2023 新年快乐!~~


http://www.ppmy.cn/news/8705.html

相关文章

Java个人家乡博客源码

概述 个人博客相册家乡主题&#xff0c;用户注册后可以发布关于家乡的特色文章介绍&#xff0c;可以发布照片&#xff0c;相册管理&#xff0c;留言&#xff0c;评论&#xff0c;回复&#xff0c;收藏&#xff0c;关注 演示视频 https://www.bilibili.com/video/BV1iy4y1x7w6…

Python数据分析案例16——水质检测(支持向量机)

本次带来图片分类的案例&#xff0c;水质检测。 数据展示 五种类别的水质&#xff0c;图片形式储存的&#xff1a; 前面1是代表水质的类别标签&#xff0c;后面是样本个数。 图片特征构建 import numpy as np import pandas as pd import matplotlib.pyplot as plt import o…

Python代码实现学生管理系统

Python代码实现学生管理系统 需求说明 实现一个命令行版本的学生管理系统 功能: 新增学生 显示学生 查找学生 删除学生 存档到文件 创建入口函数 使用一个全局列表 students 表示所有学生信息. 使用 menu 函数和用户交互. 这是一个自定义函数. 使用 insert , show ,…

56. 数据增广 / 图像增广

1. CES上的真实故事 2. 数据增强 增加一个已有数据集&#xff0c;使得有更多的多样性 在语言里加入各种不同的背景噪音改变图片的颜色和形状 例如&#xff0c;我们可以以不同的方式裁剪图像&#xff0c;使感兴趣的对象出现在不同的位置&#xff0c;减少模型对于对象出现位置…

Python全栈开发(一)——环境搭建和入门

今天是2023年的第一天&#xff0c;接下来的一个月里&#xff0c;我将持续更新关于python全栈开发的相关知识&#xff0c;前面一段时间都是基础语法。主要分成四大块&#xff1a;基础、面向对象、MYSQL数据库、Django框架。话不多说&#xff0c;进入到今天的主题。 1.文档和工具…

【CSP】邻域均值

邻域均值 邻域均值 题意比较好理解&#xff0c;就是算一些数字。如果采用暴力方法的话&#xff0c;就是用一个边长为 2∗r12*r12∗r1 的正方形框框住大矩阵&#xff0c;然后遍历这个框&#xff0c;求出其平均值&#xff0c;然后移动正方形框&#xff0c;直到大矩阵内所有像…

MySql底层索引原理

前言 我们都知道MySql索引效率很高&#xff01;那其中的原理是什么呢&#xff1f;先跑出个问题来&#xff1a;二叉树、红黑树&#xff08;二叉平衡树&#xff09;、BTree&#xff08;平衡多叉树&#xff09;、Btree这几种类型中哪一种是mysql索引所选择的呢&#xff1f; 这个…

更新和删除数据

目录1、更新数据2、根据其他表更新数据3、 删除数据4、根据其他表删除数据对于不加WHERE条件的UPDATE和DELETE要格外谨慎&#xff01; 1、更新数据 1.1 更新全部数据&#xff1a;使用UPDATE关键字。语法如下&#xff1a; UPDATE 表名 SET 字段名新的值; 比如&#xff0c;更新学…