如果了解了ajax,请坐电梯

    • 前言
    • ajax的能干什么?
      • 哪里用到了ajax?
    • 后端
    • 前端
    • 数据交互
    • 整体实现思路
  • 实时接收消息
    • html前端
      • js 和 ajax
  • 实时发送消息
    • HTML
    • js
    • ajax对应的方法
      • 注意点
    • 效果图
      • 有问题请看这里

前言


私信(聊天)功能,有一点是不能忽略的,那就是消息的实时发送与实时接收,否则的话就直接退化成为留言板功能了。

之前我在论坛中有问到这个实现的方法,我考虑了websocket 和 ajax 长轮询这两个方法,很多人也有说websocket比较消耗资源。最终在权衡服务器和客户端的情况下,使用了ajax方法(websocket不会写)


ajax的能干什么?

使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。(节选自百度百科)

简单的来说,使用ajax,页面不刷新就可以验证用户名是否存在。在页面不刷新的情况下向服务器端发送一个请求,在得到服务器的响应后,把结果重新传到页面上并进行显示。

哪里用到了ajax?


尝试在百度输入一个候选词,然后下方会弹出推荐,使用键盘上下进行选择。在你还没有按下回车的时候,页面的内容就已经变了,而如果是刷新的话,文本框中的内容就应该已经没有了,但是使用ajax就可以有这样的效果。

后端

  • Spring boot
  • Mybatis
  • MySQL

前端

  • HTML
  • CSS
  • JS
  • jquery
  • ajax

数据交互

前后端通过JSON数据交互。

整体实现思路

  1. 列表中选择一个自己要聊天的对象
  2. 使用 ajax 显示消息
  3. 发送消息 ,使用 ajax 避免刷新,实时显示
  4. 长轮询,每 2 秒发送一次查询请求并实时显示消息
  5. 确保每次直达底部的最新消息

实时接收消息

@ResponseBody@GetMapping("/userCenter/chat/{receiver}")public String chatWithOthers(@PathVariable("receiver") String receiver,Model model, HttpSession session)  {//搜索用户的聊天状态User user = (User) session.getAttribute("loginUser");String sender = user.getUserName();List<ChatListDTO> chatLists = chatListService.list(sender);model.addAttribute("chatLists", chatLists);if (userMapper.selectUserByName(receiver)==null){model.addAttribute("noUser","noUser");return "";}//更改消息数的时候,receiver是发送者,而sender是接收者messageMapper.updateMessageCount(receiver,sender);//查找属于sender的两人会话List<MessageDTO> list = messageService.messagesList(sender, receiver, sender);JSONArray array= JSONArray.parseArray(JSON.toJSONString(list));return array.toJSONString();}

html前端

这里是从后端查询了当前用户的聊天列表,并进行遍历显示。

<ul><li th:id="${item.chatList.others}" th:each="item : ${chatLists}" class="chat-item"><!--                    th:href="@{'/userCenter/communicate/'+${item.chatList.others}}"--><span th:onclick="chat([[${item.chatList.others}]])"><img th:src="${item.others.imgUrl}" class="chat-img"><span class="chat-user">[[${item.chatList.others}]]</span></span><span class="chat-time"th:text="${#dates.format(item.chatList.lastReplyTime,'yyyy-MM-dd HH:mm')}"></span></li></ul>

js 和 ajax

name 已经在 onclick 里面传过。

整体思路:往后端发送请求查询,然后往前端返回 JSON ,然后遍历显示。

鉴于会有新信息,要实时接收新信息,就可以使用 setInterval( 一个显示的 function (),2000),这表示两秒查询一次并回显。

function chat(name) {$("#chat_content").val("");$("#receiver_name").attr("value", name.toString());$(".chat-item").removeClass("background");$("#" + name).addClass("background");var others = name;var totol;var chatArea = $("#chat_area");var time = 0;$("#noChat").hide();$("#chat").css("display", "block");$.ajax({type: "get",url: "/userCenter/chat/" + others,dataType: "json",success: function (data) {chatArea.html("");data = JSON.stringify(data);var jsonData = JSON.parse(data);totol = jsonData.length;for (var i = 0; i < totol; i++) {var msg = jsonData[i];var sender = msg.sender.userName;var imgUrl = msg.sender.imgUrl;var content = msg.message.content;var div_class;var img_class;var msg_time = msg.message.gmtCreate;if (msg_time - time > 60000) {time = msg_time;msg_time = new Date(msg_time).toLocaleString().replace(/:\d{1,2}$/, ' ');} else {msg_time = "";}if (sender != others) {//如果我是发送者div_class = "sender";img_class = "reply-img";} else {div_class = "receiver";img_class = "receiver-img";}var message = "<br style=\"line-height: 60px\">" +"<p style='text-align: center'>"+ msg_time+ "</p>" +"<div class=\"msg-div\">" +"<div class=" + div_class + ">" +"<img src= "+ imgUrl +"  class=" + img_class + ">" +"<div class=\"content-msg\">"+ content +"</div>" +"</div></div>";chatArea.append(message);chatArea.scrollTop(9999);}},error: function () {alert("错误 ")}})setInterval(function () {var times = 0;$.ajax({type: "get",url: "/userCenter/chat/" + others,dataType: "json",success: function (data) {data = JSON.stringify(data);var times = 0;var jsonData = JSON.parse(data);var newTotal = jsonData.length;if (newTotal == totol) {console.log("无新消息");} else {chatArea.html("");totol = newTotal;for (var i = 0; i < totol; i++) {var msg = jsonData[i];var sender = msg.sender.userName;var imgUrl = msg.sender.imgUrl;var content = msg.message.content;var div_class;var img_class;var msg_time = msg.message.gmtCreate;if (msg_time - times > 60000) {times = msg_time;msg_time = new Date(msg_time).toLocaleString().replace(/:\d{1,2}$/, ' ');} else {msg_time = "";}if (sender != others) {//如果我是发送者div_class = "sender";img_class = "reply-img";} else {div_class = "receiver";img_class = "receiver-img";}console.log(img_class);var message = "<br style=\"line-height: 60px\">" +"<p style='text-align: center'>"+ msg_time+ "</p>" +"<div class=\"msg-div\">" +"<div class=" + div_class + ">" +"<img src= "+ imgUrl +"  class=" + img_class + ">" +"<div class=\"content-msg\">"+ content +"</div>" +"</div></div>";$("#chat_area").append(message);$("#chat_area").scrollTop(9999);}}},error: function () {alert("错误 ")}})}, 2000);}

实时发送消息

因为显示消息是使用ajax实现的,所以我们就可以通过一个标签来获得聊天对象的名字(id)。在显示聊天信息的时候已经把下面的值改变了。

<span id="receiver_name" value=""></span>

HTML

这里的表单最开始使用的是form,但是因为调用ajax的时候的 success 和 error 都没有执行,就把 form 变成了 div,所有的样式还是和form一样的。

<div id="chat_form" class="padding-top-30px"><textarea id="chat_content" name="chatContent" class="form-control"placeholder="给对方打个招呼吧!" cols="20" rows="8"></textarea><br><button type="submit" onclick="sendMsg()"  id="content_submit"class="btn btn-info btn-primary btn-right">提交</button></div>

js

   function sendMsg() {var chatContent =$("#chat_content");var receiverName = $("#receiver_name").attr("value");var content = chatContent.val();var chatArea = $("#chat_area");$.ajax({type: "post",url: "/chat/" + receiverName,data:{"content": content},async:false,dataType: "text",success:function (data) {chatContent.val('');var jsonData = JSON.stringify(data);var msg1 = jsonData.message;var msgContent = msg1.content;var sender1 = jsonData.sender;var msg_time = jsonData.gmtCreate;msg_time = new Date(msg_time).toLocaleString().replace(/:\d{1,2}$/, ' ');var imgUrl = sender1.imgUrl;var div_class = "sender";var img_class = "reply-img";var message = "<br style=\"line-height: 60px\">" +"<p style='text-align: center'>"+ msg_time+ "</p>" +"<div class=\"msg-div\">""<div class=" + div_class + ">" +"<img src= "+ imgUrl +"  class=" + img_class + ">" +"<div class=\"content-msg\">"+ msgContent +"</div>" +"</div></div>";chatArea.append(message);chatArea.scrollTop(9999);},error:function (data) {data = JSON.stringify(data);alert("failed " + data);}})}

ajax对应的方法

@ResponseBody
@PostMapping(value = "/chat/{receiver}")public String sendMassage(@PathVariable("receiver") String receiver,@RequestParam String content,HttpSession session) {MessageDTO dto = new MessageDTO();User user = (User) session.getAttribute("loginUser");String sender = user.getUserName();Long current;//创建两个人的消息for (int i = 1; i <= 2; i++) {Message msg = new Message();current = System.currentTimeMillis();String id = sender + "-" + receiver + "-" + current;msg.setId(id);msg.setSender(sender);msg.setReceiver(receiver);msg.setHasRead(0);msg.setContent(content);msg.setGmtCreate(current);if (i == 1) {msg.setForUser(sender);User senderUser = userMapper.selectUserByName(sender);dto.setSender(senderUser);dto.setMessage(msg);} else {msg.setForUser(receiver);User receiveUser = userMapper.selectUserByName(receiver);dto.setSender(receiveUser);}//插入消息messageMapper.insertMsg(msg);}if (chatListMapper.selectChatId(sender, receiver) == null)//插入到会话列表{for (int i = 1; i <=2 ; i++) {ChatList chatList = new ChatList();current = System.currentTimeMillis();chatList.setId(sender + current);chatList.setLastReplyTime(current);//循环为两个人的对话赋值if (i == 1){chatList.setMe(sender);chatList.setOthers(receiver);}else{chatList.setMe(receiver);chatList.setOthers(sender);}chatListMapper.insertChatList(chatList);}}else {current = System.currentTimeMillis();chatListMapper.updateLastReplyTime(sender,receiver,current);}String json = JSON.toJSONString(dto);return json;}

注意点

在 ajax 中,把DataType设置成“josn”的时候,传往后台的数据 ——“你好”,会自动变成 “content = 你好”, 暂时不清楚是什么原因导致的。在更改了DataType = “text” 后,就可以正常的往后台传送参数了。

效果图

有问题请看这里

有疑问的话可以在评论区留言或者私信作者。

整个系统是一个 医学科普 + 论坛 , 如果需要作为毕业设计的话可以联系作者。

私信(聊天)功能 ajax长轮询实现相关推荐

  1. ajax长轮询 java web_网页实时聊天之js和jQuery实现ajax长轮询

    众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...

  2. java+jquery实现长轮询案例_网页实时聊天之js和jQuery实现ajax长轮询

    众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...

  3. ajax长轮询tornado,Tornado长轮询和WebSocket

    Http协议是一种请求响应式协议, 不允许服务端主动向客户端发送信息. 短轮询是一种简单的实现服务端推送消息的解决方案, 客户端以一定间隔自动向服务端发送刷新请求, 服务端返回要推送的消息作为响应. ...

  4. Comet 反Ajax: 基于jQuery与PHP实现Ajax长轮询(LongPoll)

    传统的AJAX轮询方式,客服端以用户定义的时间间隔去服务器上查询最新的数据.种这种拉取数据的方式需要很短的时间间隔才能保证数据的精确度,但太短的时间间隔客服端会对服务器在短时间内发送出多个请求. 反转 ...

  5. WEB消息提醒实现之二 实现方式-Jquery Ajax长轮询

    #Jquery Ajax长轮询 ##原理 Jquery Ajax长轮询的原理主要是,前台客户端发送ajax请求到服务器,服务器接收到请求之后会保持住连接,直到有新消息才返回响应信息并关闭连接,客户端处 ...

  6. php ajax 长轮询 表单,Thinkphp结合AJAX长轮询实现PC与APP推送详解

    前言 本文主要给大家介绍的关于Thinkphp结合AJAX长轮询实现PC与APP推送的相关内容,分享出来供大家参考学习,话不多说,来一起看看详细的介绍. 实现逻辑 某个操作(比如新建一条公告)后,触发 ...

  7. 多个ajax分别实现实现长轮询,ajax长轮询、轮询应用和介绍

    ####什么是轮询 轮询是指客户端定时向服务器发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接. ####轮询的简单实现 仅仅是说出定义来,好像很模糊,代码更加直观一些,下面就简单写一下轮 ...

  8. mysql长轮询_【系列一】ajax长轮询、轮询应用和介绍

    前言 本文是系列文章,主要介绍客户端浏览器和服务器端的通信,当然,客户端和服务器端通信有很多方式.本系列文章主要是讲不间断通信方式!不间断通信就是通信没有停止,一直进行.系列一文章主要是讲轮询和长轮询 ...

  9. Ajax轮询,Ajax长轮询和websockte

    http协议介绍: http协议是请求响应式的,每个http相应都对应一个http请求,http协议是没有状态的,多个http协议之间是没有关系的. http协议的被动性:在标准的http语义中,浏览 ...

  10. ajax长轮询 java web_浅谈Websocket、Ajax轮询和长轮询(long polling)

    浅谈Websocket.Ajax轮询和长轮询(long p0ll) 最近看到了一些介绍Websocket的文章,觉得挺有用,所以在这里将自己的对其三者的理解记录一下. 1.什么是Websocket W ...

最新文章

  1. Openstack组件部署 — Keystone Install Create service entity and API endpoints
  2. HRNet-Facial-Landmark-Detection 人脸关键点
  3. 用友伟库“抢劫”金算盘,调研数据究竟谁说了算?
  4. android/linux中的第一个init程序的启动
  5. javascript-模板方法模式-提示框归一化插件
  6. python中变量和函数的区别_关于python中带下划线的变量和函数 的意义
  7. The authenticity of host 'github.com (52.74.223.119)' can't be established.
  8. FreeRTOS | STM32H7串口中断调用FreeRTOS API,导致程序卡死
  9. .Net 开源项目资源大全
  10. 从王者荣耀看设计模式(二.单例模式)
  11. 利用border设置transparent绘制图形
  12. linux怎么更改rpcbind端口号,rpcbind_rpcbind服务是什么_rpcbind 端口
  13. W5500以太网控制器芯片(一):ioLibrary库实现TCP服务器
  14. 电商后台管理系统-权限管理模块
  15. (Android+Qt最小系统设计方案)RK3288核心板设计之软件开发环境搭建(4.0)
  16. WORDPRESS优化技巧之CDN加速
  17. SystemInit()时钟系统初始化函数解析
  18. Python最假的库:Faker
  19. 解决无法从公司 Maven 私服下载依赖的问题
  20. 24种设计模式大全-牛人详解

热门文章

  1. php和plc哪个难,致PLC初学者的入门一课,七大误区如何解决?
  2. 各个省份城市HTML,省份城市的三级联动.html
  3. redis集群 原理
  4. Redis的集群原理
  5. 艾宾浩斯曲线在线 PDF 文件生成 在线背单词 背单词计划表 高考-四级-六级-SAT-托福-雅思-GRE-17 天搞定 GRE 单词, 背单词神器-动态生成时间表! 利用艾宾浩斯记忆曲线自动生成背单
  6. 3D Max 渲染和渲染农场渲染经常会出现白点?网渲和本地通用解决~
  7. php抖音跳转地址,PHP如何实现解析抖音无水印视频
  8. Unity3D流体插件FluidSim使用总结
  9. 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
  10. 云忧cms搭建在宝塔nginx服务器,登录报错