前言:
网上大多数都是只能群发,或者只能发给自己.并没有一个案例完整的群发并且又可以客户端之间聊天的案例,特此改造好的案例给大家分享一下.只要是一对一聊天,一对多群发. 此案例是在服务器端接口方式.
内容:
此demo更直观传递实体类数据,直接上代码:创建一个maven项目,并且把代码复制过去.
第一:实体类
import lombok.Data; import java.util.UUID; @Data public class Message { //源客户端id private String clientId; //源客户端名字 private String clientName; //sessionId private UUID sessionId; //目标客户端id private String targetClientId; //目标客户端名字 private String targetClientName; //目标客户端sessionId private UUID targetSessionId; //消息类型 private String messageType; //消息类型 private String messageTime; //消息类型 private String xMessageContent; public String getClientId() { return clientId; } public void setClientId(String clientId) { this.clientId = clientId; } public String getClientName() { return clientName; } public void setClientName(String clientName) { this.clientName = clientName; } public UUID getSessionId() { return sessionId; } public void setSessionId(UUID sessionId) { this.sessionId = sessionId; } public String getTargetClientId() { return targetClientId; } public void setTargetClientId(String targetClientId) { this.targetClientId = targetClientId; } public String getTargetClientName() { return targetClientName; } public void setTargetClientName(String targetClientName) { this.targetClientName = targetClientName; } public UUID getTargetSessionId() { return targetSessionId; } public void setTargetSessionId(UUID targetSessionId) { this.targetSessionId = targetSessionId; } public String getMessageType() { return messageType; } public void setMessageType(String messageType) { this.messageType = messageType; } public String getMessageTime() { return messageTime; } public void setMessageTime(String messageTime) { this.messageTime = messageTime; } public String getxMessageContent() { return xMessageContent; } public void setxMessageContent(String xMessageContent) { this.xMessageContent = xMessageContent; } public Message(String clientId, String clientName, UUID sessionId, String targetClientId, String targetClientName, UUID targetSessionId, String messageType, String messageTime, String xMessageContent) { this.clientId = clientId; this.clientName = clientName; this.sessionId = sessionId; this.targetClientId = targetClientId; this.targetClientName = targetClientName; this.targetSessionId = targetSessionId; this.messageType = messageType; this.messageTime = messageTime; this.xMessageContent = xMessageContent; } public Message() { super(); } }
第二:监听
import com.corundumstudio.socketio.AckRequest; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnEvent; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @Component @Slf4j public class MessageEventHandler { @Autowired private SocketIOServer socketIoServer; //public static ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>(); /** * 客户端连接的时候触发 * * @param client */ @OnConnect public void onConnect(SocketIOClient client) { //连接服务器初始化值 String clientId = client.getHandshakeData().getSingleUrlParam("clientId"); String clientName = client.getHandshakeData().getSingleUrlParam("clientName"); Message msg = new Message(clientId, clientName, client.getSessionId(), null, null, null, "connect", getDate(), getXMessageContent() ); //发送给连接成功的客户端,并且发送SessionId给客户端 //socketIoServer.getClient(client.getSessionId()).sendEvent("messageevent",msg); //回发消息 client.sendEvent("messageevent", msg); //client.sendEvent("messageevent", client.getSessionId() +"已连接"); //System.out.println("客户端:" + client.getSessionId() + "已连接,\n msg=" + msg); } //消息模型 private String getXMessageContent() { String msgModel = "<xmsg></xmsg>"; return msgModel; } //取时间 private String getDate() { long currentTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd-HHmmss"); Date date = new Date(currentTime); System.out.println(formatter.format(date)); return formatter.format(date); } /** * 客户端关闭连接时触发 * * @param client */ @OnDisconnect public void onDisconnect(SocketIOClient client) { Message msg = new Message(null, null, null, null, null, null, "disconnect", getDate(), null ); //回发消息 client.sendEvent("messageevent", msg); client.sendEvent("messageevent", "断开连接"); System.out.println("客户端:" + client.getSessionId() + "断开连接"); } /** * 客户端事件 * * @param client 客户端信息 * @param request 请求信息 * @param data 客户端发送数据 */ @OnEvent(value = "messageevent") public void onEvent(SocketIOClient client, AckRequest request, Message data) { System.out.println("发来消息:" + data); //发送给指定客户端 socketIoServer.getClient(data.getTargetSessionId()).sendEvent("messageevent",data); //发送给自己客户端 socketIoServer.getClient(client.getSessionId()).sendEvent("messageevent",data); //广播消息 //sendBroadcast(); } /** * 广播消息 */ /*public void sendBroadcast() { for (SocketIOClient client : socketIOClientMap.values()) { if (client.isChannelOpen()) { client.sendEvent("Broadcast", "当前时间", System.currentTimeMillis()); } } }*/ }
第三:服务器
import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.SpringAnnotationScanner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class NettySocketioConfig { /** * netty-socketio服务器 */ @Bean public SocketIOServer socketIOServer() { com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration(); config.setHostname("localhost"); config.setPort(9092); SocketIOServer server = new SocketIOServer(config); return server; } /** * 用于扫描netty-socketio的注解,比如 @OnConnect、@OnEvent */ @Bean public SpringAnnotationScanner springAnnotationScanner() { return new SpringAnnotationScanner(socketIOServer()); } }
第四:启动类
import com.corundumstudio.socketio.SocketIOServer; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @Slf4j public class NettySocketioApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(NettySocketioApplication.class, args); } @Autowired private SocketIOServer socketIOServer; @Override public void run(String... strings) { socketIOServer.start(); System.out.println("socket.io启动成功!"); } }
第五:HTML客户端
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no"> <title>websocket-java-socketio</title> <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script> </head> <body> <h1>Socket.io Test</h1> <div><p id="status">Waiting for input</p></div> <div><p id="message">hello world!</p></div> <input id="sessionId" class="input-xlarge" type="text" placeholder="谁发送?" /> <input id="targetSessionId" class="input-xlarge" type="text" placeholder="发送给谁?" /></br> <button id="connect" onClick='connect()'/>Connect</button> <button id="disconnect" onClick='disconnect()'>Disconnect</button> <button id="send" onClick='send()'/>Send Message</button> </body> <script type="text/javascript"> /** * 前端js的 socket.emit("事件名","参数数据")方法,是触发后端自定义消息事件的时候使用的, * 前端js的 socket.on("事件名",匿名函数(服务器向客户端发送的数据))为监听服务器端的事件 **/ //初始化URL //源客户端ID var clientId="123456"; //源客户端名字 var clientName="张三"; //sessionId var sessionId=null; //目标客户端id var targetClientId=null; //目标客户端名字 var targetClientName=null; //目标客户端sessionId var targetSessionId=null; //消息类型 var messageType=null; //消息类型 var messageTime=null; //消息类型 var xMessageContent=null; var url = "http://localhost:9092?clientId="+clientId+"&"+"clientName="+clientName; var socket = io.connect(url); var firstconnect = true; function connect() { if(firstconnect) { //socket.on('reconnect', function(){ status_update("Reconnected to Server"); }); //socket.on('reconnecting', function( nextRetry ){ status_update("Reconnecting in " //+ nextRetry + " seconds"); }); //socket.on('reconnect_failed', function(){ message("Reconnect Failed"); }); //firstconnect = false; } else { socket.socket.reconnect(); } } //监听服务器连接事件 socket.on('connect', function(){ status_update("Connected to Server"); }); //监听服务器关闭服务事件 socket.on('disconnect', function(){ status_update("Disconnected from Server"); }); //监听服务器端发送消息事件 socket.on('messageevent', function(data) { message(data) //console.log("服务器发送的消息是:"+data); }); //断开连接 function disconnect() { socket.disconnect(); } function message(data) { document.getElementById('message').innerHTML = "Server says: " + data; } function status_update(txt){ document.getElementById('status').innerHTML = txt; } function esc(msg){ return msg.replace(/</g, '<').replace(/>/g, '>'); } //点击发送消息触发 function send() { console.log("点击了发送消息,开始向服务器发送消息") var msg = { clientId:clientId, clientName:clientName, sessionId:document.getElementById('sessionId').value, targetClientId:targetClientId, targetClientName:targetClientName, targetSessionId:document.getElementById('targetSessionId').value, messageType:messageType, messageTime:null, xMessageContent:null }; socket.emit('messageevent', msg); }; </script> </html>
总结:此demo2偏向于接口方式,Vue,Wux,uni-app等整合起来相对易于整合. 本demo是对于一对一聊天,群发聊天等.