WebSocket实现聊天室业务

WebSocket实现聊天室业务的具体代码,供大家参考,具体内容如下

页面效果图

pom.xml

主要是spring-boot-starter-websocket包,websocket连接、发送信息。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-websocket</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  <dependency><!--Webjars版本定位工具-->
   <groupId>org.webjars</groupId>
   <artifactId>webjars-locator-core</artifactId>
  </dependency>
  <dependency>
   <groupId>org.webjars.npm</groupId>
   <artifactId>mdui</artifactId>
   <version>0.4.0</version>
  </dependency>
  <dependency>
   <groupId>org.webjars</groupId>
   <artifactId>jquery</artifactId>
   <version>3.3.1</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-devtools</artifactId>
   <scope>runtime</scope>
  </dependency>
  <dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.49</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

前台

html + js

websocket 前台主要包括四种方法:

  • 打开连接:onopen
  • 服务端发来消息:1.广播消息 2.更新在线人数 : onmessage
  • 关闭连接 :onclose
  • 通信失败 :onerror
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <title>WebSocket简单聊天室</title>
 <meta charset="utf-8" name="viewport" content="width=device-width">
 <link rel="stylesheet" th:href="@{/webjars/mdui/dist/css/mdui.css}">
 <script th:src="@{/webjars/jquery/jquery.min.js}"></script>
 <script th:src="@{/webjars/mdui/dist/js/mdui.js}"></script>
</head>
<body class="mdui-theme-primary-indigo mdui-theme-accent-pink">

<div class="mdui-container">
 <div class="mdui-toolbar mdui-color-theme">
  <a class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">menu</i></a>
  <span class="mdui-typo-title">简单聊天室</span>
  <div class="mdui-toolbar-spacer"></div>
  <a class="mdui-btn mdui-btn-icon" href="https://www.jianshu.com/p/964370d9374e" target="_blank"><i
    class="mdui-icon material-icons">search</i></a>
  <a class="mdui-btn mdui-btn-icon" th:href="@{/}"><i
    class="mdui-icon material-icons">exit_to_app</i></a>
  <a class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">more_vert</i></a>
 </div>
</div>

<div>
 <div class="mdui-container container_text">

  <div class="mdui-row">
   <div class="mdui-col-xs-12 mdui-col-sm-6">
    <div class="mdui-col-xs-12 mdui-col-sm-10">
     <div class="mdui-textfield-floating-label" style="margin-top:15px">
      <i class="mdui-icon material-icons">欢迎:</i>
      <i class="mdui-icon" id="username" th:text="${username}"></i>
     </div>
    </div>
    <div class="mdui-col-xs-12 mdui-col-sm-10">
     <div class="mdui-textfield mdui-textfield-floating-label">
      <i class="mdui-icon material-icons">textsms</i>
      <label class="mdui-textfield-label">发送内容</label>
      <input class="mdui-textfield-input" id="msg"/>
     </div>
     <div class="mdui-container" style="padding:20px 35px">
      <button class="mdui-btn mdui-color-theme-accent mdui-ripple"
        onclick="sendMsgToServer()">发送 (enter)
      </button>
      <button class="mdui-btn mdui-color-theme mdui-ripple"
        onclick="clearMsg()">清屏
      </button>
     </div>
    </div>
   </div>

   <div class="mdui-col-xs-6 mdui-col-sm-5" style="padding:10px 0">
    <div class="mdui-chip">
     <span class="mdui-chip-icon mdui-color-blue">
      <i class="mdui-icon material-icons"></i></span>
     <span class="mdui-chip-title">聊天内容</span>
    </div>

    <div class="mdui-chip">
     <span class="mdui-chip-icon mdui-color-blue">
      <i class="mdui-icon material-icons">face</i></span>
     <span class="mdui-chip-title">在线人数</span>
     <span class="mdui-chip-title chat-num">0</span>
    </div>
    <div class="message-container">

    </div>
   </div>

  </div>
 </div>
</div>

<script th:inline="javascript">

 /**
  * WebSocket客户端
  *
  * 使用说明:
  * 1、WebSocket客户端通过回调函数来接收服务端消息。例如:webSocket.onmessage
  * 2、WebSocket客户端通过send方法来发送消息给服务端。例如:webSocket.send();
  */
 function getWebSocket() {
  /**
   * WebSocket客户端 PS:URL开头表示WebSocket协议 中间是域名端口 结尾是服务端映射地址
   */
  var webSocket = new WebSocket(/*[[${webSocketUrl}]]*/ 'ws://localhost:8080/chat');
  /**
   * 当服务端打开连接
   */
  webSocket.onopen = function (event) {
   console.log('WebSocket打开连接');
  };

  /**
   * 当服务端发来消息:1.广播消息 2.更新在线人数
   */
  webSocket.onmessage = function (event) {
   console.log('WebSocket收到消息:%c' + event.data, 'color:green');
   //获取服务端消息
   var message = JSON.parse(event.data) || {};
   var $messageContainer = $('.message-container');
   //喉咙发炎
   if (message.type === 'SPEAK') {
    $messageContainer.append(
     '<div class="mdui-card" style="margin: 10px 0;">' +
     '<div class="mdui-card-primary">' +
     '<div class="mdui-card-content message-content">' + message.username + ":" + message.msg + '</div>' +
     '</div></div>');
   }
   $('.chat-num').text(message.onlineCount);
   //防止刷屏
   var $cards = $messageContainer.children('.mdui-card:visible').toArray();
   if ($cards.length > 5) {
    $cards.forEach(function (item, index) {
     index < $cards.length - 5 && $(item).slideUp('fast');
    });
   }
  };

  /**
   * 关闭连接
   */
  webSocket.onclose = function (event) {
   console.log('WebSocket关闭连接');
  };

  /**
   * 通信失败
   */
  webSocket.onerror = function (event) {
   console.log('WebSocket发生异常');

  };
  return webSocket;
 }

 var webSocket = getWebSocket();

 /**
  * 通过WebSocket对象发送消息给服务端
  */
 function sendMsgToServer() {
  var $message = $('#msg');
  if ($message.val()) {
   webSocket.send(JSON.stringify({username: $('#username').text(), msg: $message.val()}));
   $message.val(null);
  }

 }

 /**
  * 清屏
  */
 function clearMsg() {
  $(".message-container").empty();
 }

 /**
  * 使用ENTER发送消息
  */
 document.onkeydown = function (event) {
  var e = event || window.event || arguments.callee.caller.arguments[0];
  e.keyCode === 13 && sendMsgToServer();
 };

</script>

</body>
</html>

后台

WebSocketChatApplication - 启动类

@SpringBootApplication
@RestController
public class WebSocketChatApplication {

 /**
  * 登陆界面
  */
 @GetMapping("/")
 public ModelAndView login() {
  return new ModelAndView("/login");
 }

 /**
  * 聊天界面
  */
 @GetMapping("/index")
 public ModelAndView index(String username, String password, HttpServletRequest request) throws UnknownHostException {
  if (StringUtils.isEmpty(username)) {
   username = "匿名用户";
  }
  ModelAndView mav = new ModelAndView("/chat");
  mav.addObject("username", username);
  mav.addObject("webSocketUrl", "ws://"+InetAddress.getLocalHost().getHostAddress()+":"+request.getServerPort()+request.getContextPath()+"/chat");
  return mav;
 }

 public static void main(String[] args) {
  SpringApplication.run(WebSocketChatApplication.class, args);
 }
}

WebSocketConfig - WebSocket配置类

@Configuration
public class WebSocketConfig {

 /**
  * 用于扫描和注册所有携带ServerEndPoint注解的实例。
  * <p>
  * PS:若部署到外部容器 则无需提供此类。
  */
 @Bean
 public ServerEndpointExporter serverEndpointExporter() {

  return new ServerEndpointExporter();
 }
}

Message - 封装信息类

/**
 * WebSocket 聊天消息类
 */
public class Message {

 public static final String ENTER = "ENTER";
 public static final String SPEAK = "SPEAK";
 public static final String QUIT = "QUIT";

 private String type;//消息类型

 private String username; //发送人

 private String msg; //发送消息

 private int onlineCount; //在线用户数

 public static String jsonStr(String type, String username, String msg, int onlineTotal) {
  return JSON.toJSONString(new Message(type, username, msg, onlineTotal));
 }

 public Message(String type, String username, String msg, int onlineCount) {
  this.type = type;
  this.username = username;
  this.msg = msg;
  this.onlineCount = onlineCount;
 }

 public static String getENTER() {
  return ENTER;
 }

 public static String getSPEAK() {
  return SPEAK;
 }

 public static String getQUIT() {
  return QUIT;
 }

 public String getType() {
  return type;
 }

 public void setType(String type) {
  this.type = type;
 }

 public String getUsername() {
  return username;
 }

 public void setUsername(String username) {
  this.username = username;
 }

 public String getMsg() {
  return msg;
 }

 public void setMsg(String msg) {
  this.msg = msg;
 }

 public int getOnlineCount() {
  return onlineCount;
 }

 public void setOnlineCount(int onlineCount) {
  this.onlineCount = onlineCount;
 }
}

WebSocketChatServer - 聊天服务端

前台对应的四种传输,后台进行处理操作

/**
 * WebSocket 聊天服务端
 *
 * @see ServerEndpoint WebSocket服务端 需指定端点的访问路径
 * @see Session WebSocket会话对象 通过它给客户端发送消息
 */

@Component
@ServerEndpoint("/chat")
public class WebSocketChatServer {

 /**
  * 全部在线会话 PS: 基于场景考虑 这里使用线程安全的Map存储会话对象。
  */
 private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();

 /**
  * 当客户端打开连接:1.添加会话对象 2.更新在线人数
  */
 @OnOpen
 public void onOpen(Session session) {
  onlineSessions.put(session.getId(), session);
  sendMessageToAll(Message.jsonStr(Message.ENTER, "", "", onlineSessions.size()));
 }

 /**
  * 当客户端发送消息:1.获取它的用户名和消息 2.发送消息给所有人
  * <p>
  * PS: 这里约定传递的消息为JSON字符串 方便传递更多参数!
  */
 @OnMessage
 public void onMessage(Session session, String jsonStr) {
  Message message = JSON.parseObject(jsonStr, Message.class);
  sendMessageToAll(Message.jsonStr(Message.SPEAK, message.getUsername(), message.getMsg(), onlineSessions.size()));
 }

 /**
  * 当关闭连接:1.移除会话对象 2.更新在线人数
  */
 @OnClose
 public void onClose(Session session) {
  onlineSessions.remove(session.getId());
  sendMessageToAll(Message.jsonStr(Message.QUIT, "", "", onlineSessions.size()));
 }

 /**
  * 当通信发生异常:打印错误日志
  */
 @OnError
 public void onError(Session session, Throwable error) {
  error.printStackTrace();
 }

 /**
  * 公共方法:发送信息给所有人
  */
 private static void sendMessageToAll(String msg) {
  onlineSessions.forEach((id, session) -> {
   try {
    session.getBasicRemote().sendText(msg);
   } catch (IOException e) {
    e.printStackTrace();
   }
  });
 }

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 用java WebSocket做一个聊天室

    最近一个项目中,需要用到Java的websocket新特性,于是就学了一下,感觉这技术还挺好玩的,瞬间知道网页上面的那些在线客服是怎么做的了. 先看图: 实现了多客户机进行实时通讯. 下面看代码项目结构图:很简单,就1个类,1个页面 然后看具体代码 先看后端代码 package com.main; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.

  • 基于Tomcat7、Java、WebSocket的服务器推送聊天室实例

    前言 HTML5 WebSocket实现了服务器与浏览器的双向通讯,双向通讯使服务器消息推送开发更加简单,最常见的就是即时通讯和对信息实时性要求比较高的应用.以前的服务器消息推送大部分采用的都是"轮询"和"长连接"技术,这两中技术都会对服务器产生相当大的开销,而且实时性不是特别高.WebSocket技术对只会产生很小的开销,并且实时性特别高.下面就开始讲解如何利用WebSocket技术开发聊天室.在这个实例中,采用的是Tomcat7服务器,每个服务器对于WebSoc

  • 使用WebSocket实现即时通讯(一个群聊的聊天室)

    随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据. 传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据:这种客户端是主动方,服务端是被动方的传统Web模式对于信息变化不频繁的Web应用来说造成的麻烦

  • 微信小程序websocket聊天室的实现示例代码

    背景 最近做了一个微信小程序的即时通讯功能,之前我也做过node.js的websocket服务,不过是在web端应用的socket.io服务.小程序本身对http.websocket等连接均有诸多限制,所以这次项目选择了node.js自带的ws模块. 服务端 初始化一个node.js项目,引入ws模块 const webSocket = require('ws'); 创建websocket实例,并设置监听端口 const wss = new webSocket.Server({ port: 30

  • golang基于websocket实现的简易聊天室程序

    本文实例讲述了golang基于websocket实现的简易聊天室.分享给大家供大家参考,具体如下: 先说点无关的,最近忙于工作没有更新博客,今天休息顺便把golang websocket研究了一下,挺好玩的,写了一个聊天室,分享给大家. websocket包 : code.google.com/p/go.net/websocket 文档 : http://go.pkgdoc.org/code.google.com/p/go.net/websocket 首先安装websocket包 复制代码 代码

  • Android使用Websocket实现聊天室

    最近的项目中要实现一个聊天的功能,类似于斗鱼TV的聊天室功能,与服务器端人商量后决定用WebSocket来做,但是在这之前我只知道Socket但是听都没有听过WebSocket,但是查看了相关的材料以后发现实现一个聊天室其实是很简单的!下面我们先来看看WebSocket. Autobahn|Android 是由Autobahn开发一个开源的Java/Android网络库,实现了WebSocket协议和Web应用程序消息传输协议来创建本地移动的WebSocket/ WAMP的客服端. WebSoc

  • php基于websocket搭建简易聊天室实践

    本文实例讲述了php基于websocket搭建简易聊天室实践.分享给大家供大家参考.具体如下: 1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短连接和长连接.短连接一般可以用ajax实现,长连接就是websocket.短连接实现起来比较简单,但是太过于消耗资源.websocket高效不过兼容存在点问题.websocket是html5的资源 2.前

  • 基于Swoole实现PHP与websocket聊天室

    websocket Websocket只是一个网络通信协议 就像 http.ftp等都是网络通信的协议:不要多想: 相对于HTTP这种非持久的协议来说,Websocket是一个持久化网络通信的协议: WebSocket和HTTP的关系 有交集,但是并不是全部. Websocket只是借用了HTTP的一部分协议来完成一次握手.(HTTP的三次握手,此处只完成一次) http和websocket 请求头对比: HTTP: 原来的时候,客户端通过http(骑马)带着信请求服务器,服务器处理请求(写回信

  • php+html5基于websocket实现聊天室的方法

    本文实例讲述了php+html5基于websocket实现聊天室的方法.分享给大家供大家参考.具体如下: html5的websocket 实现了双向通信,折腾了几天弄了个聊天室,分享给大家 <?php error_reporting(E_ALL); ob_implicit_flush(); $sk=new Sock('127.0.0.1',8000); $sk->run(); class Sock{ public $sockets; public $users; public $master;

  • 使用Java和WebSocket实现网页聊天室实例代码

    在没介绍正文之前,先给大家介绍下websocket的背景和原理: 背景 在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更

随机推荐