猜数字+表白墙(html+css+JS)

目录

1.猜数字

2. 表白墙

3. 服务器版的表白墙

4. 将表白墙的数据在数据库中持久化保存


1.猜数字

 这里只是用JS实现了一下逻辑,没有用CSS修改样式

<!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>猜数字</title>
</head>
<body>
    <button id="resetBtn">重新开始一局游戏</button> <br>
    <span>要猜的数字:</span>
    <input type="text">
    <button id="guessBtn">猜</button> <br>
    <span>已经猜的次数:</span> <span id="guessCount">0</span> <br>
    <span>结果:</span> <span id="result"></span>

    <script>
        //1. 先拿到上面的元素
        let resetBtn = document.querySelector('#resetBtn');
        let input = document.querySelector('input');
        let guessBtn = document.querySelector('#guessBtn');
        let resultSpan = document.querySelector('#result');
        let guessCountSpan = document.querySelector('#guessCount');

        //2. 生成一个 1-100 的随机整数,然后向下取整
        let  toGuess = Math.floor(Math.random() * 100) + 1;
        console.log(toGuess);
        //Math.random得到的是[0,1)的整数

        //3. 实现点击 猜 按钮的逻辑
        guessBtn.onclick = function() {
            //1. 读取到 input 中输入的内容,并转为整数
            if (input.value == '') {
                return;
            }
            let curNum = parseInt(input.value);
            //2. 判定大小关系,并给出提示
            if(curNum < toGuess) {
                resultSpan.innerHTML = '低了';
                resultSpan.style.color = 'red';
            } else if (curNum > toGuess) {
                resultSpan.innerHTML = '高了';
                resultSpan.style.color = 'red';
            } else {
                resultSpan.innerHTML = '猜对了';
                resultSpan.style.color = 'green';
            }

            //3. 更新 猜 的次数
            let guessCount = parseInt(guessCountSpan.innerHTML); 
            guessCount += 1;
            guessCountSpan.innerHTML = guessCount;
        }
        //4. 实现  reset 操作的逻辑(开始新的游戏)
        resetBtn.onclick = function() {
            //让页面刷新
            //location(操作页面链接) 和 document(操作页面内容) 是并列关系的对象
            //loacation 用来控制页面的链接/地址.通过reload操作就可以刷新页面
            location.reload();
        }
        
    </script>
</body>
</html>

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>表白墙</title>
</head>
<body>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .container {
            width: 100%;
        }

        h3 {
            text-align: center;
            padding: 30px 0;
            font-size: 24px;

        }

        p {
            text-align: center;
            color: #666;
            padding: 10px 0;
        }

        .row {
            width: 400px;
            height: 50px;
            margin: 0 auto;

            display: flex;
            justify-content: center;
            align-items: center;
        }

        .row span {
            width: 80px;
            font-size: 20px;
        }

        .row input {
            width: 300px;
            height: 40px;
            line-height: 40px;
            font-size: 20px;
            text-indent: 0.5em;
            /* 去掉输入框的轮廓线 */
            outline: none;
        }

        .row #submit {
            width: 380px;
            height: 40px;
            font-size: 20px;
            line-height: 40px;
            margin: 0 auto;

            color: white;
            background-color: orange;
            /* 去掉边框 */
            border: none;
            border-radius: 5px;
        }

        /* 伪类选择器表示按下使出现变化 */
        .row #submit:active {
            background-color: gray;
        }
    </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>
        // 当用户点击 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 = '';
            }
        }
    </script>
</body>
</html>

3. 服务器版的表白墙

前面拿前端代码写的表白墙,提交的数据,如果网页一刷新就没有了 

现在需要让保存的数据能够在服务器这边保存,就可以保证即使关闭页面,数据也不会丢失

(1) 先分析一下需求 

 (2) 还需要分析清楚请求和响应的细节,请求是什么样的,响应什么样的

针对发送数据给服务器:

请求: POST /message    HTTP/1.1

Content-Type: application/json; charset=utf8

{ "form": "小强子", "to": "小黑子", "message": "你在狗叫什么" } 

//这个就是把当前具体传输的数据给表示出来

响应: HTTP/1.1 200 OK

从服务器获取到已经保存的数据

请求: GET /message

响应: HTTP/1.1 200 OK

Content-Type: application/json; charset=utf8

{

   { "form": "小强子", "to": "小黑子", "message": "你在狗叫什么" } 

   { "form": "小强子", "to": "小黑子", "message": "你在狗叫什么" } 

   { "form": "小强子", "to": "小黑子", "message": "你在狗叫什么" } 

}

Message 类 

public class Message {
    private String from;
    private String to;
    private String message;

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

 MessageServlet 类

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 28463
 * Date: 2022—11—21
 * Time: 17:51
 */

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    //这个对象在多个方法中都需要使用
    private ObjectMapper objectMapper = new ObjectMapper();
    private List<Message> messagesList = new ArrayList<>();

    //负责让页面获取到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //显示声明当前的响应数据格式,不要让客户端去"猜"
        resp.setContentType("application/json; charset=utf8");
        //这一行代码,把messageList 转成 json 字符串, 并且返回给页面就行了
        resp.getWriter().write(objectMapper.writeValueAsString(messagesList));
    }

    //提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到 body 中的数据并解析
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);
        // 把这个 message 保存一下,保存在内存中
        messagesList.add(message);
        resp.setStatus(200);

        System.out.println("提交数据成功: from=" + message.getFrom() + ", to=" +
                message.getTo() + ", message=" + message.getMessage());
    }
}

表白墙.html 

<!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>表白墙</title>
</head>
<body>
    <style>
        .container {
            width: 400px;
            /* margin 外边距. 第一个数字上下外边距, 第二个数字表示水平外边距. 如果水平设置成 auto 表示元素就水平居中~~ */
            margin: 0 auto;
        }

        h1 {
            text-align: center;
        }

        p {
            text-align: center;
            color: #666;
        }

        .row {
            height: 40px;
            display: flex;
            /* 水平居中 */
            justify-content: center;
            /* 垂直居中 */
            align-items: center;
        }

        .row span {
            width: 100px;
        }

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

        .row button {
            width: 306px;
            height: 40px;
            color: white;
            background: orange;
            border: none;
        }

        .row button:active {
            background-color: #666;
        }
    </style>

    <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>提交</button>
        </div>
    </div>

    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

    <script>
        let container = document.querySelector('.container');
        let button = document.querySelector('button');
        button.onclick = function() {
            // 1. 获取到输入框的内容
            let inputs = document.querySelectorAll('input');
            let from = inputs[0].value;
            let to = inputs[1].value;
            let message = inputs[2].value;
            if (from == '' || to == '' || message == '') {
                alert('当前输入框内容为空!');
                return;
            }
            console.log(from + ", " + to + ", " + message);
            // 2. 能够构造出新的 div, 用来保存用户提交的内容
            let rowDiv = document.createElement('div');
            rowDiv.className = 'row';
            rowDiv.innerHTML = from + " 对 " + to + " 说: " + message;
            container.appendChild(rowDiv);
            // 3. 提交完之后, 清空输入框的内容
            for (let i = 0; i < inputs.length; i++) {
                inputs[i].value = '';
            }

            let data = {
                from: from,
                to: to,
                message: message
            };
            // 4. 点击发送按钮, 给服务器发个 post 请求. 
            $.ajax({
                type: 'post',
                url: 'message',
                // url: '/java105/message',
                // 这里放的是 body 的内容
                data: JSON.stringify(data),
                contentType: "application/json; charset=utf8",
                success: function(body) {
                    console.log("提交数据成功");
                }
            });
        }

        // 直接写在 script 标签里的代码, 都是在页面加载的时候执行的. 
        // 来获取服务器的数据
        function getMessages() {
            $.ajax({
                type: 'get' ,
                url: 'message',
                success: function(body) {
                    // body 就是响应的 body 内容, json 数组. 
                    // jquery 非常智能的帮我们把 json 数组给解析成了 js 对象数组
                    // 但是有个前提条件, 就是响应的 Content-Type 得是 application/json
                    let container = document.querySelector('.container');
                    for (let i = 0; i < body.length; i++) {
                        let message = body[i];
                        // 根据这个元素构造一个 div.row, 来容纳数据
                        // <div class="row">
                        //     黑猫 对 白猫 说: 喵
                        // </div>
                        let row = document.createElement('div');
                        row.className = 'row';
                        row.innerHTML = message.from + " 对 " + message.to + " 说: " + message.message;
                        container.appendChild(row);
                    }
                }
            });
        }

        getMessages();
    </script>
</body>
</html>

运行程序

整个程序,有两个环节涉及到前后端交互

1. 点击提交的时候,把当前输入框的内容发送给服务器

2. 页面加载的时候,从服务器获取到数据的列表

1. 点击提交的时候,把当前输入框的内容发送给服务器

客户端在按钮的 onclick 中,构造 ajax,发个 post请求

 2. 页面加载的时候,从服务器获取到数据的列表


4. 将表白墙的数据在数据库中持久化保存

这就需要用到数据库的JDBC了

先设计数据库表结构,表中有什么

message 表 (from, to, message) 

 

 加入JDBC后的代码

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

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 javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 28463
 * Date: 2022—11—21
 * Time: 17:51
 */

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    //这个对象在多个方法中都需要使用
    private ObjectMapper objectMapper = new ObjectMapper();
//    private List<Message> messagesList = new ArrayList<>();

    //负责让页面获取到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //显示声明当前的响应数据格式,不要让客户端去"猜"
        resp.setContentType("application/json; charset=utf8");
        //这一行代码,把messageList 转成 json 字符串, 并且返回给页面就行了
        List<Message> messageList = null;
        try {
            messageList = load();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.getWriter().write(objectMapper.writeValueAsString(messageList));
    }

    //提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到 body 中的数据并解析
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);
        // 把这个 message 保存一下,保存在内存中
//        messagesList.add(message);
        try {
            save(message);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.setStatus(200);

        System.out.println("提交数据成功: from=" + message.getFrom() + ", to=" +
                message.getTo() + ", message=" + message.getMessage());
    }

    private List<Message> load() throws SQLException {
        //从数据库查看数据
        // 把数据保存到数据库中

        //1. 先有一个数据源
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java11?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("111111");

        //2. 建立连接
        Connection connection = dataSource.getConnection();

        //3.构造 SQL
        String sql = "select * from message";
        PreparedStatement statement = connection.prepareStatement(sql);

        //4. 执行sql进行插入操作
        ResultSet resultSet = statement.executeQuery();

        //6. 遍历结果集合
        List<Message> messageList = new ArrayList<>();
        while (resultSet.next()) {
            Message message = new Message();
            message.setFrom(resultSet.getString("from"));
            message.setTo(resultSet.getString("to"));
            message.setMessage(resultSet.getString("message"));
            messageList.add(message);
        }

        //6. 关闭连接
        statement.close();
        connection.close();
        return messageList;
    }

    private void save(Message message) throws SQLException {
        // 把数据保存到数据库中

        //1. 先有一个数据源
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java11?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("111111");

        //2. 建立连接
        Connection connection = dataSource.getConnection();

        //3.构造 SQL
        String sql = "insert into message values(?, ?, ?)";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setString(1,message.getFrom());
        statement.setString(2,message.getTo());
        statement.setString(3, message.getMessage());

        //4. 执行sql进行插入操作
        int ret = statement.executeUpdate();
        System.out.println("ret = " + ret);

        //5. 关闭连接
        statement.close();
        connection.close();
    }
}

重新运行程序,添加数据

可以看到idea日志打印成功 

 

 在MySql中查询刚刚插入的数据,可以看到插入成功了


5. 使用单例模式表示DataSource

前面在这两个方法中写了两个DataSource,并且都一模一样,这样写不好,所以最好的办法就是把这两个DataSource只写一份,使用单例模式表示出来

 单例模式有两种一种是饿汉模式,一种是懒汉模式

最好写懒汉模式,因为饿汉是在类加载的时候就创建,而懒汉是在第一次使用的时候才创建,懒汉模式的效率是更高的

并且还需要考虑的是,Servlet代码中,是否有 多线程的安全问题?

Servlet写的是一个服务器,在同一时刻,可能要处理多个客户端的请求

当多个客户端同时发来请求时,服务器就要同时处理多个请求,Tomcat内部也正是使用了多线程方式,所以要注意加锁的问题

写一个单例模式,把DataSource放进去

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 28463
 * Date: 2022—11—23
 * Time: 15:57
 */
//使用这个类来封装DataSource
public class DBUtil {
    private static volatile DataSource dataSource = null;
    public static DataSource getDataSource() {
        if(dataSource == null) {
            synchronized (DBUtil.class) {
                if(dataSource == null) {
                    dataSource = new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java11?characterEncoding=utf8&useSSL=false");
                    ((MysqlDataSource)dataSource).setUser("root");
                    ((MysqlDataSource)dataSource).setPassword("111111");
                }
            }
        }
        return dataSource;
    }

    private DBUtil() {
    }
}

然后修改MessageServlet中的代码

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

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 javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 28463
 * Date: 2022—11—21
 * Time: 17:51
 */

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    //这个对象在多个方法中都需要使用
    private ObjectMapper objectMapper = new ObjectMapper();
//    private List<Message> messagesList = new ArrayList<>();

    //负责让页面获取到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //显示声明当前的响应数据格式,不要让客户端去"猜"
        resp.setContentType("application/json; charset=utf8");
        //这一行代码,把messageList 转成 json 字符串, 并且返回给页面就行了
        List<Message> messageList = null;
        try {
            messageList = load();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.getWriter().write(objectMapper.writeValueAsString(messageList));
    }

    //提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到 body 中的数据并解析
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);
        // 把这个 message 保存一下,保存在内存中
//        messagesList.add(message);
        try {
            save(message);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.setStatus(200);

        System.out.println("提交数据成功: from=" + message.getFrom() + ", to=" +
                message.getTo() + ", message=" + message.getMessage());
    }

    private List<Message> load() throws SQLException {
        //从数据库查看数据
        // 把数据保存到数据库中

        //1. 先有一个数据源
        DataSource dataSource = DBUtil.getDataSource();

        //2. 建立连接
        Connection connection = dataSource.getConnection();

        //3.构造 SQL
        String sql = "select * from message";
        PreparedStatement statement = connection.prepareStatement(sql);

        //4. 执行sql进行插入操作
        ResultSet resultSet = statement.executeQuery();

        //6. 遍历结果集合
        List<Message> messageList = new ArrayList<>();
        while (resultSet.next()) {
            Message message = new Message();
            message.setFrom(resultSet.getString("from"));
            message.setTo(resultSet.getString("to"));
            message.setMessage(resultSet.getString("message"));
            messageList.add(message);
        }

        //6. 关闭连接
        statement.close();
        connection.close();
        return messageList;
    }

    private void save(Message message) throws SQLException {
        // 把数据保存到数据库中

        //1. 先有一个数据源
        DataSource dataSource = DBUtil.getDataSource();

        //2. 建立连接
        Connection connection = dataSource.getConnection();

        //3.构造 SQL
        String sql = "insert into message values(?, ?, ?)";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setString(1,message.getFrom());
        statement.setString(2,message.getTo());
        statement.setString(3, message.getMessage());

        //4. 执行sql进行插入操作
        int ret = statement.executeUpdate();
        System.out.println("ret = " + ret);

        //5. 关闭连接
        statement.close();
        connection.close();
    }
}

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快到锅里来呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值