Dowemo

Spring boot provides a few default configuratio for websocket, simplifying websocket, and we'll use spring boot websocket and add stomp and sockjs support to quickly write a simple page chat room that enables broadcast message push and private message push.

Limit the code below only to code, requiring html page code or project full source code to here to see ( using idea import directly ).

Basic page:

To close the server, the client automatically reconnect:

No reconnect after the number of retries:

The project is written into server and client, so it's also divided into two aspects.

Service

Because of the default configuration of spring boot, it greatly simplifies development, and there are only two places to write on the server side: Configuring classes and controlle.

Of course, you need to introduce dependencies first ( using a gradle as a package management tool )


compile('org.springframework.boot:spring-boot-starter-web')


compile('org.springframework.boot:spring-boot-starter-websocket')






Writing configuration classes

Next is the configuration class WebSocketConfig for websocket, the explanation of the configuration entry


@Configuration


@EnableWebSocketMessageBroker


public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {


 @Override


 public void configureMessageBroker(MessageBrokerRegistry registry) {


 registry.enableSimpleBroker("/topic", "/user");//"/topic" 用于给客户端订阅广播信息,"/user"用于给客户端订阅点对点消息



 //registry.setApplicationDestinationPrefixes("/app");//客户端向服务器发送消息时 URL 为:【/app + controller中 @MessageMapping 的地址】,此处暂时不使用该配置


 //registry.setUserDestinationPrefix("/user/");//客户端向指定用户发送(一对一)信息时 URL 前缀是"/user/",即使不配置默认也是"/user/"


 }


 @Override


 public void registerStompEndpoints(StompEndpointRegistry registry) {


 registry.addEndpoint("/endpoint").withSockJS();//注册客户端websocket连接的端口


 }


}






Write controller


@Controller


public class WebsocketController {


 /**


 * 广播推送


 * @param text


 * @param sessionId


 * @return


 * @throws Exception


 */


 @MessageMapping(value = "/chat")


 @SendTo("/topic/getResponse")


 public String talk(@Payload String text, @Header("simpSessionId") String sessionId) throws Exception {


 return "【" + sessionId + "】说:【" + text + "】";


 }


 /**


 * 点对点推送


 * @param text


 * @param sessionId


 * @return


 * @throws Exception


 */


 @MessageMapping(value = "/speak")


 @SendToUser(value = "/personal")


 public String speak(@Payload String text, @Header("simpSessionId") String sessionId) throws Exception {


 return text;


 }


 /**


 * 异常信息推送


 * @param exception


 * @return


 */


 @MessageExceptionHandler


 @SendToUser(value = "/errors")


 public String handleException(Throwable exception) {


 return exception.getMessage();


 }


}






Here are some notes that you need to speak:
- method annotation
- @ MessageMapping ( value ="/url") matches the url of the client send message;
- @ sendto and @ sendToUser are used to subscribe to the and messages for the client;
- parameter annotation
- @ payload: assignment using the body of the frame;
- @ header ("xxx"): Assign a value to xxx in the headers of the frame;

As you can see the data, you can see that you can also use SimpMessagingTemplate for message forwarding, which can be understood:


@MessageMapping("/chat") 


public void chat(String value){


 this.simpMessagingTemplate.convertAndSend("/topic/getResponse", value); 


}






Equivalent


@MessageMapping("/chat")


@SendTo("/topic/getResponse")


public String chat(String value) {


 return value;


}






Client

A client 's code is primarily a series of operations for websocket using javascript, because you need to use the stomp api, so you can refer to the to summarize the.

Basic operations are as follows


var socket = new SockJS('/endpoint');


stompClient = Stomp.over(socket);


stompClient.connect(


 {}, 


 function connectCallback (frame) {...}, 


 function errorCallBack (error) {...}


);






message push


//获取 socket 连接的sessionId,即从 socket._transport.url 中使用正则截取


var sessionId = //([^/]+)/websocket/.exec(socket._transport.url)[1];


console.log("connected, session id:" + sessionId);


......


//订阅私人消息


var subscription_personal = stompClient.subscribe('/user/' + sessionId + '/personal', function callBack (response) {


 if (response.body) {


 printToScreen("【私人消息】" + response.body);


 } else {


 printToScreen("收到一个空消息");


 }


}


......


//发送消息


stompClient.send("/speak", headers, JSON.stringify(body));









Broadcast message push


......


//订阅广播消息


var subscription_broadcast = stompClient.subscribe('/topic/getResponse', function callBack (response) {


 if (response.body) {


 printToScreen("【广播】" + response.body);


 } else {


 printToScreen("收到一个空消息");


 }


});


......


//发送广播消息


stompClient.send("/chat", headers, JSON.stringify(body));









Exception message push


//获取 websocket 连接的 sessionId


var sessionId = //([^/]+)/websocket/.exec(socket._transport.url)[1];


//订阅异常消息


var subscription_errors = stompClient.subscribe('/user/' + sessionId + '/errors', function callBack (response) {


 if (response.body) {


 printToScreen("【异常消息】" + response.body);


 } else {


 printToScreen("收到一个空消息");


 }


});










Automatic reconnect mechanism

Use javascript to set mechanism, automatically after disconnecting with the server, and reconnect to 10 no longer reconnect


function errorCallBack (error) {


 document.getElementById("state-info").innerHTML = "连接断开";


 console.log('连接断开【' + error + '】');



 if (curTryNum <= maxTryNum) {


 document.getElementById("state-info").innerHTML = "连接关闭,10秒后重新连接......";


 console.log("连接关闭,10秒后重新连接......");



 // 10秒后重新连接,实际效果:每10秒重连一次,直到连接成功


 setTimeout(function () {


 connect();


 }, 10000);


 } else {


 document.getElementById("state-info").innerHTML = "连接关闭,且已超过最大重连次数,不再重连";


 console.log("连接关闭,且已超过最大重连次数,不再重连");


 }


}









Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs