import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.socket.mysocket.util.SocketUtil;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
- @Author: JCccc
- @Description:
- @Date: 2022/6/23 21:21
*/
@Component
public class MySocketHandler {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private SocketIOServer socketIoServer;
@PostConstruct
private void start(){
try {
socketIoServer.start();
}catch (Exception e){
e.printStackTrace();
}
}
@PreDestroy
private void destroy(){
try {
socketIoServer.stop();
}catch (Exception e){
e.printStackTrace();
}
}
@OnConnect
public void connect(SocketIOClient client) {
String userFlag = client.getHandshakeData().getSingleUrlParam(“userFlag”);
SocketUtil.connectMap.put(userFlag, client);
log.info("客户端userFlag: "+ userFlag+ “已连接”);
}
@OnDisconnect
public void onDisconnect(SocketIOClient client) {
String userFlag = client.getHandshakeData().getSingleUrlParam(“userFlag”);
log.info(“客户端userFlag:” + userFlag + “断开连接”);
SocketUtil.connectMap.remove(userFlag, client);
}
}
代码简析:
![](https://img-blog.csdnimg.cn/aa0e9f47075644c9ac07fbe6ebdf4768.png)
#### ⑥ 封装的socket 小函数
SocketUtil.java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
-
@Author: JCccc
-
@Description:
-
@Date: 2022/6/23 21:28
*/
@Component
public class SocketUtil {private final Logger log = LoggerFactory.getLogger(this.getClass());
//暂且把用户&客户端信息存在缓存
public static ConcurrentMap<String, SocketIOClient> connectMap = new ConcurrentHashMap<>();@OnEvent(value = “CHANNEL_SYSTEM”)
public void systemDataListener(String receiveMsg) {
if (!StringUtils.hasLength(receiveMsg)){
return;
}
JSONObject msgObject = (JSONObject) JSON.parse(receiveMsg);
String userFlag = String.valueOf(msgObject.get(“from”));
String content = String.valueOf(msgObject.get(“content”));
log.info(“收到用户 : {} 推送到系统频道的一条消息 :{}”,userFlag,content );
}public void sendToAll(Map<String, Object> msg,String sendChannel) {
if (connectMap.isEmpty()){
return;
}
//给在这个频道的每个客户端发消息
for (Map.Entry<String, SocketIOClient> entry : connectMap.entrySet()) {
entry.getValue().sendEvent(sendChannel, msg);
}
}public void sendToOne(String userFlag, Map<String, Object> msg,String sendChannel) {
//拿出某个客户端信息
SocketIOClient socketClient = getSocketClient(userFlag);
if (Objects.nonNull(socketClient) ){
//单独给他发消息
socketClient.sendEvent(sendChannel,msg);
}
}/**
- 识别出客户端
- @param userFlag
- @return
*/
public SocketIOClient getSocketClient(String userFlag){
SocketIOClient client = null;
if (StringUtils.hasLength(userFlag) && !connectMap.isEmpty()){
for (String key : connectMap.keySet()) {
if (userFlag.equals(key)){
client = connectMap.get(key);
}
}
}
return client;
}
}
代码简析:
![](https://img-blog.csdnimg.cn/bd5a673046a24052a1f7dd6214a5d992.jpeg)
#### ⑦写1个接口,模拟场景,前端页面调用后端接口,做消息推送
TestController.java
import com.socket.mysocket.dto.MyMessage;
import com.socket.mysocket.util.SocketUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
-
@Author: JCccc
-
@Description:
-
@Date: 2022/06/13 21:50
*/
@RestController
public class TestController {
public final static String SEND_TYPE_ALL = “ALL”;
public final static String SEND_TYPE_ALONE = “ALONE”;
@Autowired
SocketUtil socketUtil;@PostMapping(“/testSendMsg”)
public String testSendMsg(@RequestBody MyMessage myMessage){
Map<String, Object> map = new HashMap<>();
map.put(“msg”,myMessage.getContent());//群发 if (SEND_TYPE_ALL.equals(myMessage.getType())){ socketUtil.sendToAll( map,myMessage.getChannel()); return "success"; } //指定单人 if (SEND_TYPE_ALONE.equals(myMessage.getType())){ socketUtil.sendToOne(myMessage.getTo(), map, myMessage.getChannel()); return "success"; } return "fail";
}
}
代码简析:
![](https://img-blog.csdnimg.cn/bd942945e0b349b9bf5a026e2a429aef.jpeg)
好了,7步了。一切已经就绪了。
### 前端简单页面
接下来搞点前端HTML页面, 玩一玩看看效果:
![](https://img-blog.csdnimg.cn/12dca7a95df140b483889dca8884767a.png)
第一个页面:
TestClientStudentJC.html
代码简析:
第二个页面,跟第一个基本一样,改一下用户唯一标识:
TestClientStudentPU.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>我要连SOCKET</title>
<base>
<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<style>
body {
padding: 20px;
}
#console {
height: 450px;
overflow: auto;
}
.msg-color {
color: green;
}
</style>
</head>
<body>
<div id="console" class="well"></div>
<div id="conversationDiv">
<labal>给系统推消息</labal>
<input type="text" id="content"/>
<button id="btnSendToSystem" onclick="sendSys();">发送</button>
</div>
</body>
<script type="text/javascript">
var socket;
connect();
function connect() {
var userFlag = 'user_PU';
var opts = {
query: 'userFlag=' + userFlag
};
socket = io.connect('http://localhost:8503', opts);
socket.on('connect', function () {
console.log("连接成功");
output('当前用户是:' + userFlag );
output('<span class="msg-color">连接成功了。</span>');
});
socket.on('disconnect', function () {
output('<span class="msg-color">下线了。 </span>');
});
socket.on('CHANNEL_STUDENT', function (data) {
let msg= JSON.stringify(data)
output('收到学生频道消息了:' + msg );
console.log(data);
});
socket.on('CHANNEL_SYSTEM', function (data) {
let msg= JSON.stringify(data)
output('收到系统全局消息了:' + msg );
console.log(data);
});
}
function sendSys() {
console.log('发送消息给服务端');
var content = document.getElementById('content').value;
socket.emit('CHANNEL_SYSTEM',JSON.stringify({
'content': content,
'from': 'user_PU'
}));
}
function output(message) {
var element = $("<div>" + message + "</div>");
$('#console').prepend(element);
}
</script>
</html>
OK,把项目跑起来,开始玩。
直接访问客户端页面 模拟学生 JC连接socket:
http://127.0.0.1:8089/TestClientStudentJC.html
可以看到服务端有监测到:
这里监测的:
先试试客户端给系统推消息先:
可以看到服务端成功收到消息:
这种方式,其实是因为服务监听了相关的频道:
前端使用JS推到这个系统频道:
ps: 其实前端给服务端推消息,其实调用接口就可以。
OK,进入核心应用场景1:
群发,所有人都能收到 系统给连上的客户端都推送消息
{
“type”: “ALL”,
“content”:“你们好,这是一条广播消息,全部人都能收到”,
“channel”:“CHANNEL_SYSTEM”
}
看看效果:
一线互联网大厂Java核心面试题库
正逢面试跳槽季,给大家整理了大厂问到的一些面试真题,由于文章长度限制,只给大家展示了部分题目,更多Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等已整理上传,感兴趣的朋友可以看看支持一波!
.cn/eec7593b232e41c5805e63d5ac5a338b.png)
{
“type”: “ALL”,
“content”:“你们好,这是一条广播消息,全部人都能收到”,
“channel”:“CHANNEL_SYSTEM”
}
看看效果:
一线互联网大厂Java核心面试题库
[外链图片转存中…(img-XblIeQ7j-1714459741673)]
正逢面试跳槽季,给大家整理了大厂问到的一些面试真题,由于文章长度限制,只给大家展示了部分题目,更多Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等已整理上传,感兴趣的朋友可以看看支持一波!