A WebScoketS profile

RFC 6455, or webSockets protocol, provides a standardized way to establish full-duplex, two-way communication channels between clients and servers, even over a single TCP connection. WebSockets protocol, which is different from HTTP’s TCP protocol, but designed to work over HTTP, can use ports 40 or 443 and reuse existing firewall rules;

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080
Copy the code

WebSockets interaction starts with the HTTP protocol, using the Upgrade header to use the Upgrade connection; If the non-200 status succeeds, the response looks like the following; If WebSocket Server is running on Nginx, WebSocket Upgrade Requests need to be configured. If it is running on a cloud, check whether the cloud supports WebSocket.

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp
Copy the code

HTTP vs. WebSocket

  1. In HTTP and REST an application needs a lot of URLs; Applications and clients interact with these URLs in a request and response style; The server routes these requests to http-based urls or methods or headers for processing;
  2. WebSockets are usually initialized with a single link, and all application messages flow over the same TCP connection; This points to a completely different asynchronous, event-driven messaging architecture.
  3. WebSocket is a low-end protocol that, unlike HTTP, does not specify any semantic information in the content of a message; This means that there is no way to route or process this information unless the client and server agree semantically;
  4. WebSocket clients and servers communicate by using more advanced messaging protocols (e.gSTOMP) and HTTP based handshake requestsSec-WebSocket-ProtocolThe header.

Three Points for attention

WebSockets can make Web pages dynamic and interactive. However, in many cases, Ajax and HTTP streaming or long Polling (polling) can provide a simple and effective solution. HTTP stream and polling are suitable for infrequent message interactions, WebSockets are suitable for frequent message interactions; On the Internet, with no Upgrade header or free long links closed, your limited proxy may rule out WebSockets interactions;

Websocket configuration and dependencies

4.1 depend on

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> </parent> <dependencies> <! Websocket dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>Copy the code

4.2 configuration

/** * @author LSC * @description <p> WebSocket configuration class </p> * @date 2019/11/12 22:27 */ // Use STOMP protocol to transmit message broker based messages, Controller support @ Controller class using the @ MessageMapping @ EnableWebSocketMessageBroker @ Configurable @ EnableWebSocket @ Component to the public class WebConfig implements WebSocketMessageBrokerConfigurer { @Override public void RegisterStompEndpoints (StompEndpointRegistry registry) {// registerStompEndpoints and map the specified url registry.addendpoint ("/websocket")
                .setAllowedOrigins("*"// Add.withsockjs () to allow cross-domain access; Override public void configureMessageBroker(MessageBrokerRegistry registry) { Only conform to the path of the just send messages registry. EnableSimpleBroker ("/topic"); }}Copy the code

Five entity class

5.1 Accept message Entities

/** * @author LSC * @description <p> @date 2019/11/12 22:42 */ public class AcceptMessages {private String name; public StringgetName() {
        returnname; }}Copy the code

5.2 Sending Message Entities

/** * @author LSC * @description <p> * @date 2019/11/12 22:42 */ public class SendMessages {private String  responseMessage; public StringgetResponseMessage() {
        return responseMessage;
    }

    public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; }}Copy the code

Six controller

/** * @author * @description <p> WebSockets </p> * @date 2019/11/12 22:49 */ @controller public class WebSocketsController { @MessageMapping("/welcome"RequestMapping @sendto (@requestMapping)"/topic/getResponse"Public SendMessages broadcast(AcceptMessages AcceptMessages){ System.out.println(acceptMessages.getName()); SendMessages sendMessages = new SendMessages(); sendMessages.setResponseMessage("Knowledge Seeker :"+acceptMessages.getName());
        returnsendMessages; }}Copy the code

Vii Front Page

Create a templates directory under the resource directory to store WebSockets. HTML. Create a static directory under the resource directory. Create a js directory under its sub-directory to store sockjs.min.js, stomp.min.js, jquery-3.3.1.min.js.

<! DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/> <title> Springboot Broadcast WebSocket</title> </head> <body onload="disconnect()">
<noscript><h2 style="color: #ffff0000;">Sorry,not support the WebSocket</h2></noscript>
<div>
    <div>
        <button id="connect" onclick="connect();"</button> <button id="disconnect" disabled="disabled" onclick="disconnect();"</button> </div> <div id="conversationDiv"<label> Enter your name </label> <inputtype="text" id="name"/>
        <button id="sendName" onclick="sendName();"> send </button> <p id="response"></p>
    </div>
</div>
<script th:src="@{js/sockjs.min.js}"></script>
<script th:src="@{js/stomp.min.js}"></script>
<script th:src="@ {js/jquery - 3.3.1. Min. Js}"></script>
<script type="text/javascript"> var stompClient = null; // Set up the connectionfunction setConnected(connected) {
        document.getElementById("connect").disabled = connected;
        document.getElementById("disconnect").disabled = ! connected; document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden';
        $("#response").html(); } / / connectionfunction connect() {// The endpoint is websocket var socket = new SockJS('/websocket'); // Use ssocket protocol stompClient = stomp.over (socket); / / connect stompClient. Connect ({},function (frame) {
            setConnected(true);
            console.log('Connected:'+ frame); // in @sendto define a path to subscribe messages to the target stompClient.subscribe('/topic/getResponse'.function(response) { showResponse(JSON.parse(response.body).responseMessage); })}); }function disconnect() {
        if(stompClient ! = null) { stompClient.disconnect(); }setConnected(false);
        console.log('Disconnected');
    }
    function sendName() {
        var name = $('#name').val(); // Controller @messagemapping defines sending a message to the destination stompClient.send("/welcome", {}, JSON.stringify({'name': name}));
    }
    function showResponse(message) {
        $("#response").html(message);
    }
</script>
</body>
</html>
Copy the code

Eight-view forwarding

When the client request address is localhost:8080/ws, the springMVC view forwarder goes to WebSockets.

/** * @author LSC * @description <p> </p> * @date 2019/11/12 23:35 */ @component public works without any additional information class WebMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry Registry) {/ / forward registry configuration view. AddViewController ("/ws").setViewName("/WebSockets"); }}Copy the code

Nine rendering

That is, one browser sends a message, other connected browsers can also receive the message, that is, broadcast form;

X References

Reference 1: JavaEE development disruptor reference 2: spring-web source code: youku1327