赞
踩
所谓WebSocket, 类似于Socket,它的作用是可以让Web应用中的客户端和服务端建立全双工通信。在基于Spring的应用中使用WebSocket一般可以有以下三种方式:
下面,我将对这三种实现方式做一个简单介绍,此外有关WebSocket性质的更多介绍可以参考以下这篇文章:WebSocket探秘
注:本篇文章的完整源码可以参考:https://github.com/zifangsky/WebSocketDemo
这里监听了客户端的连接端口/reverse
,并定义了如何处理客户端发来的消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package cn.zifangsky.samplewebsocket.websocket;
import javax.websocket.OnMessage; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import java.io.IOException;
/** * ReverseWebSocketEndpoint * * @author zifangsky * @date 2018/9/30 * @since 1.0.0 */ @ServerEndpoint("/reverse") public class ReverseWebSocketEndpoint {
@OnMessage public void handleMessage(Session session, String message) throws IOException { session.getBasicRemote().sendText("Reversed: " + new StringBuilder(message).reverse()); }
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package cn.zifangsky.samplewebsocket.config;
import cn.zifangsky.samplewebsocket.websocket.ReverseWebSocketEndpoint; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/** * WebSocket相关配置 * * @author zifangsky * @date 2018/9/30 * @since 1.0.0 */ @Configuration @EnableWebSocket public class WebSocketConfig{
@Bean public ReverseWebSocketEndpoint reverseWebSocketEndpoint() { return new ReverseWebSocketEndpoint(); }
@Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | <html xmlns:th="http://www.thymeleaf.org"> <head> <meta content="text/html;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>WebSocket Examples: Reverse</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script th:src="@{/layui/layui.js}"></script> <link th:href="@{/layui/css/layui.css}" rel="stylesheet"> <style type="text/css"> #connect-container { margin: 0 auto; width: 400px; }
#connect-container div { padding: 5px; margin: 0 7px 10px 0; }
.layui-btn { display: inline-block; } </style> <script type="text/javascript"> var ws = null;
$(function () { var target = $("#target"); if (window.location.protocol === 'http:') { target.val('ws://' + window.location.host + target.val()); } else { target.val('wss://' + window.location.host + target.val()); } });
function setConnected(connected) { var connect = $("#connect"); var disconnect = $("#disconnect"); var reverse = $("#reverse");
if (connected) { connect.addClass("layui-btn-disabled"); disconnect.removeClass("layui-btn-disabled"); reverse.removeClass("layui-btn-disabled"); } else { connect.removeClass("layui-btn-disabled"); disconnect.addClass("layui-btn-disabled"); reverse.addClass("layui-btn-disabled"); }
connect.attr("disabled", connected); disconnect.attr("disabled", !connected); reverse.attr("disabled", !connected); }
//连接 function connect() { var target = $("#target").val();
ws = new WebSocket(target); ws.onopen = function () { setConnected(true); log('Info: WebSocket connection opened.'); }; ws.onmessage = function (event) { log('Received: ' + event.data); }; ws.onclose = function () { setConnected(false); log('Info: WebSocket connection closed.'); }; }
//断开连接 function disconnect() { if (ws != null) { ws.close(); ws = null; } setConnected(false); }
//文字反转 function reverse() { if (ws != null) { var message = $("#message").val(); log('Sent: ' + message); ws.send(message); } else { alert('WebSocket connection not established, please connect.'); } }
//日志输出 function log(message) { console.debug(message); } </script> </head> <body> <noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!</h2></noscript> <div> <div id="connect-container" class="layui-elem-field"> <legend>Reverse</legend> <div> <input id="target" type="text" class="layui-input" size="40" style="width: 350px" value="/reverse"/> </div> <div> <button id="connect" class="layui-btn layui-btn-normal" οnclick="connect();">Connect</button> <button id="disconnect" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="disconnect();">Disconnect </button>
</div> <div> <textarea id="message" class="layui-textarea" placeholder="请输入需要反转的内容" style="width: 350px"></textarea> </div> <div> <button id="reverse" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="reverse();">Reverse message </button> </div> </div> </div> </body> </html> |
启动项目后访问页面,效果如下:
Spring 4.0为WebSocket通信提供了支持,包括:
发送和接收消息的低层级API;
发送和接收消息的高级API;
用来发送消息的模板;
支持SockJS,用来解决浏览器端、服务器以及代理不支持WebSocket的问题。
使用Spring提供的低层级API实现WebSocket,主要需要以下几个步骤:
定义一个继承了AbstractWebSocketHandler
类的消息处理类,然后自定义对”建立连接“、”接收/发送消息“、”异常情况“等情况进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package cn.zifangsky.samplewebsocket.websocket;
import cn.zifangsky.samplewebsocket.service.EchoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler;
import javax.annotation.Resource; import java.text.MessageFormat;
/** * 通过继承 {@link org.springframework.web.socket.handler.AbstractWebSocketHandler} 的示例 * * @author zifangsky * @date 2018/10/9 * @since 1.0.0 */ public class EchoWebSocketHandler extends TextWebSocketHandler{ private final Logger logger = LoggerFactory.getLogger(getClass());
@Resource(name = "echoServiceImpl") private EchoService echoService;
@Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.debug("Opened new session in instance " + this); }
@Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { //组装返回的Echo信息 String echoMessage = this.echoService.echo(message.getPayload()); logger.debug(MessageFormat.format("Echo message \"{0}\"", echoMessage));
session.sendMessage(new TextMessage(echoMessage)); }
@Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { session.close(CloseStatus.SERVER_ERROR); logger.debug("Info: WebSocket connection closed."); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package cn.zifangsky.samplewebsocket.config;
import cn.zifangsky.samplewebsocket.websocket.EchoWebSocketHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/** * WebSocket相关配置 * * @author zifangsky * @date 2018/9/30 * @since 1.0.0 */ @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer{
@Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(echoWebSocketHandler(), "/echoMessage"); registry.addHandler(echoWebSocketHandler(), "/echoMessage_SockJS").withSockJS(); }
/** * 通过继承 {@link org.springframework.web.socket.handler.AbstractWebSocketHandler} 的示例 */ @Bean public WebSocketHandler echoWebSocketHandler(){ return new EchoWebSocketHandler(); }
} |
从上面代码可以看出,这里除了配置了基本的WebSocket
(也就是/echoMessage这个连接地址),还使用SockJS
配置了浏览器不支持WebSocket
技术时的替代方案(也就是/echoMessage_SockJS这个连接地址)。
i)echo.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | <html xmlns:th="http://www.thymeleaf.org"> <head> <meta content="text/html;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>WebSocket Examples: Reverse</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script th:src="@{/layui/layui.js}"></script> <link th:href="@{/layui/css/layui.css}" rel="stylesheet"> <style type="text/css"> #connect-container { margin: 0 auto; width: 400px; }
#connect-container div { padding: 5px; margin: 0 7px 10px 0; }
.layui-btn { display: inline-block; } </style> <script type="text/javascript"> var ws = null;
$(function () { var target = $("#target"); if (window.location.protocol === 'http:') { target.val('ws://' + window.location.host + target.val()); } else { target.val('wss://' + window.location.host + target.val()); } });
function setConnected(connected) { var connect = $("#connect"); var disconnect = $("#disconnect"); var echo = $("#echo");
if (connected) { connect.addClass("layui-btn-disabled"); disconnect.removeClass("layui-btn-disabled"); echo.removeClass("layui-btn-disabled"); } else { connect.removeClass("layui-btn-disabled"); disconnect.addClass("layui-btn-disabled"); echo.addClass("layui-btn-disabled"); }
connect.attr("disabled", connected); disconnect.attr("disabled", !connected); echo.attr("disabled", !connected); }
//连接 function connect() { var target = $("#target").val();
ws = new WebSocket(target); ws.onopen = function () { setConnected(true); log('Info: WebSocket connection opened.'); }; ws.onmessage = function (event) { log('Received: ' + event.data); }; ws.onclose = function () { setConnected(false); log('Info: WebSocket connection closed.'); }; }
//断开连接 function disconnect() { if (ws != null) { ws.close(); ws = null; } setConnected(false); }
//Echo function echo() { if (ws != null) { var message = $("#message").val(); log('Sent: ' + message); ws.send(message); } else { alert('WebSocket connection not established, please connect.'); } }
//日志输出 function log(message) { console.debug(message); } </script> </head> <body> <noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!</h2></noscript> <div> <div id="connect-container" class="layui-elem-field"> <legend>Echo</legend> <div> <input id="target" type="text" class="layui-input" size="40" style="width: 350px" value="/echoMessage"/> </div> <div> <button id="connect" class="layui-btn layui-btn-normal" οnclick="connect();">Connect</button> <button id="disconnect" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="disconnect();">Disconnect </button>
</div> <div> <textarea id="message" class="layui-textarea" placeholder="请输入请求的内容" style="width: 350px"></textarea> </div> <div> <button id="echo" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="echo();">Echo message </button> </div> </div> </div> </body> </html> |
ii)echo_sockjs.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | <html xmlns:th="http://www.thymeleaf.org"> <head> <meta content="text/html;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>WebSocket Examples: Reverse</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.1.4/sockjs.min.js"></script> <script th:src="@{/layui/layui.js}"></script> <link th:href="@{/layui/css/layui.css}" rel="stylesheet"> <style type="text/css"> #connect-container { margin: 0 auto; width: 400px; }
#connect-container div { padding: 5px; margin: 0 7px 10px 0; }
.layui-btn { display: inline-block; } </style> <script type="text/javascript"> var ws = null;
$(function () { var target = $("#target"); if (window.location.protocol === 'http:') { target.val('http://' + window.location.host + target.val()); } else { target.val('https://' + window.location.host + target.val()); } });
function setConnected(connected) { var connect = $("#connect"); var disconnect = $("#disconnect"); var echo = $("#echo");
if (connected) { connect.addClass("layui-btn-disabled"); disconnect.removeClass("layui-btn-disabled"); echo.removeClass("layui-btn-disabled"); } else { connect.removeClass("layui-btn-disabled"); disconnect.addClass("layui-btn-disabled"); echo.addClass("layui-btn-disabled"); }
connect.attr("disabled", connected); disconnect.attr("disabled", !connected); echo.attr("disabled", !connected); }
//连接 function connect() { var target = $("#target").val();
ws = new SockJS(target); ws.onopen = function () { setConnected(true); log('Info: WebSocket connection opened.'); }; ws.onmessage = function (event) { log('Received: ' + event.data); }; ws.onclose = function () { setConnected(false); log('Info: WebSocket connection closed.'); }; }
//断开连接 function disconnect() { if (ws != null) { ws.close(); ws = null; } setConnected(false); }
//Echo function echo() { if (ws != null) { var message = $("#message").val(); log('Sent: ' + message); ws.send(message); } else { alert('WebSocket connection not established, please connect.'); } }
//日志输出 function log(message) { console.debug(message); } </script> </head> <body> <noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!</h2></noscript> <div> <div id="connect-container" class="layui-elem-field"> <legend>Echo With SockJS</legend> <div> <input id="target" type="text" class="layui-input" size="40" style="width: 350px" value="/echoMessage_SockJS"/> </div> <div> <button id="connect" class="layui-btn layui-btn-normal" οnclick="connect();">Connect</button> <button id="disconnect" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="disconnect();">Disconnect </button>
</div> <div> <textarea id="message" class="layui-textarea" placeholder="请输入请求的内容" style="width: 350px"></textarea> </div> <div> <button id="echo" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="echo();">Echo message </button> </div> </div> </div> </body> </html> |
具体效果省略,可自行运行源码查看。
所谓STOMP(Simple Text Oriented Messaging Protocol),就是在WebSocket基础之上提供了一个基于帧的线路格式(frame-based wire format)层。它对发送简单文本消息定义了一套规范格式(STOMP消息基于Text,当然也支持传输二进制数据),目前很多服务端消息队列都已经支持STOMP,比如:RabbitMQ、 ActiveMQ等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package cn.zifangsky.stompwebsocket.config;
import cn.zifangsky.stompwebsocket.interceptor.websocket.MyChannelInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.ChannelRegistration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/** * WebSocket相关配置 * * @author zifangsky * @date 2018/9/30 * @since 1.0.0 */ @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{ @Autowired private MyChannelInterceptor myChannelInterceptor;
@Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/stomp-websocket").withSockJS(); }
@Override public void configureMessageBroker(MessageBrokerRegistry registry) { //客户端需要把消息发送到/message/xxx地址 registry.setApplicationDestinationPrefixes("/message"); //服务端广播消息的路径前缀,客户端需要相应订阅/topic/yyy这个地址的消息 registry.enableSimpleBroker("/topic"); }
@Override public void configureClientInboundChannel(ChannelRegistration registration) { registration.interceptors(myChannelInterceptor); }
} |
从上面代码可以看出,这里设置了好几个地址,简单解释如下:
首先注册了一个名为/stomp-websocket的端点,也就是STOMP客户端连接的地址。
此外,定义了服务端处理WebSocket消息的前缀是/message,这个地址用于客户端向服务端发送消息(比如客户端向/message/hello这个地址发送消息,那么服务端通过@MessageMapping(“/hello”)这个注解来接收并处理消息)
最后,定义了一个简单消息代理,也就是服务端广播消息的路径前缀(比如客户端监听/topic/greeting这个地址,那么服务端就可以通过@SendTo(“/topic/greeting”)这个注解向客户端发送STOMP消息)。
需要注意的是,上面代码中还添加了一个名为MyChannelInterceptor的拦截器,目的是为了在客户端断开连接后打印一下日志。相关代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package cn.zifangsky.stompwebsocket.interceptor.websocket;
import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.simp.stomp.StompCommand; import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.stereotype.Component;
import java.security.Principal; import java.text.MessageFormat;
/** * 自定义{@link org.springframework.messaging.support.ChannelInterceptor},实现断开连接的处理 * * @author zifangsky * @date 2018/10/10 * @since 1.0.0 */ @Component public class MyChannelInterceptor implements ChannelInterceptor{ private final Logger logger = LoggerFactory.getLogger(getClass());
@Override public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) { StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); StompCommand command = accessor.getCommand();
//用户已经断开连接 if(StompCommand.DISCONNECT.equals(command)){ String user = ""; Principal principal = accessor.getUser(); if(principal != null && StringUtils.isNoneBlank(principal.getName())){ user = principal.getName(); }else{ user = accessor.getSessionId(); }
logger.debug(MessageFormat.format("用户{0}的WebSocket连接已经断开", user)); } }
} |
@MessageMapping
注解用于监听指定路径的客户端消息,而@SendTo
注解则用于将服务端的消息发送给监听了该路径的客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package cn.zifangsky.stompwebsocket.controller;
import cn.zifangsky.stompwebsocket.model.websocket.Greeting; import cn.zifangsky.stompwebsocket.model.websocket.HelloMessage; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller;
/** * Greeting * @author zifangsky * @date 2018/9/30 * @since 1.0.0 */ @Controller public class GreetingController {
@MessageMapping("/hello") @SendTo("/topic/greeting") public HelloMessage greeting(Greeting greeting) { return new HelloMessage("Hello," + greeting.getName() + "!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | <html xmlns:th="http://www.thymeleaf.org"> <head> <meta content="text/html;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>WebSocket Examples: Reverse</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.1.4/sockjs.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script> <script th:src="@{/layui/layui.js}"></script> <link th:href="@{/layui/css/layui.css}" rel="stylesheet"> <style type="text/css"> #connect-container { margin: 0 auto; width: 400px; }
#connect-container div { padding: 5px; margin: 0 7px 10px 0; }
.layui-btn { display: inline-block; } </style> <script type="text/javascript"> var stompClient = null;
$(function () { var target = $("#target"); if (window.location.protocol === 'http:') { target.val('http://' + window.location.host + target.val()); } else { target.val('https://' + window.location.host + target.val()); } });
function setConnected(connected) { var connect = $("#connect"); var disconnect = $("#disconnect"); var echo = $("#echo");
if (connected) { connect.addClass("layui-btn-disabled"); disconnect.removeClass("layui-btn-disabled"); echo.removeClass("layui-btn-disabled"); } else { connect.removeClass("layui-btn-disabled"); disconnect.addClass("layui-btn-disabled"); echo.addClass("layui-btn-disabled"); }
connect.attr("disabled", connected); disconnect.attr("disabled", !connected); echo.attr("disabled", !connected); }
//连接 function connect() { var target = $("#target").val();
var ws = new SockJS(target); stompClient = Stomp.over(ws);
stompClient.connect({}, function () { setConnected(true); log('Info: STOMP connection opened.');
//订阅服务端的/topic/greeting地址 stompClient.subscribe("/topic/greeting", function (greeting) { log('Received: ' + JSON.parse(greeting.body).content); }) },function () { //断开处理 setConnected(false); log('Info: STOMP connection closed.'); }); }
//断开连接 function disconnect() { if (stompClient != null) { stompClient.disconnect(); stompClient = null; } setConnected(false); log('Info: STOMP connection closed.'); }
//向服务端发送姓名 function sendName() { if (stompClient != null) { var username = $("#username").val(); log('Sent: ' + username); stompClient.send("/message/hello", {}, JSON.stringify({'name': username})); } else { alert('STOMP connection not established, please connect.'); } }
//日志输出 function log(message) { console.debug(message); } </script> </head> <body> <noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!</h2></noscript> <div> <div id="connect-container" class="layui-elem-field"> <legend>STOMP Message With SockJS</legend> <div> <input id="target" type="text" class="layui-input" size="40" style="width: 350px" value="/stomp-websocket"/> </div> <div> <button id="connect" class="layui-btn layui-btn-normal" οnclick="connect();">Connect</button> <button id="disconnect" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="disconnect();">Disconnect </button>
</div> <div> <input id="username" type="text" class="layui-input" size="40" style="width: 350px" placeholder="请输入你的姓名" value=""/> </div> <div> <button id="echo" class="layui-btn layui-btn-normal layui-btn-disabled" disabled="disabled" οnclick="sendName();">Say hello </button> </div> </div> </div> </body> </html> |
启动项目后访问页面,效果如下:
参考:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。