Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 (一

    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)]

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了一个非常方便的方式来整合WebSocketSTOMP协议,可以非常容易地在应用程序中添加实时消息推送功能。下面是实现的步骤: 1.添加依赖 在pom.xml中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2.创建WebSocket配置类 创建一个类来配置WebSocket支持: ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); } } ``` 该类通过@EnableWebSocketMessageBroker注解启用了WebSocket消息代理功能,并实现了WebSocketMessageBrokerConfigurer接口来配置消息代理。 configureMessageBroker()方法配置了一个简单的消息代理,它将以“/topic”为前缀的消息发送到代理。应用程序的目标前缀将是“/app”。 registerStompEndpoints()方法将“/ws”路径注册为STOMP端点,并启用SockJS支持。 3.编写控制器 创建一个控制器来处理WebSocket请求: ```java @Controller public class WebSocketController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception { Thread.sleep(1000); // simulated delay return new Greeting("Hello, " + message.getName() + "!"); } } ``` @MessageMapping注解表示该方法可以处理来自“/app/hello”的消息。@SendTo注解表示当处理完成后,将结果发送到“/topic/greetings”主题。 4.创建实体类 创建HelloMessage和Greeting实体类: ```java public class HelloMessage { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Greeting { private String content; public Greeting(String content) { this.content = content; } public String getContent() { return content; } } ``` 5.创建前端页面 在前端页面中使用STOMP.js和SockJS来连接WebSocket,发送和接收消息: ```html <!DOCTYPE html> <html> <head> <title>WebSocket Example</title> <script src="https://cdn.jsdelivr.net/sockjs/1.1.4/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/stomp.js/2.3.3/stomp.min.js"></script> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> </head> <body> <div> <label for="name">What is your name?</label> <input type="text" id="name" name="name"> <button id="connect">Connect</button> </div> <br/> <div> <label for="message">Message:</label> <input type="text" id="message" name="message"> <button id="send">Send</button> </div> <br/> <div id="greetings"></div> <script> var stompClient = null; function connect() { var socket = new SockJS('/ws'); stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', function(greeting){ showGreeting(JSON.parse(greeting.body).content); }); }); } function disconnect() { if (stompClient !== null) { stompClient.disconnect(); } console.log("Disconnected"); } function sendName() { stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); } function showGreeting(message) { $("#greetings").append("<tr><td>" + message + "</td></tr>"); } $(function () { $("form").on('submit', function (e) { e.preventDefault(); }); $("#connect").click(function() { connect(); }); $("#disconnect").click(function() { disconnect(); }); $("#send").click(function() { sendName(); }); }); </script> </body> </html> ``` 在页面中,我们使用了SockJS和STOMP.js,创建一个WebSocket连接。我们可以使用connect()函数来建立连接,使用sendName()函数来发送消息,并使用showGreeting()函数来显示接收到的消息。 最后,我们需要在应用程序的主类上添加@SpringBootApplication注解,并运行应用程序。 这样,当用户在页面上输入一个名字并点击“Connect”按钮时,将建立一个WebSocket连接,并向服务器发送一个消息。服务器将在1秒钟后返回一个问候语,并将其发送到“/topic/greetings”主题。浏览器将接收到这个消息,并通过showGreeting()函数显示它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值