用Servlet实现一个简单的表白墙

1. 准备工作

创建项目,引入依赖......

将静态页面放到项目中(放在webapp目录下):


当前,这个表白墙页面,已经可以输入内容,点击提交之后也能显示内容,后续后端要做的工作即:

①存档

用户点提交的时候,把刚才输入的内容通过网络传输给服务器,由服务器保存这个数据.

②读档

后续有页面加载的时候,此时就通过网络,从服务器获取到之前保存好的内容.

都需要进行前后端交互接口的约定.

约定好,前端会给后端发起一个什么样的HTTP请求,后端返回什么样的HTTP响应.


html中的每个元素,同时都可以映射到js中的一个对象.(文档-对象模型)

通过对象的属性,就能获取到页面的内容.

修改对象的属性,也就能更新页面的内容.

2. 后端操作

非持久化保存数据: 

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();

    //此处把消息保存到内存中(一旦重启服务器,内存数据就没了)
    private List<Message> messageList = new ArrayList<>();    //更科学的方式,应该是保存到数据库中

    //用来实现存档操作
    @Override
    protected 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");
    }


    //用来实现读档操作
    @Override
    protected 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;

    @Override
    public 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<>();    //更科学的方式,应该是保存到数据库中

    //用来实现存档操作
    @Override
    protected 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");
    }




    //用来实现读档操作
    @Override
    protected 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.构造SQL
        String 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.执行SQL
        statement.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.构造SQL
        String sql = "select * from message";
        PreparedStatement statement = connection.prepareStatement(sql);
        //4.执行SQL
        ResultSet 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代码都是被下载到浏览器中,并执行的)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NAT地址转换内外网通信

实验要求&#xff1a;内网地址通过nat转换成外网地址&#xff0c;联通外网服务器&#xff0c;达到内网外网互通 拓扑结构&#xff1a; 配置完成后&#xff0c;在ar1的G1口设置抓包&#xff0c;在pc1设备上ping ar2的地址&#xff0c;通过查看抓包信息&#xff0c;可以看到访问…

49 el-input 的 模型 视图 双向同步

前言 这里来看一下 el-input 这边的 数据 和 视图的双向绑定 最开始 我以为 这部分的处理应该是 vue 这边实现的, 但是跟踪调试了一下 发现这部分的处理是业务这边 自己实现的 这部分 还是有一些 值得记录的东西, 从这里 要去理解的而是 vue 这边从宏观的框架上面来说 帮我们…

python如何画奥运五环

绘制奥运五环主要涉及到Python中的turtle绘图库运用&#xff1a; 程序源代码为&#xff1a; import turtle turtle.width(10) turtle.color(black) turtle.circle(50) turtle.penup() turtle.goto(120,0) turtle.pendown() turtle.color(red) turtle.circle(50) turtle.penup()…

HWOD:整型数组排序

一、知识点 while(1){}表示永久循环 使用break结束循环 二、题目 1、描述 输入整型数组和排序标识&#xff0c;对其元素按照升序或降序进行排序 2、数据范围 1<n<1000 0<val<100000 3、输入 第一行输入数组元素个数 第二行输入待排序的数组&#x…

第十四届蓝桥杯(八题C++ 题目+代码+注解)

目录 题目一&#xff08;日期统计 纯暴力&#xff09;&#xff1a; 代码&#xff1a; 题目二&#xff08;01串的熵 模拟&#xff09;&#xff1a; 代码&#xff1a; 题目三&#xff08;治炼金属&#xff09;&#xff1a; 代码&#xff1a; 题目四&#xff08;飞机降落 深度…

【JAVASE】学习数组的定义与使用

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a; 再无B&#xff5e;U&#xff5e;G-CSDN博客 目标&#xff1a; 1. 理解数组基本概念 2. 掌握数组的基本用法…

星际门计划:微软与OpenAI联手打造未来AI超级计算机

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

windows安装mysql

win r cmd 以管理员权限运行。数据库配置文件my.ini放到安装包里&#xff0c;配置文件内路径根据实际情况修改&#xff0c;配置文件字符集根据实际需要修改。 1、cd c:\mysql\bin切换目录 2、mysqld --initialize --console 初始化数据库&#xff0c;初始化完成…

[操作系统课设]GeeKOS操作系统的研究与实现

一.GeekOS操作系统概论 1.1教学操作系统 &#xff08;1&#xff09;针对RISC结构MIPS处理器 操作系统&#xff1a;Nachos、OS/161 &#xff08;2&#xff09;针对CISC结构Intel IA-32 (or x86)通用处理 操作系统&#xff1a;MINIX、GeekOS 我们用到的是&#xff1a;GeekOS 1&…

SpringMvc执行流程源码解析

一、简介 Spring web Mvc是基于ServletApi构建的原始Web模块&#xff0c;从一开始就包含在Spring框架中&#xff1b; 从Servlet到SpringMvc 最典型的MVc就是JSPServletjavaBean的模式&#xff1b; 弊端&#xff1a; 1、xml下配置Servlet的映射非常麻烦&#xff0c;效率低&…

OpenHarmony实战:命令行工具hdc安装应用指南

一、工具概述 hdc&#xff08;OpenHarmony Device Connector&#xff09;是为开发人员提供的用于设备连接调试的命令行工具&#xff0c;该工具需支持部署在 Windows/Linux/Mac 等系统上与 OpenHarmony 设备&#xff08;或模拟器&#xff09;进行连接调试通信。 简言之&#xf…

16进制的字符串转byte[]数组 以及将字节数组转换成十六进制的字符串

16进制的字符串转byte[]数组 public class ClientString16 {@Testpublic void get16Str(){String str="48 47 12 00 14 12 16 08 15 0d 30 0f 02 30 30 30 30 30 30 30 30 30 30 00 c2";byte[] bytes = hexStringToByteArray(str);getBytetoString(bytes);//String …

Redis实战篇-添加优惠卷

3.3 添加优惠卷 每个店铺都可以发布优惠券&#xff0c;分为平价券和特价券。平价券可以任意购买&#xff0c;而特价券需要秒杀抢购&#xff1a; tb_voucher&#xff1a;优惠券的基本信息&#xff0c;优惠金额、使用规则等 tb_seckill_voucher&#xff1a;优惠券的库存、开始抢…

(一)基于IDEA的JAVA基础10

相信最近许多朋友学习语言可能会有焦虑&#xff0c;“现在人工智能这么发达&#xff0c;丢个指令进去它就还给你一个结果&#xff0c;我们学习它还有意义吗&#xff1f;”。 对于这个问题&#xff0c;就像我们小学学习算数&#xff0c;我们明知道有计算器这么方便的东西&#…

Java 处理Mysql获取树形的数据

Mysql数据&#xff1a; 代码如下&#xff1a; Entity&#xff1a; Data Accessors(chain true) public class Region {private BigInteger id;//名称private String name;//父idprivate BigInteger parentId;private List<Region> children;private Integer createTim…

Spring 事件广播机制详解

前言 写这篇文章的初衷源自对 Spring 框架中事件机制的好奇心。在编写观察者模式代码示例时&#xff0c;我突然想起了 Spring 框架中支持多事件监听的特性&#xff0c;例如ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent等等。传统的观察者模式通常是基于单…

基于springboot+vue实现的驾校信息管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

YOLOv9改进策略 :IoU优化| Inner-IoU基于辅助边框的IoU损失,高效结合新型边界框相似度度量(MPDIoU)| 二次创新

💡💡💡本文独家改进:Inner-IoU引入尺度因子 ratio 控制辅助边框的尺度大小用于计算损失,新型边界框相似度度量(MPDIoU)MPDIoU损失进行有效结合 💡💡💡适用场景:小目标数据集,进一步提升检测精度,强烈推荐 《YOLOv9魔术师专栏》将从以下各个方向进行创新: …

【Java八股面试系列】Arraylist和HashMap的底层原理

文章目录 ArrayList源码总&#xff1a;构造方法扩容机制remove HashMap总&#xff1a;构造方法细节问题putVal()方法resize()方法Hash值 HashMap常见问题 ConcurrentHashMap总&#xff1a;putVal()方法自己的测试 为什么重写HashCode和equals ArrayList源码 总&#xff1a; *…

代码随想录算法训练营三刷day41 | 动态规划之 343. 整数拆分 96.不同的二叉搜索树

三刷day41 343. 整数拆分确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp的初始化确定遍历顺序举例推导dp数组 96.不同的二叉搜索树确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组…