用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.rhkb.cn/news/294310.html

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

相关文章

计算机网络(第八版)-第1章课后习题参考答案

计算机网络(第八版)-第1章课后习题参考答案 本文是对自己之前文章的格式化&#xff1a;https://blog.csdn.net/qq_46396470/article/details/132788972?spm1001.2014.3001.5502 T1-01 计算机网络向用户可以提供哪些服务&#xff1f; 连通性和共享 &#xff0c;例如音频&…

微信小程序开发【从入门到精通】——页面导航

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

JavaSE——面向对象高级三(5/5)-泛型方法、泛型的通配符、泛型擦除和注意事项

目录 泛型方法 泛型的通配符 泛型擦除和注意事项 泛型方法 修饰符 <类型变量,类型变量,...> 返回值类型 方法名(形参列表){ } public static <T> void test(T t){} 注意&#xff1a;下面这种不是泛型方法 public E get(int index){return (E) arr[index]; } 具体…

RTOS中临界区嵌套保护的实现原理(基于RT-Thread)

0 前言 什么是临界区&#xff08;临界段&#xff09;&#xff1f; 裸机编程中由于不涉及线程和线程切换&#xff0c;因此没有临界区这一个概念。在RTOS中由于存在线程切换等场景&#xff0c;便有了临界区这个概念。简单来说&#xff0c;临界区就是不允许被中断的代码区域。什么…

代码随想录算法训练营第39天|62.不同路径 |63. 不同路径 II

代码随想录算法训练营第39天|62.不同路径 |63. 不同路径 II 详细布置 62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流&#xff0c;很难想到。 https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.html 视频讲解&#xff1a;https…

网络钓鱼升级 Darcula如何窃取用户信息

近日&#xff0c;网络安全领域一种名为 “Darcula” 的网络钓鱼欺诈&#xff08;PhaaS&#xff09;悄然兴起。这种新型钓鱼方式不同于传统的手段&#xff0c;它巧妙地利用了谷歌信息和 iMessage 的富通信服务&#xff08;RCS&#xff09;&#xff0c;成为了网络犯罪分子的新手段…

dockerfile制作-pytoch+深度学习环境版

你好你好&#xff01; 以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 文档内容docker相关术语docker常用命令容器常用命令根据dockerfile创建容器dokerfile文件内容 docker问题&#xff1a;可能的原因和解决方法示例修改修改后的D…

vscode调试Unity

文章目录 vscode调试UnityC#环境需求开始调试 Lua添加Debugger环境配置联系.txt文件配置Java环境 添加调试代码断点不生效的问题 vscode调试Unity C# 现在使用vscode调试Unity的C#代码很简单&#xff0c;直接在vscode的EXTENSIONS里面搜索“Unity”&#xff0c;第一个就是&am…

YOLOv8改进 | 细节涨点篇 | 利用YOLOv8自带的RayTune进行超参数调优

一、本文介绍 本文给大家带来的改进机制是利用Ray Tune进行超参数调优,在YOLOv8的项目中目前已经自带了该超参数调优的代码,我们无需进行任何的改动,只需要调用该方法输入我们的一些指令即可,当然了,这些超参数的设置还是比较又学问的,本文的内容也是应群友的需求进行发…

研发设计人员能力级别定义

研发设计人员能力&级别定义 1. 源由2. 级别定义3. 级别能力3.1 助理工程师3.1.1 工作内容3.1.2 级别晋升3.1.3 详细描述 3.2 初级工程师3.2.1 工作内容3.2.2 级别晋升3.2.3 详细描述 3.3 高级工程师3.3.1 工作内容3.3.2 级别晋升3.3.3 详细描述 3.4 资深工程师3.4.1 工作内…

【Entity Framework】EF中的增删改查

【Entity Framework】EF中的增删改查 文章目录 【Entity Framework】EF中的增删改查一、概述二、DbContext数据上下文三、EntityState五个状态值四、EF添加数据4.1 EF Add方式4.2 EF 通过改变对象的状态为 Added4.3 调用方sql4.4 调用存储过程 五、EF修改数据5.1 不查询数据库&…

仿真黑科技EasyGo DeskSim 2022

DeskSim2022的FPGA支持多种solver的混合应用&#xff0c;对于每一种solver可以采用不同的仿真步长&#xff0c;以下图模型为例&#xff0c;模型运行在FPGA上&#xff0c;FPGA解算方式采用的是Power Electronic & FPGA Coder解算&#xff0c;其中电力电子电路部分采用了两种…

ssm013小型企业办公自动化系统的设计和开发+vue

小型企业办公自动化系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对小型企业办公信息管理混乱&am…

wps 开发插件

官方文档参考wps官方文档参考 1.环境安装 安装wps https://www.wps.cn/ 安装Node.js https://nodejs.org/en 安装代码编辑器 Visual Studio Code https://code.visualstudio.com/ 环境检查-进入cmd查看 node -v2.demo 2.1 demo下载 打开vscode&#xff0c;新建终端 安装…

C#学习笔记 面试提要

冒泡 for (int m 0; m < arr.Length; m) { for (int n 0; n < arr.Length - 1 - m; n) { if (arr[n] > arr[n1]) { int temp arr[n]; arr[n] arr[n 1]; arr[n1] temp; } } } 选择 for (int m 0; m < arr.Length; m) { int index 0; for (int n 1; n < …

HackTheBox-Mist

整体思路 端口扫描->Pluck CMS组件文件读取漏洞->文件上传获取shell->创建指向exe的快捷方式来提权-> 信息收集&端口利用 namp -sSVC 10.10.11.17目标只开放了80端口&#xff0c;将mist.htb加入到hosts文件后&#xff0c;访问mist.htb Pluck CMS文件读取 在…

中科驭数超低时延网络解决方案入选2023年度金融信创优秀解决方案

近日&#xff0c;由中国人民银行领导、中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布「2023年度第三期金融信创优秀解决方案」&#xff0c;中科驭数超低时延网络解决方案从众多方案中脱颖而出&#xff0c;成功入选&#xff0c;代表了该方案的技术创新和金融实践…

HUAWEI 华为交换机 配置 Eth-Trunk 接口流量本地优先转发示例(堆叠)

组网需求 说明 S5720I-10X-PWH-SI-AC 和 S5720I-6X-PWH-SI-AC 不支持此配置。 如 图 3-23 所示&#xff0c;为了增加设备的容量采用设备堆叠技术&#xff0c;将 Switch3 和 Switch4通过专用的堆叠电缆链接起来&#xff0c;对外呈现为一台逻辑交换机。为了实现设备间的备份、…

算法题->盛最多水的容器C语言和JAVA双指针解法

盛最多水的容器C语言和JAVA双指针解法 题目描述: 力扣链接:https://leetcode.cn/problems/container-with-most-water/description/ 题意: 根据数组中的值(高)和下标差值(宽),求能容纳最多的体积V. 例子: 输出49的求解过程,根据木桶效应,存储水的高度由短木板决定,故 V 短…

瑞_23种设计模式_迭代器模式

文章目录 1 迭代器模式&#xff08;Iterator Pattern&#xff09;★★★1.1 介绍1.2 概述1.3 迭代器模式的结构1.4 中介者模式的优缺点1.5 中介者模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 JDK源码解析 &#x1f64a; 前言&#xff1a;本文…