先看一下页面效果,有点简单粗暴!哈哈哈哈哈,别介意.

本文参考:SpringBoot2.0集成WebSocket,实现后台向前端推送信息

新建一个springboot项目

引入相关依赖

  <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency> <!--com.alibaba/fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency> <!--websocket依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency> <!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Java代码

WebSocketConfig

@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}

PageController

@RestController
public class PageController {
@GetMapping("chat")
public ModelAndView toChat(){
return new ModelAndView("/chat");
}
}

WebSocketServer

@ServerEndpoint("/chat/{userName}")
@Component
@Slf4j
public class WebSocketServer { /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
private static int onlineCount = 0;
/**concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/
private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
/**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session; /**接收userId*/
private String userName=""; /**
* @Description: 连接建立成功调用的方法
* @params: [session, userId]
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:13 PM
*/
@OnOpen
public void onOpen(Session session,@PathParam("userName") String userName) {
this.session = session;
this.userName=userName;
if(webSocketMap.containsKey(userName)){
webSocketMap.remove(userName);
webSocketMap.put(userName,this);
//加入set中
}else{
webSocketMap.put(userName,this);
//加入set中
addOnlineCount();
//在线数加1
} log.info("用户连接:"+userName+",当前在线人数为:" + getOnlineCount()); try {
sendMessage("{\"msg\":\"连接成功\"}");
} catch (IOException e) {
log.error("用户:"+userName+",网络异常!!!!!!");
}
} /**
* @Description: 连接关闭调用的方法
* @params: []
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:13 PM
*/
@OnClose
public void onClose() {
if(webSocketMap.containsKey(userName)){
webSocketMap.remove(userName);
//从set中删除
subOnlineCount();
}
log.info("用户退出:"+userName+",当前在线人数为:" + getOnlineCount());
} /**
* @Description: 收到客户端消息后调用的方法
* @params: [message, session]
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:13 PM
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("用户消息:"+userName+",报文:"+message);
//可以群发消息
//消息保存到数据库、redis
if(StringUtils.isNotBlank(message)){
try {
//解析发送的报文
JSONObject jsonObject = JSON.parseObject(message);
//追加发送人(防止串改)
jsonObject.put("sender",this.userName);
String receiver=jsonObject.getString("receiver");
//传送给对应toUserId用户的websocket
if(StringUtils.isNotBlank(receiver)&&webSocketMap.containsKey(receiver)){
webSocketMap.get(receiver).sendMessage(jsonObject.toJSONString());
}else{
log.error("请求的receiver:"+receiver+"不在该服务器上");
//否则不在这个服务器上,发送到mysql或者redis
}
}catch (Exception e){
e.printStackTrace();
}
}
} /**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("用户错误:"+this.userName+",原因:"+error.getMessage());
error.printStackTrace();
} /**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
} /**
* @Description: 发送消息
* @params: [message, userId]
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
log.info("发送消息到:"+userId+",报文:"+message);
if(StringUtils.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(message);
}else{
log.error("用户"+userId+",不在线!");
}
} /**
* @Description: 获取在线人数
* @params: []
* @return: int
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static synchronized int getOnlineCount() {
return onlineCount;
} /**
* @Description: 在线人数+1
* @params: []
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
} /**
* @Description: 在线人数-1
* @params: []
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}

前端HTMl

<div class="layui-container">
<div class="layui-row">
<div class="layui-col-md12">
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 25px;">
<legend style="margin-left: 40%;">简单粗暴的聊天界面</legend>
</fieldset>
<div class="grid-demo grid-demo-bg2" style="text-align: center">
<form class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">接收者</label>
<div class="layui-input-block">
<input type="text" id="receiver" lay-verify="title" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发送者</label>
<div class="layui-input-block">
<input type="text" id="sender" autocomplete="off" class="layui-input">
</div>
</div> <div class="layui-form-item layui-form-text">
<label class="layui-form-label">消息</label>
<div class="layui-input-block">
<textarea placeholder="请输入内容" class="layui-textarea" id="msg"></textarea>
</div>
</div>
<div class="layui-col-md12" style="margin-left: 4%">
<div class="layui-tab layui-tab-card" style="height: 200px;overflow: auto">
<fieldset class="layui-elem-field layui-field-title">
<legend>消息记录</legend>
</fieldset>
<div id="msgDiv"> </div>
</div>
</div> <div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="layui-btn layui-btn-primary" onclick="establishConnection()">
建立连接
</button>
<button type="button" class="layui-btn layui-btn-primary" onclick="sendMessage()">发送消息
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script type="text/javascript" th:src="@{/javascript/jquery-2.1.4.js}"></script>
<!--layui-->
<script type="text/javascript" th:src="@{/plugins/layui/layui.js}"></script>

JavaScript代码

var socket;
if (typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else { /***建立连接*/
function establishConnection() {
var userName = $("#sender").val();
if (userName == '' || userName == null) {
alert("请输入发送者");
return;
}
//实现化WebSocket对象,指定要连接的服务器地址与端口 建立连接
var socketUrl = "" + window.location.protocol + "//" + window.location.host + "/chat/" + userName;
socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
if (socket != null) {
socket.close();
socket = null;
}
socket = new WebSocket(socketUrl);
//打开事件
socket.onopen = function () {
console.log("开始建立链接....")
};
//关闭事件
socket.onclose = function () {
console.log("websocket已关闭");
};
//发生了错误事件
socket.onerror = function () {
console.log("websocket发生了错误");
};
/**
* 接收消息
* @param msg
*/
socket.onmessage = function (msg) {
msg = JSON.parse(msg.data);
if (msg.msg != '连接成功') {
$("#msgDiv").append('<p class="user">用户名:' + msg.sender + '</p><p class="chat">' + msg.msg + '</p>');
}
};
} /**
* 发送消息
*/
function sendMessage() {
var msg = $("#msg").val();
if (msg == '' || msg == null) {
alert("消息内容不能为空");
return;
}
var receiver = $("#receiver").val();
if (receiver == '' || receiver == null) {
alert("接收人不能为空");
return;
}
var msgObj = {
receiver: receiver,
msg: msg
};
socket.send(JSON.stringify(msgObj));
}
}

【SpringBoot】WebSocket在线聊天的更多相关文章

  1. 微服务-springboot+websocket在线聊天室

    一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  2. Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统

    ThinkPHP使用Swoole需要安装 think-swoole Composer包,前提系统已经安装好了Swoole PECL 拓展* tp5的项目根目录下执行composer命令安装think- ...

  3. html5 websocket 示例,websocket在线聊天,php websocket实例

    WebSocket在线测试工具 http://ws.douqq.com/ 1.连接格式为 ws://IP/域名:端口(示例ws://119.29.3.36:5354) 2.对于内网的测试环境,只需填入 ...

  4. Spring Websocket实现简易在线聊天功能

    针对Spring Websocket的实现,我参照了其他博主的文章https://www.cnblogs.com/leechenxiang/p/5306372.html 下面直接给出实现: 一.引入相 ...

  5. Swoole 实现在线聊天

    Swoole 跟 thinkphp5 结合开发 WebSocket 在线聊天通讯系统 ThinkPHP 使用 Swoole 需要安装 think-swoole Composer 包,前提系统已经安装 ...

  6. SpringBoot+Vue+WebSocket 实现在线聊天

    一.前言 本文将基于 SpringBoot + Vue + WebSocket 实现一个简单的在线聊天功能 页面如下: 在线体验地址:http://www.zhengqingya.com:8101 二 ...

  7. 基于WebSocket和SpringBoot的群聊天室

    引入 普通请求-响应方式:例如Servlet中HttpServletRequest和HttpServletResponse相互配合先接受请求.解析数据,再发出响应,处理完成后连接便断开了,没有数据的实 ...

  8. 在线聊天室的实现(1)--websocket协议和javascript版的api

    前言: 大家刚学socket编程的时候, 往往以聊天室作为学习DEMO, 实现简单且上手容易. 该Demo被不同语言实现和演绎, 网上相关资料亦不胜枚举. 以至于很多技术书籍在讲解网络相关的编程时, ...

  9. 使用websocket实现在线聊天功能

    很早以前为了快速达到效果,使用轮询实现了在线聊天功能,后来无意接触了socket,关于socket我的理解是进程间通信,首先要有服务器跟客户端,服务的启动监听某ip端口定位该进程,客户端开启socke ...

  10. 使用WebSocket实现简单的在线聊天室

    前言:我自已在网上找好了好多 WebSocket 制作 在线聊天室的案列,发现大佬们写得太高深了 我这种新手看不懂,所以就自已尝试写了一个在线简易聊天室 (我只用了js 可以用jq ) 话不多说,直接 ...

随机推荐

  1. SQL Case条件判断语句

    问题描述:在表中取到一些值做出判断,配合监控监测一些表中的数据.使用select case when if 来做条件查询判断 CASE 表达式遍历条件并在满足第一个条件时返回一个值(类似于 if-th ...

  2. nginx 极简教程

    什么是 Nginx? Nginx (engine x) 是一款轻量级的 Web 服务器 .反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理? 反向代理(Reverse Pro ...

  3. C#版本LINQ增强开源库

    LINQ对应的中文名称是:语言集成查询,是对一系列直接将查询功能集成到C#语言技术的统称,我们最常用的场景是,用于数据库的查询功能. 在.Net中,本身对Objects也支持LINQ的扩展,但是对于一 ...

  4. 【Zookeeper】(二)安装与配置

    1 安装 安装JDK(参考项目部署) 将Zookeeper拷贝到Linux下 解压 tar -zxvf apache-zookeeper-3.5.10-bin.tar.gz -C /opt/modul ...

  5. Linux(二)文件权限和压缩

    1 搜索查找类 1.1 查找定位文件 find <搜索范围.路径> <选项> find将从指定目录下递归地遍历其各个子目录,将满足条件的文件显示在终端. 选项说明 -name: ...

  6. ADC采样时间、Chirp扫频时间、Chirp重复周期的区分

    图1 FMCW雷达信号参数 在德州仪器TI毫米波雷达中,开发板参数配置往往涉及如图1所示的信号参数. 宏观上看,信号参数包括\(ADC\)采样时间.脉冲重复周期(\(Chirp\)扫频周期)和帧时间( ...

  7. Abp框架Web站点的安全性提升

    本文将从GB/T 28448-2019<信息安全技术 网络安全等级保护测评要求>规定的安全计算环境中解读.摘要若干安全要求,结合Abp框架,对站点进行安全升级. [身份鉴别]应对登录的用户 ...

  8. 10分钟极速入门dash应用开发

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,几天前我发布了由我开源维护的dash通用网页组件库fac的0 ...

  9. [操作系统] - 进程切换&进程控制

    2.1.6 进程切换 名称解析 进程的上下文(Context) 当一个进程在执行时,CPU的所有寄存器的值.进程的状态以及堆栈中的内容被称为进程的上下文Context 进程的切换(switch) 当内 ...

  10. jquery 禁用按钮无效 disabled属性设置无效

    禁用按鈕 $(this).prop("disabled", true); 啟用按鈕 $(this).prop("disabled", false); 禁用按鈕 ...