用Servlet实现一个简单的表白墙

1. 准备工作

创建项目,引入依赖......

将静态页面放到项目中(放在webapp目录下):


当前,这个表白墙页面,已经可以输入内容,点击提交之后也能显示内容,后续后端要做的工作即:

①存档

用户点提交的时候,把刚才输入的内容通过网络传输给服务器,由服务器保存这个数据.

②读档

后续有页面加载的时候,此时就通过网络,从服务器获取到之前保存好的内容.

都需要进行前后端交互接口的约定.

约定好,前端会给后端发起一个什么样的HTTP请求,后端返回什么样的HTTP响应.


html中的每个元素,同时都可以映射到js中的一个对象.(文档-对象模型)

通过对象的属性,就能获取到页面的内容.

修改对象的属性,也就能更新页面的内容.

2. 后端操作

非持久化保存数据: 

class Message{public String from;public String to;public String message;@Overridepublic String toString() {return "Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();//此处把消息保存到内存中(一旦重启服务器,内存数据就没了)private List<Message> messageList = new ArrayList<>();    //更科学的方式,应该是保存到数据库中//用来实现存档操作@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.读取请求的body,转换成Java对象Message message = objectMapper.readValue(req.getInputStream(),Message.class);//2.得到message之后,把message保存到服务器中messageList.add(message);System.out.println("服务器收到message: "+ message );//3.返回响应(不太必要,主要是返回一个200 OK就行了,body可以没有)resp.setStatus(200);resp.getWriter().write("ok");}//用来实现读档操作@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//把我们内存中的这些Message,组织成json格式,返回到响应中.String respJson = objectMapper.writeValueAsString(messageList);//告诉浏览器,返回的响应的body是一个json格式.resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}
}

持久化保存数据:

class Message{public String from;public String to;public String message;@Overridepublic String toString() {return "Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();//此处把消息保存到内存中(一旦重启服务器,内存数据就没了)//private List<Message> messageList = new ArrayList<>();    //更科学的方式,应该是保存到数据库中//用来实现存档操作@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.读取请求的body,转换成Java对象Message message = objectMapper.readValue(req.getInputStream(),Message.class);//2.得到message之后,把message保存到服务器中//messageList.add(message);try {save(message);} catch (SQLException e) {e.printStackTrace();}System.out.println("服务器收到message: "+ message );//3.返回响应(不太必要,主要是返回一个200 OK就行了,body可以没有)resp.setStatus(200);resp.getWriter().write("ok");}//用来实现读档操作@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//把我们内存中的这些Message,组织成json格式,返回到响应中.List<Message> messageList = null;try {messageList = load();} catch (SQLException e) {e.printStackTrace();}String respJson = objectMapper.writeValueAsString(messageList);//告诉浏览器,返回的响应的body是一个json格式.resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}//通过jdbc,往数据库中存一个数据.private void save(Message message) throws SQLException {//1.创建数据源DataSource dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("808250");//2.建立连接Connection connection = dataSource.getConnection();//3.构造SQLString sql = "insert into message values(?,?,?)";PreparedStatement statement = connection.prepareStatement(sql);statement.setString(1,message.from);statement.setString(2,message.to);statement.setString(3,message.message);//4.执行SQLstatement.executeUpdate();//5.释放资源,关闭连接statement.close();connection.close();}private List<Message> load() throws SQLException {//1.创建数据源DataSource dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("808250");//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.from = resultSet.getString("from");message.to = resultSet.getString("to");message.message = resultSet.getString("message");messageList.add(message);}//6.关闭连接,释放资源resultSet.close();;statement.close();connection.close();return messageList;}
}

2.1 存档(非持久化保存数据) 

针对存档操作来说,前端发起一个HTTP请求.

此处约定使用json格式,把数据输出到后端.

让服务器返回一个HTTP响应. HTTP/1.1 200OK.


当前这个程序并不能在服务器重启之后保存数据,也就是把数据保存在了内存里,这样的设定并不科学.应该让数据持久化保存.

在刚才的代码基础上,引入数据库,来保存上述数据.

2.2 读档

前端页面加载的时候,需要从服务器拿到之前已经提交的数据.

响应的json应该是数组了,返回的数据会有多条.


2.3 用数据库-持久化保存数据

 2.3.1 引入数据库的依赖(驱动包)
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.32</version>
</dependency>
2.3.2 创建数据库,创建数据表

2.3.3 编写代码 

JDBC操作数据库,完成这里的数据存和取.

3. 前端操作

3.1 "存档"请求

 


先让js代码发起"存档"请求.

需要前端和后端通过HTTP交互,使用ajax.

 


 

这个相对路径的基准路径,就是当前HTML所在的路径.

写了相对路径message,就相当于在message基础上,加上一层/messageWall

一般会优先写作相对路径的方式.

后续如果要修改context path就比较方便,对于代码影响比较小了.



用户点击提交按钮,触发js提交数据的代码.

1.ajax方法会根据输入的参数,构造出HTTP请求,发给服务器.

2.服务器就会执行到对应的doPost方法.

3.响应回来之后,执行刚才设置好的success回调函数.


 

回调函数,其实是有三个参数的.

success(result,status,xhr)

对于JS的函数来说,参数如果不用,可以不写.

这里的body是形参,名字无所谓,一个参数的时候,就表示响应的body.

这个操作是把收到的数据显示到浏览器的控制台上,而不是页面上.


3.2 "读档"请求


此时也需要把这个json字符串,反向转换回js对象数组.

但是,实际上,jquery自动帮我们做好了这里的解析操作.

此时,形参body,已经是js的对象数组了,不需要使用JSON.parse进行解析.


4. 修改代码后,重启服务器没反应

4.1 先抓包

通过抓包,就能先把问题确定出,是前端还是后端的问题.

如果抓包发现,ajax的HTTP请求就没发出来,大概率是前端的问题.

如果发出来了,并且内容符合要求,大概率是后端的问题.

4.2 关注前端代码(HTTP请求没发出来)

此时更需要关注的是,浏览器里的情况.(js代码都是被下载到浏览器中,并执行的)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/786072.shtml

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

相关文章

[中级]软考_软件设计_计算机组成与体系结构_04_寻址地址

寻址地址 概念指令的概念 寻址方式立即寻址方式直接寻址方式间接寻址方式寄存器寻址方式寄存器间接寻址方式往年真题 概念 指令的概念 一条指令就是机器语言的一个语句&#xff0c;它是一组有意义的二进制代码&#xff0c;指令的基本格式如下&#xff1a; 操作码字段地址码字…

基于springboot实现企业客户管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现企业客户管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个企业客户管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述企…

鸿蒙HarmonyOS应用开发之Node-API支持的数据类型和接口

Node-API的数据类型 napi_status 是一个枚举数据类型&#xff0c;表示Node-API接口返回的状态信息。 每当调用一个Node-API函数&#xff0c;都会返回该值&#xff0c;表示操作成功与否的相关信息。 typedef enum {napi_ok,napi_invalid_arg,napi_object_expected,napi_stri…

计算机网络面试问题(一)

1.在浏览器中输⼊URL并按下回⻋之后会发⽣什么 2.TCP三次握⼿的过程,为什么三次握手 TCP&#xff08;传输控制协议&#xff09;的三次握⼿是建⽴⽹络连接的过程&#xff0c;确保通信双⽅能够正确地进⾏数据传输。 第⼀次握⼿&#xff08;SYN&#xff09;&#xff1a; 客户端&am…

Php_Code_challenge13

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 开启一个会话&#xff0c;在SESSION变量"nums"为空时则对"nums","time","whoami"进行赋值&#xff0c;并在120秒后关闭会话&#xff0c;创建一个变量"$value"…

第6章 数据存储操作

思维导图 6.1 引言 数据存储与操作包括对存储数据的设计、实施和支持&#xff0c;最大化实现数据资源的价值&#xff0c;贯穿于数据创建/获取到处置的整个生命周期。 6.1.1 业务驱动因素 数据存储与操作活动对于依赖数据的企业来说非常关键&#xff0c;这些活动的主要驱动因素是…

Meta Pixel:助你实现高效地Facebook广告追踪

Meta Pixel 像素代码是用來衡量Facebook广告效果的一个官方数据工具&#xff0c;只要商家有在Facebook上投放广告就需要串联Meta Pixel 像素代码来查看相关数据。 它本质上是一段 JavaScript 代码&#xff0c;安装后可以让用户在自己网站上查看到访客活动。它的工作原理是加载…

记windows配置maven环境变量

配置环境变量 idea中配置maven

C++教学——从入门到精通 4.setw()语句

这次玩点新鲜的------setw() 这家虎是啥呢&#xff1f; 我们编程输出的时候总是要输出空格&#xff0c;但有些时候又点的手都麻了 这时setw语句就派上用场了 具体怎么用呢&#xff1f; 如下图 #include"iostream"// #include"iomanip"// bits/stdc…

AI智能写作:巧用AI大模型让新媒体变现插上翅膀【文末送书】

文章目录 一、AI智能写作的崛起二、AI智能写作与新媒体变现AI智能写作的挑战与应对策略 AI智能写作&#xff1a;巧用AI大模型让新媒体变现插上翅膀【文末送书】 近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术的发展日新月异&#xff0c;逐渐渗透到了各行各业&…

稻盛和夫|普通人如何才能取得非凡成就?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 稻盛和夫老先生曾经回答过这么一个问题&#xff1a; 资质平庸的普通人如何才能取得非凡的成就&#xff1f; 稻盛和夫认为&#xff1a;人生成就能力努力态度。 也就是&#xff1a;做一个努力工作却不甘于只做眼前的事&a…

Verilog基础【二】

3.1 Verilog 连续赋值 关键词&#xff1a;assign&#xff0c; 全加器 连续赋值语句是 Verilog 数据流建模的基本语句&#xff0c;用于对 wire 型变量进行赋值。&#xff1a; assign LHS_target RHS_expression &#xff1b;LHS&#xff08;left hand side&#xff09;…

linux 系统安装php 8.0.2

1. 安装包准备 https://www.php.net/distributions/php-8.0.22.tar.gz 我下载到 /usr/local/src 这个目录了 cd /usr/local/srcwget https://www.php.net/distributions/php-8.0.22.tar.gz 2. tar 解压 然后进到解压的文件夹 tar -zxvf php-8.0.22.tar.gz cd php-8.0.2…

鸿蒙OS开发实例:【NAPI入门】

背景 公司内部已经有现成的MQTT动态库&#xff0c;想在HarmonyOS平台上共享使用。查找官方指导后&#xff0c;发现可以通过NAPI方式&#xff0c;将MQTT C库导入进来&#xff0c;然后封装一层ArkTS接口就可直接使用。 本篇内容是在按照官方指导下&#xff0c;自己做的一些调研…

Latex绘制多行多TSNE列子图

Latex绘制多行多列TSNE子图 问题描述解决办法 问题描述 写论文需要绘制TSNE可视化图像。 解决办法 代码如下 \usepackage{subfigure}\begin{figure*}\centering\small\subfigure[aaa]{\includegraphics[width0.18\textwidth]{Figure/MFPT_v5_train_tsne_user0_bs0.png}}\su…

Docker 学习

一起学习,加油芹菜!!! 镜像:相当于模板,容器:相当于服务器 镜像:(centos镜像、mysql镜像、nginx镜像、redis镜像、自己的应用程序等) 容器:想让镜像跑起来就需要创建容器,相当于服务器,容器与容器之间是隔离的,安全性较高 1)yum包更新到最新 sudo yum upd…

neo4j使用详解(六、cypher即时时间函数语法——最全参考)

Neo4j系列导航&#xff1a; neo4j及简单实践 cypher语法基础 cypher插入语法 cypher插入语法 cypher查询语法 cypher通用语法 cypher函数语法 6.时间函数-即时类型 表示具体的时刻的时间类型函数 6.1.date函数 年-月-日时间函数&#xff1a; yyyy-mm-dd 6.1.1.获取date da…

C++ vector 数组/向量

文章目录 【 1. vector 的声明与初始化 】1.1 vector 的声明1.2 vector 的初始化1.2.1 构造一个空的 vector1.2.2 指定数量初值的方式初始化 vector1.2.3 迭代器的方式初始化1.2.4 构造一个相同的 vector 【 2. vector 的相关操作 】2.1 插入元素2.1.1 在vector的末尾插入新元素…

IPv4地址

IP v4 由32位二进制构成、可以用点分十进制表示。 例如&#xff1a;192.168.1.1 11000000101010000000000100000001 由网络位和主机位组成。为了区分网络位和主机位&#xff0c;需要用子网掩码&#xff0c;子网掩码也是由32位二进制构成&#xff0c;连续的1对应网络位&#…

HDMI 2.1b 规范解读

HDMI 规范 HDMI 2.1b 是最新版 HDMI 规范&#xff0c;支持一系列更高的视频分辨率和刷新频率&#xff0c;包括 8K60 和 4K120 以及高达 10K 的分辨率。同时支持动态 HDR 格式&#xff0c;带宽能力增加到 48Gbps HDMI。 新的超高速 HDMI 线缆支持 48Gbps 带宽。该线缆可确保提供…