This is the third day of my participation in the More text Challenge. For details, see more text Challenge

This article is participating in the “Java Theme Month – Java Development in action”. See the link to the event for more details

[TOC]

In the previous section, we looked at the pros and cons of WebSocket. We analyzed webSocket versus HTTP and summarized the scenarios using WebSocket. Today xiaobian takes you through an example to use the next version of webSocket.

Sockjs introduction

SockJs is a browser library that provides a cross-browser API that establishes a low-latency, full-duplex, cross-domain communication channel between the browser and the server.

Cause of occurrence

Browsers such as Internet Explorer may lack webSocket support; our last chapter was developed in Google Chrome. Internet Explorer is not tested here, but some older browsers do not support Websocket. SockJs is very compatible with browsers. Optimized on top of the original WebSocket. Sockjs implements two-way communication by polling in browsers that do not support WebSocket.

Environment set up

Integrate springboot sockjs

Springboot supports SOckJS very well. Just add sockJS mode publishing to the existing WebSocket configuration. As in the previous WebSocket section we need to add configuration to sockJS. WithSockJS is all you need to turn on sockjs support. We can also add interceptors to authenticate access. We can then publish the channel on the specified path


@Configuration
// The annotations enable the use of STOMP to transport Message Broker based messages. The controller supports @Messagemapping as well as @RequestMapping
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer   {


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {// Register the STOMP node (endpoint) and map the specified URL
        // Register a STOMP endpoint and specify that the SockJS protocol is used
        registry.addEndpoint("/endpointAric")
                .setAllowedOrigins("*")
                .addInterceptors(createSessionInterceptor())
                .withSockJS();

    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {// Configure Message Broker
        // Broadcast should be configured with a /topic message broker
        registry.enableSimpleBroker("/topic"."/queue");
        //registry.setApplicationDestinationPrefixes("/app");
        // The subscription prefix used by the point-to-point (as shown in the client subscription path). If not set, the default is /user/
        registry.setUserDestinationPrefix("/user/");

    }

    /** * Configure the client inbound channel interceptor */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.setInterceptors(createUserInterceptor());

    }


    @Bean
    public HandshakeInterceptor createSessionInterceptor(a){
        return new SessionAuthHandshakeInterceptor();
    }
    /* Add client channel interceptors to spring IOC container */
    @Bean
    public UserInterceptor createUserInterceptor(a) {
        return new UserInterceptor();
    }


    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration.setMessageSizeLimit(500 * 1024 * 1024);
        registration.setSendBufferSizeLimit(1024 * 1024 * 1024);
        registration.setSendTimeLimit(200000); }}Copy the code

registry.enableSimpleBroker(“/topic”, “/queue”); The queue is the communication channel between the client and the server.

Usage scenarios

In this section, we’ll try using WebSocket in a chat room.

Chat room development

Above we have configured the environment on the server side so that we can develop the communication content within the channel. The chat room uses WebSocket to communicate, which solves the real time of our Ajax calls. The accuracy of the message is guaranteed. No delay.

The benefit of sockJs is that it is encapsulated by SpringBoot one layer later! We develop webSocket channels just as easily as we develop interfaces. We only need messageMapping annotations to complete our data reception. The rest of the client work is the same as the previous set of work logic only needs to respond to the use of SockJS to communicate.

Point-to-point communication

/* Point-to-point communication */ @messagemapping (value = "/sendToUser") public void templateTest1(@payload String message, @Header("userId") String userId, @Headers Map<String, Object> headers) { int i = 1; For (SimpUser user: userregistry.getusers ()) {system.out.println (" user "+ i++ + "--" + user); } CustomUser userInfo = (CustomUser) ((Map)(headers.get("simpSessionAttributes"))).get(CoreConstants.USERINFO); String fromUserId = String.valueOf(userInfo.getUserId()); / / send a message to the specified user messagingTemplate. ConvertAndSendToUser (userId, "/queue/message",new AricResponse(fromUserId,userId,message)); if (! Fromuserid.equals (userId)) {// send one to yourself, Message synchronization messagingTemplate. ConvertAndSendToUser (fromUserId, "/ queue/message," new AricResponse (fromUserId, userId, message)); } / / message new messageService. InsertBackMessage (fromUserId, userId, message); }Copy the code

@messagemapping (value = “sendToUser”) This annotation implements the acceptance of client requests. Send (“/sendToUser”, {‘userId’: userId},content); UserId is the ID sent by the client user to the specified user. Content is the content sent. The server receives the information sent by the front-end through the @payload and @header annotations. Why do you write that in the above code where you get the sender user ID? Now let’s look at how the client connects

Socket = new SockJS(host+"/endpointAric"); // Obtain the client object of STOMP subprotocol stompClient = stomp.over (socket); // obtain the client object of STOMP subprotocol stompClient = stomp.over (socket); // Initiates a webSocket connection to the server and sends the CONNECT frame stompClient.connect({userId: Currentuser.userid}, function connectCallback(frame) {subscribe(); Console. log(" Connection successful "); }, function errorCallBack(error) {// Callback method console.log(" connection failed "+error); if (errorTimes < 10) { errorTimes++; setTimeout("connect();" , 8000); }});Copy the code

The client passes in the id of the current user when connecting, and this explains why the server gets the user information that way. It is then sent to the specified user via /queue/message. Because we have been specified in the configuration of websocket registry. SetUserDestinationPrefix (“/user/”); So the server sends a message to /queue/message, and the client subscribing to it needs to add a user, which is /user/queue/message

function subscribe() { stompClient.subscribe('/user/queue/message', function (response) { var returnData = JSON.parse(response.body); If (returnData.fromuserid == returnData.touserid) {setMessageInnerHTML(currentUser.userid, returnData, 0); } else if (returnData.fromuserid == currentUser.userid) { SetMessageInnerHTML (ReturnData.touserID, returnData, 1); } else {// the message sent by others setMessageInnerHTML(returnData.fromuserid, returnData, 0); }}); }Copy the code

Group chat

/** * Multi-room chat room * @param chatRoomId * @param Message * @return */ @messagemapping ("/welcome/{chatRoomId}") // When the browser sends a request to the server, map /welcome the address via @messagemapping, similar to @responsemapping @sendto ("/topic/getResponse/{chatRoomId}") public AricResponse Say (@header ("userId")) String userId,@DestinationVariable("chatRoomId") String chatRoomId, AricMessage) {try {Thread. Sleep (1000); } catch (InterruptedException e) { e.printStackTrace(); } return new AricResponse(userId,null,"welcome," + message.getName()+chatRoomId + "!" ); }Copy the code

Group chat is much easier than single chat. When we send messages, we only need to send them to the room channel. People in the group chat only need to subscribe to the room number information. I won’t go over the code here. If you have any questions, you can find me by joining the team below.

The effect

conclusion

Sockjs is compatible with various browsers on the basis of WebSocket, which makes our development friendly. If you are using Java as a Server and happen to use the Spring Framework as a Framework, then SockJS is recommended because Spring Framework itself is the Java Server implementation recommended by SockJS. A Java client implementation is also provided.

If you are using Node.js as a server, then you should definitely choose socket. IO, which starts with Node.js, and of course the server provides an engine. io-server-Java implementation. You can even use it