SpringBoot+WebSocket
1.导入依赖:
-- Spring Boot 2.x 使用 javax.websocket
-- Spring Boot 3.x 使用 jakarta.websocket
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
package com.js.config;
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
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public MyEndpointConfigure newConfigure() {
return new MyEndpointConfigure();
}
}
package com.js.httpclenlient;
import com.hy.core.toolkit.util.CollectionUtil;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Component
@ServerEndpoint(value = "/socket/{archivecode}")
public class WebSocketServer {
private static AtomicInteger online = new AtomicInteger();
private static Map<Long, List<Session>> sessionPools = new HashMap<>();
@Resource
private RemoteAccessClient remoteAccessClient;
public void sendMessage(List<Session> sessions, String message) throws IOException{
if(CollectionUtil.isNotEmpty(sessions)){
sessions.stream().forEach(
session-> {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
);
}
}
@OnOpen
public void onOpen(Session session, @PathParam(value = "archivecode") Long archivecode){
List<Session> sessions = sessionPools.get(archivecode);
if(CollectionUtil.isNotEmpty(sessions)){
sessions.add(session);
sessionPools.put(archivecode, sessions);
}else {
List<Session> sessionList = new ArrayList<>();
sessionList.add(session);
sessionPools.put(archivecode, sessionList);
}
addOnlineCount();
System.out.println(archivecode + "加入webSocket!当前人数为" + online);
try {
sendMessage( sessions, "欢迎" + archivecode + "加入连接!");
} catch (IOException e) {
throw new IllegalArgumentException("webSocket建立连接失败");
}
}
@OnClose
public void onClose(Session session,@PathParam(value = "archivecode") String archivecode){
Set<Long> sessionkey = sessionPools.keySet();
for (Long key : sessionkey) {
List<Session> sessions = sessionPools.get(key);
boolean contains = sessions.contains(session);
if(contains){
sessions.remove(session);
}
}
sessionPools.remove(archivecode);
subOnlineCount();
System.out.println(archivecode + "断开webSocket连接!当前人数为" + online);
}
@OnMessage
public void onMessage(String message) throws IOException{
Set<Long> companyIds = sessionPools.keySet();
for (Long companyid : companyIds) {
List<Session> sessions = sessionPools.get(companyid);
try {
sendMessage(sessions, message);
} catch(Exception e){
e.printStackTrace();
}
}
}
@OnError
public void onError(Session session, Throwable throwable){
System.out.println("发生错误");
throwable.printStackTrace();
}
public void sendInfo(Long archivecode, String message){
List<Session> sessions = sessionPools.get(archivecode);
try {
sendMessage(sessions, message);
}catch (Exception e){
e.printStackTrace();
}
}
public List<Session> getSession(Long archivecode){
List<Session> sessions = sessionPools.get(archivecode);
return sessions;
}
public static void addOnlineCount(){
online.incrementAndGet();
}
public static void subOnlineCount() {
online.decrementAndGet();
}
}
package com.js.controller;
import cn.hutool.json.JSONUtil;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@RequestMapping(value = "/denseRack/alarm", method = RequestMethod.POST)
public void testSocket1(@RequestBody FilealertInformation dto) throws JsonProcessingException {
Long archiveCompanyId = ThreadLocalUtil.getArchiveCompanyId();
dto.setPageRefreshType("warning");
String s = JSONUtil.toJsonStr(dto);
webSocketServer.sendInfo(archiveCompanyId, s);
}
测试发送
结果
Spring boot接入websocket时,启动报错
Spring Boot 2.x
javax.websocket.server.ServerContainer not available
Spring Boot 3.x
jakarta.websocket.server.ServerContainer not available
问题原因
1. 因为spring boot内带tomcat,tomcat中的websocket会有冲突。
解决方案:
spring boot启动时排除tomcat依赖包即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
@SpringBootTest启动时没有启动servlet
解决方案:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Spring Boot 与WebSocket API版本不对应
Spring Boot 2.x 使用 javax.websocket
Spring Boot 3.x 使用 jakarta.websocket
解决方案:
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>2.1.0</version>
</dependency>