springboot + websocket + spring-messaging实现服务器向浏览器广播式
目录结构
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.web.socket</groupId> <artifactId>websocket</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>websocket Maven Webapp</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <finalName>websocket</finalName> </build> </project>
WebSocketConfig.java
package com.web.socket.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 //表示开启使用STOMP协议来传输基于代理的消息,Broker就是代理的意思。 @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{ @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker(AppConfig.BROKER); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //这一行代码用来注册STOMP协议节点,同时指定使用SockJS协议。 registry.addEndpoint(AppConfig.ENDPOINT).withSockJS(); } }
AppConfig.java
package com.web.socket.config; public class AppConfig { /** * 被订阅的频道 */ public static final String SUBSCRIBE = "/topic/message"; /** * stomp节点 */ public static final String ENDPOINT = "/endpointYC"; /** * 消息代理 */ public static final String BROKER = "/topic"; }
WebSocketController.java
package com.web.socket.controller; import java.io.IOException; 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 org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import com.web.socket.config.AppConfig; import com.web.socket.entity.RequestMessage; import com.web.socket.entity.ResponseMessage; @Controller public class WsController { @Autowired private SimpMessagingTemplate simpMessagingTemplate; /** * @title websocket产生消息,并推送 * @param message * @return */ @MessageMapping("/ws")//和@RequestMapping类似 @SendTo(AppConfig.SUBSCRIBE)//当服务器有消息需要推送的时候,会对订阅了@SendTo中路径的浏览器发送消息 public ResponseMessage say(RequestMessage message) { System.out.println(message.getName()); return new ResponseMessage(message.toString()); } /** * @title http请求产生消息,并推送 * @param message * @return * @throws IOException */ @PostMapping("/http") @ResponseBody public String send(@RequestBody RequestMessage message) throws IOException { System.out.println(message.getName()); simpMessagingTemplate.convertAndSend(AppConfig.SUBSCRIBE,new ResponseMessage(message.toString()) ); return "success"; } }
ws.html
<html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>广播式WebSocket</title> <script th:src="@{static/js/sockjs.min.js}"></script> <script th:src="@{static/js/stomp.js}"></script> <script th:src="@{static/js/jquery-3.3.1.min.js}"></script> </head> <body onload="disconnect()"> <noscript><h2 style="color: #e80b0a;">Sorry,浏览器不支持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"/> <label>内容</label><input type="text" id="content"/> <button id="sendName" onclick="sendName();">发送</button> <p id="response"></p> </div> </div> <script type="text/javascript"> var stompClient = null; /** * 设置组件样式 * @param {Object} connected */ function setConnected(connected) { document.getElementById("connect").disabled = connected; document.getElementById("disconnect").disabled = !connected; document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden'; $("#response").html(); } /** * 创建socket连接 */ function connect() { //链接SockJS 的endpoint 名称为endpointSang var socket = new SockJS('/endpointYC'); //使用stomp子协议的WebSocket 客户端 stompClient = Stomp.over(socket); //链接Web Socket的服务端。 stompClient.connect({}, function (frame) { setConnected(true); //订阅/topic/message频道,并对收到信息进行处理 stompClient.subscribe('/topic/message', function (response) { showResponse(JSON.parse(response.body).responseMessage); }) }); } /** * 断开连接 */ function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); } /** * 向服务器发送消息 */ function sendName() { var name = $('#name').val(); var content = $('#content').val(); stompClient.send("/ws", {}, JSON.stringify({'name': name,'content':content,'date':new Date()})); } /** * 替换文本 * @param {Object} message 服务器返回数据 */ function showResponse(message) { $("#response").html(message); } </script> </body> </html>
使用浏览器访http://127.0.0.1/ws就可以测试websocket方式广播。
在有socket连接的情况下,访问http://127.0.0.1/http,并使用post方式请求,就可以在ws页面看到发送的数据了。