package top.itjie.java.demo.websoket.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import top.itjie.java.demo.websoket.dao.UserDao;
import top.itjie.java.demo.websoket.pojo.*;
import top.itjie.java.demo.websoket.utils.JsonUtil;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service("wsService")
public class WsService {
@Autowired
private UserDao userDao;
private Logger logger = LoggerFactory.getLogger(this.getClass());
private final ConcurrentHashMap<Session, UserStatus> sessionMap = new ConcurrentHashMap<>();
public ConcurrentHashMap getSessionMap(){
return sessionMap;
}
/**
* 处理消息
*/
public void handleMessage(Session session, String message) throws IOException {
logger.info("进入处理消息");
Map map = JsonUtil.string2Obj(message, Map.class);
int type = map == null? 0 : (map.get("type") == null? 0 : (int) map.get("type"));
// type = 1, 处理登录
if(type == 1){
LoginReq loginReq = JsonUtil.string2Obj(message, LoginReq.class);
handleLogin(session, loginReq);
}
}
/**
* 设置SessionMap
* @param session 会话
* @param userStatus 用户状态
*/
public void putSession(Session session, UserStatus userStatus){
sessionMap.put(session, userStatus);
logger.info("现在共有: {} 个活跃连接.", sessionMap.size());
}
/**
* 移除会话
* @param session 会话
*/
public void removeSession(Session session){
sessionMap.remove(session);
}
/**
* 定时任务, 给登录成功的用户发随机数
* @throws IOException
*/
@Scheduled(fixedRate = 2000)
public void scheduleTask() throws IOException {
logger.info("进入发送随机数");
logger.info("[连接检测] 当前活跃用户数: {}", sessionMap.size());
for (Session session : sessionMap.keySet()){
Heartbeat heartbeat = new Heartbeat(2, "心跳");
session.getBasicRemote().sendText(JsonUtil.obj2String(heartbeat));
logger.info("[发送心跳] userId:{}", sessionMap.get(session).getUserId());
// 给登录成功的用户发随机数
if(sessionMap.get(session).getStatus() == 1){
// 生成一个随机数保留两位小数
double random = (double) Math.round(Math.random() * 100 * 100) / 100;
DataResp dataResp = new DataResp(3, random, System.currentTimeMillis());
session.getBasicRemote().sendText(JsonUtil.obj2String(dataResp));
logger.info("[发送消息] userId:{}, message: {}", sessionMap.get(session).getUserId(), dataResp);
}
}
}
void handleLogin(Session session, LoginReq loginReq) throws IOException {
// 用户不存在
if(!userDao.checkUserId(loginReq.getUserId())){
LoginResp loginResp = new LoginResp(1, 0, "用户不存在!");
session.getBasicRemote().sendText(JsonUtil.obj2String(loginResp));
logger.info("[用户登录] loginReq: {}, 登录失败, 用户不存在!", loginReq);
return;
}
// 密码错误
if(!userDao.passwordValid(loginReq.getUserId(), loginReq.getPassword())) {
LoginResp loginResp = new LoginResp(1, 0, "密码不正确!");
session.getBasicRemote().sendText(JsonUtil.obj2String(loginResp));
logger.info("[用户登录] loginReq: {}, 登录失败, 密码不正确!", loginReq);
return;
}
LoginResp loginResp = new LoginResp(1, 1, "登录成功!");
session.getBasicRemote().sendText(JsonUtil.obj2String(loginResp));
// 登录成功更新该会话状态
UserStatus userStatus = sessionMap.get(session);
userStatus.setUserId(loginReq.getUserId());
userStatus.setStatus(1);
logger.info("[用户登录] loginReq: {}, 登录成功!", loginReq);
}
}
基于springboot实现的websoket服务
需积分: 0 7 浏览量
更新于2023-10-17
收藏 43KB RAR 举报
WebSocket是Web交互技术的一种新标准,它允许服务器与客户端之间建立长连接,实现实时通信。在传统的HTTP协议中,每次请求-响应都需要重新建立连接,而WebSocket则提供了一种低延迟、高效率的方式,使得数据可以双向流动,极大地提高了实时性。Spring Boot,作为Java开发的一个轻量级框架,提供了方便快捷的方式来构建WebSocket服务。接下来,我们将深入探讨如何基于Spring Boot实现WebSocket服务。
我们需要在Spring Boot项目中引入WebSocket相关的依赖。在`pom.xml`文件中添加以下Maven依赖:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
```
接下来,配置WebSocket。在Spring Boot的配置类中创建一个`WebSocketConfig`,并使用`@Configuration`和`@EnableWebSocket`注解来启用WebSocket功能:
```java
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyWebSocketHandler(), "/websocket").withSockJS();
}
}
```
在这里,我们创建了一个`MyWebSocketHandler`类,它需要继承自`WebSocketHandler`接口,并实现其中的方法,如`afterConnectionEstablished`、`handleTextMessage`等,用于处理连接建立后的操作以及接收到的消息。
```java
@Component
public class MyWebSocketHandler extends TextWebSocketHandler {
private Set<WebSocketSession> sessions = new CopyOnWriteArraySet<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.add(session);
System.out.println("New client connected");
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
for (WebSocketSession s : sessions) {
if (!s.equals(session)) {
s.sendMessage(message);
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
sessions.remove(session);
System.out.println("Client disconnected");
}
}
```
以上代码展示了如何管理WebSocket会话,当有新的连接建立时,将该会话添加到集合中;当连接关闭时,从集合中移除。`handleTextMessage`方法用于处理接收到的消息,并广播给其他在线的客户端。
为了测试WebSocket服务,我们还需要创建一个前端页面,使用JavaScript或库(如jQuery或Vue.js)来发起WebSocket连接。例如,使用JavaScript可以这样实现:
```html
<!DOCTYPE html>
<html>
<head>
<script>
var socket = new WebSocket("ws://localhost:8080/websocket");
socket.onopen = function(event) {
console.log("Connected to WebSocket server.");
socket.send("Hello from client!");
};
socket.onmessage = function(event) {
console.log("Received: " + event.data);
};
socket.onclose = function(event) {
console.log("Disconnected from WebSocket server.");
};
</script>
</head>
<body>
<h1>WebSocket Test</h1>
</body>
</html>
```
在这个例子中,前端页面通过JavaScript建立WebSocket连接,并发送一条消息。当收到消息时,会在控制台打印出来。
至此,我们已经实现了基于Spring Boot的WebSocket服务。这个服务能够接收并广播消息,同时允许前端页面进行实时通信。这在实时聊天、股票交易、在线游戏等场景中非常有用。要进一步优化和扩展,可以考虑添加权限控制、消息编码解码、心跳检测等功能。通过这种方式,Spring Boot的灵活性和易用性使得开发WebSocket服务变得简单而高效。
code_idea
- 粉丝: 117
- 资源: 12
最新资源
- 二自由度整车模型 资料包含状态空间方程、微分方程两种建模方式 输入为前轮转角,输出为质心侧偏角、横摆角速度,以此进行车辆状态分析 可自定义前轮转角延时输出、自定义调节整车参数 附带说明文档
- 蓄电池超级电容混合储能系统simulink能量管理仿真模型
- 基于共享储能电站的工业用户日前优化经济调度方法 文献复现 首先提出共享储能电站的概念,分析其商业运营模式 然后将共享储能电站应用到工业用户经济优化调度中,通过协调各用户使用共享储能电站进行充电和放电
- 微电网两阶段鲁棒优化经济调度方法 针对微电网内可再生能源和负荷的不确定性,建立了min-max-min 结构的两阶段鲁棒优化模型,可得到最恶劣场景下运行成本最低的调度方案 模型中考虑了储能、需求侧负
- 三菱Q系列程序 三菱Q程序,主站Q02UCPU++FX3128M+FX3S14M+FX3U-485通信主从控制 QX42.QY42P等输入输出模块.QD70P8定位控制模块 锂电池包膜机机 ,搭
- 06-试用期员工转正审批表.docx
- 08-试用期员工转正申请表.doc.docx
- 01-试用期及转正管理制度.doc
- 02-试用期转正管理制度.doc
- 00-转正管理制度.doc
- 05-员工试用期转正审批表.docx
- 04-试用期员工转正审批考核表.docx
- 07-试用期转正评估表.doc.docx
- 11-试用期员工转正通知书+定薪单.docx
- 13-试用期转正流程图.doc.docx
- 09-试用期员工转正申请表.xlsx