今天使用springboot的websocket是发现其中有许多细节问题,所以决定记录下来,希望下次使用能够借鉴这次的心得体会,这里就不在描述什么是websocket了,对了随便提一句,websocket是http长连接在http1.1提出的。http是应用层的协议
服务端依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
|
加入以上依赖即可
服务端配置
关于websocket的配置
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
| @Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("webSocketServer") //这里指明父地址
.setAllowedOrigins("*") //允许所有源访问
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// super.configureMessageBroker(registry);
// 以下说明若不理解 请保留疑问,继续往下阅读
// 订阅名称 注意这里参数表示客户端订阅的地址前缀,
registry.enableSimpleBroker("/user1","/topic");
// 全局使用消息前缀 客户端发送消息前缀
registry.setApplicationDestinationPrefixes("/app");
// 点对点使用的订阅前缀 不设置默认为 /user 该字符一定要在订阅名称中出现
registry.setUserDestinationPrefix("/user1");
}
|
创建消息对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class ClientMessage {
private String msg;
public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; }
}
|
编写controller
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
| @Controller
public class WebSocketController {
//这里为广播模式 类似消息群发
@MessageMapping("/sendTest") //请求路径
@SendTo("/topic/sub1") //表示返回消息到订阅了该url的所有客户端
public ServiceMessage send(ClientMessage client){
System.out.println("接收到的消息" + client.getMsg());
return new ServiceMessage("我收的你发的" + client.getMsg());
}
@Autowired private SimpMessagingTemplate simpMessagingTemplate; //用于服务器主动发送消息 //这里为单点模式 类似于私聊 @MessageMapping("/dan") // 发送的订阅路径为/user1/{userId}/{message}这里的user1是不是有点熟悉呢 请参考关于websocket的配置 // /user/路径是默认的一个,如果想要改变,必须在config 中setUserDestinationPrefix public void dan(ClientMessage msg){ System.out.println("你要发送到哪里呢" + msg.getMsg()); // 下面三个参数依次为 {userId},{message},与发送数据 simpMessagingTemplate.convertAndSendToUser("123456","/message",msg.getMsg()); }
}
|
客户端
客户端一
实现了广播发送与私信发送
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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
| <html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>广播式WebSocket</title>
<script type="text/javascript" src="js/jquery-1.9.1.js"></script>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.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"/> <button id="sendName" onclick="sendName();">发送</button> <button id="sendName" onclick="sendName1();">1对1 发送</button> <p id="response"></p> </div>
</div>
<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';
// $("#connect").disabled = connected;
// $("#disconnect").disabled = !connected;
$("#response").html();
}
//-----------------------------------华丽分割线--------------------------------------
function connect() {
//注意到这里的webSocketServer了吗 这里的就是在关于websocket的配置 中进行的配置 前面是进入项目地址
var socket = new SockJS('http://127.0.0.1:8080/springboot/webSocketServer');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected:' + frame);
//注意到下面的/topic/sub1 该url与@SendTo("/topic/sub")中的相同表示 订阅了这一url 即加入 //群聊
stompClient.subscribe('/topic/sub1', function (response) {
//response.body 返回字符串
showResponse(JSON.parse(response.body).msg);
})
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log('Disconnected');
}
//发送群发消息
function sendName() {
var name = $('#name').val();
console.log('name:' + name);
// /app/sendTest 这里的app为所有发送消息前缀 在关于websocket的配置中配置
// sendTest则为@MessageMapping("/sendTest")
stompClient.send("/app/sendTest", {}, JSON.stringify({'msg': name}));
}
//发送私聊消息
function sendName1() {
var name = $('#name').val();
console.log('name:' + name);
//同上
stompClient.send("/app/dan", {}, JSON.stringify({'msg': name}));
}
function showResponse(message) {
$("#response").html(message);
}
</script>
</body>
</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
|
function connect() { var socket = new SockJS('http://127.0.0.1:8080/springboot/webSocketServer'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected:' + frame); stompClient.subscribe('/topic/sub1', function (response) { showResponse(JSON.parse(response.body).msg); }); // 主要是这里 // 这里实现了自己独有的url订阅路径 user1在哪里设置呢 我相信你们应该知道了 // 123456则表示uerId, message表示{message} // 结合控制器的写法 我相信应该可以明白的 stompClient.subscribe('/user1/123456/message', function (response) { showResponse(response.body); }) }, function errorCallBack(error) { // 连接失败时(服务器响应 ERROR 帧)的回调方法 alert("连接失败"); } ); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log('Disconnected'); } function sendName() { var name = $('#name').val(); console.log('name:' + name); stompClient.send("/app/sendTest", {}, JSON.stringify({'msg': name})); } function showResponse(message) { $("#response").html(message); }
|
这里加入了连接中断的处理