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*/@OnOpenpublic void onOpen(Session session) {sessionMap.put(session.getId(), session);log.info("websocket is open");}/*** 收到客户端消息时执行的操作** @param text* @return*/@OnMessagepublic String onMessage(String text) {log.info("收到了一条消息:" + text);return "已经收到你的消息";}/*** 连接关闭时的时候执行的操作* @param session*/@OnClosepublic 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 {@Beanpublic 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>