基于Servlet建立表白墙网站

目录

一、设计思想

二、设计表白墙页面(前端--VSCode)

1、效果图

2、html部分(网页上有哪些内容)

3、css部分(页面内容的具体样式)

4、js部分(页面行为)

三、借助Servlet实现客户端与服务器交互

1、服务器的功能

2、客户端发送数据--服务器保存并做出响应

(1)客户端发送数据(json类型请求)

(2)服务器接收数据--保存数据并发送响应给客户端

3、客户端获取当前所有表白数据--服务端响应所有数据

(1)客户端发送请求(无请求正文)

(2)服务器接收请求--将保存的所有表白数据响应给客户端

4、客户端将收到的所有数据显示到页面

四、运行效果

五、问题改进

(1)引入mysql资源依赖

(2)建表

(3)获得数据源

(4)收到客户端的post请求保存数据

(5)收到客户端的get请求返回数据


一、设计思想

二、设计表白墙页面(前端--VSCode)

1、效果图
2、html部分(网页上有哪些内容)
html 复制代码
<body>
    <div class="container">
        <h1>表白墙</h1>
        <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 class="row">
            xxx 对 xx 说 xxxx
        </div> 
    </div>

<div class="container"> 表示一个包含内容的区域;

<div class="row"> 表示一个包含行内容的区域;

3、css部分(页面内容的具体样式)
html 复制代码
<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>表白墙</title>
    <style>
        /* * 通配符选择器, 是选中页面所有元素 */
        * {
            /* 消除浏览器的默认样式. */
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .container {
            width: 600px;
            margin: 20px auto;
        }

        h1 {
            text-align: center;
        }

        p {
            text-align: center;
            color: #666;
            margin: 20px 0;
        }

        .row {
            /* 开启弹性布局 */
            display: flex;
            height: 40px;
            /* 水平方向居中 */
            justify-content: center;
            /* 垂直方向居中 */
            align-items: center;
        }

        .row span {
            width: 80px;
        }

        .row input {
            width: 200px;
            height: 30px;
        }

        .row button {
            width: 280px;
            height: 30px;
            color: white;
            background-color: orange;
            /* 去掉边框 */
            border: none;
            border-radius: 5px;
        }

        /* 点击的时候有个反馈 */
        .row button:active {
            background-color: grey;
        }
    </style>

</head>

选中某个标准,{}里描述这个标签应该具有什么样式。

4、js部分(页面行为)
javascript 复制代码
<script>
        // 实现提交操作. 点击提交按钮, 就能够把用户输入的内容提交到页面上显示. 
        // 点击的时候, 获取到三个输入框中的文本内容
        // 创建一个新的 div.row 把内容构造到这个 div 中即可. 
        let containerDiv = document.querySelector('.container');
        let inputs = document.querySelectorAll('input');
        let button = document.querySelector('#submit');
        button.onclick = function() {
            // 1. 获取到三个输入框的内容
            let from = inputs[0].value;
            let to = inputs[1].value;
            let message = inputs[2].value;
            if (from == '' || to == '' || message == '') {
                return;
            }
            // 2. 构造新 div
            let rowDiv = document.createElement('div');
            rowDiv.className = 'row message';
            rowDiv.innerHTML = from + ' 对 ' + to + ' 说: ' + message;
            containerDiv.appendChild(rowDiv);
            // 3. 清空之前的输入框内容
            for (let input of inputs) {
                input.value = '';
            }
        }
</script>

通过js代码可以实现网页和用户以及网页和服务器的交互。(以上代码还未实现和服务器的交互)

三、借助Servlet实现客户端与服务器交互

1、服务器的功能

以上代码也可以实现表白墙的功能,但是发现未和服务器建立连接,数据保存在浏览器内存里,刷新浏览器数据就会消失,且该客户端也看不到上一个客户端的留言,所以就要和服务器进行交互。

服务器的功能:(1)页面加载的时候要获取到当前表白数据,由服务器响应发送;(2)客户端发送数据时,服务器要接受并保存数据。

2、客户端发送数据--服务器保存并做出响应
(1)客户端发送数据(json类型请求)

①规定请求为json类型,方法为post,请求正文样子:

javascript 复制代码
{
  "from":from,
  "to":to,
  "message":message
}

在点击提交按钮后,发送数据给服务端,即在function函数里实现。需要引入第三方库:jquery库

②实现代码(VSCode--js语言)

javascript 复制代码
// 4. 把用户填写的内容, 发送给服务器. 让服务器来保存. 
            //    $ 是 jquery 提供的全局变量. ajax 就是 $ 的一个方法. 
            //    ajax 的参数是一个 js 对象, 可以有很多属性
            let requestBody = {
                "from": from,   // from 变量里的值, 就是第一个输入框的内容, "张三"
                "to": to,       // to 变量的值, 就是第二个输入框的内容, "李四"
                "message": message  // message 变量的值, 就是第三个输入框的内容, "我喜欢你很久了"
            };
            // 上述 body 是一个 js 对象, 还需要转成 json 字符串. 
            let jsonRequest = JSON.stringify(requestBody);
            $.ajax({
                type: 'post',
                url: 'message',
                contentType: 'application/json; charset=utf8',
                data: jsonRequest,
                success: function(responseBody) {
                    // 这个回调就是收到响应之后要执行的代码了. 
                    // 前端使用 console.log 打印日志到控制台. (chrome 开发者工具的控制台)
                    console.log("responseBody: " + responseBody);
                }
            });
(2)服务器接收数据--保存数据并发送响应给客户端

①服务器需要把请求正文json字符串转为java对象,且把请求上传的数据增加到列表中,给客户端响应一个json字符串,响应正文为:

javascript 复制代码
{
  "ok" : "true"
}

②实现代码(IDEA--java语言)

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;

class Request{  //请求正文json字符串转为java对象
    public String from;
    public String to;
    public String message;

    @Override
    public String toString() {
        return "Request{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

class Response{
    public boolean ok;
}

@WebServlet("/message")
public class messageServlet extends HttpServlet{
    List<Request> list=new ArrayList<>();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper=new ObjectMapper();
        Request request=objectMapper.readValue(req.getInputStream(),Request.class); //转为java对象
        System.out.println("请求内容:"+request);
        list.add(request); //保存数据
        resp.setStatus(200); //响应返回一个状态码
        Response response=new Response(); //响应的java对象
        response.ok=true;
        String jsonResponse=objectMapper.writeValueAsString(response); //响应转为json字符串
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(jsonResponse);
    }
}
3、客户端获取当前所有表白数据--服务端响应所有数据
(1)客户端发送请求(无请求正文)

①请求方法为get方法,加载页面时发送该请求。

②实现代码(VSCode--js语言)

javascript 复制代码
  // 直接在 script 里面写的 js 代码, 就是在页面加载时被执行到的. 
        // 发起一个 get 请求, 从服务器获取到数据
        // get 请求不需要 body, 也就不需要上述 data 和 contentType 属性了. 
        $.ajax({
            type:'get',
            url:'message',
            success:function(body){
                //这个回调就是收到响应之后要执行的代码了. 
                //客户端将收到的所有数据显示到页面
            }
        })

客户端收到响应后,显示数据的代码下一步实现。

(2)服务器接收请求--将保存的所有表白数据响应给客户端

①服务器需要将保存数据的数组转为json数组,将json数组响应给客户端,

②实现代码(IDEA--java语言)

java 复制代码
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper=new ObjectMapper();
        resp.setStatus(200);  //响应返回一个状态码
        resp.setContentType("application/json;charset=utf8");
        String jsonResponse=objectMapper.writeValueAsString(list); //jackson支持把一个数组对象转为json数组
        resp.getWriter().write(jsonResponse);
    }
4、客户端将收到的所有数据显示到页面

①客户端将收到的所有表白数据显示在页面上,在success:function(body){}回调函数中实现;

②响应中header中带有:Content-Type:appliaction/json,jquery库就会自动把响应的json正文转为js对象。eg:resp.setContentType("application/json;charset=utf8");

若响应中header中没有:Content-Type:appliaction/json,客户端拿到响应后,在回调函数中就会调用body = JSON.parse(body) ;

③实现代码(VSCode--js语言)

javascript 复制代码
success: function(body) {
                //这个回调就是收到响应之后要执行的代码了. 
                //客户端将收到的所有数据显示到页面
                // 由于响应中已经有 Content-Type: application/json 了, 就不需要使用 parse 方法手动转换了.  
                // body = JSON.parse(body);

                // 拿到 container 这个元素
                let containerDiv = document.querySelector('.container');
                // 处理服务器返回的响应数据. (json 格式的数组了)
                for (let i = 0; i < body.length; i++) {
                    // body 是一个数组, 此时 message 也就是 js 对象了. 
                    // 这个 message 对象里, 有三个属性, from, to, message
                    let message = body[i];

                    // 根据 message 对象构建 html 片段, 把这个片段给显示到网页上. 
                    // createElement 方法就能构造出一个 html 标签. 
                    // 此时就得到了 <div></div> 
                    let div = document.createElement('div');
                    // 还需要往里面设置一个 属性 , class="row" (设置这个属性, 是为了让 css 能够给这个元素设置一些样式)
                    // 此时就得到了 <div class="row"></div>
                    div.className = 'row';
                    // 给这个 div 里设置内容
                    // 此时就得到了 <div class="row">张三 对 李四 说: 我喜欢你很久了</div>
                    div.innerHTML = message.from + " 对 " + message.to + " 说: " + message.message;
                    // 把 div 添加到 containerDiv 的末尾
                    containerDiv.appendChild(div);
                }
            }

四、运行效果

需注意:需要将前端代码放在webapp包中(IDEA)

效果图

刷新或者重新打开页面,数据依旧存在。

五、问题改进

上述虽然实现了基于服务器的通信,但是若后台服务器停止运行,则所有的数据也都没有了,所以我们需要将数据存在数据库里,即使服务器停止运行了,再次重启时数据依然存在。

(1)引入mysql资源依赖
(2)建表

message表,里面有from、to、message属性。

sql 复制代码
create database if not exists message_wall charset utf8;
use message_wall;
-- 删表目的是为了, 防止之前数据库里有一样的表, 对咱们的代码产生干扰.
drop table if exists message;
create table message (`from` varchar(1024), `to` varchar(1024), message varchar(1024));
(3)获得数据源
java 复制代码
private DataSource datasource=new MysqlDataSource(); //导入数据源 向上转型
    @Override
    //获取数据源--在HttpServlet被实例化后调用该方法
    public void init() throws ServletException {
        ((MysqlDataSource) datasource).setUrl("jdbc:mysql://127.0.0.1:3306/message_wall?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource) datasource).setUser("root");  //用户名
        ((MysqlDataSource) datasource).setPassword("272222"); //密码
    }
(4)收到客户端的post请求保存数据
java 复制代码
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper=new ObjectMapper();
        Request request=objectMapper.readValue(req.getInputStream(),Request.class); //转为java对象
        System.out.println("请求内容:"+request);
        try {
            save(request);//保存数据
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        resp.setStatus(200); //响应返回一个状态码
        Response response=new Response(); //响应的java对象
        response.ok=true;
        String jsonResponse=objectMapper.writeValueAsString(response); //响应转为json字符串
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(jsonResponse);
    }
 private void save(Request request) throws SQLException {
        //建立连接
        Connection connection=datasource.getConnection();
        //创建执行语句
        String sql="insert into message values(?,?,?)"; //?是通配符
        //转成服务器能看懂的语句 客户端已提前解析好,mysql直接运行
        PreparedStatement statement=connection.prepareStatement(sql);
        statement.setString(1,request.from);  //第一个问号内容
        statement.setString(2,request.to);    //第二个问号内容
        statement.setString(3,request.message);  //第三个问号内容
        //执行sql语句
        statement.executeUpdate();
        //回收资源
        statement.close();
        connection.close();
    }
(5)收到客户端的get请求返回数据
java 复制代码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Request> list=null;
        ObjectMapper objectMapper=new ObjectMapper();
        resp.setStatus(200);  //响应返回一个状态码
        resp.setContentType("application/json;charset=utf8");
        try {
            list=load();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        String jsonResponse=objectMapper.writeValueAsString(list); //jackson支持把一个数组对象转为json数组
        resp.getWriter().write(jsonResponse);
    }
private List<Request> load() throws SQLException {
        //建立连接
        Connection connection=datasource.getConnection();
        //创建执行语句
        String sql="select * from message";
        //转成服务器能看懂的语句 客户端已提前解析好,mysql直接运行
        PreparedStatement statement=connection.prepareStatement(sql);
        //执行sql语句
        ResultSet resultSet=statement.executeQuery();
        //添加到返回数组
        List<Request> list1=new ArrayList<>();
        while (resultSet.next()){
            Request request=new Request();
            request.from=resultSet.getString("from");
            request.to=resultSet.getString("to");
            request.message=resultSet.getString("message");
            list1.add(request);
        }
        return list1;
    }

服务器重启后,数据依旧存在。

相关推荐
咕德猫宁丶21 分钟前
Spring Boot 邂逅Netty:构建高性能网络应用的奇妙之旅
java·spring boot·后端
C++小厨神26 分钟前
C#语言的函数实现
开发语言·后端·golang
计算机-秋大田1 小时前
基于JAVA的微信点餐小程序设计与实现(LW+源码+讲解)
java·开发语言·后端·微信·小程序·课程设计
jcsx1 小时前
证券量化交易选择合适的编程语言
javascript·servlet·numpy·pandas·pyqt
四念处茫茫1 小时前
【C语言系列】深入理解指针(3)
c语言·开发语言·visual studio
Eiceblue1 小时前
Java 实现Excel转HTML、或HTML转Excel
java·html·excel·idea
安的列斯凯奇7 小时前
SpringBoot篇 单元测试 理论篇
spring boot·后端·单元测试
架构文摘JGWZ8 小时前
FastJson很快,有什么用?
后端·学习
BinaryBardC8 小时前
Swift语言的网络编程
开发语言·后端·golang
邓熙榆8 小时前
Haskell语言的正则表达式
开发语言·后端·golang