重点需要注意前端和后端的SocketIO的版本,socketio在2.0.x才开始支持4.0协议。
可以看https://mvnrepository.com/artifact/com.corundumstudio.socketio/netty-socketio,引用最新版本。
<dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>2.0.11</version> </dependency>
服务端代码:
import lombok.Data;@Data
public class Message {private String senderName;private String targetUserName;private String message;}
import javax.annotation.PreDestroy;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;@CrossOrigin
@Component
@Slf4j
public class SocketIOConfig {@Value("${socket.host}")private String SOCKETHOST;@Value("${socket.port}")private int SOCKETPORT;private SocketIOServer server;@Beanpublic SocketIOServer socketIOServer() {Configuration config = new Configuration();config.setHostname(SOCKETHOST);config.setPort(SOCKETPORT);server = new SocketIOServer(config);server.start();server.addConnectListener(new ConnectListener() {@Overridepublic void onConnect(SocketIOClient client) {log.info("new user connected with socket " + client.getSessionId());}});server.addDisconnectListener(new DisconnectListener() {@Overridepublic void onDisconnect(SocketIOClient client) {client.getNamespace().getAllClients().stream().forEach(data-> {log.info("user disconnected "+data.getSessionId().toString());});}});return server;}@PreDestroypublic void stopSocketIOServer() {this.server.stop();}}
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
@Log4j2
public class SocketIOController {@Autowiredprivate static SocketIOServer socketServer;public static SocketIOServer getSocketIOServer(){return socketServer;}SocketIOController(SocketIOServer socketServer){this.socketServer=socketServer;this.socketServer.addConnectListener(onUserConnectWithSocket);this.socketServer.addDisconnectListener(onUserDisconnectWithSocket);this.socketServer.addEventListener("替换内容", Message.class, onSendMessage);}public ConnectListener onUserConnectWithSocket = new ConnectListener() {@Overridepublic void onConnect(SocketIOClient client) {log.info("Perform operation on user connect in controller");}};public DisconnectListener onUserDisconnectWithSocket = new DisconnectListener() {@Overridepublic void onDisconnect(SocketIOClient client) {log.info("Perform operation on user disconnect in controller");}};public DataListener<Message> onSendMessage = new DataListener<Message>() {@Overridepublic void onData(SocketIOClient client, Message message, AckRequest acknowledge) throws Exception {log.info(message.getSenderName()+" user send message to user "+message.getTargetUserName()+" and message is "+message.getMessage());socketServer.getBroadcastOperations().sendEvent("替换内容",message);}};}
前端测试代码如下:
<!DOCTYPE html>
<html>
<head><title>长时间任务</title><script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.7.5/socket.io.js"></script><script>var socket = io('http://localhost:8756', {autoConnect: false, // 禁止自动连接extraHeaders: {'Access-Control-Allow-Origin': '*', // 设置跨域请求头},transports: ['websocket', 'polling', 'flashsocket'],});//连接和断开时触发事件socket.on('connect', function() {console.log('已连接到服务器');}); socket.on('disconnect', function() {console.log('已断开');});function start() {console.log('连接中...'); socket.connect();} function stopTask() {socket.disconnect();} //这个用于测试自义定事件function test() {const data={name:'123',id:111}socket.emit('替换内容', data);}socket.on('event_name', function(data) {console.log('后端事件返回值:', data);});</script>
</head>
<body><button onclick="start()">连接</button><button onclick="stopTask()">断开</button><button onclick="test()">测试前端发一个事件</button>
</body>
</html>