前言:
近日,项目开发中需要用到客户端扫码登录,第一时间想到了几种方案:
- Ajax轮询
- 长连接
- WebSocket
后端:
第一步:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
第二步:编写WebSocket配置类
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册一个 stomp 终端(这个路径待会js里面会用到)
// 如果需要跨域,在addEndpoint后面调用 setAllowedOrigins("*")
registry.addEndpoint("/myEndpoint").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 注册多个(参数是可变参数)服务端接收消息前缀(这个路径待会js里面也会用到)
registry.setApplicationDestinationPrefixes("/receiver");
// 注册多个(参数是可变参数)服务端发送消息前缀(这个路径待会js里面会结合实现类路径用到)
registry.enableSimpleBroker("/queueSender", "/topicSender");
}
}
第三步:编写消息接收/发送实现类
@Slf4j
@Controller
public class WebSocketTestController {
/**
* 收到消息并推送给 发送人
*
* @param message 浏览器端发送的参数
* @return 浏览器端接收的内容
*/
@MessageMapping("/testQueueSend")
@SendToUser("/queueSender/queueSend")
public String testReceiveAndQueueSend(String message) {
log.debug("{} 收到消息: {}", "testReceiveAndQueueSend", message);
return "收到了消息" + message + ",并且发送给了发送人";
}
/**
* 收到消息并推送给 所有人
*
* @param message 浏览器端发送的参数
* @return 浏览器端接收的内容
*/
@MessageMapping("/testTopicSend")
@SendTo("/topicSender/topicSend")
public String testReceiveAndTopicSend(String message) {
log.debug("{} 收到消息: {}", "testReceiveAndTopicSend", message);
return "收到了消息" + message + ",并且发送给了所有人";
}
}
前端:
第一步及最后一步:ctrl+c, ctrl+v,请看代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>WebSocket测试</title>
<script src="http://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="http://code.jquery.com/jquery-3.3.1.min.js"></script><!-- 请注意IE浏览器兼容性 -->
</head>
<body>
<input id="input_queue_send" type="text" placeholder="输入消息进行发送"/>
<button οnclick="queueSend()">发送(将收到一对一消息)</button>
<br/>
<input id="input_topic_send" type="text" placeholder="输入消息进行发送"/>
<button οnclick="topicSend()">发送(将收到广播消息)</button>
<br/>
<button οnclick="unSubscription()">取消消息订阅</button>
<button οnclick="disconnectWebSocket()">关闭连接</button>
<br/>
<hr/>
<div id="message_box">
</div>
<script type="application/javascript">
// 定义一个sock连接(并没有进行连接),url和服务端定义的stomp终端是一致的
var _sockJS = new SockJS("/myEndpoint");
// 创建一个客户端对象
var _stompClient = Stomp.over(_sockJS);
// 连接服务端(参数依次为 header,success,error)
_stompClient.connect({}, function () {
printLog("WebSocket已连接!");
// 订阅服务端发送的消息,用于接收消息
doSubscribeQueue();
}, function () {
printLog("WebSocket连接失败!")
});
// 订阅消息对象,用于关闭订阅
var _subscribeQueue, _subscribeTopic;
// 参数依次为 订阅地址,收到消息做什么,header
function doSubscribeQueue() {
// 一对一消息(注意url前面需要加上/user)
_subscribeQueue = _stompClient.subscribe("/user/queueSender/queueSend", function (data) {
printLog("收到 一对一消息 " + data.body);
}, {});
printLog("已订阅 一对一消息");
// 广播消息
_subscribeTopic = _stompClient.subscribe("/topicSender/topicSend", function (data) {
printLog("收到 广播消息 :" + data.body);
}, {});
printLog("已订阅 广播消息");
}
// 断开WebSocket连接
function disconnectWebSocket() {
if (_stompClient != null) {
_stompClient.disconnect();
printLog("WebSocket连接已断开!")
}
}
// 取消订阅消息
function unSubscription() {
if (_subscribeQueue) {
_subscribeQueue.unsubscribe();
}
if (_subscribeTopic) {
_subscribeTopic.unsubscribe();
}
printLog("取消订阅消息");
}
// 向服务器发送消息(服务器将发送给发送者)
function queueSend() {
var message = $("#input_queue_send").val();
// 参数依次为 发送地址,header,消息
_stompClient.send("/receiver/testQueueSend", {}, message);
printLog("发送 一对一消息 " + message);
}
// 向服务器发送消息(服务器将广播给所有客户端)
function topicSend() {
var message = $("#input_topic_send").val();
// 参数依次为 发送地址,header,消息
_stompClient.send("/receiver/testTopicSend", {}, message);
printLog("发送 广播消息 " + message);
}
function printLog(log) {
console.log(log);
$("#message_box").append("<div>" + log + "</div>");
}
</script>
</body>
</html>
好了,文章到此结束,快去试下吧!