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>