前后端:表白墙程序

前端

最终效果:
在这里插入图片描述

<!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>

    <style>
        /*  *是选中所以元素;让盒子不被撑大 ;消除浏览器的默认样式*/
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;


        }
        /* 这个对外层盒子操作 */
        .container{
            /* 水平方向左右auto外边距;就是居中状态 */
            margin: 0 auto;
            /* 宽度设置600px */
            width:600px ;

        }
        /* 让h1标签的文字居中 */
        h1{
            text-align: center;

        }
        /* 让p标签的文字居中 */
        p{
            text-align: center;
            /* 让这里的文字颜色浅一点 */
            color: #666;
       
        }
        /* 把这里设置弹性布局 */
        .row{
            display: flex;
            /* 让这里div高一点 */
            height: 40px;
            /* 水平方向居中 */
            justify-content: center;
            /* 垂直方向居中 */
            align-items: center;

        }
        /* 针对输入框三个div */
        .row span{
            width: 80px;
        }
        .row input{
            width:250px ;
            height: 28px;

        }
        .row button{
            width:100px ;
            height: 20px;
            color: black;
            background-color: orange;
            /* 设置圆角矩形 */
            border-radius: 5px;
            /* 按钮去边框 */
            border: none;
            /*有个问题; 点击后什么效果都没有;也不知道点了没 */


        }
        /* 伪类选择器;点击后有一个效果变化 */
        .row button :active{
           background-color: red;

        }
    </style>
<body>
    <!-- 让整体水平居中 -->
    <div class="container">
        
        <h1>表白墙 </h1>
        <p>提示:输入内容后点击提交,信息会显示到下方表格中</p>
    <!-- 让这三个位置分别为一个div -->
        <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>


</body>
</html>

js逻辑:希望点击提交后能够在下方显示

在这里插入图片描述

但是有个问题;我们希望提交后;这上面框的内容应该清空;好让下一个输入更方便。


<script>
        // 实现提交操作;点击按钮;就能把用户输入的东西显示到页面显示
        // 点击后获得三个输入框文本内容;把内容构造到一个新创建的div.row中
        
        let containerDiv=document.querySelector('.container');

        // 选中所有input标签
        let inputs=document.querySelectorAll('input');
        let button=document.querySelector('button');
        // 对这个点击进行事件响应
        button.onclick=function(){
           //获取三个输入框的内容  
           let from =inputs[0].value; 
           let to =inputs[1].value;  
           let msg =inputs[2].value;   
           
           //构造一个新div ;并给它赋予row属性
           let rowDiv =document.createElement('div');
           rowDiv.className='row'; 
           rowDiv.innerHTML=from+'对'+to+'说'+msg;  
        //    最后把这个div添加进去  let containerDiv=document.querySelector('.container');
        containerDiv.appendChild(rowDiv);

        // 清空之前的输入框内容
            for(let input of inputs){

                input.value=' ';
            }


        }

</script>

在这里插入图片描述
但是这里又有点问题;如果为空的时候点提交;会 对 、说也显示在下面

在这里插入图片描述
所以我们遇到任何一个为空就应该直接结束


            if(from==''||to==''|| msg==''){


                return;
            }

增加撤销功能:
在这里插入图片描述
但是这又出现问题;当没有任何数据时点击撤销;连撤销按钮把自己撤销了。
修改逻辑:
在这里插入图片描述

整体代码:

<!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>

    <style>
        /*  *是选中所以元素;让盒子不被撑大 ;消除浏览器的默认样式*/
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;


        }
        /* 这个对外层盒子操作 */
        .container{
            /* 水平方向左右auto外边距;就是居中状态 */
            margin: 0 auto;
            /* 宽度设置600px */
            width:600px ;

        }
        /* 让h1标签的文字居中 */
        h1{
            text-align: center;

        }
        /* 让p标签的文字居中 */
        p{
            text-align: center;
            /* 让这里的文字颜色浅一点 */
            color: #666;
       
        }
        /* 把这里设置弹性布局 */
        .row{
            display: flex;
            /* 让这里div高一点 */
            height: 40px;
            /* 水平方向居中 */
            justify-content: center;
            /* 垂直方向居中 */
            align-items: center;

        }
        /* 针对输入框三个div */
        .row span{
            width: 80px;
        }
        .row input{
            width:250px ;
            height: 28px;

        }
        .row button{
            width:100px ;
            height: 20px;
            color: black;
            background-color: orange;
            /* 设置圆角矩形 */
            border-radius: 5px;
            /* 按钮去边框 */
            border: none;
            /*有个问题; 点击后什么效果都没有;也不知道点了没 */


        }
        /* 伪类选择器;点击后有一个效果变化;这里冒号之间还不能随便空格的;不然就没效果 */
        .row button:active{
           background-color: grey;

        }
      
    </style>
<body>
    <!-- 让整体水平居中 -->
    <div class="container">
        
        <h1>表白墙 </h1>
        <p>提示:输入内容后点击提交,信息会显示到下方表格中</p>
    <!-- 让这三个位置分别为一个div -->
        <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 class="row">
        <button id="submit">
            提交
        </button>
    </div>

    <!-- 增加一个撤销按钮;上面的button就选择器得修改 -->
    <div class="row">
        <button id="revert" >
            撤销
        </button>
    </div>
    
   

    </div>
<script>
        // 实现提交操作;点击按钮;就能把用户输入的东西显示到页面显示
        // 点击后获得三个输入框文本内容;把内容构造到一个新创建的div.row中
        
        let containerDiv=document.querySelector('.container');

        // 选中所有input标签
        let inputs=document.querySelectorAll('input');
        // let button=document.querySelector('button');因为增加一个撤销按钮;就不能再是这么选择
        let button=document.querySelector('#submit');



        // 对这个点击进行事件响应
        button.onclick=function(){
           //获取三个输入框的内容  
           let from =inputs[0].value; 
           let to =inputs[1].value;  
           let msg =inputs[2].value;   
           
          
           //任何一个为空直接结束 
            // if(from == ''|| to == ''|| msg == ''){


            //     return;
            // }
            if (from == '' || to == '' || msg == '') {
                return;
            }
          
             //构造一个新div ;并给它赋予row属性
           let rowDiv =document.createElement('div');

        //    rowDiv.className='row '; 
        rowDiv.className='row mssage'; 

           rowDiv.innerHTML=from+'对'+to+'说'+msg;  
        //    最后把这个div添加进去  let containerDiv=document.querySelector('.container');
        containerDiv.appendChild(rowDiv);

        // 清空之前的输入框内容
            for(let input of inputs){
//  空字符串;什么都不能写;不能写个空格去
                input.value='';
            }


        }
          

        // 撤销逻辑
        let revertButton = document.querySelector('#revert');
        revertButton.onclick = function() {
            // 点击事件;删除最后一条消息. 
            // 选中所有的 row, 找出最后一个 row, 然后进行删除

            // let rows = document.querySelectorAll('.row');
            let rows = document.querySelectorAll('.mssage');
            
// 加上个条件;没有的时候就不删除;不然会报错;直接结束了
            if (rows == null || rows.length == 0) {
                return;
            }
            containerDiv.removeChild(rows[rows.length - 1]);
        }
</script>

</body>
</html>

后端

需求分析:我们上述页面有个问题;关闭或者刷新一下;数据就全没了。所以我们要实现能保存这些数据(提交一次保存一次到服务器);让其它用户也能看到这些数据(刷新或者打开页面就读取全部的数据)

前后端交互:约定好前后端的交互数据格式;请求是什么样;响应是什么样;浏览器啥时候发请求;浏览器按什么样格式解析。
设计:
1:点击提交;浏览器把表白信息发到服务器;数据格式约定是有很多种的。
请求:
在这里插入图片描述

响应:
这里并不需要响应什么特别东西给浏览器;我们要做的重点是把这里数据解析;保存下来;方便下次能取
在这里插入图片描述

2:页面加载;浏览器从服务器获取表白信息;
请求:
在这里插入图片描述

响应
在这里插入图片描述

代码实现:创建maven项目;7步走
1:创建maven项目;
2:导入依赖;maven中央仓库;搜索servlet;选择servlet API 3.1.0版本。复制粘贴到pomxl下
3:创建目录结构;在main下创建webapp;在webapp下创建WEB-INF;在WEB-INF下创建web.xml;在web.xml投名状加上;让tomcat带着项目跑
4:编写代码:继承HttpServlet类;如果没出现这个类那就刷新一下maven;
编写代码:注解得要和我们上面约定的请求路径是一样的
在这里插入图片描述

处理POST请求:我们先定义一个类;描述请求body内容;使用jackson进行json解析。因为我们上面的约定请求内容body是
在这里插入图片描述
导入jackson依赖:maven中央仓库;jackson;选择2.14.1版本;注意拷贝的位置是和Servlet 依赖是同级
在这里插入图片描述
使用jackson初始化我们的类对象:
在这里插入图片描述
我们这里先使用顺序表储存一下这些内容:
在这里插入图片描述

GET请求:
对POST请求处理写完成;现在GET请求处理:GET请求就是获取数据;把顺序表的数据返回给前端就好了
在这里插入图片描述
响应的数据也是json格式;那我们需要把这个List转成json格式:这里可以使用到writeValue:把java对象转成json格式字符串;

在这里插入图片描述
这个方法的作用先是把顺序表转成数组【】;里面的每一个对象是{};对象里面的值是键值对;json格式
在这里插入图片描述

现在后端部分已经完成:但是前端还没有发送请求的功能;一般后端开发在没有前端对接的情况下使用Postman测试是否能交互是很方便的。
在这里插入图片描述
现在我们打开Postman测试一下交互功能是否正常:
效果确实发送成功了;但是因为我们对响应并没有做过多的处理;我们send多几次试试看;然后获取get请求就能收到多个数据了。
在这里插入图片描述
这里如果出现输入中文;而响应的结果;英文是没有问题;中文却显示问号?代替;那就可能是没有设置响应的编码resp.setCharacterEncoding(“utf8”);。这个还得写在 resp.getWriter().write(json);上面才有效果
在这里插入图片描述
这里的发送;一次只能发送这样的一条json格式数据;只是跟我们服务器的处理代码是对应的;如果先一次发多条;像数组一样。那服务器的代码也得修改。

json演示:
如果没有请求参数Student没有的字段会怎么样;或者Student的字段比json的参数多出来的会怎么样???
在这里插入图片描述
难道是说 String s=“{“classId”:2,“studentId”:100}”; 的写法才能发挥出右边的效果 ? {“classId”:2,“StudentId”:100}

整体后端代码:

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;


@WebServlet("/message")


public class MessageWall extends HttpServlet {
        //    创建这个顺序用来储存传过来被jackson处理后的body
        public List<Message> messagesList=new ArrayList<>();
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        super.doGet(req, resp);
            ObjectMapper objectMapper=new ObjectMapper();
        //            转成json对象并且写到响应中;resp.getWriter()这个参数是表示转成json对象往哪写
        // 分两步写效果是一样的
                 String json= objectMapper.writeValueAsString(messagesList);
                 System.out.println(json);
          // resp.setCharacterEncoding("utf8");
           resp.setContentType("application/json; charset=utf8");
                  resp.getWriter().write(json);
//            objectMapper.writeValue(resp.getWriter(),messagesList);
//            resp.setStatus(200);




    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        super.doPost(req, resp);
        ObjectMapper objectMapper=new ObjectMapper();
        Message message=objectMapper.readValue(req.getInputStream(),Message.class);
//        System.out.println(message.from);证明这里传入的字符串是没问题;正确初始化到了
//        System.out.println(message.to);
        //每提交一次就发一次POST请求就执行这个方法一次;就把内容添加进顺序表一次
        messagesList.add(message);
        //        设置返回的状态码;默认也是返回200
        resp.setStatus(200);

    }
}



class Message{
        //    处理请求的body;使用jackson;变量名一样它会根据body自动给这些初始化.所以我们得保证这些属性的名字一样
        public String from;
        public String to;
        public String message;


}

5:打包
6:部署
7:使用

前端请求构建

编写前端代码;让页面来发起请求;并且解析响应;我们的需求;Post点击提交的时候发起;get是页面加载的时候发起。因为我们还是得要通过tomcat启动前端代码;所以先把前端代码粘贴到webapp目录下。

Ajax:
jQuery 选择 3.x minified 鼠标左键复制链接.然后粘贴到script标签

在这里插入图片描述
构建js对象;把文本框获取的内容赋值到这个对象里;再把这个对象转成字符串传输。js内置json转换库;这就比较方便;不像刚才java需要jackson的第三方库转换。

需要添加的代码:

在这里插入图片描述
这里得放这里面来;点击后的才产生这一系列的情况
在这里插入图片描述

处理get请求:页面刷新、加载就发送一个ajax构建get请求;实现读档操作。
我们后端对这个get请求响应的结果是读档;把格式转成字符串;到浏览器会自动帮我们解析成js数组body。我们只需要从这个数组取元素就好了。
在这里插入图片描述

找BUG:

提交数据后轻轻刷新一下;变成下面的效果:(先找到这个是什么意思;未定义的意思;极有可能:前端这个东西未定义)
在这里插入图片描述

在这里插入图片描述
当出现问题时;抓包;确认响应的数据是啥;如果数据没问题;那就说明是前端bug;如果响应数据有问题;说明是后端bug。

问题1:当输入URL时;这就是构建一个GET请求;然后服务器就会响应;把结果写到下面;但是我们什么都没有输入。

解决方法;我们可以判断一下;当链表为空时;也就是没有提交任何的数据;就不发送写回响应字符串。
在这里插入图片描述

问题2:当一直刷新时会一直出现;刚才的问题只解决了空的情况;空的情况随便你怎么刷新都行。现在是不空了;当我输入一次后一直刷新就出现这个bug。而且是我只刷新一次就弹满这个东西。当这个问题2解决后;问题1不处理也行;因为之前是对数据的错误处理导致的这两个bug。
在这里插入图片描述
先放一下;抓包的结果是后端的数据是没有问题的。(只能说当时还是太年轻;只顾看内容;内容是问题的;但是内容的数据类型不是json;得瞄一眼数据的类型是什么)
在这里插入图片描述
在这里插入图片描述
可能的情况:前端的处理方式不对;但是经过反复的检查和处理;发现前端并没有问题;后端发的数据打印出结果的格式也是没有问题;那就可能浏览器的识别不知道这是json格式的数据;所以没法处理;我们在设置字符集时并没有指定说这是json格式数据。所以浏览器就按照自己的方式认为这是什么数据;按什么方式解析。

在这里插入图片描述
整体代码:(注意:在写相关代码时一定得注意细节;稍有不慎可能结果就请求没法发送;没法响应;没法解析等;而且这里没达到预期效果往往是不显示错误的;需要自己去找提示;找错误)

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;


@WebServlet("/message")


public class MessageWall extends HttpServlet {
        //    创建这个顺序用来储存传过来被jackson处理后的body
        public List<Message> messagesList=new ArrayList<>();
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        super.doGet(req, resp);
            ObjectMapper objectMapper=new ObjectMapper();
        //            转成json对象并且写到响应中;resp.getWriter()这个参数是表示转成json对象往哪写
        // 分两步写效果是一样的
//                 String json= objectMapper.writeValueAsString(messagesList);
//                 System.out.println(json);
          //  resp.setCharacterEncoding("utf8");
            resp.setContentType("application/json; charset=utf8");
//                  resp.getWriter().write(json);
//            if(messagesList.size()==0){
//
//                return;
//            }
            objectMapper.writeValue(resp.getWriter(),messagesList);
//            resp.setStatus(200);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        super.doPost(req, resp);
        ObjectMapper objectMapper=new ObjectMapper();
        Message message=objectMapper.readValue(req.getInputStream(),Message.class);
//        System.out.println(message.from);证明这里传入的字符串是没问题;正确初始化到了
//        System.out.println(message.to);
        //每提交一次就发一次POST请求就执行这个方法一次;就把内容添加进顺序表一次
        messagesList.add(message);
        //        设置返回的状态码;默认也是返回200
        resp.setStatus(200);
        System.out.println("收到请求");


    }

class Message{
        //    处理请求的body;使用jackson;变量名一样它会根据body自动给这些初始化.所以我们得保证这些属性的名字一样
        public String from;
        public String to;
        public String message;
}

数据库版本

我们需求想数据持久化保存:
1:使用流对象;写入文本文件;但是文本文件无法灵活增删查改等
2:借助数据库
创建数据表:里面内容是from,to,message。想使用关键字命名得加反引号;左上角。
在这里插入图片描述

连接数据库:
maven中央仓库搜索mysql;选择JDBC选择需要的版本8.0.32;导入mysql依赖;我们是maven项目;直接把修改配置它就会自动下载导入的;放与Servlet的配置同级下。

 <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.32</version>
        </dependency>

数据库的连接

import com.mysql.cj.jdbc.MysqlDataSource;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//数据库的连接;把连接的过程封装一下;作为工具类;提供一些static让我们使用更方便
public class DBlianjie {
//    静态成员相当于饿汉单例模式
public static DataSource dataSource=new MysqlDataSource();

//初始化DataSource
static {

    ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/liao?characterEncoding=utf8&useSSL=false");
    ((MysqlDataSource)dataSource).setUser("root");
    ((MysqlDataSource)dataSource).setPassword("111111");
}

//    通过这个方法建立连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();


}
//通过这个方法释放资源
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){

        // 此处的三个 try catch 分开写更好, 避免前面的异常导致后面的代码不能执行.
        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();
            }
        }

    }

}

代码上添加两个方法:我们存元素和取元素就来自这两个方法
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
//数据库版本表白墙程序

@WebServlet("/message")


public class MessageWallJDBC  extends HttpServlet {
        //    创建这个顺序用来储存传过来被jackson处理后的body
        public List<Message> messagesList=new ArrayList<>();
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //   super.doGet(req, resp);
            resp.setContentType("application/json; charset=utf8");
            ObjectMapper objectMapper=new ObjectMapper();
//            ObjectMapper对json的操作
             //  这个方法返回的结果就是我们储存的全部数据
            List<Message> messageList=getall();
            System.out.println("收到get请求");
//            String jsonResp = objectMapper.writeValueAsString(messageList);
//            resp.getWriter().write(jsonResp);
//            写错单词我艹
       objectMapper.writeValue(resp.getWriter(),messageList);





    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        super.doPost(req, resp);
        ObjectMapper objectMapper=new ObjectMapper();
        Message message=objectMapper.readValue(req.getInputStream(),Message.class);
        //message是读取到提交的body
       add(message);
        //        设置返回的状态码;默认也是返回200
        resp.setStatus(200);
        System.out.println("收到post请求");


    }

    //   从数据库存一条消息
public void add(Message message){
    //    用来提升变量作用域
    Connection connection=null;
    PreparedStatement statement=null;
   //1建立连接
    try {
       connection=DBlianjie.getConnection();
   // 2       构造sql语句;?占位符;后面可以通过set***替换占位符
        String sql="insert into message values(?, ?,?)";
         statement= connection.prepareStatement(sql);
//        这里替换的下标开始位置是1下标开始
        statement.setString(1,message.from);
        statement.setString(2,message.to);
        statement.setString(3,message.message);
//3执行sql
statement.executeUpdate();
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
//  写finally保证能被执行到;  没有使用到查询;就用空代替。作用域不够得往外提
finally {
        DBlianjie.close(connection,statement,null);
    }

}

   //   从数据库取所有消息 查询操作
public  List<Message> getall(){
    List<Message> messageList=new ArrayList<>();
    Connection connection=null;
    PreparedStatement statement=null;
    ResultSet resultSet=null;
//1建立连接
    try {
    connection=DBlianjie.getConnection();

// 2构造sql语句
        String sql="select *from message";
        statement=connection.prepareStatement(sql);
//      3  执行sql
        resultSet= statement.executeQuery();

//4遍历结果集;
        while (resultSet.next()){
         Message message=new Message();
//         这里的"from"是表的列名;给这个对象里的内容赋值;然后doget就继续把这个对象转成json;然后当body发给前端

            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释放资源;断开连接
        DBlianjie.close(connection,statement,resultSet);
    }

return messageList;
}


}





class Message{
        //    处理请求的body;使用jackson;变量名一样它会根据body自动给这些初始化.所以我们得保证这些属性的名字一样
        public String from;
        public String to;
        public String message;


}

代码的逻辑是不变的;只是储存变成数据库;读取也是如此;
以上代码大功告成;虽然差强人意;但是必须要刷新才能看到最新的消息;可以使用refresh或者websocket(应用层协议)实现服务器主动推送数据。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

while(true)energy++;

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

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

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

打赏作者

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

抵扣说明:

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

余额充值