function setConnected(connected) {
document.getElementById("connect").disabled = connected;
document.getElementById("disconnect").disabled = !connected;
$("#response").html();
}
function connect() {
var socket = new SockJS("http://localhost:9908/publicServer");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/all', function (response) {
var responseData = document.getElementById('responseData');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(response.body));
responseData.appendChild(p);
});
},{});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendMsg() {
var content = document.getElementById('content').value;
stompClient.send("/all",{},JSON.stringify({'content': content}));
}
</script>
Seems your browser doesn’t support Javascript! Websocket relies on Javascript being
enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<labal>连接广播频道</labal>
<button id="connect" onclick="connect();">Connect</button>
<labal>取消连接</labal>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
</div>
<div id="conversationDiv">
<labal>广播消息</labal>
<input type="text" id="content"/>
<button id="sendMsg" onclick="sendMsg();">Send</button>
</div>
<div>
<labal>接收到的消息:</labal>
<p id="responseData"></p>
</div>
简析:
![](https://img-blog.csdnimg.cn/20210831154047786.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
趁热打铁,我们模拟系统后端给前端推送广播消息,通过接口模拟:
TestController.java
/**
-
@Author JCccc
-
@Description
-
@Date 2021/8/20 8:53
*/
@Controller
public class TestController {
@Autowired
public SimpMessagingTemplate template;
/**
* 广播
*
* @param msg
*/
@ResponseBody
@RequestMapping("/pushToAll")
public void subscribe( @RequestBody Message msg) {
template.convertAndSend("/topic/all", msg.getContent());
}
}
简析:
我们推送消息,直接用 SimpMessagingTemplate ,
用的是convertAndSend 广播方式推送到对于的主题目的地 destination 。
(可以看到其实还有convertAndSendToUser ,不着急,后面会说,这是发送给某个连接用户的)
![](https://img-blog.csdnimg.cn/20210831155705437.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_19,color_FFFFFF,t_70,g_se,x_16)
直接把项目跑起来,打开页面开始测试:
![](https://img-blog.csdnimg.cn/20210831160826246.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
我们先点击connect ,连接成功:
![](https://img-blog.csdnimg.cn/20210831161023377.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
可以看到实际上stomp.min.js 最终也是转化成为 ws/wss这种方式成功连接:
![](https://img-blog.csdnimg.cn/20210831161125787.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
调用测试接口,推送广播消息:
![](https://img-blog.csdnimg.cn/20210831162012479.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/20210831162208822.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
在console其实也能看到:
![](https://img-blog.csdnimg.cn/20210831162253557.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
广播功能就到这,接下来是 点对点。
前端页面:
privateExample.html
<meta charset="UTF-8">
<title>聊起来</title>
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.0.min.js"
integrity="sha256-JAW99MJVpJBGcbzEuXk4Az05s/XyDdBomFqNlM3ic+I=" crossorigin="anonymous"></script>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById("connect").disabled = connected;
document.getElementById("disconnect").disabled = !connected;
$("#response").html();
}
function connect() {
var socket = new SockJS("http://localhost:9908/privateServer");
stompClient = Stomp.over(socket);
stompClient.heartbeat.outgoing = 20000;
// client will send heartbeats every 20000ms
stompClient.heartbeat.incoming = 0;
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/user/' + document.getElementById('user').value + '/message', function (response) {
var responseData = document.getElementById('responseData');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(response.body));
responseData.appendChild(p);
});
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendMsg() {
var headers = {
login: 'mylogin',
passcode: 'mypasscode',
// additional header
'accessToken': 'HWPO325J9814GBHJF933'
};
var content = document.getElementById('content').value;
var to = document.getElementById('to').value;
stompClient.send("/alone", {'accessToken': 'HWPO325J9814GBHJF933'}, JSON.stringify({
'content': content,
'to': to
}));
}
</script>
Seems your browser doesn’t support Javascript! Websocket relies on Javascript being
enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<labal>连接用户</labal>
<input type="text" id="user"/>
<button id="connect" onclick="connect();">Connect</button>
</div>
<div>
<labal>取消连接</labal>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
</div>
<div id="conversationDiv">
<labal>发送消息</labal>
<div>
<labal>内容</labal>
<input type="text" id="content"/>
</div>
<div>
<labal>发给谁</labal>
<input type="text" id="to"/>
</div>
<button id="sendMsg" onclick="sendMsg();">Send</button>
</div>
<div>
<labal>接收到的消息:</labal>
<p id="responseData"></p>
</div>
简析:
![](https://img-blog.csdnimg.cn/20210902181420517.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
趁热打铁,我们模拟系统后端给前端推送点对点消息(指定某个用户),通过接口模拟:
/**
* 点对点
*/
@ResponseBody
@RequestMapping("/pushToOne")
public void queue(@RequestBody Message msg) {
System.out.println("进入方法");
/*使用convertAndSendToUser方法,第一个参数为用户id,此时js中的订阅地址为
"/user/" + 用户Id + "/message",其中"/user"是固定的*/
template.convertAndSendToUser(msg.getTo(), "/message", msg.getContent());
}
用的是convertAndSendToUser 推送到指定的用户 ,对于的主题目的地 destination(/message)
也许看到这里,你会觉得很奇怪,为什么我们推的主题是 /message,但是前端订阅的却是
> "/user/" + 用户Id + "/message"
我们直接看源码:
![](https://img-blog.csdnimg.cn/20210902185317157.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/20210902185338291.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_18,color_FFFFFF,t_70,g_se,x_16)
ok,应该不用多说,代码帮我们自己拼接起来了,跟前端订阅规则保持一致。
直接跑项目,测试一下:
模拟我们连接的用户标识 19901 ,连接成功
![](https://img-blog.csdnimg.cn/20210902190009240.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
使用postman调用我们的测试接口,模拟系统指定推送消息到 19901 这个人 :
![](https://img-blog.csdnimg.cn/20210902191022933.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
然后也给20011发送一下消息:
![](https://img-blog.csdnimg.cn/20210902191010398.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
然后看到对应的用户也能收到对应的消息:
![](https://img-blog.csdnimg.cn/20210902190934407.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
对点推送,广播推送,也已经完毕了 。
这种情况就是相当于使用http接口方式,去撮合后端服务做 消息推送。
其实spring还提供了一些好玩的注解,
@MessageMapping 这个注解是对称于 @EnableWebSocketMessageBroker
![](https://img-blog.csdnimg.cn/20210902191357448.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
也就是说,如果我们使用@EnableWebSocketMessageBroker ,那么我们在接口上面其实就能直接使用 @MessageMapping。
怎么用?
![](https://img-blog.csdnimg.cn/20210902191514413.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_20,color_FFFFFF,t_70,g_se,x_16)
然后前端代码里面 的使用:
![](https://img-blog.csdnimg.cn/20211011091510837.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP55uu5qCH6Z2S5bm0,size_16,color_FFFFFF,t_70,g_se,x_16)
这样我们就可以通过前端直接调用相关接口了:
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/0676e703a982199215def271937d5539.jpeg)
![img](https://img-blog.csdnimg.cn/img_convert/62438cea2ea78f87052720749bf21d73.png)
![img](https://img-blog.csdnimg.cn/img_convert/64b0d926e5935008c15bd7c4e8e5b24b.png)
![img](https://img-blog.csdnimg.cn/img_convert/38c945a19fb6d1af312d8f00df653925.png)
![img](https://img-blog.csdnimg.cn/img_convert/3b7a7ee93dc5ea4cabee106e5dcdd73e.png)
![img](https://img-blog.csdnimg.cn/img_convert/a559ee24ee97117e45d442b71b4b4dec.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)**
![img](https://img-blog.csdnimg.cn/img_convert/57253ff64eefdddb22743b5e1cccf9c2.jpeg)
# 总结
面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。
我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
# 面试题及解析总结
![三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经](https://img-blog.csdnimg.cn/img_convert/a586ac67832ffc92308bdc73322f91ce.webp?x-oss-process=image/format,png)
# 大厂面试场景
![三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经](https://img-blog.csdnimg.cn/img_convert/a5814658f3643725248d002ad17a8d61.webp?x-oss-process=image/format,png)
# 知识点总结
![三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经](https://img-blog.csdnimg.cn/img_convert/81335acca0f7e2e54633d7af1ef36086.webp?x-oss-process=image/format,png)
链图片转存中...(img-Tp3RjNRl-1712109404897)]
[外链图片转存中...(img-yL8FctiD-1712109404897)]
[外链图片转存中...(img-u2RhcIiV-1712109404898)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)**
[外链图片转存中...(img-eN8ipX1K-1712109404898)]
# 总结
面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。
我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
# 面试题及解析总结
[外链图片转存中...(img-uUYuJFGA-1712109404898)]
# 大厂面试场景
[外链图片转存中...(img-XrO36UjF-1712109404899)]
# 知识点总结
[外链图片转存中...(img-wiOsb7yl-1712109404899)]