springboot two implementations of integrated websocket

Differences, advantages and disadvantages with conventional http WebSocket protocol described here is probably

A, websocket and http 

http protocol is used in the application layer protocol, he is based on the tcp protocol, the http protocol to establish a link must have a three-way handshake to send a message. http links into short links, long link, the link is a short three-way handshake each request to send their information. That is, each corresponding to a request response. Long link link is maintained within a certain period of time. Continue to keep the TCP connection open. The client communicates with the server, the client must be initiated by server then returns the result. The client is active, the server is passive. 
HTML5 WebSocket is in agreement, he is to address the client to initiate multiple http requests to the server resources browser must go through a long period of problems in rotation born, he realized multiplexing, he is a full-duplex communication. Customer and end the browser may transmit information simultaneously at webSocket protocol.

Second, long-lasting connection is connected to an HTTP websocket

HTTP1.1 default long link connection (persistent connection),

That remains linked within a certain time limit, the client needs to request a large amount of resources to the server in a short time, continue to keep the TCP connection open. The client communicates with the server, the client must be initiated by server then returns the result. The client is active, the server is passive.

  On a TCP connection can transmit multiple Request / Response messages, so in essence still Request / Response messages will still be a waste of resources, real-time performance is not strong and other issues.

If not persistent connections that short connection, each resource must establish a new connection, HTTP is used by the underlying TCP, every time you use three-way handshake to establish a TCP connection, that is, each request corresponds to a response, will result in a great waste of resources.

  Long polling, i.e., the client sends a long timeout Request, the connection server hold live, Response returned when new data arrives

Websocket just create a persistent connection of a Request / Response messages, after all TCP connection, avoiding the redundancy of the header information generated many times as necessary to establish Request / Response messages.

Websocket HTTP handshake only once, so that the entire communication process is based on a connection / state, and the server can be achieved websocket the initiative to contact the client, which is http impossible.

springboot integration of different implementations websocket:

pom add dependencies


<dependency>
<the groupId> org.springframework.boot </ the groupId>
<the artifactId> Starter-Spring-Boot-WebSocket </ the artifactId>
</ dependency>
 involving js connected to the server, so it wrote the corresponding html, where integrated under thymeleaf template, before and after separation of the front end of the project this one is all to do


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置文件:

server:
port: 8885

#添加Thymeleaf配置
thymeleaf:
cache: false
prefix: classpath:/templates/
suffix: .html
mode: HTML5
encoding: UTF-8
content-type: text/html
 

1: Custom WebSocketServer, websocket method using the underlying, provide the corresponding onOpen, onClose, onMessage, onError method

1.1: Adding webSocketConfig configuration class

/ **
* Open support WebSocket
* the Created by huiyunfei ON 2019/5/31.
* /
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter () {
return new new ServerEndpointExporter ();
}
}
1.2: Add the server class webSocketServer

com.example.admin.web Package;

/ **
. * 2019/5/31 the Created by huiyunfei ON
* /

@ServerEndpoint ( "/ WebSocket / {SID}")
@Component
@ SLF4J
public class WebSocketServer {
// static variable, used to record the current number of open connections. It should be designed to be thread-safe.
static int = 0 onlineCount Private;
// Concurrent security thread package Set, MyWebSocket used to store the object corresponding to each client.
static CopyOnWriteArraySet Private <WebSocketServer> webSocketSet new new CopyOnWriteArraySet = <WebSocketServer> ();

// with the connection session to a client, the client needs to send its data via
Private the Session the session;

// received SID
Private SID String = "";


* /
/ **
* connect to establish a successful method called // * *
@OnOpen
public void onOpen (the Session the session, @PathParam ( "sid") String sid) {
the session = this.session;
webSocketSet.add (the this); // set to join in
addOnlineCount (); // Online plus 1
log.info ( "new window starts listening to:" + sid + ", the current line number is" + getOnlineCount ());
this.sid = SID;
the try {
the sendMessage ( "connection successful");
} the catch (IOException E) {
log.error ( "WebSocket the IO exception");
}
}
* /
/ **
* call connection is closed methods
* // *
@OnClose
public void onClose () {
webSocketSet.remove (the this); // delete from the set in
subOnlineCount (); // online minus 1
log.info ( "there is a close connection to the current number of online! "+ getOnlineCount ());
}
* /
/ **
* method the client calls received after the end of message
*
message * @param message is sent by the client // * *
@OnMessage
void the onMessage public (String Message, the Session the session) {
log.info ( "Information:" "receive from the window" Message + + + SID);
// group message
for (WebSocketServer Item: webSocketSet) {
the try {
item.sendMessage ( Message);
} the catch (IOException E) {
e.printStackTrace ();
}
}
}
* /
/ **
*
* @param the session
* @param error
* // *
@OnError
public void the onError (the Session the session, the Throwable error) {
log.error ( "error");
error.printStackTrace ();
}
* /
/ **
* push server actively implement
* * //
public void the sendMessage (String Message) throws IOException {
this.session.getBasicRemote () sendText, (Message);.
}
* /
/ **
* Bulk custom message
* * * //
public static void sendInfo (String Message, @ PathParam ( "SID") String SID) throws IOException {
log.info ( "push message to the window" + sid + ", push content:" + message);
for (WebSocketServer Item: webSocketSet) {
the try {
// set here can only push the sid to the null to push all the
IF (SID == null) {
item.sendMessage (Message);
} the else IF (item.sid.equals (SID)) {
item.sendMessage (Message);
}
} the catch (IOException E) {
Continue;
}
}
}
public int getOnlineCount the synchronized static () {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
return webSocketSet;
}
}
1.3:添加对应的controller























Result return;
}
 1.4: providing page socket1.html

<! DOCTYPE HTML>
<HTML lang = "EN">
<head>
<Meta charset = "UTF-. 8"> </ Meta>
<title> the Title </ title>
</ head>
<body>
Hello World!

</ body>
<Script>
var Socket;
IF (typeof (WebSocket) == "undefined") {
the console.log ( "your browser does not support WebSocket");
} {the else
the console.log ( "your browser supports WebSocket ");
// WebSocket achieve the object of specifying a server address to be connected to the port to establish a connection
// equivalent
index = new new WebSocket (" WS: // localhost: 8885 / WebSocket / 2 ");
// new new Socket = WebSocket ( "$ {basePath the WebSocket} / $ {cid}" the replace ( "HTTP", "WS").);
// open the event
index.= function OnOpen () {
the console.log ( "the Socket open");
//socket.send ( "This is a message from the client" + location.href + new Date () );
};
// get the message event
index.onmessage = function (MSG) {
the console.log (msg.data);
// start processing a discovery message into the front end of the trigger logic
};
// Close event
index.onclose = function () {
Console .log ( "Socket closed");
};
// error occurred event
index.onerror = function () {
Alert ( "the Socket error has occurred");
// At this point you can try to refresh the page
}
// when leaving the page , Close Socket
//jquery1.8 has been discarded, has been removed in 3.0
// $ (window) .unload (function () {
// the Socket.close ();
//});
}
</ Script>
< / html>
 summary:

Browser to access the debug localhost: 8885 / system / index / 1 Jump to socket1.html, js connected to the server and automatically transmitted to the server cid, push message server to the client corresponding to the page (cid distinguish between different requests, in server there are provided methods inputted message)

2.1: WebSocket protocol based STOMP

The advantage of using STOMP is that it is entirely a messaging queue mode, you can use the idea of ​​producers and consumers to recognize it, to send a message of producers, consumers receive messages. Consumers can subscribe to a different destination, to get a different push messages, developers do not need to manage these subscriptions previous relationship with the push destination, spring's official website there is a simple spring-boot of stomp-demo, if it is based springboot, you can try to write a simple demo based on spring tutorial above.

 

Provide websocketConfig configuration class

/ **
* @Description:
registerStompEndpoints (StompEndpointRegistry Registry)
configureMessageBroker (MessageBrokerRegistry config)
effect of this method is to define the message broker, the various popular thing about specification information is provided in the connection request message.
registry.enableSimpleBroker ( "/ topic") means that the client subscription address prefix information, that is, the client receives an address prefix information service end message (comparative around, read the entire example, probably will be able to understand)
registry.setApplicationDestinationPrefixes ( "/ app") refers to the prefix server receives the address prefix meaning that the client to the server message address
* @author: [email protected]
* @date: 2019/5/31
* /
@ the Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig the extends AbstractWebSocketMessageBrokerConfigurer {

// effect of this method is to add a service endpoint, connected to the receiving client.
// registry.addEndpoint ( "/ socket") represents adds a / socket endpoint, the client can connect through this endpoint.
// withSockJS () role is to open SockJS support,
@Override
public void registerStompEndpoints (StompEndpointRegistry Registry) {
registry.addEndpoint ( "/ Socket") withSockJS ();.
}
@Override
public void configureMessageBroker (MessageBrokerRegistry Registry) {
// prefix indicates subscription address information of the client, i.e. the client receiving the address prefix information server message
registry.enableSimpleBroker ( "/ Topic");
// prefix as the service means receives address, meaning that the client message to a server address
registry.setApplicationDestinationPrefixes ( "/ app ");
}
}
 2.2: Controller provides an interface corresponding to the request

// page request
@GetMapping ( "/ SOCKET2")
public ModelAndView SOCKET2 () {// String @ PathVariable the userId
ModelAndView new new ModelAndView MAV = ( "HTML / SOCKET2");
//mav.addObject("userId ", the userId);
MAV return;
}

/ **
* @Description: this method is sent by a client request power WebSocket announcement, using @MessageMapping
* @author: [email protected]
* @date: 2019/5/31
* /
@MessageMapping ( "/ Change-Notice") // client config server configured to receive a prefix when accessing the server should also add examples: / App / Change Notice-
@SendTo ( "/ Topic / Notice") / / config subscribe prefix configured remember to add
public CUSTOMMESSAGE the Greeting (CUSTOMMESSAGE the message) {
System.out.println ( "server receives the message:" + message.toString ());
// we use this method message forwarding sent!
//this.simpMessagingTemplate.convertAndSend("/topic/notice ", value); (may regularly send a message to the client using a timer)
// @Scheduled (FIXEDDELAY = 1000L)
// public void Time () {
// messagingTemplate .convertAndSend ( "/ System / Time", new new a Date () toString ().);
//}
// may be transmitted using a sendTo
return Message;
}
2.3: providing socket2.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Spring Boot+WebSocket+广播式</title>

</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">貌似你的浏览器不支持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>
<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.2.1.min.js}"></script>
<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';
$('#response').html();
}

function connect() {
var socket = new SockJS('/socket'); //1
stompClient = Stomp.over(socket);//2
stompClient.connect({}, function(frame) {//3
setConnected(true);
console.log('开始进行连接Connected: ' + frame);
stompClient.subscribe('/topic/notice', function(respnose){ //4
showResponse(JSON.parse(respnose.body).responseMessage);
});
});
}


function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}

function sendName() {
var name = $('#name').val();
stompClient.send("/app/change-notice", {}, JSON.stringify({ 'name': name }));//5
}

function showResponse(message) {
var response = $("#response");
response.html(message);
}
</script>
</body>
</ HTML>
2.4: corresponding reference can go online download js

2.5: browser to access the debug localhost: 8885 / system / socket2, click connection to the server, the data content may be pushed to the message server and the server is pushed back.

2.6: Implement rotational training front-end and server can page Ajax in rotation can also add back-end timer

@Component
@EnableScheduling
public class TimeTask {
Private static Logger Logger = LoggerFactory.getLogger (TimeTask.class);

@Scheduled (cron = "? 0/20 * * * *")
public void the Test () {
System.err.println ( "********* scheduled task execution **************");
CopyOnWriteArraySet <WebSocketServer> webSocketSet =
WebSocketServer.getWebSocketSet ();
int I = 0;
webSocketSet.forEach (C -> {
the try {
c.sendMessage ( "sending" + new new a Date () toLocaleString ());.
} the catch (IOException E) {
e.printStackTrace ();
}
});

System.err.println ( " / n the timing task completion ....... ");
}
}
code https://github.com/huiyunfei/spring-cloud.The project in git admin

Push broadcast mode and ad hoc mode STOMP protocol message may be based on reference:
https://www.cnblogs.com/hhhshct/p/8849449.html

https://www.cnblogs.com/jmcui/p/8999998.html
----------------
Disclaimer: This article is CSDN original blogger "not Touxing mao" in article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
Original link: https: //blog.csdn.net/huiyunfei/article/details/90719351

Guess you like

Origin www.cnblogs.com/Jeremy2001/p/11525082.html