当前位置: 首页 > article >正文

基于java注解实现websocket详解

1.1 明确java服务端需要的类

服务终端类:用java注解来监听连接@ServerEndpoint、连接成功@OnOpen、连接关闭@OnClose、收到消息等状态@OnMessage
配置类:把spring中的ServerEndpointExporter对象注入进来

1.2 创建java服务项目

类型要专门选成maven项目

springboot版本选择较低的版本

添加日志依赖

搜索增加websocket依赖

1.3 启动main文件检测是否运行

不报错就算运行成功

1.4 创建com/example/demo/WsServerEndpont.java监听websocket


对websocket面临各种操作时的反应进行设定

package com.example.demo;

import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 监听websocket地址
 */
@ServerEndpoint("/myWs")
@Component
@Slf4j  //打印日志
public class WsServerEndpont {
    static Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 连接建立时执行的操作
     * ConcurrentHashMap 和HashMap的区别是他是线程安全的
     * map文件的创建是给所有来连接的客户分配一个key区分保存,客户连接时是以session方式进行的
     * static保证变量属于类而不是对象
     * log.info打印日志
     *
     * @param session
     */


    @OnOpen
    public void onOpen(Session session) {
        sessionMap.put(session.getId(), session);
        log.info("websocket is open");
    }

    /**
     * 收到客户端消息时执行的操作
     *
     * @param text
     * @return
     */
    @OnMessage
    public String onMessage(String text) {
        log.info("收到了一条消息:" + text);
        return "已经收到你的消息";
    }

    /**
     * 连接关闭时的时候执行的操作
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        sessionMap.remove(session.getId(), session);
        log.info("websocket is close");
    }

    /**
     * 在这里是每隔两秒就对所有客户端发送一次心跳
     * 想要在任何时刻发消息给客户端,需要借助springboot的定时任务,这个需要在主类中实现DemoApplication.java开启定时任务支持
     * 这个类结束,需要创建一个新的类WebSocketConfig,这是注入Spring WebSocket框架的一个对象
     */
    @Scheduled(fixedRate = 2000)
    public void sendMsg() {
        for (String key : sessionMap.keySet()) {
            try {
                sessionMap.get(key).getBasicRemote().sendText("心跳");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

1.5 启动心跳是定时任务,这个功能需要在主类中进行开启

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling //开启定时任务
@SpringBootApplication
public class DemoApplication {

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

}

1.6 这个时候spring框架并不能扫描到服务终端,需要添加一个配置类

com/example/demo/WebSocketConfig.java

package com.example.demo;

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

/**
 * @Configuration 是固定模式,表示这个是一个配置类
 * @Bean 上下两个注解是配合使用的,代表把依赖包里的一些类,注入进来为一个Bean
 */@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

1.7 到这服务端搭建完成,重启main文件,准备编写客户端

在src文件夹下新建src/main/resources/ws-client.html

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>ws client</title>  
</head>  
<body>  
  
</body>  
<script>  
<!--    设置连接位置-->  
    let ws = new WebSocket("ws://localhost:8080/myWs")  
    ws.onopen = function (){  
        // 设置连接时发送的消息  
        ws.send("hello")  
    }  
    //打印获取的消息  
    ws.onmessage = function (message){  
        console.log(message.data)  
    }  
</script>  
</html>

浏览器打开html,服务端接收到消息

在浏览器的f12消息里显示了服务器发送的心跳请求


http://www.kler.cn/a/417927.html

相关文章:

  • YOLO 标注工具 AutoLabel 支持 win mac linux
  • MVC core 传值session
  • 缓存与缓冲
  • pip安装github上的开源软件包
  • 学习笔记043——HashMap源码学习1
  • 南京仁品耳鼻喉专科医院:12月启动公益义诊月
  • 如何更好地设计SaaS系统架构
  • MATLAB期末复习笔记(上)
  • 基于Java Springboot 求职招聘平台
  • 爬虫框架快速入门——Scrapy
  • QT 实现组织树状图
  • flutter底部导航栏中间按钮凸起,导航栏中间部分凹陷效果
  • Cursor AI快捷键的使用场景及作用
  • 【机器学习】机器学习算法与模型:逻辑回归算法
  • 电销卡风险管理系统
  • springboot358智慧社区居家养老健康管理系统(论文+源码)_kaic
  • 【大数据学习 | Spark调优篇】数据序列化(kryo序列化)
  • 鸿蒙学习使用模拟器运行应用(开发篇)
  • 深度学习基础03_BP算法(下)过拟合和欠拟合
  • 工程设计与总承包行业数字化转型:现状洞察、挑战突围与前景展望
  • 基于Java Springboot学生信息管理系统
  • asyncio.ensure_future 与 asyncio.create_task:Python异步编程中的选择
  • 汉字笔画分割959张图片带注释的YOLO,COCO,VOC格式的数据集
  • Vue-指令-案例
  • java——Spring MVC的工作流程
  • Python 中的 Lxml 库与 XPath 用法