【JavaEE初阶】Servlet (三)MessageWall

在我们之前博客中写到的留言墙页面,有很严重的问题:(留言墙博客)

  1. 如果刷新页面/关闭页面重开,之前输入的消息就不见了.
  2. 如果一个机器上输入了数据,第二个机器上是看不到的.

针对以上问题,我们的解决思如如下:
让服务器来存储用户提交的数据,由服务器保存.
当有新的浏览器打开页面的时候,从服务器获取数据.

此时服务器就可以用来存档和读档.

设计程序:
写web程序,务必要重点考虑前后端如何交互,约定好前后端交互的数据格式.
设计前后端交互接口: 1.请求是什么样 2. 响应是什么样 3.浏览器什么时候发送这个请求 4. 浏览器按照什么格式来解析

在我们的留言墙程序中,以下环节涉及到前后端交互:

  1. 点击提交,浏览器把表白墙信息发送到服务器这里
  2. 页面加载,浏览器从服务器获取到表白信息.
  1. 点击提交,浏览器把表白墙信息发送到服务器这里
    请求:
    POST/message
    按照json格式:
{from:"i",to:"you",message:"hello"
}

响应:
HTTP/1.1 200 OK

  1. 页面加载,浏览器从服务器获取到表白信息.
    请求:
    GET/message
    响应:
    HTTP/1.1 200 OK
    body部分:
[{from:"i",to:"you",message:"hello"}{from:"i",to:"you",message:"hello"}
]

此处约定的目的是为了前端代码和后端代码能够对应上.约定的方式可以有很多种.
通过约定,我们可以写出后端代码为:

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;class Message{public String from;public String to;public String message;
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {private List<Message> messageList = new ArrayList<>();ObjectMapper objectMapper = new ObjectMapper();//    向服务器提交数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//读取body中的内容,解析成 Message 对象Message message = objectMapper.readValue(req.getInputStream(),Message.class);//保存messageList.add(message);//设置状态码resp.setStatus(200);}//    从服务器获取数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//显示告诉浏览器,数据是 json 格式,字符集是 utf8resp.setContentType("application/json;charset=utf8");//通过 writeValue 将 messageList(java对象) 转成 json 格式并将其写入 resp 中//objectMapper.writeValue(resp.getWriter(),messageList);//把java对象转成json字符串String jsonResp = objectMapper.writeValueAsString(messageList);System.out.println("jsonResp: "+jsonResp);//把这个字符串写回到响应 body 中resp.getWriter().write(jsonResp);}
}

通过Postman 构造POST请求,使用json语法编辑body部分,点击两次发送,再通过GET获取得到响应如下:
在这里插入图片描述
存档:
其次,我们再看前端代码:在前端代码中使用ajax发送一个post请求.
在这里插入图片描述
通过fiddler得到:
在这里插入图片描述
通过dopost 执行:
在这里插入图片描述
通过resp.setStatus(200);回到回调函数:
在这里插入图片描述
读档:根据ajax创建GET响应:
在这里插入图片描述
打开fiddler可以看到:
在这里插入图片描述
GET请求触发doGet方法:
在这里插入图片描述
我们可以得到完整的前端代码(包含撤销功能):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>MessageBoard</title><style>*{/* 消除浏览器的默认样式 */margin: 0;padding: 0;/* 保证盒子不会撑大 */box-sizing: border-box;/* background-color: rgba(255, 192, 203, 0.436); */}.container{width: 600px;margin: 20px auto;}h1 {text-align: center;}p {text-align: center;color: #666;margin: 20px 0;}.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: white;background-color: orange;/* 去掉边框 */border: none;border-radius: 5px;}/* 点击的时候有个反馈 */.row button:active {background-color: grey;}</style>
</head>
<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.3/jquery.min.js"></script><script>//实现提交操作,点击提交,就能够吧用户输入的内容提交到页面上显示//点击时,获取到三个输入框的文本内容//创建一个新的div.rom把内容构造到这个div中即可.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 message';rowDiv.innerHTML = from +" 对 "+to+' 说 : '+msg;containerDiv.appendChild(rowDiv);//3.清空输入聊天框for(let input of inputs){input.value = '';}//4. [新增] 给服务器发起post请求,把上述数据提交到服务器//定义一个js对象let body = {from:from,to:to,message:msg};//将对象转成json字符串strBody = JSON.stringify(body);$.ajax({type:'post',url:'message',data:strBody,contentType:"application/json; charset=utf-8",success:function(body){console.log("发布成功.");}});}let revertButton = document.querySelector('#revert');revertButton.onclick = function(){//删除最后一条消息//选中所有的row,找出最后一个row,然后删除let rows = document.querySelectorAll('.message');if (rows == null || rows.length == 0) {return;}containerDiv.removeChild(rows[rows.length - 1]);//[新增]删除$.ajax({type: 'delete',url: 'message',success: function(body){// 1.先选中父元素ConversationDiv,然后删除所有子元素let ConversationDiv = document.querySelector('.Conversation');while(ConversationDiv.firstChild){ConversationDiv.removeChild(ConversationDiv.firstChild)}for(let message of body){// 2.对响应数据内容进行页面显示,对每一个message元素构造一个divlet resultDiv = document.createElement('div');resultDiv.className = 'row message result';resultDiv.innerHTML = message.from + ' 对: ' + message.to + ' 说: ' + message.message;ConversationDiv.appendChild(resultDiv);}}})}//[新增]在页面加载的时候,发送GET请求,从服务器获取到数据并添加到页面中$.ajax({type:'get',url:'message',success:function(body){let containerDiv = document.querySelector('.container');for(let message of body){let rowDiv = document.createElement('div');rowDiv.className ='row message';rowDiv.innerHTML = message.from +' 对 '+ message.to +' 说 : ' + message.message;containerDiv.appendChild(rowDiv);}}});</script>
</body>
</html>

在这里插入图片描述
刷新页面后数据也不会消失.
但是以上重启服务器后数据就消失了,所以我们可以把数据写入数据库中进行长久的保存.
C:\Users\xxxflower>mysql -uroot -p
Enter password: ****
create table message(from varchar(20),to varchar(20),message varchar(1024));
注意,由于from和to都是sql中的关键字,所以需要使用`.
创建表:
在这里插入图片描述
完整的后端代码:
MessageServlet.java:

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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;class Message{public String from;public String to;public String message;
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {//private List<Message> messageList = new ArrayList<>();private ObjectMapper objectMapper = new ObjectMapper();//    向服务器提交数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//读取body中的内容,解析成 Message 对象Message message = objectMapper.readValue(req.getInputStream(),Message.class);//保存save(message);//messageList.add(message);//设置状态码resp.setStatus(200);}//    从服务器获取数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//显示告诉浏览器,数据是 json 格式,字符集是 utf8resp.setContentType("application/json;charset=utf-8");//通过 writeValue 将 messageList(java对象) 转成 json 格式并将其写入 resp 中//objectMapper.writeValue(resp.getWriter(),messageList);//把java对象转成json字符串List<Message> messageList = load();String jsonResp = objectMapper.writeValueAsString(messageList);System.out.println("jsonResp: " + jsonResp);//把这个字符串写回到响应 body 中resp.getWriter().write(jsonResp);}//使用jdbc 往数据库里面存消息private void save(Message message) {//JDBCConnection 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) {throw new RuntimeException(e);}finally {//4.关闭连接DBUtil.close(connection,statement,null);}}//从数据库取所有消息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;}@Overrideprotected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json; charset=utf-8");// 从数据库获取所有表白信息// 1.获取最后一份表白信息,并从数据库删除List<Message> messageList = load();if(messageList.size() == 0){return;}Message messageEnd = messageList.get(messageList.size()-1);int count = delete(messageEnd);if(count == 1){System.out.println("留言信息删除成功");}else {System.out.println("留言信息删除失败");}// 2.获取删除最后一条信息后的 全部表白信息,并写回到浏览器messageList = load();objectMapper.writeValue(resp.getOutputStream(), messageList);}private int delete(Message message) {Connection connection = null;PreparedStatement preparedStatement = null;int count = 0;try {// 1.获取连接connection = DBUtil.getConnection();// 2.编写sqlString sql = "delete from message where `from` = ? and `to` = ? and message = ?";// 3.获取预编译对象,进行预编译preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, message.from);preparedStatement.setString(2, message.to);preparedStatement.setString(3, message.message);// 4.执行sql语句count = preparedStatement.executeUpdate();// 5.处理结果} catch (SQLException throwables) {throwables.printStackTrace();} finally {DBUtil.close(connection, preparedStatement, null);}return count;}
}

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;//这个类用于封装数据库连接过程
//此处把 DBUtil 作为一个工具类,提供 static 方法供其他代码使用
public class DBUtil {//静态成员跟随类对象,类对象在整个进程中只有唯一一份//静态成员相当于也是唯一的实例(单例模式,饿汉模式)private static DataSource dataSource = new MysqlDataSource();//使用静态代码块针对 DataDource 进行初始化操作static {((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/javaee?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("0828");}//建立连接public static Connection getConnection() throws SQLException {return dataSource.getConnection();}//断开连接 释放资源public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){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();}}}
}

最终实现效果:
请添加图片描述

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

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

相关文章

基于java的坦克大战游戏的设计与实现--答辨PPT--【毕业论文】

文章目录 本系列校训毕设的技术铺垫PPT主体层次封面页目录页&#xff1a;设计工具与相关技术&#xff1a;系统分析总体设计&#xff1a;详细设计测试结论&#xff1a; 小技巧 本系列校训 互相伤害互相卷&#xff0c;玩命学习要你管&#xff0c;天生我才必有用&#xff0c;我命…

React(1)——快速入门

一、React背景简介 官网和资料 英文官网: https://reactjs.org/中文官网: 快速入门 – React (docschina.org) 3、如果JS基础忘了及时查看文档&#xff1a;JavaScript - 学习 Web 开发 |多核 (mozilla.org) JavaScript - 标签 - 汤姆大叔 - 博客园 (cnblogs.com) 4、React…

Neo4j图数据基本操作

Neo4j 文章目录 Neo4jCQL结点和关系增删改查匹配语句 根据标签匹配节点根据标签和属性匹配节点删除导入数据目前的问题菜谱解决的问题 命令行窗口 neo4j.bat console 导入rdf格式的文件 :GET /rdf/ping CALL n10s.graphconfig.init(); //初始化 call n10s.rdf.import.fetch(&q…

【软件测试】webdriver常用API演示(Java+IDEA+chrome浏览器)

1.元素定位方法 对象的定位应该是自动化测试的核心&#xff0c;要想操作一个对象&#xff0c;首先应该识别这个对象。一个对象就是一个人一样&#xff0c;他会有各种的特征&#xff08;属性&#xff09;&#xff0c;如比我们可以通过一个人的身份证号&#xff0c;姓名&#xf…

Redis 笔记,基本数据类型、持久化、主从、集群等等问题

标题 &#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 标题Redis 基础笔记1、安装及环境搭建2、Redis 数据类型2.1、String2.2、List2.3、Hash2.4、Set2.5、Zset2.6、BitMap2.7、HyperLogLog2.8、Geospatial2.9、Stream 3、Redis 持久…

「BLIP 微调指南」以 Image-Text Captioning 任务为例

前言&#xff1a;近日需要用到 BLIP 微调下游任务&#xff0c;搜索发觉如今并无 BLIP 微调教程&#xff0c;下面就以 Image-Text Captioning 任务为例&#xff0c;演示如何完成 BLIP 模型在自己数据集上的微调。 目录 1. BLIP 介绍2. 关键代码定位3. 关键参数赋值4. 模型定义&a…

HTML一些基础知识

1、Web标准&#xff1a;主要包含结构、表现、行为。结构用于对网页元素进行整理和分类&#xff0c;主要指HTML。表现用于设置网页元素的板式、颜色、大小等外观样式&#xff0c;主要指的是CSS。行为主要指的是网页模型的定义以及交互的编写&#xff0c;主要是js文件。 Html相当…

DAY1,Qt [ 手动实现登录框(信息调试类,按钮类,行编辑器类,标签类的使用)]

1.手动实现登录框&#xff1b; ---mychat.h---头文件 #ifndef MYCHAT_H #define MYCHAT_H#include <QWidget> #include <QDebug> //打印信息 #include <QIcon> //图标 #include <QPushButton> //按钮 #include <QLineEdit> //行编辑器类 #in…

尚硅谷大数据项目《在线教育之采集系统》笔记002

视频地址&#xff1a;尚硅谷大数据项目《在线教育之采集系统》_哔哩哔哩_bilibili 目录 P032 P033 P033 P034 P035 P036 P032 P033 # 1、定义组件&#xff0c;为各组件命名 a1.sources r1 a1.channels c1 a1.sinks - k1# 2、配置sources&#xff0c;描述source a1.sour…

微服务划分的原则

微服务的划分 微服务的划分要保证的原则 单一职责原则 1、耦合性也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密&#xff0c;其耦合性就越强&#xff0c;模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及…

hive删除数据进行恢复

在实际开发或生产中&#xff0c;hive表如果被误删&#xff0c;如被truncate或是分区表的分区被误删了&#xff0c;只要在回收站的清空周期内&#xff0c;是可以恢复数据的&#xff0c;步骤如下&#xff1a; &#xff08;1&#xff09; 先找到被删除数据的存放目录&#xff0c;…

Neo4j数据库中导入CSV示例数据

本文简要介绍Neo4j数据库以及如何从CSV文件中导入示例数据&#xff0c;方便我们快速学习测试图数据库。首先介绍简单数据模型以及基本图查询概念&#xff0c;然后通过LOAD CSV命令导入数据&#xff0c;生成节点和关系。 环境准备 读者可以快速安装Neo4j Desktop&#xff0c;启…

1.2 网络安全法律法规

数据参考&#xff1a;CISP官方 目录 国家立法体系网络安全法解析网络安全相关法律 一、国家立法体系 1、我国的立法体系 我国的立法体系在网络空间治理中扮演着基础工作的角色。为了应对快速发展的网络技术和威胁&#xff0c;我国采取了多级立法机制来完善网络空间的法律…

【EI/SCOPUS会议征稿】2023年第四届新能源与电气科技国际学术研讨会 (ISNEET 2023)

作为全球科技创新大趋势的引领者&#xff0c;中国一直在为科技创新创造越来越开放的环境&#xff0c;提高学术合作的深度和广度&#xff0c;构建惠及全民的创新共同体。这些努力为全球化和创建共享未来的共同体做出了新的贡献。 为交流近年来国内外在新能源和电气技术领域的最新…

【Postman】Postman接口测试进阶用法详解:断言、全局与环境变量、关联、批量执行用例、读取外部文件实现参数化

文章目录 一、Postman断言1、断言位置2、Postman的常用断言3、操作实例 二、全局变量与环境变量1、二者区分2、设置全局变量3、设置环境变量 三、Postman接口关联1、概念2、操作步骤 四、批量执行测试用例1、操作步骤2、查看结果 五、读取外部文件实现参数化1、使用场景2、操作…

Vite+Typescript+Vue3学习笔记

ViteTypescriptVue3学习笔记 1、项目搭建 1.1、创建项目(yarn) D:\WebstromProject>yarn create vite yarn create v1.22.19 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages...success Installed…

2023-将jar包上传至阿里云maven私有仓库(云效制品仓库)

一、背景介绍 如果要将平时积累的代码工具jar包&#xff0c;上传至云端&#xff0c;方便团队大家一起使用&#xff0c;一般的方式就是上传到Maven中心仓库&#xff08;但是这种方式步骤多&#xff0c;麻烦&#xff0c;而且上传之后审核时间比较长&#xff0c;还不太容易通过&a…

Python语法(二、内置函数)

数学计算库 Python ​math ​模块提供了许多对浮点数的数学运算函数。 Python ​cmath ​模块包含了一些用于复数运算的函数。 import math 内置函数 关键字 自定义函数 Python函数的定义。定义函数需要用def 关键字实现&#xff0c;具体的语法格式如下&#xff1a; def 函…

CAN学习笔记3:STM32 CAN控制器介绍

STM32 CAN控制器 1 概述 STM32 CAN控制器&#xff08;bxCAN&#xff09;&#xff0c;支持CAN 2.0A 和 CAN 2.0B Active版本协议。CAN 2.0A 只能处理标准数据帧且扩展帧的内容会识别错误&#xff0c;而CAN 2.0B Active 可以处理标准数据帧和扩展数据帧。 2 bxCAN 特性 波特率…

部署问题集合(十八)Windows环境下使用两个Tomcat

下载Tomcat Tomcat镜像下载地址&#xff1a;https://mirrors.cnnic.cn/apache/tomcat/进入如下地址&#xff1a;zip的是压缩版&#xff0c;exe是安装版 修改第二个Tomcat配置文件 第一步&#xff1a;编辑conf/server.xml文件&#xff0c;修改三个端口&#xff0c;有些版本改…