【JavaEE】Servlet:表白墙

文章目录

  • 一、前端
  • 二、前置知识
  • 三、代码
    • 1、后端
    • 2、前端
    • 3、总结
  • 四、存入数据库
    • 1、引入 mysql 的依赖,mysql 驱动包
    • 2、创建数据库数据表
    • 3、调整上述后端代码
      • 3.1 封装数据库操作,和数据库建立连接
      • 3.2 调整后端代码

一、前端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>表白墙</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.container {width: 800px;margin: 0 auto;}.container h2 {text-align: center;margin: 30px;}.row {height: 50px;display: flex;justify-content: center;margin-top: 5px;line-height: 50px;}.row span {height: 50px;width: 100px;line-height: 50px;}.row input {height: 50px;width: 300px;line-height: 50px;}.row button {height: 50px;width: 400px;margin: 10px 0px;color: white;background-color: orange;border: none;border-radius: 10px;}.row button:active {background-color: grey;}</style>
</head>
<body><div class="container"><h2>表白墙</h2><div class="row"><span></span><input type="text" id="from"></div><div class="row"><span>对谁</span><input type="text" id="to"></div><div class="row"><span></span><input type="text" id="message"></div><div class="row"><button>提交</button></div></div><script src="https://code.jquery.com/jquery-3.7.1.min.js"></script><script>let container = document.querySelector('.container');let fromInput = document.querySelector('#from');let toInput = document.querySelector('#to');let messageInput = document.querySelector('#message');let button = document.querySelector('button');button.onclick = function() {let from = fromInput.value;let to = toInput.value;let message = messageInput.value;if(from=='' || to=='' || message=='||') {return;}let newDiv = document.createElement('div');newDiv.className = 'row';newDiv.innerHTML = from + "对" + to + "说" + message;container.appendChild(newDiv);fromInput.value = '';toInput.value = '';messageInput.value = ''; }</script>
</body>
</html>

二、前置知识

pom.xml 里面的依赖确保了在开发阶段项目能够编译和运行,但在部署到Tomcat服务器时,Tomcat会提供这些类,因此不需要将它们打包到最终的WAR文件中。

运行项目一般是两级路径:

  1. 第一级:Context path:
    context path代表了当前的 webapp(网站),一个 tomcat 上是可以同时部署多个 webapp(网站)的,webapps 目录下的每个目录都是一个单独的 webapp,所以有的资料也把tomcat叫做容器。
    如何确定 Context path:
    (1)如果是通过 startup.bat 启动的 tomcat,webapps 里对应的 war 包名/目录名就是这个 webapp 的 Context path;
    (2)如果是通过 smart tomcat 启动 tomcat,是在启动的配置项中手动指定的 Context path(这种是另外的一种运行 tomcat 的方式)
  2. 第二级路径:就是 ServletPath
    这个是根据代码中的 @WebServlet 注解来确定的或者就是 webapp下面的静态文件/目录

以下是完整项目的目录:

三、代码

1、后端

创建 Message.java 和 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.util.ArrayList;
import java.util.List;// 对应到前端传来的请求 body 格式
// 此处要保证每个属性名字和 JSON 里的 key 对应
// 同时要保证这几个格式是 public 或者提供 public 的 getter 方法
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();List<Message> messageList = new ArrayList<>();// 负责实现让服务器从客户端拿数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 把 body 的 json 数据解析出来, json格式的字符串(通过输入流获取) -> 对象Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 2. 把这个数据保存起来,最简单的是保存到内存中messageList.add(message);System.out.println("message: " + message);// 3. 返回成功的响应resp.setContentType("application/json;charset=utf8"); // application/json;charset=utf8resp.getWriter().write("{\"ok\": 1}");}// 负责实现让客户端从服务器拿数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");// 对象 -> json格式的字符串String respString = objectMapper.writeValueAsString(messageList);resp.getWriter().write(respString);}
}

2、前端

事实上只有注释行为新的步骤(也就是第103行)后面才是更新的代码,前面和上面的前端代码一样。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>表白墙</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.container {width: 800px;margin: 0 auto;}.container h2 {text-align: center;margin: 30px;}.row {height: 50px;display: flex;justify-content: center;margin-top: 5px;line-height: 50px;}.row span {height: 50px;width: 100px;line-height: 50px;}.row input {height: 50px;width: 300px;line-height: 50px;}.row button {height: 50px;width: 400px;margin: 10px 0px;color: white;background-color: orange;border: none;border-radius: 10px;}.row button:active {background-color: grey;}</style>
</head>
<body><div class="container"><h2>表白墙</h2><div class="row"><span></span><input type="text" id="from"></div><div class="row"><span>对谁</span><input type="text" id="to"></div><div class="row"><span></span><input type="text" id="message"></div><div class="row"><button>提交</button></div></div><script src="https://code.jquery.com/jquery-3.7.1.min.js"></script><script>let container = document.querySelector('.container');let fromInput = document.querySelector('#from');let toInput = document.querySelector('#to');let messageInput = document.querySelector('#message');let button = document.querySelector('button');button.onclick = function() {let from = fromInput.value;let to = toInput.value;let message = messageInput.value;if(from=='' || to=='' || message=='||') {return;}let newDiv = document.createElement('div');newDiv.className = 'row';newDiv.innerHTML = from + "对" + to + "说" + message;container.appendChild(newDiv);fromInput.value = '';toInput.value = '';messageInput.value = '';// 新的步骤,将刚才输入框里取得的数据构造成 POST 请求,提交给后端服务器// jsonlet messageJson = {// 字符串: 变量from: from,to: to,message: message};$.ajax({type: 'post',// 相对路径url: 'message',// 绝对路径// url: '/MessageWall1/message',contentType: 'application/json;charset=utf8',data: JSON.stringify(messageJson), // JSON 转成 JSON 格式的字符串success: function() {alert("提交成功");},// 返回状态码不是2xx就触发此函数error: function() {alert("提交失败");}});}// 这个函数在页面加载/刷新的时候调用,通过这个函数从服务器获取到当前的消息列表,显示在页面上function load() {$.ajax({type: 'get',url: 'message',success: function(body) {// 此处 body 已经是 json , ajax 会根据contentType自动转换let container = document.querySelector('.container');for(let message of body) {let newDiv = document.createElement('div');newDiv.className = 'row';newDiv.innerHTML = message.from + " 对 " + message.to + " 说 " + message.message;container.appendChild(newDiv);}}});}// 函数调用写在这里就表示页面加载的时候来执行load();</script>
</body>
</html>

json的key只能是字符串类型.此处写的 from其实是"from" .只不过咱们这里图省事,把"省略了
json中表示字符串,单弓|号或者双引号都行.
在这里插入图片描述

在这里插入图片描述

3、总结

  1. 打开页面/刷新页面,先执行前端load();
  2. load()会执行ajax,ajax会发生一个HTTP请求给服务器,GET /message,这里面的success先不执行,后面才会执行
  3. 这个HTTP请求通过网络发送给tomcat,进一步触发doGet方法,doGet方法执行里面的逻辑,将List转换成JSON,构造HTTP响应返回给客户端
  4. 客户端收到返回数据触发回调函数,也就是success,success执行里面的逻辑,将服务器返回的数据(body)显示到页面上

四、存入数据库

当服务器重启,List 里面的数据会丢失,应该怎样解决这个问题?
关键是要把数据存储在服务器的硬盘上面
1、存入文件里面,使用 IO 流来写文件/读文件
2、存入数据库里面,使用 MYSQL+JDBC

JDBC(Java Database Connectivity)是Java编程语言中用于执行SQL语句的一组API(应用程序接口)。它为数据库访问提供了一种标准的方法,使得Java程序可以与各种关系型数据库进行交互,而无需关心具体的数据库实现细节。

这里使用存入数据库的方式来解决问题:

1、引入 mysql 的依赖,mysql 驱动包

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
</dependency>

2、创建数据库数据表

create database MessageWall;
use MessageWall;drop table if exists MessageWall;
create table MessageWall (`from` varchar(100),`to` varchar(100),message varchar(1024)
);

3、调整上述后端代码

3.1 封装数据库操作,和数据库建立连接

新建一个类 DBUtil.java

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
//import com.mysql.jdbc.Connection;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;// 通过这个类完成建立数据库的连接的过程
// 建立连接需要使用 DataSource,并且一个程序有一个 DataSource 实例即可,这里用单例模式来实现
public class DBUtil {private static DataSource dataSource = null;private static DataSource getDataSource() {if (dataSource == null) {dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1/messagewall?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("1234");}return dataSource;}public static Connection getConnection() throws SQLException {return getDataSource().getConnection();}public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {// 后创建的先释放// 此处分开写 try-catch 是因为一个地方异常了不会影响其他的 close 执行if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (preparedStatement != null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

3.2 调整后端代码

MessageServlet.java

@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();// List<Message> messageList = new ArrayList<>();// 负责实现让服务器从客户端拿数据@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 把 body 的 json 数据解析出来, json格式的字符串(通过输入流获取) -> 对象Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 2. 把这个数据保存起来,最简单的是保存到内存中// messageList.add(message);save(message);System.out.println("message: " + message);// 3. 返回成功的响应resp.setContentType("application/json;charset=utf8"); // application/json;charset=utf8resp.getWriter().write("{\"ok\": 1}");}// 负责实现让客户端从服务器拿数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");// 对象 -> json格式的字符串List<Message> messageList= load();String respString = objectMapper.writeValueAsString(messageList);resp.getWriter().write(respString);}// 把当前的消息存到数据库中private void save(Message message) {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.执行SQL语句int ret = statement.executeUpdate();if (ret != 1) {System.out.println("插入失败");} else {System.out.println("插入成功");}} catch (SQLException e) {e.printStackTrace();} finally {// 4.关闭连接DBUtil.close(connection, statement, null);}}// 从数据库查询到记录private List<Message> load() {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;List<Message> messageList = new ArrayList<>();try {// 1.建立连接connection = DBUtil.getConnection();// 2.构造SQL语句String sql = "select * from message";statement = connection.prepareStatement(sql);// 3.执行SQLresultSet = statement.executeQuery(sql);// 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;}
}

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

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

相关文章

调用阿里通义千问大语言模型API-小白新手教程-python

阿里大语言模型通义千问API使用新手教程 最近需要用到大模型&#xff0c;了解到目前国产大模型中&#xff0c;阿里的通义千问有比较详细的SDK文档可进行二次开发,目前通义千问的API文档其实是可以进行精简然后学习的,也就是说&#xff0c;是可以通过简单的API调用在自己网页或者…

《硬件架构的艺术》笔记(七):处理字节顺序

介绍 本章主要介绍字节顺序的的基本规则。&#xff08;感觉偏软件了&#xff0c;不知道为啥那么会放进《硬件架构的艺术》这本书&#xff09;。 定义 字节顺序定义数据在计算机系统中的存储格式&#xff0c;描述存储器中的MSB和LSB的位置。对于数据始终以32位形式保存在存储器…

【STM32】在 STM32 USB 设备库添加新的设备类

说实话&#xff0c;我非常想吐槽 STM32 的 USB device library&#xff0c;总感觉很混乱。 USB Device library architecture 根据架构图&#xff1a; Adding a custom class 如果你想添加新的设备类&#xff0c;必须修改的文件有 usbd_desc.cusbd_conf.cusb_device.c 需要…

C 语言学习-06【指针】

1、目标单元与简介存取 直接访问和间接访问 #include <stdio.h>int main(void) {int a 3, *p;p &a;printf("a %d, *p %d\n", a, *p);*p 10;printf("a %d, *p %d\n", a, *p);printf("Enter a: ");scanf("%d", &a)…

docker镜像、容器、仓库介绍

docker docker介绍docker镜像命令docker容器命令docker仓库 docker介绍 官网 Docker 是一种开源的容器化平台&#xff0c;用于开发、部署和运行应用。它通过将应用程序及其依赖项打包到称为“容器”的单一包中&#xff0c;使得应用能够在任何环境下运行&#xff0c;不受底层系…

《用Python画蔡徐坤:艺术与编程的结合》

简介 大家好&#xff01;今天带来一篇有趣的Python编程项目&#xff0c;用代码画出知名偶像蔡徐坤的形象。这个项目使用了Python的turtle库&#xff0c;通过简单的几何图形和精心设计的代码来展示艺术与编程的结合。 以下是完整的代码和效果介绍&#xff0c;快来试试看吧&…

网络层协议IP

对于网络层我们直接通过IP协议来了解其内容 一.IP协议 首先我们先来了解几个概念&#xff1a; 主机&#xff1a;配有IP地址&#xff0c;但是不进行路由控制的设备 路由器&#xff1a;配有IP地址&#xff0c;同时进行路由控制的设备 节点&#xff1a;主机和路由器的统称 所以现在…

国土安全部发布关键基础设施安全人工智能框架

美国国土安全部 (DHS) 发布建议&#xff0c;概述如何在关键基础设施中安全开发和部署人工智能 (AI)。 https://www.dhs.gov/news/2024/11/14/groundbreaking-framework-safe-and-secure-deployment-ai-critical-infrastructure 关键基础设施中人工智能的角色和职责框架 https:/…

Windows系统电脑安装TightVNC服务端结合内网穿透实现异地远程桌面

文章目录 前言1. 安装TightVNC服务端2. 局域网VNC远程测试3. Win安装Cpolar工具4. 配置VNC远程地址5. VNC远程桌面连接6. 固定VNC远程地址7. 固定VNC地址测试 前言 在追求高效、便捷的数字化办公与生活的今天&#xff0c;远程桌面服务成为了连接不同地点、不同设备之间的重要桥…

lua除法bug

故事背景&#xff0c;新来了一个数值&#xff0c;要改公式。神奇的一幕出现了&#xff0c;公式算出一个非常大的数。排查是lua有一个除法bug,1除以大数得到一个非常大的数。 function div(a, b)return tonumber(string.format("%.2f", a/b)) end print(1/73003) pri…

洛谷 B3635 硬币问题 C语言 记忆化搜索

题目&#xff1a; https://www.luogu.com.cn/problem/B3635 用贪心可以但是会有测试点不过。比如15,11111115.或者55515&#xff0c;如果你是贪心把最大值的硬币放在第一个&#xff0c;那么这个测试点就错误了。用记忆化搜索可以&#xff0c;因为贪心只能测一次&#xff0c;记…

【数据结构与算法】合并链表、链表分割、链表回文结构

主页&#xff1a;HABUO&#x1f341;主页&#xff1a;HABUO &#x1f341;如果再也不能见到你&#xff0c;祝你早安&#xff0c;午安&#xff0c;晚安&#x1f341; 1.合并链表 题目&#xff1a;将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链…

NuGet如何支持HTTP源

今天是2024年11月21号&#xff0c;最近更新了VisualStudio后发现HTTP的包源已经默认禁止使用了&#xff0c;生成时会直接报错。如下图&#xff1a; 官方也明确指出了要想使用HTTP包源的解决办法&#xff0c;这里就简单总结一下。 一、全局配置 1、全局NuGet包的配置文件路径在…

ArcGIS API for Javascript学习

一、ArcGIS API for Javascript 介绍 ArcGIS API for Javascript 是由美国 Esri 公司推出&#xff0c;跟随ArcGIS 9.3 同时发布的&#xff0c;是Esri 基于dojo 框架和 REST 风格实现的一套编程接口。通过 ArcGIS API for Javascript可以对ArcGIS for Server 进行访问&#xff…

React表单联动

Ant Design 1、dependencies Form.Item 可以通过 dependencies 属性&#xff0c;设置关联字段。当关联字段的值发生变化时&#xff0c;会触发校验与更新。 一种常见的场景&#xff1a;注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段&#x…

Spring Boot教程之五:在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序

在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序 IntelliJ IDEA 是一个用 Java 编写的集成开发环境 (IDE)。它用于开发计算机软件。此 IDE 由 Jetbrains 开发&#xff0c;提供 Apache 2 许可社区版和商业版。它是一种智能的上下文感知 IDE&#xff0c;可用于在各种应用程序…

丹摩征文活动|实现Llama3.1大模型的本地部署

文章目录 1.前言2.丹摩的配置3.Llama3.1的本地配置4. 最终界面 丹摩 1.前言 Llama3.1是Meta 公司发布的最新开源大型语言模型&#xff0c;相较于之前的版本&#xff0c;它在规模和功能上实现了显著提升&#xff0c;尤其是最大的 4050亿参数版本&#xff0c;成为开源社区中非常…

STM32F103外部中断配置

一、外部中断 在上一节我们介绍了STM32f103的嵌套向量中断控制器&#xff0c;其中包括中断的使能、失能、中断优先级分组以及中断优先级配置等内容。 1.1 外部中断/事件控制器 在STM32f103支持的60个可屏蔽中断中&#xff0c;有一些比较特殊的中断&#xff1a; 中断编号13 EXTI…

docker run m3e 配置网络,自动重启,GPU等 配置渠道要点

启动命令&#xff1a; docker run -d --restart always -p 6008:6008 --gpus all --name m3e --network fastgpt_fastgpt stawky/m3e-large-api 配置渠道m3e base url要像我这样填写才行&#xff0c;不然回出问题 模型要选m3e 密钥填&#xff1a;sk-aaabbbcccdddeeefffggghhhi…

ubuntu24挂载硬盘记录

1、显示硬盘及所属分区情况。在终端窗口中输入如下命令&#xff1a; sudo fdisk -l 找到自己硬盘的分区 我的地址/dev/sda 2、显示硬盘及所属分区情况。在终端窗口中输入如下命令&#xff0c;格式化自己硬盘&#xff1a; sudo mkfs -t ext4 /dev/sda 3、在终端窗口中输入如下…