package org.springblade.common.handler;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.corundumstudio.socketio.*;
|
import com.corundumstudio.socketio.annotation.OnConnect;
|
import com.corundumstudio.socketio.annotation.OnDisconnect;
|
import com.corundumstudio.socketio.annotation.OnEvent;
|
import com.corundumstudio.socketio.protocol.Packet;
|
import org.springblade.core.mp.support.Condition;
|
import org.springblade.core.tool.api.R;
|
import org.springblade.core.tool.utils.StringUtil;
|
import org.springblade.modules.modules.entity.FunctionEntity;
|
import org.springblade.modules.modules.entity.ModulesEntity;
|
import org.springblade.modules.modules.service.IFunctionService;
|
import org.springblade.modules.modules.service.IModulesService;
|
import org.springblade.modules.modules.vo.FunctionVO;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.core.annotation.Order;
|
import org.springframework.stereotype.Component;
|
import com.corundumstudio.socketio.SocketIOServer;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.PostConstruct;
|
import javax.annotation.PreDestroy;
|
import java.net.ServerSocket;
|
import java.util.ArrayList;
|
import java.util.Collection;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.function.BiConsumer;
|
|
|
/**
|
* SocketIo启动类
|
*/
|
@Component
|
@Order(value = 1)
|
public class SocketIOService {
|
|
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
|
private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();
|
|
@Autowired
|
private SocketIOServer socketIOServer;
|
|
/**
|
* Spring IoC容器创建之后,在加载SocketIOConfiguration Bean之后启动
|
*/
|
@PostConstruct
|
private void autoStartup() throws Exception {
|
start();
|
}
|
|
/**
|
* Spring IoC容器在销毁SocketIOConfiguration Bean之前关闭,避免重启项目服务端口占用问题
|
*/
|
@PreDestroy
|
private void autoStop() throws Exception {
|
stop();
|
}
|
|
public void start() {
|
socketIOServer.start();
|
log.info("socket.io初始化服务完成");
|
}
|
|
/**
|
* 连接时
|
*/
|
@OnConnect
|
public void onConnect(SocketIOClient client) {
|
String connectInfo = client.getHandshakeData().getSingleUrlParam("connectInfo");
|
SocketEntity socketEntity = parseMsg(connectInfo);
|
|
if (clientMap.containsKey(socketEntity.getCurrent())){
|
client.sendEvent("connectError",R.fail("连接已存在"));
|
log.info("设备{}连接已存在",socketEntity.getCurrent());
|
}else {
|
clientMap.put(socketEntity.getCurrent(),client);
|
client.sendEvent("connectOk",R.success("连接成功"));
|
log.info("设备{}连接成功",socketEntity.getCurrent());
|
}
|
}
|
|
/**
|
* 监听前端订阅相同事件发送过来的信息
|
*
|
* @param client
|
* @param ackRequest
|
* @param data
|
*/
|
@OnEvent(value = "msg")
|
public void OnEvent(SocketIOClient client, AckRequest ackRequest, String data) {
|
log.info("发来消息:" + data);
|
}
|
|
/**
|
* 图册上下页控制
|
*/
|
@OnEvent(value = "changeImgPage")
|
public void OnEventImgChange(SocketIOClient client, AckRequest ackRequest, String data) {
|
log.info("图册变更:" + data);
|
SocketEntity socketEntity = parseMsg(data);
|
if (socketEntity.getMsg().equals("previous")) {
|
//上一页
|
clientMap.get(socketEntity.getTarget()).sendEvent("previousPage", "previous");
|
} else {
|
//下一页
|
clientMap.get(socketEntity.getTarget()).sendEvent("nextPage", "next");
|
}
|
}
|
|
/**
|
* 菜单控制
|
*/
|
@OnEvent(value = "menuChange")
|
public void OnEventMenuChange(SocketIOClient client, AckRequest ackRequest, String data) {
|
log.info("菜单变更:" + data);
|
SocketEntity socketEntity = parseMsg(data);
|
log.info("控制的设备是:{}", parseMsg(client.getHandshakeData().getSingleUrlParam("connectInfo")).getTarget());
|
clientMap.get(socketEntity.getTarget()).sendEvent("menuChange", socketEntity.getMsg());
|
}
|
|
/**
|
* 断开连接时
|
*
|
* @param client
|
*/
|
@OnDisconnect()
|
public void OnEvent(SocketIOClient client) {
|
String connectInfo = client.getHandshakeData().getSingleUrlParam("connectInfo");
|
SocketEntity socketEntity = parseMsg(connectInfo);
|
//保证断连只会断连自己,不会断连其他客户端
|
clientMap.forEach((key,value)->{
|
if (value.getSessionId().equals(client.getSessionId())){
|
clientMap.remove(key);
|
}
|
});
|
log.info("设备{}断开连接",socketEntity.getCurrent());
|
}
|
|
public void stop() {
|
if (socketIOServer != null) {
|
socketIOServer.stop();
|
socketIOServer = null;
|
}
|
log.info("socket.io服务已关闭");
|
}
|
|
/**
|
* 此方法为获取client连接中的参数,可根据需求更改
|
*
|
* @param client
|
* @return
|
*/
|
private String getParamsByClient(SocketIOClient client) {
|
// 从请求的连接中拿出参数(这里的sid必须是唯一标识)
|
Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
|
List<String> list = params.get("UID");
|
if (list != null && list.size() > 0) {
|
return list.get(0);
|
}
|
return null;
|
}
|
|
/**
|
* 获取连接的客户端ip地址
|
*
|
* @param client: 客户端
|
* @return: java.lang.String
|
*/
|
private String getIpByClient(SocketIOClient client) {
|
String sa = client.getRemoteAddress().toString();
|
return sa.substring(1, sa.indexOf(":"));
|
}
|
|
/**
|
* 解析参数,转化为实体类
|
*/
|
private SocketEntity parseMsg(String msg) {
|
return JSON.parseObject(msg, SocketEntity.class);
|
}
|
|
|
}
|