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;
/**
* websocket配置类中
*/
@Configuration
public class WebSocketConfig {
/**
* 第一个配置是因为使用springboot内置容器,自己开发时需要配置,如果有独立的容器需要将其注释掉,
* 也就意味着,如果将项目打成WAR包,部署到服务器,使用Tomcat启动时,需要注释掉ServerEndpointExporter配置;
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
/**
* MyEndpointConfigure配置是因为我的需求需要,需要在websocket类中注入service层或者dao层的接口,
* MyEndpointConfigure配置就是为了解决websocket无法注入的问题,如果没有需要可以不用配置
* @return
*/
@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;
/**
* @author
* @Description: WebSocket服务端代码,包含接收消息,推送消息等接口
*/
@Component
@ServerEndpoint(value = "/socket/{archivecode}")
public class WebSocketServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static AtomicInteger online = new AtomicInteger();
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象的session。
private static Map<Long, List<Session>> sessionPools = new HashMap<>();
@Resource
private RemoteAccessClient remoteAccessClient;
/**
* 发送消息方法
* @param sessions 客户端与socket建立的会话
* @param message 消息
* @throws IOException
*/
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);
}
}
);
}
}
/**
* 连接建立成功调用
* @param session 客户端与socket建立的会话
* @param archivecode 客户端的archivecode
*/
@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建立连接失败");
}
}
/**
* 关闭连接时调用
* @param 关闭连接的客户端的session
*/
@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);
}
/**
* 收到客户端消息时触发(群发)
* @param message
* @throws IOException
*/
@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();
}
}
}
/**
* 发生错误时候
* @param session
* @param throwable
*/
@OnError
public void onError(Session session, Throwable throwable){
System.out.println("发生错误");
throwable.printStackTrace();
}
/**
* 给指定用户发送消息
* @param archivecode 用户名
* @param message 消息
* @throws IOException
*/
public void sendInfo(Long archivecode, String message){
List<Session> sessions = sessionPools.get(archivecode);
try {
sendMessage(sessions, message);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 根据用户名获取session会话对象
* @param archivecode
* @return
*/
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;
/**
* 6.密集架报警信息实时更新获取
*/
@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
解决方案:
<!-- SpringBoot3 引入以下依赖,并删除之前的 javax.websocket依赖 -->
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>2.1.0</version>
</dependency>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/188449.html