• Servlet 综合案例:表白墙


    在这里插入图片描述

    请添加图片描述

    ⭐️前言⭐️

    在学习过上文【Servlet API详解】的各位小主们,相信对Servlet的基本使用已经有了一定的掌握,这篇博文,博主带大家来手把手搭建一个小网站——表白墙,是对【JavaScript进阶3.2 表白墙案例】的一个升级版,也是对前边知识的一个综合运用,相信通过这一篇博文,能让各位小主get到一个网站的开发流程大概是什么样的,期待与你的共同进步!

    🍉博客主页: 🍁【如风暖阳】🍁
    🍉精品Java专栏【JavaSE】【备战蓝桥】、【JavaEE初阶】【MySQL】【数据结构】
    🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

    🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉

    🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

    🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)GitHub


    请添加图片描述

    请添加图片描述

    🍅1.约定接口

    实现这个表白墙案例的第一步,就是需要自定义应用层协议,确定好客户端服务器如何进行交互

    数据能够进行存储的格式有很多种,也就是前后端需要共同指定数据格式,以便在客户端向服务器发送给去数据请求后,能够按照彼此约定好的应用层协议进行数据解析

    对于表白墙来说,主要要提供两个接口,要约定好客户端要发送一个怎样的HTTP请求服务器返回一个怎样的HTTP响应,下边我们会直接指定数据格式json格式:

    接口一
    告诉服务器,当前留言了一条怎样的数据
    (当用户点击提交按钮的时候,就会给服务器发送一个HTTP请求,让服务器把这个消息给存下来)
    在这里插入图片描述

    接口二
    从服务器获取到当前都有哪些留言数据
    (当页面加载,就需要从服务器获取到曾经存储的留言内容)
    在这里插入图片描述

    在我们确定好接口后,就可以进行代码的编写了。

    🍅2.后端框架搭建

    我们接下来,就按照常规Servlet程序的搭建流程进行搭建,先进性整体框架的搭建。

    1.创建maven项目
    在这里插入图片描述
    2.引入依赖
    (引入Servlet依赖和JSON依赖)
    在这里插入图片描述
    3.创建目录
    在这里插入图片描述
    4.编写代码
    (只编写简单代码,用于测试是否搭建接口完成)

    @WebServlet("/message")
    public class MessageServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("hello get");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("hello post");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5、6.打包部署
    在这里插入图片描述
    7.验证
    在这里插入图片描述

    🍅3.实现服务器端代码

    先将消息列表存储到内容中(通过顺序表实现)

    /**
     * 与json格式对应的类
     */
    class Message {
        public String from;
        public String to;
        public String message;
    }
    
    @WebServlet("/message")
    public class MessageServlet extends HttpServlet {
        //用于将类和json进行转换的类
        private ObjectMapper objectMapper=new ObjectMapper();
        //用于存放消息的顺序表
        private List<Message> messages=new ArrayList<>();
    
        /**
         * 处理提交消息请求,对数据进行保存
         */
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Message message=objectMapper.readValue(req.getInputStream(),Message.class);
            messages.add(message);
            //指定响应的数据格式
            resp.setContentType("application/json;charset=utf8");
            resp.getWriter().write("{\"ok\":true}");
        }
    
        /**
         *获取消息列表,把消息列表中的内容返回给客户端
         */
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //将Java对象转成JSON格式字符串
            String jsonString=objectMapper.writeValueAsString(messages);
            System.out.println("jsonString:"+jsonString);
            resp.setContentType("application/json;charset=utf8");
            resp.getWriter().write(jsonString);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    🍅4.构造请求测试服务器端

    利用应用postman来进行构造请求,用于测试服务器端代码。
    在这里插入图片描述
    postman可自行下载,专门用来构造HTTP请求,进行服务器端的测试。

    首先我们在idea通过smart tomcat启动服务器,然后进行测试。
    在这里插入图片描述
    对接口一进行测试,构造POST请求,输入数据。
    在这里插入图片描述

    对接口二进行测试,构造GET请求,得到对接口一测试时输入的消息列表,测试完成。
    在这里插入图片描述

    🍅5.调整前端页面代码

    在之前文章【JavaScript进阶3.2 表白墙案例】的表白墙代码可以直接拿来用,再进行调整,完成两个接口的功能即可。
    在这里插入图片描述
    将该前端html文件拷贝到webapp目录下,再进一步调整完善前端代码的ajax请求

    对前端代码的调整,主要的逻辑有两部分:
    1.点击提交按钮时,ajax要构造数据发送给服务器。
    2.页面加载的时候,从服务器获取消息列表,并在界面上直接显示。

    首先我们还是先引入jQuery
    在这里插入图片描述
    功能1:把当前输入框的内容,构造成一个HTTP POST请求,通过ajax发送给服务器。
    在这里插入图片描述
    功能2:通过函数完成消息列表的获取打印。
    在这里插入图片描述
    完整前端代码:

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
                background-color: rgb(30,100,200);
            }
    
            .container {
                width: 100%;
            }
    
            h3 {
                text-align: center;
                padding: 30px 0;
                font-size: 24px;
                color: rgb(255,140,10);
            }
            p {
                text-align: center;
                color: rgba(255, 50, 100);
                font-size: 18px;
                padding: 5px 0;
            }
            .row {
                width: 400px;
                height: 50px;
                margin: 0 auto;
    
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .row span{
                width: 100px;
                height: 40px;
                text-align: center;
                padding-right: 0px;
                font-size: 24px;
                color: rgb(255,140,10);
            }
            .row input {
                width: 300px;
                height: 40px;
                border: 2px solid  rgb(255, 140,160);
                border-radius: 5px;
                outline: 0;
                text-align: left;
                padding-left: 0px;
                margin-left: 0px;
                text-indent: 0.4em;
                font-size: 20px;
    
                color: rgb(9, 245, 135);
            }
            .row #submit{
                width: 200px;
                height: 40px;
                border-radius: 10px;
                font-size: 24px;
                border: 0px solid  rgb(255, 140, 160);
                background-color:  rgb(255, 140, 160);
                color:  aliceblue;
                line-height: 40px;
                margin-top: 8px;
            }
            .row #submit:active{
                background-color: rgb(140,180,240);
            }
        style>
    
        <div class="container">
            <h3>表白墙h3>
            <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>
    
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js">script>
        <script>
            function getMessages() {
                $.ajax({
                    type:"get",
                    url:'message',
                    success:function(body) {
                        let container=document.querySelector('.container');
                        for(let message of body) {
                            let div=document.createElement('div');
                            div.innerHTML=message.from+'对'+message.to+'说:'+message.message;
                            div.className='row';
                            container.appendChild(div);
                        }
                    }
                })
            }
    
            getMessages();
            // 当用户点击submit,就会获取到input中的内容,从而把内容构造成一个div,插入到页面末尾
            let submitBtn=document.querySelector('#submit');
            submitBtn.onclick=function() {
                // 1.获取到3个input中的内容
                let inputs=document.querySelectorAll('input');
                let from=inputs[0].value;
                let to=inputs[1].value;
                let msg=inputs[2].value;
                if(from==''||to==''||msg=='') {
                    // 用户还没有提交完,暂时先不提交数据
                    return;
                }
                // 2.生成一个新的div,内容是input里面的内容,把这个新的div加到页面中
                let div=document.createElement('div');
                div.innerHTML=from+'对'+to+'说:'+msg;
                div.className='row';
                let container=document.querySelector('.container');
                container.appendChild(div);
                //3.清空之前输入框内的内容
                for(let i=0;i<inputs.length;i++) {
                    inputs[i].value='';
                }
    
                //4.功能一
                let body={
                    from:from,
                    to:to,
                    message:msg
                };
                $.ajax({
                    type:"post",
                    url:"message",
                    contentType:"application/json;charset=utf8",
                    data:JSON.stringify(body),
                    success:function(body) {
                        alert("消息提交成功!");
                    },
                    error:function(body) {
                        alert("消息提交失败!");
                    }
                });
            }
        script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164

    效果预览:
    请添加图片描述
    通过将消息存入内容的方式,只要服务器不重启,可以使得页面即使刷新,消息列表也不会丢失,但如果将服务器重启,消息列表一定会丢失。所以如果想要将数据持久化存储,需要将数据写入硬盘,可以通过写入文件或者写入数据库的方式,下边我们就将消息存入数据库,实现数据的持久化存储

    🍅6.数据存入数据库

    1)引入mysql数据库依赖
    在这里插入图片描述
    2)创建数据库
    在这里插入图片描述

    3)创建DBUtil类,用于与数据库的交互。

    public class DBUtil {
        private static final String url="jdbc:mysql://localhost:3306/homework?characterEncoding=utf8&useSSL=false";
        private static final String user="root";
        private static final String password="1234";
    
        private volatile static DataSource dataSource=null;
    
        //线程安全的单例模式
        private static DataSource getDataSource() {
            if(dataSource==null) {
                synchronized (DBUtil.class) {
                    if(dataSource==null) {
                        dataSource=new MysqlDataSource();
                        ((MysqlDataSource)dataSource).setURL(url);
                        ((MysqlDataSource)dataSource).setUser(user);
                        ((MysqlDataSource)dataSource).setPassword(password);
                    }
                }
            }
            return dataSource;
        }
    
        public static Connection getConnection() throws SQLException {
            return getDataSource().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();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    由于客户端发出的请求可能存在线程安全的问题,所以得到数据源的方法使用线程安全的单例模式
    在这里插入图片描述
    4)调整Servlet代码,完成数据存入数据库

    关键方法:
    在这里插入图片描述
    在这里插入图片描述

    完整代码:

    /**
     * 与json格式对应的类
     */
    class Message {
        public String from;
        public String to;
        public String message;
    }
    
    @WebServlet("/message")
    public class MessageServlet extends HttpServlet {
        //用于将类和json进行转换的类
        private ObjectMapper objectMapper=new ObjectMapper();
        //用于存放消息的顺序表
    //    private List messages=new ArrayList<>();
    
        /**
         * 处理提交消息请求,对数据进行保存
         */
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Message message=objectMapper.readValue(req.getInputStream(),Message.class);
    //        messages.add(message);
            //指定响应的数据格式
            resp.setContentType("application/json;charset=utf8");
            resp.getWriter().write("{\"ok\":true}");
        }
    
        /**
         *获取消息列表,把消息列表中的内容返回给客户端
         */
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //将Java对象转成JSON格式字符串
            String jsonString=objectMapper.writeValueAsString(messages);
            System.out.println("jsonString:"+jsonString);
            resp.setContentType("application/json;charset=utf8");
            resp.getWriter().write(jsonString);
        }
    
        /**
         * 把一条消息保存到数据库中
         * @param message
         */
        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
                statement.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(connection,statement,null);
            }
        }
    
        /**
         * 从数据库中获取到所有的消息
         * @return
         */
        private List<Message> load() {
            List<Message> messages=new ArrayList<>();
            Connection connection=null;
            PreparedStatement statement=null;
            ResultSet resultSet=null;
            try {
                connection=DBUtil.getConnection();
                String sql="select * from message";
                statement=connection.prepareStatement(sql);
                resultSet=statement.executeQuery();
                while (resultSet.next()) {
                    Message message=new Message();
                    message.from=resultSet.getString("from");
                    message.to=resultSet.getString("to");
                    message.message=resultSet.getString("message");
                    messages.add(message);
                }
    
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(connection,statement,resultSet);
            }
            return messages;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    效果演示:
    请添加图片描述

    由上述演示可得,现在的消息已经写入数据库,能够持久化存储了,至此,表白墙小案例也就大功告成了,快自己动手试试吧!


    ⭐️最后的话⭐️
    总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

    请添加图片描述

  • 相关阅读:
    HDFS WEB API 测试
    黑盒(功能)测试基本方法
    C++20:constexpr、consteval和constinit
    差分信号变送器模块使用说明
    java“俄罗斯方块”
    支持5G LAN的UPF转发模型
    JVM 垃圾回收机制(可达性分析、引用计数)
    https比http安全在哪
    操作系统的运行机制
    Linux系统调优详解(九)——sar查看系统整体运行状态
  • 原文地址:https://blog.csdn.net/qq_60856948/article/details/127666582