程序设计——前后端分离实现简单表白墙

devtools/2024/10/9 13:30:47/
http://www.w3.org/2000/svg" style="display: none;">

文章目录

  • 一、前端页面样式代码
  • 二、前后端衔接
    • 1. 后端创建 maven 项目
    • 2. 针对前后端交互的解释以及后端代码的实现
      • 针对 post 请求解释前后端衔接
      • 针对 Get 请求解释前后端衔接
    • 3.后端与数据库的联系以及对数据的存取
      • 单独封装数据库连接代码
      • 解释后端存储 save 数据的代码
      • 解释后端读取 load 数据代码
  • 三、总结

本篇文章所实现的这个表白墙,是一个前后端分离的一个 web 程序。

本篇文章中整体的代码本人以及上传至 gitee 如有需要可以访问查看:整体代码

这篇文章会重点解释后端的实现,对此,前端页面样式构建的代码不会进行过多的解释,将会直接的呈现在大家面前。

一、前端页面样式代码

<!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><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: wheat;background-color: #ff6600;border: none;}/* 让点击的时候有一个反馈 */.row button:active{background-color: #535350;}
</style><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><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>javascript">// 在这里实现提交操作,点击提交按钮,就可以将用户输入的内容提交到页面上来显示//在点击的时候获取三个输入框中的文本内容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 构造divlet rowDiv = document.createElement('div');rowDiv.className = 'row massage';rowDiv.innerHTML = from + '对' + to + '说' + msg;containerDiv.appendChild(rowDiv);//3.清空前面的输入for(let input of inputs){input.value = '';}// 4. [新增] 给服务器发起 post 请求, 把上述数据提交到服务器这边let body = {"from": from,"to": to,"message": msg};let strBody = JSON.stringify(body);console.log("strBody: " + strBody);$.ajax({type: 'post',url: 'message',data: strBody,contentType: "application/json; charset=utf8",success: function(body) {console.log("数据发布成功");}});}let revertButton = document.querySelector('#revert');revertButton.onclick = function(){//删除最后一条消息//选中所有的 row ,找出最后一个 rowlet rows = document.querySelectorAll('.massage');if (rows == null || rows.length == 0) {return;}containerDiv.removeChild(rows[rows.length-1]);}// [新增] 在页面加载的时候, 发送 GET 请求, 从服务器获取到数据并添加到页面中$.ajax({// 将前面获取到变量名的值 给到这边对应的 valuetype: 'get',url: 'message',success: function(body) {// 此处拿到的 body 就是一个 js 的对象数组了. // 本来服务器返回的是一个 json 格式的字符串, 但是 jquery 的 ajax 能够自动识别// 自动帮我们把 json 字符串转成 js 对象数组// 接下来遍历这个数组, 把元素取出来, 构造到页面中即可let containerDiv = document.querySelector('.container')for (let message of body) {// 针对每个元素构造一个 divlet rowDiv = document.createElement('div');rowDiv.className = 'row message';rowDiv.innerHTML = message.from + '对' + message.to + '说:' + message.message;containerDiv.appendChild(rowDiv);}}});
</script></body>
</html>

浏览器页面展示:
https://img-blog.csdnimg.cn/2ce29a1f563848fcaf4e85c594899425.png" alt="在这里插入图片描述" />

二、前后端衔接

1. 后端创建 maven 项目

  1. 创建必要的目录文件 webapp、WEB-INF、web.xml
    https://img-blog.csdnimg.cn/477561bf4b0f4aec922d9426e7819f6f.png" alt="在这里插入图片描述" />
    这里的 web.xml 中的代码如下:
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app><display-name>Archetype Created Web Application</display-name>
</web-app>
  1. 调整 pom.xml
    这里需要再 maven 仓库中引入三个对应的 jar 包。分别是:
    servlet 该 jar 包提供了大量后续代码需要使用的 Tomcat API。
    jackson: 便于前后端使用 Jackson 进行键值对构建
    mysql: 用于之后将交互信息存储到数据库中,用于之后访问时信息不会消失。
    代码展示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>MassageWall</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies>
<!--对应的 servlet 的 jar 包--><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--对应的 Jackson 的 jar 包--><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.1</version></dependency><!--对应的 mysql 的 jar 包--><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency></dependencies></project>
  1. 将前端页面拷贝到 webapp 中
    https://img-blog.csdnimg.cn/1c0c2f8a5dd847f4b3765630d7c4c2ef.png" alt="在这里插入图片描述" />
    要注意,这里的 html 文件必须放对地方,否则后面代码的运行就会出现问题。

2. 针对前后端交互的解释以及后端代码的实现

首先,这里我们需要在 main 文件下创建一个新的 Java 文件,并在其中创建出两个新的类,来书写我们的后端代码。如图:
https://img-blog.csdnimg.cn/2f39e3ea91264878b1e3538d49871ddb.png" alt="在这里插入图片描述" />

当前的代码是在 massageServlet 中实现的。

在所有的代码实现之前,我们都需要进行规划,来确保我们每一步都在正确的方向上。
对于这里的代码,我们首先就需要进行约定。

这里的约定,本质上就是描述一个 前后端信息交互时的格式。

针对 post 请求解释前后端衔接

  • 前端页面的 post 请求约定

这里切记一点,这里的 前端页面 是存放在 webapp 文件夹中的,后端代码是可以接收到其发出的 post 请求的。

前端页面中,点击提交时就会发出一个 post 请求。
此时,就会发送一个如下图所示的 Json 字符串。这个字符串就是对应的约定格式。
https://img-blog.csdnimg.cn/51ae2ee8121549b7a3479ecc5e2cf1f5.png" alt="在这里插入图片描述" />
在前端代码中,构建这样的请求代码截取下来就是下图形式:
https://img-blog.csdnimg.cn/74e7a50428a5476b95b7656a0e05ef7f.png" alt="在这里插入图片描述" />

  • 后端页面接受 post 请求的约定

对于后端代码,接受 post 请求实现的是 doPost 方法。在接受传入的信息之前,后端代码需要定义一个 class 来作为约定来接受信息。如图:
https://img-blog.csdnimg.cn/01a723d17e2e4b63835db9a3ad5e543c.png" alt="在这里插入图片描述" />
下半部分是 doPost 方法的实现,其中 readValue 会将获取到的 json 字符串转化为 java 对象。
后端代码这里的作用是: 将前端传递的信息进行获取并储存起来。

注: https://img-blog.csdnimg.cn/b4820dc2dc2a42dd9d18e48aeaa8ae41.png" alt="在这里插入图片描述" />
这个问题会在后面与数据库连接的代码中进行讲解。

整体上来简单解释一下前后端 post 请求之间的配合。
https://img-blog.csdnimg.cn/6571bcaa609146f8a610f33d16eccd04.png" alt="在这里插入图片描述" />

针对 Get 请求解释前后端衔接

  • 前端页面的 get 请求

对于前端页面,我们知道,在我们根据文件目录进行访问时,每次访问,前面的数据信息就会消失。
但是,在与后端连接时,前端页面在加载时,就会向后端服务器发送一个 get 请求获取之前的信息。
之后将其显示在浏览器的页面上。

前端连接的代码如下:
https://img-blog.csdnimg.cn/30bac6e5d926439aae2c3522103ccdd9.png" alt="在这里插入图片描述" />
这里的 ajax 会将后端传递过来的 json 格式字符串识别为 js 能够识别的数据。

  • 后端代码实现 doGet 方法

对于后端,在得到前端 get 请求之后。就会执行 doGet 方法来实现对前端的相应。
即就是,将之前的信息进行读取并解析为 json 字符串后,将其发送到前端的 body 中
代码如下:
https://img-blog.csdnimg.cn/23c8adc19b274ed6a7b3dd8149816800.png" alt="在这里插入图片描述" />

注:
https://img-blog.csdnimg.cn/53ddd35589c943209cdf47c8a0b625da.png" alt="在这里插入图片描述" />
同样的,这句读取代码会在后面与数据库连接时进行解释。

整体上简单解释一下前后端在 get 请求之间的配合。大致如下:
https://img-blog.csdnimg.cn/27f7b4ab6af84dc98bee08d73679d1e9.png" alt="在这里插入图片描述" />

3.后端与数据库的联系以及对数据的存取

到这里,前后端之间的信息交互的代码已经结束了。
从这里开始,我将会进行后端对数据的存储,以及前端页面加载时数据从数据库中的读取进行解释。

单独封装数据库连接代码

首先在 DBUtil 中单独实现一个数据库连接的类,将其进行封装。

java">import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;//通过这个类将数据库连接封装一下
// 此处这个类作为一个工具类,提供 static 方法供以调用
public class DBUtil {//静态成员跟随类对象,类对象在整个进程中只有一份//静态成员相当于是唯一的事例。(单例模式,饿汉模式)private static DataSource dataSource = new MysqlDataSource();//这里的代码在类加载的时间就会被创建出来static{//使用静态代码块,针对 DataSource 进行初始化//这里与 JDBC 有相似之处,需要将连接的信息建立起来((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/wall?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("wjh123456");}//通过这个方法来建立连接public static Connection getConnection() throws SQLException {return dataSource.getConnection();}//通过这个方法断开连接,释放资源//connection    就是指连接的状态//statement     是指当前正在执行的 sql 语句//resultSet     是指当前正在获取 sql 语句执行的结果public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){// 此处的三个 try catch 分开写更好, 避免前面的异常导致后面的代码不能执行.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();}}}
}

这里的代码还是比较好理解的,大致分为两部分:
1、实现一个连接方法,将代码和数据库的连接独立出来,在其他方法请求时立即反应并进行连接。(饿汉模式)。

这里的 static 使得代码在类加载时就已经生产出来了,也就是说一直在等待着被连接。

2、实现一个关闭方法,断开连接,并注意异常的处理。

注意事项:https://img-blog.csdnimg.cn/1cbeda95a2884459952cbcbedb1178d7.png" alt="这里是引用" />

解释后端存储 save 数据的代码

https://img-blog.csdnimg.cn/52029050bd6a4f308c66afd5f566c90c.png" alt="在这里插入图片描述" />
这里解释的就是在 doPost 中的 save 方法。

这里的 save 与 JDBC 中的存储非常相似,代码不难理解,大致分为四步:
1、建立连接
2、构造 SQL 语句
3、执行 SQL 语句
4、断开连接

代码如下:

java">    private void save(Message message){//JDBC 操作Connection connection = null;PreparedStatement statement = null;try {//1. 建立连接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. 执行 sqlstatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}finally {// 4. 关闭连接.保证代码一定可以执行到DBUtil.close(connection, statement, null);}}

注意事项:
https://img-blog.csdnimg.cn/55dfc71df01f41bd8794857f5e211523.png" alt="在这里插入图片描述" />

解释后端读取 load 数据代码

https://img-blog.csdnimg.cn/6fff8be1e50f4852b67f1c8b4b3ed0fa.png" alt="在这里插入图片描述" />
这里解释的就是 doGet 中的 load 方法。

同样的,这里的代码与 JDBC 中的操作很是相似,代码同样不难理解,大致分为下面四步:
1、与数据库建立连接
2、构造 SQL 语句
3、执行 SQL 语句
4、遍历结果集合,并存放到链表中进行返回
5、断开与数据库连接

java">    //从数据库中获取所有消息private List<Message> load(){List<Message> messageList = new ArrayList<>();Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {// 1. 和数据库建立连接connection = DBUtil.getConnection();// 2. 构造 SQLString sql = "select * from message";statement = connection.prepareStatement(sql);// 3. 执行 SQLresultSet = statement.executeQuery();// 4. 遍历结果集合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 {// 5. 需要释放资源, 断开连接DBUtil.close(connection, statement, resultSet);}return messageList;}

三、总结

到这里,前后端分离的实现就已经大功告成了。

整体的运行展示:
1.启动服务器
https://img-blog.csdnimg.cn/d1fe84421aab469ca1f34b12d49d0b8c.png" alt="在这里插入图片描述" />
2.访问网页页面
https://img-blog.csdnimg.cn/5c0fdd31d06640b68b5e740bcd5f43a1.png" alt="在这里插入图片描述" />

从整体的逻辑上看,前端,后端,数据库三者之间的联系,大致如下图所示:
https://img-blog.csdnimg.cn/968284cd33ef4573a00984a8fe746565.png" alt="在这里插入图片描述" />
码子不易,您小小的点赞是对我最大的鼓励!!!


http://www.ppmy.cn/devtools/38903.html

相关文章

OpenAI计划下周一宣布对标谷歌搜索的竞品;苹果将使用自有服务器芯片为AI工具提供支持 | 最新快讯

《科创板日报》5月10日讯 今日科创板早报的主要内容还有&#xff1a;行业协会&#xff1a;硅片价格已经脱离供需基本面运行&#xff0c;并朝向非理性方向发展&#xff1b;中芯国际、华虹公司Q1净利同比大降。 【市场动态】 OpenAI计划下周一宣布对标谷歌搜索的竞品 OpenAI计…

基于C++函数基础中的形参与实参

在C中&#xff0c;函数的形参&#xff08;形式参数&#xff09;是在函数定义时声明的参数&#xff0c;而实参&#xff08;实际参数&#xff09;是在函数调用时传递给函数的值或变量。 形参的作用是定义函数在执行时所需要的输入&#xff0c;它们在函数体内被当做局部变量使用。…

设计模式-观察者模式

作者持续关注 WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 目录 定义 特点 使用场景 优缺点 (1) 优点 (2)…

【DevOps】Ubuntu防火墙配置:如何封禁黑客攻击源IP

在网络安全防护的实践中&#xff0c;及时识别并封锁恶意攻击的IP地址是至关重要的。本文将指导您如何使用Ubuntu系统的防火墙工具有效地封禁那些试图侵入网络的黑客IP。通过详细的步骤和实用的命令&#xff0c;即使是初学者也能轻松掌握如何配置防火墙&#xff0c;增强您的网络…

神经网络中的归一化

我们今天介绍一下神经网络中的归一化方法~ 之前学到的机器学习中的归一化是将数据缩放到特定范围内&#xff0c;以消除不同特征之间的量纲和取值范围差异。通过将原始数据缩放到一个特定的范围内&#xff0c;比如[0,1]或者[-1,1]&#xff0c;来消除不同特征之间的量纲和取值范围…

12.轻量级锁原理及其实战

文章目录 轻量级锁原理及其实战1.轻量级锁的核心原理2.轻量级锁的演示2.1.轻量级锁的演示代码2.2.结果分析 3.轻量级锁的分类3.1.普通自旋锁3.2.自适应自旋锁 4.轻量级锁的膨胀 轻量级锁原理及其实战 引入轻量级锁的主要目的是在多线程环境竞争不激烈的情况下&#xff0c; 通过…

机器学习各个算法的优缺点!(下篇) 建议收藏。

上篇地址&#xff1a;机器学习各个算法的优缺点&#xff01;&#xff08;上篇&#xff09; 建议收藏。-CSDN博客 直接进入主题。 目录 6.降维算法 7.聚类算法 8.贝叶斯算法 9.人工神经网络 10.深度学习 谢谢观看。 6.降维算法 降维算法是一类用于减少数据维度的技术。 …

iOS——SDWebImage源码学习

什么是SDWebImage SDWebImage是一个流行的iOS和macOS平台上的开源库&#xff0c;用于异步加载和缓存网络图片。它提供了一套简单易用的API&#xff0c;使得在应用中加载网络图片变得更加方便和高效。 主要特点和功能&#xff1a; 异步加载&#xff1a;SDWebImage通过异步方式…