SpringBoot 整合 WebSocket(topic广播)javascript
一、什么是WebSockethtml
WebSocket为游览器和服务器提供了双工异步通讯的功能,即游览器能够向服务器发送消息,服务器也能够向游览器发送消息。WebSocket需游览器的支持,如IE十、Chrome 13+、Firefox 6+,这对咱们如今的游览器来讲都不是问题。java
WebSocket是经过一个socket来实现双工异步通信能力的。可是直接使用WebSocket(或SockJS:WebSocket协议的模拟,增长了当游览器不支持WebSocket的时候的兼容支持)协议开发程序显得特别繁琐, 咱们会使用它的子协议STOMP,它是一个更高级别的协议,STOMP协议使用一个基于帧的格式来定义消息,与HTTP的request和reponse相似(具备相似于@RequestMapping的@MassageMapping)jquery
二、什么是STOMPweb
STOMP,Streaming Text Orientated Message Protocol,是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。
它提供了一个可互操做的链接格式,容许STOMP客户端与任意STOMP消息代理(Broker)进行交互,相似于OpenWire(一种二进制协议)。因为其设计简单,很容易开发客户端,所以在多种语言和多种平台上获得普遍应用。其中最流行的STOMP消息代理是Apache ActiveMQ。spring
STOMP协议工做于TCP协议之上,使用了下列命令:
1)、SEND 发送
2)、SUBSCRIBE 订阅
3)、UNSUBSCRIBE 退订
4)、BEGIN 开始
5)、COMMIT 提交
6)、ABORT 取消
7)、ACK 确认
8)、DISCONNECT 断开
浏览器
三、为何须要WebSocket服务器
答案很简单,由于 HTTP 协议有一个缺陷:通讯只能由客户端发起。
举例来讲,咱们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议作不到服务器主动向客户端推送信息。若是想持续从服务的获取消息,则只能使用轮询或创建长链接的方法来实现,可是这样或浪费不少没必要要的资源。而webSocket则解决了这个问题,通讯可由双方发起,只须要创建一次链接,服务的端就能够持续从服务端得到消息。主要用来作消息通知,消息推送等模块
websocket
四、SpringBoot使用 STOMP 消息步骤app
1)、添加pom文件依赖
2)、java方式配置websocket stomp
3)、消息实体类
4)、书写控制层
5)、书写页面
五、Pom 依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
六、java方式配置websocket stomp
package com.example.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { /** * 配置连接端点 * @param registry */ @Override public void registerStompEndpoints(StompEndpointRegistry registry){ registry.addEndpoint("/endpointWisely").withSockJS(); } /** * 配置消息代理 * @param registry */ @Override public void configureMessageBroker(MessageBrokerRegistry registry){ registry.enableSimpleBroker("/topic"); } }
七、消息实体类
package com.example.demo.PoJo; /** * 消息接受 */ public class WiselyMessage { private String name; public String getName(){ return name; } }
package com.example.demo.PoJo; /** * 消息返回 */ public class WiselyResponse { private String responseMessage; public WiselyResponse(String responseMessage){ this.responseMessage = responseMessage; } public String getResponseMessage(){ return responseMessage; } }
八、书写控制层
package com.example.demo.controller; import com.example.demo.PoJo.WiselyMessage; import com.example.demo.PoJo.WiselyResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Controller; import java.security.Principal; @Controller public class WsController { /** * MessageMapping 相似于 RequestMapping * SendTo 订阅地址 相似于 订阅一个URL (个人理解就是 调用了这个方法 在返回的时候会给订阅该url的地址发送数据) * @param message * @return * @throws Exception */ @MessageMapping("/welcome") @SendTo("/topic/getResponse") public WiselyResponse say(WiselyMessage message) throws Exception { Thread.sleep(3000); return new WiselyResponse("Welcome," + message.getName() + "!"); } }
九、书写页面
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Spring Boot+WebSocket+广播式</title> </head> <body onload="disconnect()"> <noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</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> <script th:src="@{sockjs.min.js}"></script> <script th:src="@{stomp.min.js}"></script> <script th:src="@{jquery.js}"></script> <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('/endpointWisely'); //1 stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/topic/getResponse', function(respnose){ //2 showResponse(JSON.parse(respnose.body).responseMessage); }); }); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendName() { var name = $('#name').val(); //3 stompClient.send("/welcome", {}, JSON.stringify({ 'name': name })); } function showResponse(message) { var response = $("#response"); response.html(message); } </script> </body> </html>
十、客户端发送和接收消息图解