Springboot2+WebSocket

news/2025/2/9 8:28:08 标签: websocket, spring boot

一、引入依赖

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

二、添加配置

新增配置文件

config/WebSocketConfig.java

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

@Configuration
public class WebSocketConfig {
    /**
     * 这个Bean的作用是自动注册使用了@ServerEndpoint注解的Bean
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

三、新建互通类

/**
 * description:  平台同步
 */
@Component
@Slf4j
// 类似于controlelr 服务点
@ServerEndpoint(value = "/webSocket/{username}")
public class PlatformAsyncWebSocket {

    /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
    private static int onlineCount = 0;
    /**concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/
    private static ConcurrentHashMap<String,PlatformAsyncWebSocket> webSocketMap = new ConcurrentHashMap<>();
    /**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
    private Session session;
    /**接收userId*/
    private String username="";

    /**
     * 连接建立成功调用的方法*/
    @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("连接成功");
        } catch (IOException e) {
            log.error("用户:"+username+",网络异常!!!!!!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(username)){
            webSocketMap.remove(username);
            //从set中删除
            subOnlineCount();
        }
        log.info("用户退出:"+username+",当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @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("fromUserId",this.username);
                String toUserId=jsonObject.getString("toUserId");
                //传送给对应toUserId用户的websocket
                if(StringUtils.isNotBlank(toUserId)&&webSocketMap.containsKey(toUserId)){
                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                }else{
                    log.error("请求的userId:"+toUserId+"不在该服务器上");
                    //否则不在这个服务器上,发送到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);
    }


    /**
     * 发送自定义消息
     * */
    public static void sendMsg(String message,@PathParam("username") String username) throws IOException {
        log.info("发送消息到:"+username+",报文:"+message);
        if(StringUtils.isNotBlank(username)&&webSocketMap.containsKey(username)){
            webSocketMap.get(username).sendMessage(message);
        }else{
            log.error("用户"+username+",不在线!");
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        PlatformAsyncWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        PlatformAsyncWebSocket.onlineCount--;
    }


}


http://www.niftyadmin.cn/n/5230355.html

相关文章

redis相关题

1 什么是Redis Redis(Remote Dictionary Server) 是⼀个使⽤ C 语⾔编写的&#xff0c;开源的&#xff08;BSD许可&#xff09;⾼性能⾮关系型&#xff08;NoSQL&#xff09;的键值对数据库。Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串&#xff0c;…

【超详细】vue项目:Tinymce富文本使用教程以及踩坑总结+功能扩展

【【超详细】vue项目&#xff1a;Tinymce富文本使用教程以及踩坑总结功能扩展 引言&#xff1a;一、 开始二、快速开始1、安装Tinymce 三、封装成Vue组件1、文件结构2、index.vue3、dynamicLoadScript.js4、plugin.js5、toolbar.js 四、使用Tinymce组件五、业务逻辑实现1、添加…

什么是透明加密技术?透明加密有哪些优势?

透明加密技术是一种特殊的加密方法&#xff0c;它在用户毫不知情的情况下对数据进行加密和解密&#xff0c;保障了数据的安全性。用户在使用这种加密技术时&#xff0c;无需改变他们的日常操作习惯&#xff0c;加密和解密过程在后台自动进行&#xff0c;使得用户在享受数据安全…

C语言——交换两个int变量的值,不能使用第三个变量。

交换两个int变量的值&#xff0c;不能使用第三个变量。即 a3,b5,交换之后a5,b3; #include<stdio.h> int main() {int a3;int b5;printf("a%d b%d\n",a,b);aa^b;ba^b;aa^b;printf("a%d b%d\n",a,b); } “^”——按位异或操作符&#xff0c;这里的按…

Linux取消挂载相关

取消挂载&#xff08;target is busy&#xff09;问题原因 [rooticoolkj ~]# umount /data umount: /data: target is busy.(In some cases useful info about processes that usethe device is found by lsof(8) or fuser(1))报错的原因通常是由于待卸载磁盘正在使用&#xf…

B/S(Browser/Server)和C/S(Client/Server)

B/S&#xff08;Browser/Server&#xff09;和C/S&#xff08;Client/Server&#xff09;是两种常见的软件架构模式&#xff0c;用于描述客户端与服务器之间的交互方式。 B/S&#xff08;Browser/Server&#xff09;架构&#xff1a; B/S架构是一种基于浏览器和服务器的软件架构…

SQL server 基线安全加固操作

目录 账号管理、认证授权 ELK-Mssql-01-01-01 ELK-Mssql-01-01-02 ELK-Mssql-01-01-03 ​​​​​​​ ELK-Mssql-01-01-04 ​​​​​​​ ELK-Mssql-01-01-05 ​​​​​​​ELK-Mssql-01-01-06 日志配置 ELK-Mssql-02-01-01 通信协议 ELK-Mssql-03-01-01 ​​​​​…

信息化,数字化,智能化是3种不同概念吗?与机械化,自动化矛盾吗?

先说结论&#xff1a; 1、信息化、数字化、智能化确实是3种不同的概念&#xff01; 2、这3种概念与机械化、自动化并不矛盾&#xff0c;它们是制造业中不同发展阶段和不同层次的概念。 机械化&#xff1a;是指在生产过程中使用机械技术来辅助人工完成一些重复性、单一性、劳…