SpringBoot整合WebSocket案例
WebSocket简介
WebSocket协议是基于TCP的一种网络协议。它实现了浏览器与服务器全双工通信——允许服务器主动发送信息给客户端。
WebSocket是通过一个socket来实现双工异步通信的。直接使用WebSocket或者SockJS协议显得特别繁琐。使用它的子协议STOMP,它是一个更高级别的协议,STMOP协议使用一个基于帧格式来定义消息,与HTTP的Request和Response类似。
SpringBoot对使用WebSocket提供了支持,配置源码在org.springframework.boot.autoconfigure.websocket包下。
案例中使用到的maven依赖:
<!--springBoot其它依赖省略-->
<!-- webSocket -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency><!-- thymeleaf模板引擎 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- spring security -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
广播模式
广播式即服务端有消息时,会将信息发送给所有连接了当前endpoint的浏览器。
1、 写消息类
/*** 浏览器向服务端发送的消息*/public class AricMessage {private String name;public String getName() {return name;}}/*** 服务端向浏览器发送的消息*/public class AricResponse {private String responseMessage;public AricResponse(String responseMessage) {this.responseMessage = responseMessage;}public String getResponseMessage() {return responseMessage;}}
2、配置websocket
/*** 配置WebSocket*/@Configuration//注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样@EnableWebSocketMessageBrokerpublic class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {//注册STOMP协议的节点(endpoint),并映射指定的url//注册一个STOMP的endpoint,并指定使用SockJS协议registry.addEndpoint("/endpointAric").withSockJS();}@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(Message Broker)//广播式应配置一个/topic消息代理registry.enableSimpleBroker("/topic");}}
3、写Controller
/*** webSocket控制器*/@Controllerpublic class WebSocketController {@MessageMapping("/welcome") //当浏览器向服务端发送请求时,通过@MessageMapping映射/welcome这个地址,类似于@ResponseMapping@SendTo("/topic/getResponse")//当服务器有消息时,会对订阅了@SendTo中的路径的浏览器发送消息public AricResponse say(AricMessage message) {try {//睡眠1秒Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return new AricResponse("welcome," + message.getName() + "!");}}
4、在src\main\resource\templates目录下编写webSocket.html,使用thymeleaf模板引擎
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>SpringBoot实现广播式WebSocket</title><script th:src="@{sockjs.min.js}"></script><script th:src="@{stomp.min.js}"></script><script th:src="@{jquery-1.11.3.min.js}"></script></head><body><noscript><h2 style="color:#ff0000">抱歉,您的浏览器不支持改功能!</h2></noscript><div><div><button id="connect" onclick="connect();">连接</button><button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button></div><div id="conversationDiv"><label>请输入您的姓名</label><input type="text" id="name" /><button id="sendName" onclick="sendName();">发送</button><p id="response"></p></div></div></body><script type="text/javascript">var stompClient = null;function setConnected(connected){document.getElementById('connect').disabled = connected;document.getElementById('disconnect').disabled = !connected;document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';$("#response").html();}function connect(){var socket = new SockJS('/endpointAric'); //连接SockJS的endpoint名称为"endpointWisely"stompClient = Stomp.over(socket);//使用STMOP子协议的WebSocket客户端stompClient.connect({},function(frame){//连接WebSocket服务端setConnected(true);console.log('Connected:' + frame);//通过stompClient.subscribe订阅/topic/getResponse 目标(destination)发送的消息,这个是在控制器的@SentTo中定义的stompClient.subscribe('/topic/getResponse',function(response){showResponse(JSON.parse(response.body).responseMessage);});});}function disconnect(){if(stompClient != null) {stompClient.disconnect();}setConnected(false);console.log("Disconnected");}function sendName(){var name = $("#name").val();//通过stompClient.send向/welcome 目标(destination)发送消息,这个是在控制器的@MessageMapping中定义的stompClient.send("/welcome",{},JSON.stringify({'name':name}));}function showResponse(message){var response = $("#response");response.html(message);}</script></html>
5、配置viewController,为webSocket.html提供路径映射。
/*** 配置viewController,为页面提供路径映射*/@Controllerpublic class WebMvcConfig extends WebMvcConfigurerAdapter{/*** 配置viewController,提供映射路径*/@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/webSocket").setViewName("/webSocket");}}
6、打开多个浏览器,访问地址,其中一个发送消息,其它浏览器能接收消息。
点对点式
点对点方式解决消息由谁发送,由谁接收的问题。
使用到Spring Security,简单配置。
/*** Spring Security配置*/ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter{@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/", "login").permitAll() //设置Spring Security对/和"/login"路径不拦截.anyRequest().authenticated().and().formLogin().loginPage("/login")//设置Spring Security的登陆页面访问路径为login.defaultSuccessUrl("/chat") //登陆成功后转向/chat路径.permitAll().and().logout().permitAll();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//配置两个用户,角色是userauth.inMemoryAuthentication().withUser("james").password("james").roles("user").and().withUser("curry").password("curry").roles("user");}@Overridepublic void configure(WebSecurity web) throws Exception {// 设置Spring Secutiry不拦截/resources/static/目录下的静态资源web.ignoring().antMatchers("/resources/static/**");}}
配置WebSocket
/*** 配置WebSocket*/ @Configuration //注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样 @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {//注册STOMP协议的节点(endpoint),并映射指定的url//注册一个STOMP的endpoint,并指定使用SockJS协议registry.addEndpoint("/endpointAric").withSockJS();//注册名为"endpointChat"的endpointregistry.addEndpoint("/endpointChat").withSockJS();}@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(Message Broker)//广播式应配置一个/topic消息代理 // registry.enableSimpleBroker("/topic");//点对点式应配置/queue和/topic消息代理registry.enableSimpleBroker("/queue","/topic");} }
编写Controller
/*** webSocket控制器*/ @Controller public class WebSocketController {//通过simpMessagingTemplate向浏览器发送消息@Autowiredprivate SimpMessagingTemplate simpMessagingTemplate;@MessageMapping("/chat")//在springmvc中,可以直接在参数中获得principal,pinciple中包含当前用户信息public void handleChat(Principal principal,String msg){if ("james".equals(principal.getName())) {//硬编码,对用户姓名进行判断//向用户发送消息,第一个参数:接收消息的用户,第二个参数:浏览器订阅地址,第三个参数:消息simpMessagingTemplate.convertAndSendToUser("curry", "/queue/notifications", principal.getName() + "-send: " + msg);} else {simpMessagingTemplate.convertAndSendToUser("james", "/queue/notifications", principal.getName() + "-send: " + msg);}}@MessageMapping("/welcome") //当浏览器向服务端发送请求时,通过@MessageMapping映射/welcome这个地址,类似于@ResponseMapping@SendTo("/topic/getResponse")//当服务器有消息时,会对订阅了@SendTo中的路径的浏览器发送消息public AricResponse say(AricMessage message) {try {//睡眠3秒Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}return new AricResponse("welcome," + message.getName() + "!");} }
在src\main\resource\templates目录下编写login.html和chat.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>首页登陆</title> </head> <body><div th:if="${param.error}">用户名或密码错误!</div><div th:if="${param.logout}">已退出!</div><form th:action="@{/login}" method="post"><div><label>用户名: <input type="text" name="username" /> </label></div><div><label>密码: <input type="password" name="password" /> </label></div><div><input type="submit" value="登陆" /></div></form> </body> </html>
聊天页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /><title>聊天室</title><script th:src="@{sockjs.min.js}"></script><script th:src="@{stomp.min.js}"></script><script th:src="@{jquery-1.11.3.min.js}"></script> </head> <body><p>聊天室</p><form id="aricForm"><textarea rows="4" cols="60" name="text"></textarea><input type="submit" /></form><div id="output"></div> </body> <script type="text/javascript">$("#aricForm").submit(function(e){e.preventDefault();var text = $("#aricForm").find('textarea[name="text"]').val();sendSpittle(text);});var sock = new SockJS("/endpointChat");//连接endpoint名为"endpointChat"的endpointvar stomp = Stomp.over(sock);stomp.connect('guest','guest',function(frame){//订阅/user/queue/notifications发送的消息,这里与在simpMessagingTemplate.convertAndSendToUser定义地址一致,/user是必须的stomp.subscribe("/user/queue/notifications",handleNotification);});function handleNotification(message){$("#output").append("<b>Received: " + message.body + "</b><br/>");}function sendSpittle(text){stomp.send("/chat",{},text);}$("#stop").click(function(){sock.close();}); </script> </html>
配置viewController
/*** 配置viewController,为页面提供路径映射*/ @Controller public class WebMvcConfig extends WebMvcConfigurerAdapter{/*** 配置viewController,提供映射路径*/@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/webSocket").setViewName("/webSocket");registry.addViewController("/login").setViewName("/login");registry.addViewController("/chat").setViewName("/chat");}}
- 打开浏览器,实现点对点聊天
SpringBoot整合WebSocket案例相关推荐
- SpringBoot 整合WebSocket 简单实战案例
前言 这个简单实战案例主要目的是让大家了解websocket的一些简单使用. 另外使用stomp方式的: <Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 ...
- Springboot 整合Websocket+Stomp协议+RabbitMQ做消息代理 实例教程
前言 如果你还没有了解过websocket,关于整合websocket的简单入门使用,可以先看看我这篇: <SpringBoot 整合WebSocket 简单实战案例> https://b ...
- Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)
Springboot整合Websocket遇到的坑 一.使用Springboot内嵌的tomcat启动websocket 1.添加ServerEndpointExporter配置bean @Confi ...
- Springboot 整合jsp案例
Springboot 整合jsp案例 关键词 war包方式部署到tomcat,注意依赖scope和内置tomcat的排除 项目架构 配置文件:application.properties server ...
- 最简单的springboot整合websocket方式
简介 WebSocket是一种与HTTP不同的协议.两者都位于OSI模型的应用层,并且都依赖于传输层的TCP协议. 虽然它们不同,但是RFC 6455中规定:it is designed to wor ...
- 在线聊天室的消息单聊的实现——springboot整合WebSocket(二)
一.声明 项目的搭建请大家移步到:在线聊天室的消息群聊的实现--springboot整合WebSocket(一) 单聊的实现是在群聊项目上进行延申改造的. 二.引入依赖 <dependency& ...
- springboot整合websocket实现消息推送
springboot整合websocket 1.WebSocket介绍与原理 介绍:WebSocket是HTML5一种新的协议.它实现了浏览器与服务器全双工通信.一开始的握手需要借助HTTP请求完成. ...
- SpringBoot整合websocket实现在线客服聊天
websocket最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息. 浏览器和服务器只需要要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时 ...
- springboot整合freemarker案例
springboot整合freemarker案例 1.pom.xml 2.application.properties 3.实体类 4.controller 5.取普通变量的值 6.遍历集合 7.遍历 ...
- springboot整合redis案例——点赞取消点赞
目录 springboot与缓存 JSR-107 Spring缓存抽象 重要概念和缓存注解 springboot整合redis 案例一:Redis是实现点赞.取消点赞 一.Redis 缓存设计及实现 ...
最新文章
- 队列在多线程中的应用
- html进度条实现方案,两种进度条实现方案的对比
- jquery-幻灯片的移动分析
- y币充值通道_比特币如何扩容?读懂比特币链下扩容技术进展与投资现状
- Unable to find the requested .Net Framework Data Provider
- 蚂蚁金服CTO程立:金融级分布式交易的技术路径
- win8游戏开发教程开篇
- GridView控件RowDataBound事件中获取列字段途径
- 可视对讲网络协议转换器怎么使用,协议转换器使用方法详细介绍
- 功能丰富强大的开源HEVC分析软件 “ Gitl HEVC Analyzer ”
- html图片铺底代码,梦幻西游底部师徒四人动态图
- 物联网定位系统:GPS、WiFi、基站、RFID…
- iVMS-4200 Vs区别_古典占星学和现代占星学的区别
- h5微信页面在手机微信端和微信web开发者工具中都能正常显示,但是在pc端微信浏览器上打不开(显示空白)...
- ROS中使用Intel RealSense D455或L515深度相机
- [FAQ21007] 电信VoLTE开关默认值设置
- Appium的实现原理
- 张一鸣和扎克伯格,一生之敌
- 单片机编程软件很简单(22),keil单片机编程软件优化等级+概念解析
- 2022,视频号的十大机会