java实现一个简单的webSocket聊天demo

news2024/9/22 13:45:00

java实现一个简单的webSocket聊天demo

  • 一、依赖
  • 二、配置准备
  • 三、demo代码编写
  • 四、启动测试
  • 五、编写业务

一、依赖

添加pom文件依赖


   <!-- websocket-->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-websocket</artifactId>
     </dependency>
        

二、配置准备

创建webSocketConfig配置类,即注册ServerEndpointExporter,该bean用于扫描被@ServerEndpoint注解的类,并将其作为服务端.


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:15
 * @Description : webSocketConfig配置类,该bean用于扫描被@ServerEndpoint注解的类
 */
@Configuration
public class WebSocketConfig {

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

三、demo代码编写

创建被@ServerEndpoint注解的类用于作为webSocket服务器并指定连接的uri
使用注解标记对应的方法,,并启动程序。


/**
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:21
 * @Description :
 */
@ServerEndpoint(value = "/chat/{username}")
@Component
@Slf4j
public class SocketServer {
    Logger log = LoggerFactory.getLogger(getClass());

    // 保存链接的session,key为用户名,value为对应的session名
    private ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 创建连接
     * 用于监听建立连接,当有客户端与该服务端点建立连接时,将会自回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String username) {
        log.info("用户{}已创建连接", username);
    }


    /**
     * 用于监听客户端向服务端发送消息,当客户端与服务端发送消息时,将会回调该注解标注的方法
     * @param msg
     * @param username
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "username") String username){
        log.info("用户{}发来消息:{}",username,msg);
    }


    /**
     * 用于监听连接关闭,当客户端与该服务端点断开连接时,将会回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnClose
    public void onClose(Session session,@PathParam(value = "username") String username){
        log.info("用户{}已关闭连接", username);
    }


    /**
     * 用于监听该连接上的任何错误,当客户端与该服务端点的连接发生任何异常,都将回调该注解标注的方法
     * 注意该方法的参数必选Throwable,可选Sessiion以及0-n个String参数,且String参数需要使用@PathParam注解标注
     * @param throwable
     * @param username
     */
    @OnError
    public void onError(Throwable throwable,@PathParam(value = "username") String username){
        log.error("用户{}连接发生异常", username);
    }

}

四、启动测试

项目启动后,测试websocket是否可用。
webSocket在线测试网站: Websocket在线测试链接

在这里插入图片描述
日志如下:

2023-07-09 10:49:29.185  INFO 16308 --- [nio-8080-exec-5] org.sang.websocket.SocketServer         
 : 用户初夏已创建连接
2023-07-09 10:49:35.672  INFO 16308 --- [nio-8080-exec-6] org.sang.websocket.SocketServer         
 : 用户初夏已创建连接
2023-07-09 10:49:43.470  INFO 16308 --- [nio-8080-exec-7] org.sang.websocket.SocketServer       
   : 用户初夏发来消息:你好,我是初夏~

五、编写业务

成功完成基础的websocket连接,可以开始编辑业务逻辑

1.构建后台message实体类;

/**
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:58
 * @Description :
 */
public class Message {
    private Integer id;
    private String from;
    private String to;
    private String msg;
    private String date;
    private Integer type;//消息发送的类型,0系统群发,1用户私聊
    private Integer is_read;//消息是否已读,0未读,1已读

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public String getMsg() {
        return msg;
    }

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

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public Integer getType() {
        return type;
    }

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

    public Integer getIs_read() {
        return is_read;
    }

    public void setIs_read(Integer is_read) {
        this.is_read = is_read;
    }
}

2.改造方法

@ServerEndpoint(value = "/chat/{username}")
@Component
@Slf4j
public class SocketServer {
    Logger log = LoggerFactory.getLogger(getClass());

    // 保存链接的session,key为用户名,value为对应的session名
    private ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 创建连接
     * 用于监听建立连接,当有客户端与该服务端点建立连接时,将会自回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String username) {
        log.info("用户{}已创建连接", username);
        sessionMap.put(username,session);
    }


    /**
     * 用于监听客户端向服务端发送消息,当客户端与服务端发送消息时,将会回调该注解标注的方法
     * @param msg
     * @param username
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "username") String username){
        log.info("用户{}发来消息:{}",username,msg);
        Message message = JSON.parseObject(msg, Message.class);
        //根据message中的to属性获取接收消息的用户的session,利用其session将消息转发过去
        Session toSession = sessionMap.get(message.getTo());
        sendMessage(toSession, message.getMsg());
    }


    /**
     * 用于监听连接关闭,当客户端与该服务端点断开连接时,将会回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnClose
    public void onClose(Session session,@PathParam(value = "username") String username){
        log.info("用户{}已关闭连接", username);
        sessionMap.remove(username);
    }


    /**
     * 用于监听该连接上的任何错误,当客户端与该服务端点的连接发生任何异常,都将回调该注解标注的方法
     * 注意该方法的参数必选Throwable,可选Sessiion以及0-n个String参数,且String参数需要使用@PathParam注解标注
     * @param throwable
     * @param username
     */
    @OnError
    public void onError(Throwable throwable,@PathParam(value = "username") String username){
        log.error("用户{}连接发生异常", username);
    }


    /**
     * 用来发送消息的方法,参数分别为接收消息的用户的session,和对应的消息
     */
    private void sendMessage(Session toSession,String msg){
        try {
            toSession.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

3.新建三个websocket在线测试的窗口创建三个链连接


2023-07-09 11:34:13.330  INFO 5812 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 20 ms
2023-07-09 11:34:13.372  INFO 5812 --- [nio-8080-exec-1] org.sang.websocket.SocketServer          : 用户初夏1已创建连接
2023-07-09 11:34:15.302  INFO 5812 --- [nio-8080-exec-2] org.sang.websocket.SocketServer          : 用户初夏2已创建连接
2023-07-09 11:34:18.101  INFO 5812 --- [nio-8080-exec-3] org.sang.websocket.SocketServer          : 用户初夏3已创建连接

测试,用初夏2用户给初夏3发聊天消息:
在这里插入图片描述

我们可以看到,只有初夏3收到了聊天消息,初夏1没收到:
在这里插入图片描述
在这里插入图片描述
到这里,我们就实现了webSocke技术,实现聊天功能了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/735877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA环境配置汇总

1、配置项目编码 2、配置运行看板Services IDEA开启并配置Services窗口 这里已经配置好了&#xff0c;如果没有&#xff0c;就点击&#xff0c;点击Run Configuration Type&#xff0c;选择所需要的&#xff0c;点击即可。 配置spring与docker看板(按照上面的方法来配置&am…

【Python】查询SQL并用柱状图展示

需求&#xff1a; 查询2022年各月订单量&#xff0c;并用柱状图展示 SQL&#xff1a; select date_format(create_time,%Y-%m) as mon ,count(distinct order_id) as ord_cnt from prod.order_info where date_format(create_time,%Y-%m) between 2022-01 and 2022-12 group…

Mac OS装Windows系统开启虚拟化

目录 引言前提macOS开启虚拟化mac下的Windows开启虚拟化双系统开启虚拟化修改启动管理程序开启虚拟化 注意事项 引言 在开发工作中&#xff0c;很多软件需要用到virtual box&#xff0c;但是使用virtual box需要开启虚拟化&#xff0c;而有些苹果笔记本虚拟化是关闭的&#xf…

【GitHub】一条命令快速部署 Kubernetes(k8s) 集群的工具-sealos

Sealos 是一个GitHub上优秀的开源项目&#xff0c;目前项目点赞数已达&#xff1a;10.2k&#xff0c;核心特性&#xff1a; 管理集群生命周期下载和使用完全兼容 OCI 标准的分布式应用定制化分布式应用Sealos Cloud 项目开源协议&#xff1a;Apache-2.0 项目主开发语言&…

NSS [SWPUCTF 2022 新生赛]funny_web

NSS [SWPUCTF 2022 新生赛]funny_web 账号NSS 密码2122693401 私货不去细细研究了&#xff0c;直接看题。 num不等于12345&#xff0c;但是intval&#xff08;num&#xff09;等于12345 ①intval():可以获取变量的整数值intval()中有一个特性&#xff0c;其中若传入1e4&…

tensorboard与torchinfo的使用

目录 1. tensorboard1.1 本地使用1.2 远程服务器使用 2. torchinfoRef 1. tensorboard 1.1 本地使用 只需要掌握一个 torch.utils.tensorboard.writer.SummaryWriter 接口即可。 在初始化 SummaryWriter 的时候&#xff0c;通常需要指定log的存放路径。这个路径默认是 runs/…

Python脚本小工具之文件与内容搜索

目录 一、前言 二、代码 三、结果 一、前言 ​日常工作中&#xff0c;经常需要在指定路径下查找指定类型的文件&#xff0c;或者是指定内容的查找&#xff0c;在window环境中&#xff0c;即可以使用一些工具如notepad或everything&#xff0c;也可以使用python脚本。但在l…

【C++进阶】bitset位图介绍以及模拟实现

文章目录 位图介绍一、位图的引入二、位图的概念 位图模拟实现一、构造函数二、set&#xff0c;reset&#xff0c;test函数三、代码测试四、完整代码 位图介绍 一、位图的引入 先来看下边一道面试题&#xff1a; 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符…

SAR ADC version2 ——ADC背景介绍

目录&#xff1a; ADC常用指标分类 静态性能&#xff1a;微分非线性&#xff1a;DNL 积分非线性&#xff1a;INL 仿真测试DNL&#xff1a;&#xff08;码密度法&#xff09;&#xff08;code density&…

OpenCV 入门教程:像素访问和修改

OpenCV 入门教程&#xff1a;像素访问和修改 导语一、像素访问1.1 获取图像的大小1.2 访问图像的像素值1.3 修改图像的像素值 二、示例应用2.1 图像反转2.2 阈值化操作 三、总结 导语 在图像处理和计算机视觉领域&#xff0c;像素级操作是非常重要和常见的任务之一。通过像素访…

Python——将F12得到的请求头转换成其对应json格式

问题引入 最近在鼓捣爬虫准备爬爬学校网站&#xff0c;用到pthon的requests库发送get请求时需要提供headers. 需要将请求头转换成json格式的数据。json格式如下所示 headers{"Path":"xxx","User-Agent":"xxx" } 但是从网页上f12复…

21-注册中心与配置中心Nacos

已经使用过了Spring cloud提供的Geteway、openFeign。 1、注册中心与配置中心 1.1、注册中心 相当于通讯录,让应用之间相互认识。 用途: 实例的健康检查。 路由转发:为了控制成本,会对机器做动态扩容,此时IP就不固定了。 远程调用。 1.2、配置中心 动态修改线上的配…

深入解析MySQL视图、索引、数据导入导出:优化查询和提高效率

目录 1. 视图&#xff08;View&#xff09;&#xff1a; 什么是视图&#xff1f; 为什么要使用视图&#xff1f; 视图的优缺点 1) 定制用户数据&#xff0c;聚焦特定的数据 2) 简化数据操作 3) 提高数据的安全性 4) 共享所需数据 5) 更改数据格式 6) 重用 SQL 语句 …

十一.Redis发布订阅

Redis发布订阅(pub/sub)是一种消息通信模式&#xff1a;发布者(pub)发送消息&#xff0c;订阅者(sub)接受消息。此种模式下&#xff0c;消息发布者和订阅者不进行直接通信&#xff0c;发布者客户端向指定的频道&#xff08;channel&#xff09; 发布消息&#xff0c;订阅该频道…

【MQTT】Esp32数据上传采集:最新mqtt插件(支持掉线、真机调试错误等问题)

前言 这是我在Dcloud发布的插件-最完整Mqtt示例代码&#xff08;解决掉线、真机调试错误等问题&#xff09;&#xff0c;经过整改优化和替换Mqtt的js文件使一些市场上出现的问题得以解决&#xff0c;至于跨端出问题&#xff0c;可能原因有很多&#xff0c;例如&#xff0c;合法…

MySQL基础篇第3章(基本的SELECT语句)

文章目录 1、SQL概述1.1 SQL背景知识1.2 SQL分类 2、SQL语言的规则与规范2.1 基本规则2.2 SQL大小写规范 &#xff08;建议遵守&#xff09;2.3 注释2.4 命名规则2.5 数据导入指令 3、基本的SELECT语句3.0 SELECT...3.1 SELECT...FROM3.2 列的别名3.3 去除重复行3.4 空置参与运…

营销人累了看看这5部影片吧!保你再燃激情

市场瞬息万变&#xff0c;做营销需不断学习充电&#xff0c;除了看书听课之外看电影也是学习营销的有效方式。今天小马识途营销顾问给大家推荐5部市场营销人员必看的高评分电影&#xff0c;相信看完之后&#xff0c;会对你今后的发展影响深远&#xff01;话不多说直接上干货&am…

并发编程 - Event Driven 设计模式(EDA)

文章目录 EDA 概述初体验EventEvent HandlersEvent Loop 如何设计一个Event-Driven框架同步EDA框架设计MessageChannelDynamic RouterEventEventDispatcher测试同步EDA架构类图 异步EDA框架设计抽象基类 AsyncChannelAsyncEventDispatcher 并发分发消息测试 EDA 概述 EDA&…

【计算机网络】第 2 课 - 计算机网络的性能指标

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、性能指标 2.1、速率 2.2、带宽 2.3、吞吐量 2.4、时延 2.5、时延带宽积 2.6、往返时间 2.7、利用率 2.8、丢…

【Cartopy学习系列】Cartopy中的投影类型总结

一、PlateCarree&#xff08;圆柱投影&#xff09; PlateCarree 是Cartopy的默认投影&#xff0c;投影将地物投影到圆柱面上再展开&#xff0c;常用来绘制世界地图。该投影具有经线或纬线方向等度数的特点&#xff0c;亦称等经纬度投影。 class cartopy.crs.PlateCarree(cent…