Spring Boot中使用Websocket搭建即时聊天系统
1、首先在pom文件中引入Webscoekt的依赖
<!-- websocket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2、通过注解方式构建Websocket服务
package com.kk.server.chat.websocket; import com.kk.server.chat.service.CheckTokenService;
import com.kk.server.chat.service.QueryService;
import com.kk.server.chat.service.SaveMongodbService;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component; import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* Created by yxl on 2018-03-19.
*/
@ServerEndpoint("/chat/{userId}") //关键注解,将WebSocket服务端运行在 ws://[Server端IP或域名]:[Server端口]/websockets/chat/{userId} 的访问端点,客户端浏览器已经可以对 WebSocket客户端API发起HTTP长连接了。
@Component
public class ChatWebsocket { private Logger logger = Logger.getLogger(ChatWebsocket.class); private static ApplicationContext applicationContext; private SaveMongodbService saveMongodbService; private CheckTokenService checkTokenService; private QueryService queryService; //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static Map<String, Session> webSocketSet = new ConcurrentHashMap<>(); //医生web //解决Websocket不能注入bean的问题
public static void setApplicationContext(ApplicationContext applicationContext) {
ChatWebsocket.applicationContext = applicationContext;
} /**
* 连接建立成功调用的方法
*
* @param userId 用户链接ID
*/
@OnOpen //建立连接的注解,当用户建立连接时SpringBoot会监听到,然后会调用该注解下的方法
public void onOpen(@PathParam("userId") String userId, Session session) {
webSocketSet.put(userId, session);
} /**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
logger.info("进入关闭方法!");
if (session != null) {
Map<String, String> pathParameters = session.getPathParameters();
String userId = pathParameters.get("userId"); //从当前关闭session中获取用户ID,前提是建立websocket连接时带有userId,即 @ServerEndpoint("/chat/{userId}")
webSocketSet.remove(userId); //从map中移除用户
}
} /**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException { try {
JSONObject jsonObject = JSONObject.parseObject(message);
String receiver_id = jsonObject.getString("receiver_id") //接受者ID,通过该Id来获取接受者的session
Session session = webSocketSet.get("receiver_id")
if (session != null) {
session.getBasicRemote.sendText(message); //通过session发送消息
}else {
//TODO 接收方不在线,处理离线消息 }
}catch(IOException e) {
e.printStackTrace;
} } /**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
//onClose();
if (session != null) {
Map<String, String> pathParameters = session.getPathParameters();
String userId = pathParameters.get("userId"); //从当前关闭session中获取用户ID,前提是建立websocket连接时带有userId,即 @ServerEndpoint("/chat/{userId}")
webSocketSet.remove(userId); //从map中移除用户
}
logger.info("webscoket发生错误!"+error.getMessage());
error.printStackTrace();
}
}
3、前台调用方法(js)
function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("您的浏览器支持 WebSocket!"); // 打开一个 web socket
var ws = new WebSocket("ws://服务器IP:端口/chat/123");
ws.onopen = function() {
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send('{"userId":"1555855","message" : "test"}');
ws.close("666666");
alert("数据发送中...");
};
ws.onmessage = function (evt) {
console.log(evt)
alert(evt.data);
alert("数据已接收...");
}; ws.onclose = function(){
// 关闭 websocket
alert("连接已关闭...");
};
}else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
4、当然,在使用websocket聊天时,可能会遇到一些数据需要查询数据库或者Redis,但是在websocket中又不能直接注入相应的Bean实例,这个时候可以看我的另一篇博客https://www.cnblogs.com/Amaris-Lin/p/9038813.html
Spring Boot中使用Websocket搭建即时聊天系统的更多相关文章
- 在spring boot中使用webSocket组件(二)
该篇演示如何使用websocket创建一对一的聊天室,废话不多说,我们马上开始! 一.首先先创建前端页面,代码如下图所示: 1.login.html <!DOCTYPE html> < ...
- 在spring boot中使用webSocket组件(一)
最近在项目中使用到了spring的webSocket组件,在这里和大家分享下,如有错误,欢迎大家指正. 在这里我使用的IDE工具是Intellij idea,框架是spring boot.spring ...
- Spring Boot 中使用 WebSocket 实现一对多聊天及一对一聊天
为什么需要WebSocket? 我们已经有了http协议,为什么还需要另外一个协议?有什么好处? 比如我想得到价格变化,只能是客户端想服务端发起请求,服务器返回结果,HTTP协议做不到服务器主动向客户 ...
- spring boot / cloud (十七) 快速搭建注册中心和配置中心
spring boot / cloud (十七) 快速搭建注册中心和配置中心 本文将使用spring cloud的eureka和config server来搭建. 然后搭建的模式,有很多种,本文主要聊 ...
- Spring Boot 中的静态资源到底要放在哪里?
当我们使用 SpringMVC 框架时,静态资源会被拦截,需要添加额外配置,之前老有小伙伴在微信上问松哥Spring Boot 中的静态资源加载问题:"松哥,我的HTML页面好像没有样式?& ...
- (转)Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门
http://www.ityouknow.com/springboot/2019/02/12/spring-boot-webflux.html Spring 5.0 中发布了重量级组件 Webflux ...
- Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门
Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕. WebFlux 使用的场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统 ...
- 学习Spring Boot:(二十三)Spring Boot 中使用 Docker
前言 简单的学习下怎么在 Spring Boot 中使用 Docker 进行构建,发布一个镜像,现在我们通过远程的 docker api 构建镜像,运行容器,发布镜像等操作. 这里只介绍两种方式: 远 ...
- 徒手撸一个 Spring Boot 中的 Starter ,解密自动化配置黑魔法!
我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中.Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小 ...
随机推荐
- 杂项:mPaaS
ylbtech-杂项:mPaaS 1. 概述返回顶部 mPaaS 是源于支付宝 App 的移动开发平台,为移动开发.测试.运营及运维提供云到端的一站式解决方案,能有效降低技术门槛.减少研发成本.提升开 ...
- Neutron 理解 (2): 使用 Open vSwitch + VLAN 组网 [Neutron Open vSwitch + VLAN Virtual Network]
学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...
- Unity3D NGUI Sprite精灵动画
NGUI 2.6.1下载: part1 part2 NGUI 实现Sprite精灵动画很简单: 1.先制作图像集合.打开NGUI菜单下Atlas Maker,选中切好的图片,点击Add/Update按 ...
- 比较java枚举成员使用equal还是==
问题 我知道Java枚举会被编译成一个包含私有构造参数和一堆静态方法的类,当去比较两个枚举的时候,总是使用equals()方法,例如: public useEnums(SomeEnum a) { if ...
- 捷通华声TTS在Aster+中的安装过程
1)挂载TTS光碟 2)安装如下5个rpm软件包 [asterisk@TTS78:/mnt]$ls *.rpmjTTS-5.0.1.0-3.i386.rpm VocLib_Xi ...
- Windows下MySQL免安装版的安装、卸载
一.安装 1.下载 到MySQL官网http://dev.mysql.com/downloads/mysql/ 下载mysql-5.6.15-win32.zip. 2.拷贝 将mysql-5.6.15 ...
- 对于分类问题的神经网络最后一层的函数:sigmoid、softmax与损失函数
对于分类问题的神经网络最后一层的函数做如下知识点总结: sigmoid和softmax一般用作神经网络的最后一层做分类函数(备注:sigmoid也用作中间层做激活函数): 对于类别数量大于2的分类问题 ...
- javascript继承之借用构造函数(二)
//简单的函数调用 function Father() { this.nums= [1,2]; } function Son() { Father.call(this);//调用超类型,完成son继承 ...
- 阿里数据服务P6~P7晋升要点
这是我在2015年高德负责P6晋升评审为团队成员准备的要点,整理下. 1. 数据仓库难点 1.1 分布式OLAP设计与选型 传统BI 友盟,Talking Data 启明星 keylin phonie ...
- jq上下级元素查找方法
1.parent([expr]) 获取指定元素的所有父级元素 2.next([expr]) 获取指定元素的下一个同级元素 3.nextAll([expr]) 获取指定元素后面的所有同级元素 4.and ...