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

news/2024/5/19 8:26:25

文章目录

  • 一、前端页面样式代码
  • 二、前后端衔接
    • 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>// 在这里实现提交操作,点击提交按钮,就可以将用户输入的内容提交到页面上来显示//在点击的时候获取三个输入框中的文本内容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>

浏览器页面展示:
在这里插入图片描述

二、前后端衔接

1. 后端创建 maven 项目

  1. 创建必要的目录文件 webapp、WEB-INF、web.xml
    在这里插入图片描述
    这里的 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 中
    在这里插入图片描述
    要注意,这里的 html 文件必须放对地方,否则后面代码的运行就会出现问题。

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

首先,这里我们需要在 main 文件下创建一个新的 Java 文件,并在其中创建出两个新的类,来书写我们的后端代码。如图:
在这里插入图片描述

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

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

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

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

  • 前端页面的 post 请求约定

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

前端页面中,点击提交时就会发出一个 post 请求。
此时,就会发送一个如下图所示的 Json 字符串。这个字符串就是对应的约定格式。
在这里插入图片描述
在前端代码中,构建这样的请求代码截取下来就是下图形式:
在这里插入图片描述

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

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

注: 在这里插入图片描述
这个问题会在后面与数据库连接的代码中进行讲解。

整体上来简单解释一下前后端 post 请求之间的配合。
在这里插入图片描述

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

  • 前端页面的 get 请求

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

前端连接的代码如下:
在这里插入图片描述
这里的 ajax 会将后端传递过来的 json 格式字符串识别为 js 能够识别的数据。

  • 后端代码实现 doGet 方法

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

注:
在这里插入图片描述
同样的,这句读取代码会在后面与数据库连接时进行解释。

整体上简单解释一下前后端在 get 请求之间的配合。大致如下:
在这里插入图片描述

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

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

单独封装数据库连接代码

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

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、实现一个关闭方法,断开连接,并注意异常的处理。

注意事项:这里是引用

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

在这里插入图片描述
这里解释的就是在 doPost 中的 save 方法。

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

代码如下:

    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);}}

注意事项:
在这里插入图片描述

解释后端读取 load 数据代码

在这里插入图片描述
这里解释的就是 doGet 中的 load 方法。

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

    //从数据库中获取所有消息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.启动服务器
在这里插入图片描述
2.访问网页页面
在这里插入图片描述

从整体的逻辑上看,前端,后端,数据库三者之间的联系,大致如下图所示:
在这里插入图片描述
码子不易,您小小的点赞是对我最大的鼓励!!!


http://www.mrgr.cn/p/86462441

相关文章

用Golang做一个永久阻塞,有哪些小技巧 ?

用Golang做一个永久阻塞,有哪些小技巧 ? 磊丰 Go语言圈 2024-05-06 08:30 广东 听全文Go语言圈 Go语言开发者的学习好助手,分享Go语言知识,技术技巧,学习与交流Go语言开发经验,互动才有助于技术的提升,每天5分钟,助你GO语言技术快乐成长 159篇原创内容公众号学习与交流:…

vue3早已具备抛弃虚拟DOM的能力了

前言 jquery时代更新视图是直接对DOM进行操作,缺点是频繁操作真实 DOM,性能差。react和vue时代引入了虚拟DOM,更新视图是对新旧虚拟DOM树进行一层层的遍历比较,然后找出需要更新的DOM节点进行更新。这样做的缺点就是如果DOM树很复杂,在进行新旧DOM树比较的时候性能就比较差…

五一假期学习总结:从DevOps到SRE

五一假期,没出远门,带娃露营玩水玩沙骑平衡车,累的不亦乐乎。同时,也刷了一门极客时间的课程《SRE实战手册》,给我带来了一些新的认知,我将这些认知整理了以下,特此总结分享与你,强烈建议已经实践了DevOps的童鞋了解一下SRE。大家好,我是Edison。 五一假期,没出远门,…

经验之谈:我为什么选择了这样一个激进的缓存大Key治理方案

本文将结合我的一次Redis大Key的治理经验,来浅谈一下缓存大Key的治理方案选择。文中主要包括缓存大Key基础知识、大Key治理方案选择、大Key治理案例等,适合有一定开发经验的开发者阅读,希望对大家有帮助。一、引言 本文将结合我的一次Redis大Key的治理经验,来浅谈一下缓存大…

Flask教程2:flask高级视图

文章目录 add_url_rule类视图的引入装饰器的自定义与使用蓝图的使用url_prefix设置蓝图前缀 add_url_rule 欲实现url与视图函数的绑定&#xff0c;除了使用路由装饰器app.route&#xff0c;我们还可以通过add_url_rule(rule,endpointNone,view_funcNone)方法&#xff0c;其中&…

llama_index微调BGE模型

微调模型是为了让模型在特殊领域表现良好,帮助其学习到专业术语等。 本文采用llama_index框架微调BGE模型,跑通整个流程,并学习模型微调的方法。 已开源:https://github.com/stay-leave/enhance_llm 一、环境准备 Linux环境,GPU L20 48G,Python3.8.10。 pip该库即可。…

视频教程下载:为 GPTs 商店构建 10 个 GPTs获得被动收入

欢迎来到 AI 驱动的内容创作新时代 - GPT 商店。这门综合课程是您成为定制和利用 GPT 模型解决多样化应用的专家的路线图。无论你是错过了应用商店革命的初始浪潮还是乘着它取得了成功&#xff0c;这都是你站在下一个重大数字飞跃前沿的机会。 课程模块&#xff1a; - 介绍 Ch…

易语言IDE界面美化支持库

易语言IDE界面美化支持库 下载下来可以看到&#xff0c;是一个压缩包。 那么&#xff0c;怎么安装到易语言中呢&#xff1f; 解压之后&#xff0c;得到这两个文件。 直接将clr和lib丢到易语言安装目录中&#xff0c;这样子就安装完成了。 打开易语言&#xff0c;在支持库配置…

WPF之border标签边框控件、设置弧度、图片

border标签在WPF中承担着边框的角色又称之为边框标签&#xff0c;使用嵌套的方法去给一些标签添加边框&#xff0c;border标签包裹目标标签(border不能有多个子元素)。一般在给标签添加弧度时可以使用border。 常用属性 CornerRadius边框拐角的弧度&#xff0c;当宽高是一样的…

分享几个.NET开源的AI和LLM相关项目框架

前言 现如今人工智能(AI)技术的发展可谓是如火如荼,它们在各个领域都展现出了巨大的潜力和影响力。今天大姚给大家分享4个.NET开源的AI和LLM相关的项目框架,希望能为大家提供一些参考。如果你有更好的推荐,欢迎RP投稿或文末留言。https://github.com/YSGStudyHards/DotNet…

Arduino安装esp32-cam

没买下载主板的可使用usb转串口模块进行烧录,接线方式可参考arduino-esp32-cam环境配置和例程使用。 2. 软件 2.1 arduino下载安装 官网https://www.arduino.cc/en/main/software下载,我的版本是2.1.0,IDE默认安装路径为C盘,自己可以选择其他盘进行安装。 2.2 arduino配置e…

华为二层交换机与路由器连通上网实验

华为二层交换机与路由器连通上网实验 二层交换机是一种网络设备&#xff0c;用于在局域网&#xff08;LAN&#xff09;中转发数据帧。它工作在OSI模型的第二层&#xff0c;即数据链路层。二层交换机通过学习和维护MAC地址表&#xff0c;实现了数据的快速转发和广播域的隔离。 实…

ThreeJS:光线投射与3D场景交互

光线投射Raycaster 光线投射详细介绍可参考&#xff1a;https://en.wikipedia.org/wiki/Ray_casting&#xff0c; ThreeJS中&#xff0c;提供了Raycaster类&#xff0c;用于进行鼠标拾取&#xff0c;即&#xff1a;当三维场景中鼠标移动时&#xff0c;利用光线投射&#xff0c;…

解密Prompt系列28. LLM Agent之金融领域摸索:FinMem FinAgent

本章介绍金融领域大模型智能体,并梳理金融LLM相关资源。大模型智能体当前集中在个股交易决策场景,而使用大模型智能体最显著的优势在于对海量信息的高效处理,存储和信息联想。FinMEM和FinAgent本章介绍金融领域大模型智能体,并梳理金融LLM的相关资源。金融领域的大模型智能…

【webrtc】MessageHandler 6: 基于线程的消息处理:StunRequest实现包发送和超时重传

G:\CDN\rtcCli\m98\src\p2p\base\stun_request.cc使用OnMessage 实现包的发送和包的超时重传StunRequest 一个StunRequest 代表是一个独立的请求的发送STUN消息 要不是发送前构造好的,要不就是按照需要构建的使用StunRequestManager: 每一个STUNRequest 携带一个交互id 写入m…

解决HTTP 403 Forbidden错误:禁止访问目录索引问题的解决方法

解决HTTP 403 Forbidden错误&#xff1a;禁止访问目录索引问题的解决方法 过去有人曾对我说&#xff0c;“一个人爱上小溪&#xff0c;是因为没有见过大海。”而如今我终于可以说&#xff0c;“我已见过银河&#xff0c;但我仍只爱你一颗星。” 在Web开发和服务器管理中&#x…

【论文笔记】Training language models to follow instructions with human feedback A部分

Training language models to follow instructions with human feedback A 部分 回顾一下第一代 GPT-1 &#xff1a; 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式&#xff1b;模型架构是基于 Transformer 的叠加解码器&#xff08;掩码自注意…

C 认识指针

目录 一、取地址操作符&#xff08;&&#xff09; 二、解引用操作符&#xff08;*&#xff09; 三、指针变量 1、 指针变量的大小 2、 指针变量类型的意义 2.1 指针的解引用 2.2 指针 - 整数 2.3 调试解决疑惑 认识指针&#xff0c;指针比较害羞内敛&#xff0c;我们…

Unity 性能优化之静态批处理(三)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、静态批处理是什么&#xff1f;二、使用步骤1.勾选Static Batching2.测试静态合批效果 三、静态合批得限制1、游戏对象处于激活状态。2、游戏对象有一…

(二十一)springboot实战——Spring AI劲爆来袭

前言 本节内容是关于Spring生态新发布的Spring AI的介绍&#xff0c;Spring AI 是一个面向人工智能工程的应用框架。其目标是将 Spring 生态系统的设计原则&#xff0c;如可移植性和模块化设计&#xff0c;应用到人工智能领域&#xff0c;并推广使用普通的Java对象&#xff08…