In the project, you need to view the running log of the frame in the Docker container in real time in the browser, and on the server you can get tail-f execution result InputStream stream by the RESTful interface provided by Docker. The browser HTTP protocol is a request-response protocol, in order to obtain data, you must initiate a request, obviously and the Java InputStream concept is not collaborative, the server can not real-time push log stream to the browser. Using AJAX techniques, you can initiate requests asynchronously at a certain interval of time. When the browser does not initiate AJAX, the server needs to maintain the cache of the log stream, if there are many different pages to view the log, then the need to maintain multiple queues, and another question is if a log page is closed, how to clear the queue cache?
So consider using WebSocket to get the log stream in real time. WebSocket Introduction
WebSocket provides a true browser and a full duplex channel between servers. WebSocket uses HTTP request protocol upgrade headers to make requests, and server-side return 101 indicates successful protocol switching, and the underlying TCP channel stays open. Once the channel is established, the browser side uses send () to send data to the server, through the OnMessage event handler to receive server data, and each time the data is sent, do not need to transmit the HTTP Header again, greatly reducing the amount of data transfer, It is suitable for data exchange between browsers and servers for high frequency and low latency. At the same time the implementation of the real server push data to the browser.
Browser side:
The current mainstream browsers support WebSocket.
Browser |
Supported versions |
Chrome |
Supported in version 4+ |
Firefox |
Supported in version 4+ |
Internet Explorer |
Supported in version 10+ |
Opera |
Supported in version 10+ |
Safari |
Supported in version 5+ |
Service side:
Java EE 7 JSR356 provides support for WebSocket, with Tomcat starting with JSR356 support from version 7.047, and spring starting with the 4.0 version to support WebSocket. Java Implementation Method
There are several ways to use WebSocket at the Spring end
1. How to use Java EE7
2. Using the interface provided by Spring
3. Using the STOMP protocol and Spring MVC
The third way is to see the official documentation for Spring, based on WebSocket, using the simple Text oriented message Protocol (STOMP) protocol: Using WebSocket to build a interact Ive Web application
The Stom protocol, which works on the Socket, is similar to the HTTP protocol and is designed for middleware oriented to text messaging, and is a language-independent protocol in which both client and broker can communicate, regardless of the language in which the protocol is developed.
Introduction to Stom protocol
Here I will focus on how to develop the interface with Spring.
Mainly divided into the following classes, the first is the WebSocket connection before the establishment of the interception class Handshakeinterceptor, similar to the Spring MVC Handlerinteceptor, the second WebSocket processing class, responsible for the lifecycle into Row management, and the third is the configuration class, which maps the websocket request to the corresponding handler class.
**1.handshakeinterceptor
2.WebSocketHandler
3.websocketconfigurer** Dependence
Spring WebSocket relies on the following packages, version 4.0 and above, Tomcat 7.047 above, Java EE 7
<dependency>
<groupId>org.springframework</groupId>
<artifactId> spring-messaging</artifactid>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId> tomcat-embed-websocket</artifactid>
<version>8.0.23</version>
<scope>provided </scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope> Provided</scope>
</dependency>
Handshakeinterceptor
This class is similar to the handlerinteceptor used in Spring MVC to intercept HTTP requests. It has two methods,
Public interface Handshakeinterceptor {
boolean beforehandshake (serverhttprequest request, Serverhttpresponse Response,
Websockethandler Wshandler, map<string, object> attributes) throws Exception;
void Afterhandshake (ServerHTTPRequest request, serverhttpresponse response,
Websockethandler Wshandler, Exception Exception);
}
If Beforehandshake returns false, the WebSocket request is denied connection.
The request can be converted into servletserverhttprequest, and get the packaging of the httpservletrequest to obtain information such as parameter in the HTTP request. Websockethandler
As a WebSocket connection after the establishment of the processing interface, mainly the following methods.
Public interface Websockethandler {
void afterconnectionestablished (Websocketsession session) throws Exception;
void Handlemessage (websocketsession session, websocketmessage<?> message) throws Exception;
void Handletransporterror (websocketsession session, Throwable exception) throws exception;
void Afterconnectionclosed (websocketsession session, Closestatus Closestatus) throws Exception;
Boolean supportspartialmessages ();
}
For each WebSocket connection, the incoming parameter session has a unique ID, obtained by the GetId () method, that can be used to mark the WebSocket connection.
The commonly used classes are Textwebsockethandler and Binarywebsockethandler. These two classes inherit from Abstractwebsockethandler, which, when they receive the message, make judgments about the type of messages and distribute the different types. We need to cover either the Handletextmessage method or the Handlebinarymessage method separately.
public void Handlemessage (websocketsession sessions, websocketmessage<?> message) throws Exception {
if ( Message instanceof TextMessage) {
handletextmessage (sessions, (textmessage) message);
}
else if (message instanceof binarymessage) {
handlebinarymessage (sessions, (binarymessage) message);
}
else if (message instanceof pongmessage) {
handlepongmessage (sessions, (pongmessage) message);
}
else {
throw new IllegalStateException ("Unexpected WebSocket message type:" + message);
}
}
Websocketconfigurer
We have defined the handlershakeinteceptor required for the handshake and the Websockethandler for WebSocket business processing, and we also need to associate the access connection with the corresponding handler and interceptors.
@Configuration
@EnableWebMvc
@EnableWebSocket Public
class Websocketendpoint implements websocketconfigurer {
@Autowired
logwebsockethandler handler;
@Autowired
handlershakerinceptor handlershakerinceptor;
public void Registerwebsockethandlers (Websockethandlerregistry registry) {
Registry.addhandler (handler, "/ Logs.do "). Setallowedorigins (" * "). Addinterceptors (Handlershakerinceptor);
}
@Configuration is the Java class-based configuration of spring, which transforms the spring Bean into a spring configuration.
The equivalent XML configuration is as follows:
<beans xmlns= "Http://www.springframework.org/schema/beans" xmlns:xsi= Www.w3.org/2001/XMLSchema-instance "xmlns:websocket=" Http://www.springframework.org/schema/websocket "XSI:SC hemalocation= "Http://www.springframework.org/schema/beans Http://www.springframework.org/schema/beans/sprin G-beans.xsd Http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/ Spring-websocket.xsd "> <websocket:handlers allowed-origins=" * "> <websocket:mapping path="/log.do " handler= "MyHandler"/> <websocket:handshake-interceptors> <ref bean= "Myhandlershakeinceptor" "/> </websocket:handshake-interceptors> </websocket:handlers> <bean id=" Myhandlershakein Ceptor "class=" Com.haoyifen.myHandlerShakeInceptor "/> <bean id=" MyHandler "class=" Com.haoyifen.myHandler "/ > </beans>
For the setallowedorigins in Java configuration and the Allowed-origins in XML, explain that this is used to set cross-domain, simply that the general browser is forbidden for AJAX and WebSocket to cross domain Request, we need to set up on the server side to allow Web pages on other domains (such as host names or different ports) to connect to your WebSocket. "*" indicates that a Web page request on any domain can be connected, set to a trusted domain name. Client
Application of 1.Chrome Dark WebSocket Terminal
The client class in the 2.java-websocket package
3.JS
$ (document). Ready (function () {
var websocket = new WebSocket (' Ws://localhost:8081/logs.do?path=/web/logs/hadoop /hadoop-hadoop-namenode-vm10244.log ');
Websocket.onmessage = function (event) {
...
};
Websocket.onclose=function (event) {
...
}
Websocket.onerror=function (event) {
...
};
});