初入spring boot(五 )websocket
一、广播式
广播式即服务端有消息时,会将消息发送给所有连接了当前endpoint的浏览器
1.配置websocket,需要在配置类上使用@EnableWebSocketMessageBroker开启websocket支持,并通过继承AbstractWebSocketMessageBrokerConfigurer类,重写其方法来配置websocket
@Configuration
@EnableWebSocketMessageBroker //1
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) { //2
registry.addEndpoint("/endpointWisely").withSockJS();
registry.addEndpoint("/endpointChat").withSockJS();//3
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) { //4
registry.enableSimpleBroker("/queue","/topic"); //5
}
}
1. 通过@EnableWebSocketMessageBroker注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样。
2. 注册STOMP协议的节点(endpoint),并映射的指定的URL
3. 注册一个STOMP的endpoint,并指定使用SockJS协议
4. 配置消息代理(Message Broker)
5. 广播式配置一个/topic消息代理
1 @Controller 2 public class WsController { 3 4 @MessageMapping("/welcome") 5 @SendTo("/topic/getResponse") 6 public WiselyResponse say(WiselyMessage message) throws Exception { 7 Thread.sleep(3000); 8 return new WiselyResponse("Welcome, " + message.getName() + "!"); 9 } 10 11 @Autowired 12 private SimpMessagingTemplate messagingTemplate;//1 13 14 @MessageMapping("/chat") 15 public void handleChat(Principal principal, String msg) { //2 16 if (principal.getName().equals("wyf")) {//3 17 messagingTemplate.convertAndSendToUser("wisely", 18 "/queue/notifications", principal.getName() + "-send:" 19 + msg); 20 } else { 21 messagingTemplate.convertAndSendToUser("wyf", 22 "/queue/notifications", principal.getName() + "-send:" 23 + msg); 24 } 25 } 26 }
1. 当浏览器向服务端发送请求时,通过@MessageMapping("/welcome")映射/welcome这个地址,类似于@RequestMapping
2. 当服务端有消息时,会对订阅了@SendTo中的路径的浏览器发送消息
2. 脚本代码如下:ws.html
1 <!DOCTYPE html> 2 <html xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Spring Boot+WebSocket+广播式</title> 6 7 </head> 8 <body onload="disconnect()"> 9 <noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2></noscript> 10 <div> 11 <div> 12 <button id="connect" onclick="connect();">连接</button> 13 <button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button> 14 </div> 15 <div id="conversationDiv"> 16 <label>输入你的名字</label><input type="text" id="name" /> 17 <button id="sendName" onclick="sendName();">发送</button> 18 <p id="response"></p> 19 </div> 20 </div> 21 <script th:src="@{sockjs.min.js}"></script> 22 <script th:src="@{stomp.min.js}"></script> 23 <script th:src="@{jquery.js}"></script> 24 <script type="text/javascript"> 25 var stompClient = null; 26 27 function setConnected(connected) { 28 document.getElementById('connect').disabled = connected; 29 document.getElementById('disconnect').disabled = !connected; 30 document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; 31 $('#response').html(); 32 } 33 34 function connect() { 35 var socket = new SockJS('/endpointWisely'); //1 36 stompClient = Stomp.over(socket); //2 37 stompClient.connect({}, function(frame) { //3 38 setConnected(true); 39 console.log('Connected: ' + frame); 40 stompClient.subscribe('/topic/getResponse', function(respnose){ //4 41 showResponse(JSON.parse(respnose.body).responseMessage); 42 }); 43 }); 44 } 45 46 47 function disconnect() { 48 if (stompClient != null) { 49 stompClient.disconnect(); 50 } 51 setConnected(false); 52 console.log("Disconnected"); 53 } 54 55 function sendName() { 56 var name = $('#name').val(); //5 57 58 stompClient.send("/welcome", {}, JSON.stringify({ 'name': name })); 59 } 60 61 function showResponse(message) { 62 var response = $("#response"); 63 response.html(message); 64 } 65 </script> 66 </body> 67 </html>
1. 连接SockJs的endpoint名称为“/endpointWisely”
2. 使用STOMP子协议的websocket客户端
3. 连接websocket服务端
4. 通过stompClient.subscribe订阅/topic/getResponse目标发送的消息,这是由@SendTo定义的
5. 通过stompClient.send向/welcome目标发送消息,这是由@MessageMapping定义的
3. 配置viewController
1 @Configuration 2 public class WebMvcConfig extends WebMvcConfigurerAdapter{ 3 4 @Override 5 public void addViewControllers(ViewControllerRegistry registry) { 6 registry.addViewController("/ws").setViewName("/ws"); 7 registry.addViewController("/login").setViewName("/login"); 8 registry.addViewController("/chat").setViewName("/chat"); 9 } 10 11 }