WebSocket+spring example demo (sockJs library has been used)
- 2020-06-01 09:41:36
- OfStack
1, the introduction of
As the next generation of the Web standard, HTML5 has many compelling new features, such as Canvas, local storage, multimedia programming interfaces, WebSocket, and so on. Among them, WebSocket, known as "TCP of Web", attracts developers' attention. The advent of WebSocket makes it possible for browsers to provide support for Socket, providing a two-way channel between the browser and the server based on an TCP connection. Web developers can easily use WebSocket to build real-time web applications, giving them an extra weapon in their hands.
Web application information interaction process is usually the client through the browser sends a request to the server after receive and review the request and returns the result to the client, the client browser will then display information, this mechanism for information change is not particularly frequent application is easy, but for those requiring real-time applications, such as online games, online security, equipment monitoring, news online, RSS subscription push, etc., when the client browser ready to present this information, the information on the server side may have already out of date.
Therefore, keeping the information on the client side and the server side synchronized is a key element of real-time Web application, which is also a challenge for Web developers. Before the WebSocket specification came out, developers who wanted to implement these real-time Web applications had to adopt a number of tradeoffs, among which the most commonly used were polling (Polling) and Comet technologies. Comet technology is actually an improvement on polling technology, which can be subdivided into two implementations, one is a long polling mechanism, and one is called flow technology.
Html5 WebSocket is designed to replace polling and Comet technologies, giving the client browser the ability to communicate in real time like C/S desktops. The browser sends a request to the server via JavaScript to establish an WebSocket connection. Once the connection is established, the client and server can exchange data directly via the TCP connection. Because an WebSocket connection is essentially an TCP connection, it has a significant performance advantage over polling and Comet technologies in terms of data transmission stability and the amount of data transferred.
However, because web socket has high requirements for browsers, to solve this problem, sockJS was launched. SockJS is a library of JavaScript that provides API across javascript, creating a communication channel between a low-latency, full-duplex browser and web server.
2. Related environmental requirements
Spring4.0.6 (select 4.0+), tomcat7.0.55, JDK1.7.
3. Specific code
(the following code is available!)
(1) web. xml:
<?xmlversionxmlversion="1.0"encoding="UTF-8"?>
<web-app version="3.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<description> Used to test WebSocket Push based functionality </description>
<distributable/>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring The refresh Introspector Prevent memory leaks -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>testSocket.jsp</welcome-file>
</welcome-file-list>
</web-app>
(2) dispatcher-servlet.xml
<?xmlversionxmlversion="1.0"encoding="UTF-8"?>
<beans:beansxmlnsbeans:beansxmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<annotation-driven/>
<!-- Automatically scanned package name -->
<context:component-scanbase-packagecontext:component-scanbase-package="zyy.sockjs.config"></context:component-scan>
</beans:beans>
(3)HandshakeInterceptor.java
package zyy.sockjs.config;
import java.util.Map;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
@Component
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("Before Handshake");
return super.beforeHandshake(request,response,wsHandler,attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("After Handshake");
super.afterHandshake(request,response,wsHandler,ex);
}
}
(4)InfoSocketEndPoint.Java
package zyy.sockjs.config;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
@Component
public class InfoSocketEndPoint extends TextWebSocketHandler {
public InfoSocketEndPoint() {
}
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
super.handleTextMessage(session, message);
TextMessage returnMessage = new TextMessage(message.getPayload()
+ " received at server");
session.sendMessage(returnMessage);
}
}
(5)SystemWebSocketHandler.java
package zyy.sockjs.config;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
*
* @author dayu
*/
@Component
public class SystemWebSocketHandler implements WebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("connect to the websocket success......");
session.sendMessage(new TextMessage("Server:connected OK!"));
}
@Override
public void handleMessage(WebSocketSession wss, WebSocketMessage<?> wsm) throws Exception {
TextMessage returnMessage = new TextMessage(wsm.getPayload()
+ " received at server");
wss.sendMessage(returnMessage);
}
@Override
public void handleTransportError(WebSocketSession wss, Throwable thrwbl) throws Exception {
if(wss.isOpen()){
wss.close();
}
System.out.println("websocket connection closed......");
}
@Override
public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception {
System.out.println("websocket connection closed......");
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
(6)WebSocketConfig.java
package zyy.sockjs.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements
WebSocketConfigurer {
public WebSocketConfig() {
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(systemWebSocketHandler(), "/websck").addInterceptors(new HandshakeInterceptor());
System.out.println("registed!");
registry.addHandler(systemWebSocketHandler(), "/sockjs/websck/info").addInterceptors(new HandshakeInterceptor())
.withSockJS();
}
@Bean
public WebSocketHandler systemWebSocketHandler() {
return new SystemWebSocketHandler();
}
}
(7)testSocket.jsp
<%@ page language="java"contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE htmlPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"content="text/html; charset=ISO-8859-1">
<title>WebSocket/SockJS Echo Sample (Adapted from Tomcat's echo sample)</title>
<style type="text/css">
#connect-container {
float: left;
width: 400px
}
#connect-container div {
padding: 5px;
}
#console-container {
float: left;
margin-left: 15px;
width: 400px;
}
#console {
border:1px solid #CCCCCC;
border-right-color:#33333333;
border-bottom-color:#999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}
#console p {
padding: 0;
margin: 0;
}
</style>
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script type="text/javascript">
var ws = null;
var url = null;
var transports = [];
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('echo').disabled = !connected;
}
function connect() {
if (!url) {
log('Select whether to use W3C WebSocket or SockJS');
return;
}
//ws = (url.indexOf('sockjs') != -1) ?new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url);
if ('WebSocket'in window) {
ws= new WebSocket("ws://localhost:8080/SpringSocketJs/websck");
}else {
ws = new SockJS("http://localhost:8080/SpringSocketJs/sockjs/websck/info");
}
//websocket = new SockJS("http://localhost:8084/SpringWebSocketPush/sockjs/websck");
ws.onopen = function () {
setConnected(true);
//log('Info: connection opened.');
};
ws.onmessage = function (event) {
log('Received: ' + event.data);
};
ws.onclose = function (event) {
setConnected(false);
log('Info: connection closed.');
log(event);
};
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function echo() {
if (ws != null) {
var message = document.getElementById('message').value;
log('Sent: ' + message);
ws.send(message);
} else {
alert('connection not established, please connect.');
}
}
function updateUrl(urlPath) {
if (urlPath.indexOf('sockjs') != -1) {
url = urlPath;
document.getElementById('sockJsTransportSelect').style.visibility ='visible';
}
else {
if (window.location.protocol =='http:') {
url = 'ws://' + window.location.host + urlPath;
} else {
url = 'wss://' + window.location.host + urlPath;
}
document.getElementById('sockJsTransportSelect').style.visibility ='hidden';
}
}
function updateTransport(transport) {
transports = (transport == 'all') ? [] : [transport];
}
function log(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
</script>
</head>
<body>
<noscript><h2 style="color:#ff0000">Seems your browser doesn't supportJavascript!Websockets
rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<div id="connect-container">
<input id="radio1"type="radio"name="group1"onclick="updateUrl('/SpringSocketJs/websocket');">
<label for="radio1">W3C WebSocket</label>
<br>
<input id="radio2"type="radio"name="group1"onclick="updateUrl('/SpringSocketJs/sockjs/websocket');">
<label for="radio2">SockJS</label>
<div id="sockJsTransportSelect" style="visibility:hidden;">
SockJS transport:
<select onchange="updateTransport(this.value)">
<option value="all">all</option>
<option value="websocket">websocket</option>
<option value="xhr-polling">xhr-polling</option>
<option value="jsonp-polling">jsonp-polling</option>
<option value="xhr-streaming">xhr-streaming</option>
<option value="iframe-eventsource">iframe-eventsource</option>
<option value="iframe-htmlfile">iframe-htmlfile</option>
</select>
</div>
<div>
<button id="connect"onclick="connect();">Connect</button>
<button id="disconnect"disabled="disabled"onclick="disconnect();">Disconnect</button>
</div>
<div>
<textarea id="message"style="width:350px">Here is a message!</textarea>
</div>
<div>
<button id="echo"onclick="echo();"disabled="disabled">Echo message</button>
</div>
</div>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>
</html>