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
- 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;
- 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.
- 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;
- WebSocket clients and servers communicate by using more advanced messaging protocols (e.g
STOMP
) and HTTP based handshake requestsSec-WebSocket-Protocol
The 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