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.websocketSpring Boot 3.x 使用 jakarta.websocket解决方案:
< dependency> < groupId> jakarta.websocket</ groupId> < artifactId> jakarta.websocket-api</ artifactId> < version> 2.1.0</ version>
</ dependency>