【JavaEE】Servlet:表白墙

news2024/11/26 6:20:23

文章目录

  • 一、前端
  • 二、前置知识
  • 三、代码
    • 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;

    @Override
    public 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<>();

    // 负责实现让服务器从客户端拿数据
    @Override
    protected 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=utf8
        resp.getWriter().write("{\"ok\": 1}");
    }

    // 负责实现让客户端从服务器拿数据
    @Override
    protected 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 请求,提交给后端服务器
            // json
            let 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<>();

    // 负责实现让服务器从客户端拿数据
    @Override
    protected 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=utf8
        resp.getWriter().write("{\"ok\": 1}");
    }

    // 负责实现让客户端从服务器拿数据
    @Override
    protected 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.执行SQL
            resultSet = 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.coloradmin.cn/o/2247667.html

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

相关文章

python自定义枚举类的试验与思考

一 现象 在python的3.4版本之前&#xff0c;是没有枚举类的。 所以&#xff0c;我自定义实现了一个enum类&#xff0c;目录如下&#xff1a; 代码如下&#xff1a; class enum(set):def __getattr__(self, name):if name in self:return nameraise AttributeErrorif __name_…

算法编程题-寻找最近的回文数

算法编程题-寻找最近的回文数 原题描述思路简述代码实现复杂度分析参考 摘要&#xff1a;本文将对LeetCode 原题 564 寻找最近的回文数进行讲解&#xff0c;并且给出golang语言的实现&#xff0c;该实现通过了所有测试用例且执行用时超过100%的提交&#xff0c;最后给出相关的复…

[Redis#5] hash | 命令 | 内部编码 | 应用 | cache: string, json, hash对比

目录 1 命令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET HLEN HSET NX HINCRBY HINCRBYFLOAT 2 命令小结 3 内部编码 4 使用场景 5 缓存方式对比 1. 原生字符串类型 2. 序列化字符串类型&#xff0c;例如 JSON 格式 3. 哈希类型 几乎所有的主流编程…

系统设计-高性能

一、CDN 1、什么是CDN CDN 就是将静态资源分发到多个不同的地方以实现就近访问&#xff0c;进而加快静态资源的访问速度&#xff0c;减轻服务器以及带宽的负担.(可看作是一层特殊缓存服务&#xff0c;用来处理静态资源的请求) 2、CDN工作原理 静态资源是如何被缓存到 CDN 节…

单片机知识总结(完整)

1、单片机概述 1.1. 单片机的定义与分类 定义&#xff1a; 单片机&#xff08;Microcontroller Unit&#xff0c;简称MCU&#xff09;是一种将微处理器、存储器&#xff08;包括程序存储器和数据存储器&#xff09;、输入/输出接口和其他必要的功能模块集成在单个芯片上的微型…

代码管理之Gitlab

文章目录 Git基础概述场景本地修改未提交&#xff0c;拉取远程代码修改提交本地&#xff0c;远程已有新提交 GitIDEA引入Git拉取仓库代码最后位置 Git基础 概述 workspace 工作区&#xff1a;本地电脑上看到的目录&#xff1b; repository 本地仓库&#xff1a;就是工作区中隐…

基于Java Springboot古风生活体验交流网站

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

智慧社区管理系统平台提升物业运营效率与用户体验

内容概要 智慧社区管理系统平台是一个集成了多项功能的综合性解决方案&#xff0c;旨在通过先进的技术手段提升物业管理的效率和居民的生活质量。该平台不仅关注物业运营的各个方面&#xff0c;还强调用户体验的重要性。随着科技的发展&#xff0c;社区管理方式正发生着翻天覆…

Docker--通过Docker容器创建一个Web服务器

Web服务器 Web服务器&#xff0c;一般指网站服务器&#xff0c;是驻留于因特网上某种类型计算机的程序。 Web服务器可以向浏览器等Web客户端提供文档&#xff0c;也可以放置网站文件以供全世界浏览&#xff0c;或放置数据文件以供全世界下载。 Web服务器的主要功能是提供网上…

健身房小程序服务渠道开展

健身不单单是锻炼身体、保持身材&#xff0c;也是一种社交方式&#xff0c;城市里门店不少&#xff0c;每家都有一定流量和老客&#xff0c;但仅靠传统线下拉客/自然流量前往和线上朋友圈、短视频发硬广等方式还不够。 商家需要找到更多潜在目标客户&#xff0c;而消费者也对门…

利用Java爬虫获得1688商品分类:技术解析与代码示例

在电商领域&#xff0c;了解商品分类对于市场分析和产品策略至关重要。1688作为中国领先的B2B电商平台&#xff0c;其商品分类数据对于商家来说具有极高的价值。本文将详细介绍如何使用Java编写爬虫程序&#xff0c;以合法合规的方式获取1688商品分类信息&#xff0c;并提供代码…

QT:QListView实现table自定义代理

介绍 QListVIew有两种切换形式&#xff0c;QListView::IconMode和QListView::ListMode&#xff0c;通过setViewMode()进行设置切换。因为QListView可以像QTreeView一样显示树形结构&#xff0c;也可以分成多列。这次目标是将ListView的ListMode形态显示为table。使用代理&…

YOLOv10改进,YOLOv10添加SE注意力机制,二次C2f结构

摘要 理论介绍 SE 注意力机制是一种提升卷积神经网络(CNN)性能的模块,SE更关注重要的特征图,增强了网络的表现,同时仅增加了较少的参数。SE 机制包含两个主要步骤: Squeeze (压缩):对所有特征图进行全局平均池化,生成一个通道描述符。Excitation (激励):将通道描述符…

详解Servlet的使用

目录 Servlet 定义 动态页面 vs 静态页面 主要功能 Servlet的使用 创建Maven项目 引入依赖 创建目录 编写代码 打war包 部署程序 验证程序 Smart Tomcat 安装Smart Tomcat 配置Smart Tomcat插件 启动Tomcat 访问页面 路径对应关系 Servlet运行原理 Tomcat的…

【Nginx从入门到精通】05-安装部署-虚拟机不能上网简单排错

文章目录 总结1、排查步骤 一、排查&#xff1a;Vmware网关二、排查&#xff1a;ipStage 1 &#xff1a;ping 127.0.0.1Stage 2 &#xff1a;ping 宿主机ipStage 3 &#xff1a;ping 网关 失败原因解决方案Stage 4 &#xff1a;ping qq.com 总结 1、排查步骤 Vmware中网关是否…

优化求解 | 非线性最小二乘优化器Ceres安装教程与应用案例

目录 0 专栏介绍1 Ceres库介绍2 Ceres库安装3 Ceres库概念3.1 构建最小二乘问题3.1.1 残差块3.1.2 代价函数 3.2 求解最小二乘问题 4 Ceres库案例4.1 Powell函数优化4.2 非线性曲线拟合 0 专栏介绍 &#x1f525;课设、毕设、创新竞赛必备&#xff01;&#x1f525;本专栏涉及…

Flink Transformation-转换算子

map算子的使用 假如有如下数据&#xff1a; 86.149.9.216 10001 17/05/2015:10:05:30 GET /presentations/logstash-monitorama-2013/images/github-contributions.png 83.149.9.216 10002 17/05/2015:10:06:53 GET /presentations/logstash-monitorama-2013/css/print/paper…

记录一些PostgreSQL操作

本文分享一些pg操作 查看版本 select version(); PostgreSQL 11.11 查看安装的插件 select * from pg_available_extensions; 查看分词效果 select ‘我爱北京天安门,天安门上太阳升’::tsvector; ‘天安门上太阳升’:2 ‘我爱北京天安门’:1select to_tsvector(‘我爱北京天…

【ubuntu】数学人的环境搭建

Python 语言环境 python 的 pip 第三方库管理 sudo apt install python3-pippython 的 idle 界面 sudo apt install idle3R 语言环境 sudo apt install r-cran-zoo### RStudio 界面 ubuntu sudo snap install rstudio --classicJulia 语言环境 sudo snap install julia --…

android 11添加切换分屏功能

引言 自Android 7开始官方就支持分屏显示,但没有切换分屏的功能,即交换上下屏幕。直到Android 13开始才支持切换分屏,操作方式是:分屏模式下双击中间分割线就会交换上下屏位置。本文的目的就是在Android 11上实现切换分屏的功能。 下图是Android13切换分屏演示 切换分屏…