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 {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}@Beanpublic 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<>();@Resourceprivate 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);}});}}@OnOpenpublic 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建立连接失败");}}@OnClosepublic 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);}@OnMessagepublic 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();}}}@OnErrorpublic 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.websocketSpring Boot 3.x 使用 jakarta.websocket解决方案:
<dependency><groupId>jakarta.websocket</groupId><artifactId>jakarta.websocket-api</artifactId><version>2.1.0</version>
</dependency>