当前位置: 首页 > article >正文

【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;

    @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.kler.cn/a/410398.html

相关文章:

  • 图片生成视频-右进
  • Java---反射机制
  • HTML和CSS 表单、表格练习
  • SQL注入--文件读写注入--理论
  • 【Java 解释器模式】实现高扩展性的医学专家诊断规则引擎
  • 编程之路,从0开始:文件操作(2)
  • CSS 样式入门:属性全知晓
  • Leetcode 组合
  • STM32WB55RG开发(5)----监测STM32WB连接状态
  • C#里怎么样访问文件时间
  • 《Shader入门精要》透明效果
  • Qt笔记-获取HTTP的POST请求提交的数据时需要注意的地方(2024-09-02)
  • 加菲工具 - 好用免费的在线工具集合
  • newpipe搜索崩溃Ljava/lang/String;Ljava/nio/charset/Charset;
  • 多维数组与特殊矩阵:存储与压缩
  • wkhtmltopdf的安装与使用
  • 【参会邀请】第二届大数据与数据挖掘国际会议(BDDM 2024)邀您相聚江城!
  • 高标准农田智慧农业系统建设方案
  • 数字信号处理实验报告四:IIR数字滤波器设计及软件实现
  • 【spark】pyspark kerberos 案例,即pyspark-utils客户端工具类
  • CentOS7卸载node
  • C51相关实验
  • 基于RAG的text2sql解决方案vanna-ai 私有化部署使用实战
  • 【已解决】python面试、竞赛编程问题:最长递增子序列和旅行商问题(TSP)
  • C 语言学习-06【指针】
  • 探索1688关键词API接口:Python爬虫的高效之旅