依赖 pom.xml
org.springframework.boot
spring-boot-starter-websocket
cn.hutool
hutool-all
5.6.0
org.bouncycastle
bcprov-jdk15to18
1.68
com.alibaba
fastjson
1.2.7
websocket主要实现分为两个步骤:
一,websocket的一个配置类 谨记在这里已经加了@EnableWebSocket启动类就不用加了
,代码如下
//注意注解
@EnableWebSocket
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
或者不用单独新建一个配置类直接把这个bean方法放在我们启动类里面也行(注意:放启动类我们的@EnableWebSocket需要带上,@Configuration这个就可以不要了)
二,websocket的以一个调用接口或者controller层(我写了两种controller,我用的第一种)
//注意是controller注解
@Controller
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap();
private Session session;
private String userId="";
@OnOpen
public void onOpen(Session session,@PathParam("userId") String userId) {
this.session = session;
this.userId=userId;
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
webSocketMap.put(userId,this);
}else{
webSocketMap.put(userId,this);
}
System.out.println("当前连接用户:"+userId);
}
@OnClose
public void onClose() {
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
}
System.out.println("用户 "+userId+" 退出:");
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到用户消息:"+userId+",报文:"+message);
if(StrUtil.isNotBlank(message)){
try {
//解析发送的报文
JSONObject jsonObject = JSON.parseObject(message);
//追加发送人(防止串改)
jsonObject.put("fromUserId",this.userId);
String toUserId=jsonObject.getString("toUserId");
//传送给对应toUserId用户的websocket
if(StrUtil.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)){
webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
}else{
webSocketMap.get(this.userId).sendMessage("请求的userId:"+toUserId+"不在该服务器上");
System.out.println("请求的userId:"+toUserId+"不在该服务器上");
}
}catch (Exception e){
e.printStackTrace();
}
}
}
@OnError
public void onError(Session session, Throwable error) {
System.out.println("用户错误:"+this.userId+",原因:"+error.getMessage());
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public void sendInfo(String message,String userId) throws IOException {
System.out.println("发送消息到:"+userId+",报文:"+message);
if(StrUtil.isNotBlank(userId) && webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(message);
}else{
System.out.println("用户"+userId+",不在线!");
}
}
public static ConcurrentHashMap getWebSocketMap() {
return webSocketMap;
}
public static void setWebSocketMap(ConcurrentHashMap webSocketMap) {
WebSocket.webSocketMap = webSocketMap;
}
}
第二种webcontroller ,其实两种方式大差不差的都能用
//注意是controller注解
@Controller
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
}
三,下面这个才是重点,我的项目需求需要通过实时采集数据,采集到指定数量了就需要停止采集所以我用的线程来开启和关闭定时任务,定时任务我是通过手动调用来触发的。直接上测试代码:
@Component
@Slf4j
public class Jdkinvok {
@Autowired
WebSocket webSocket;
public void timer5(String code) { //这里的code需要和你websocket的userId相同不然不会实时推送数据
ScheduledThreadPoolExecutor scheduled = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
// ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(10);
scheduled.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
String message = "这里可以换成其他条件";
try {
if (message != "") { //这里可以更具自己需求换对应的数据采集方式
webSocket.sendInfo(message + "", code);
scheduled.shutdown(); //采集到了数据我就关闭线程来停止定时任务
} else {
webSocket.sendInfo("", code);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}, 0, 5, TimeUnit.SECONDS);
}
}
完事!!!不求关注和三连操作。只希望能帮助和我一样菜的人早日走上正轨



