Spring integration WebSocket application sample of

  • 2020-05-07 19:51:51
  • OfStack

The following tutorial is a collation of information on one of the company's crm systems that the site is involved in developing. Below this site collation share to this site platform for your reference

1. maven relies on


<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>

2. spring-servlet configuration


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd">
......
<!-- websocket -->
<bean id="websocket" class="cn.bridgeli.websocket.WebsocketEndPoint"/>
<websocket:handlers>
<websocket:mapping path="/websocket" handler="websocket"/>
<websocket:handshake-interceptors>
<bean class="cn.bridgeli.websocket.HandshakeInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
</beans>

Where, the corresponding path of path is the interface path of the previous segment through ws protocol

3. Implementation of HandshakeInterceptor


package cn.bridgeli.websocket;
import cn.bridgeli.utils.UserManager;
import cn.bridgeli.util.DateUtil;
import cn.bridgeli.sharesession.UserInfo;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.util.Date;
import java.util.Map;
/**
* @Description : Create handshake ( handshake ) interface 
* @Date : 16-3-3
*/
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{
private static final Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
logger.info(" Before establishing the handshake ...");
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
UserInfo currUser = UserManager.getSessionUser(attrs.getRequest());
UserSocketVo userSocketVo = new UserSocketVo();
String email= "";
if(null != currUser){
email = currUser.getEmail();
}
if(StringUtils.isBlank(email)){
email = DateUtil.date2String(new Date());
}
userSocketVo.setUserEmail(email);
attributes.put("SESSION_USER", userSocketVo);
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
logger.info(" After establishing the handshake ...");
super.afterHandshake(request, response, wsHandler, ex);
}
}

Because the old husband is not very understanding, so the maximum extent of the original code to retain, which is actually from the single sign-on to take the current login user, into UserSocketVo object, into Map. So let's look at the definition of the UserSocketVo object

4. Definition of UserSocketVo


package cn.bridgeli.websocket;
import org.springframework.web.socket.WebSocketSession;
import java.util.Date;
/**
* @Description :  The user socket Connect the entity 
* @Date : 16-3-7
*/
public class UserSocketVo {
private String userEmail; // User mailbox 
private Date connectionTime; // Successful connection time 
private Date preRequestTime; // Last request time 
private Date newRequestTime; // New request time 
private Date lastSendTime = new Date(); // The takedown is recent 1 Secondary time 
private Date lastTaskSendTime = new Date(); // The pending task is closest 1 Secondary time 
private WebSocketSession webSocketSession; // User corresponding wsSession  Default cache only 1 a 
// getXX and setXX 
}

The most important of these is the WebSocketSession property, which we'll use later

5. implementation of WebsocketEndPoint


package cn.bridgeli.websocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
/**
* @Description : websocket Processing class 
* @Date : 16-3-3
*/
public class WebsocketEndPoint extends TextWebSocketHandler{
private static final Logger logger = LoggerFactory.getLogger(WebsocketEndPoint.class);
@Autowired
private NewsListenerImpl newsListener;
@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);
}
/**
* @Description : Once the connection is established 
* @param session
* @throws Exception
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception{
UserSocketVo userSocketVo = (UserSocketVo)session.getAttributes().get("SESSION_USER");
if(null != userSocketVo){
userSocketVo.setWebSocketSession(session);
if(WSSessionLocalCache.exists(userSocketVo.getUserEmail())){
WSSessionLocalCache.remove(userSocketVo.getUserEmail());
}
WSSessionLocalCache.put(userSocketVo.getUserEmail(), userSocketVo);
newsListener.afterConnectionEstablished(userSocketVo.getUserEmail());
}
logger.info("socket Successful connection establishment ...");
super.afterConnectionEstablished(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session,CloseStatus status) throws Exception{
UserSocketVo userSocketVo = (UserSocketVo)session.getAttributes().get("SESSION_USER");
if(null != userSocketVo){
WSSessionLocalCache.remove(userSocketVo.getUserEmail());
}
logger.info("socket Connection closed successfully ...");
super.afterConnectionClosed(session, status);
}
}

6. WSSessionLocalCache implementation


package cn.bridgeli.websocket;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description : The local cache WebSocketSession The instance 
* @Date : 16-3-7
*/
public class WSSessionLocalCache implements Serializable {
private static Map<String, UserSocketVo> wsSessionCache = new HashMap<>();
public static boolean exists(String userEmail){
if(!wsSessionCache.containsKey(userEmail)){
return false;
}else{
return true;
}
}
public static void put(String userEmail, UserSocketVo UserSocketVo){
wsSessionCache.put(userEmail, UserSocketVo);
}
public static UserSocketVo get(String userEmail){
return wsSessionCache.get(userEmail);
}
public static void remove(String userEmail){
wsSessionCache.remove(userEmail);
}
public static List<UserSocketVo> getAllSessions(){
return new ArrayList<>(wsSessionCache.values());
}
}

See its implementation, the role is more obvious, store the latest data of each UserSocketVo, in fact, here we have finished the implementation of websocket, but there is still a core class (about business logic Charlie's class) is not implemented, the next Spring integration WebSocket application example (below), we will see how to implement this class.

WebSocket protocol introduces

The WebSocket protocol is an important feature of the RFC-6455 specification in one of the Web areas: full duplex, or two-way communication between the client and the server. It's an exciting feature that the industry has been exploring for a long time, using technologies such as Java Applet, XMLHttpRequest, Adobe Flash, ActiveXObject, various Comet technologies, server-side send events, and more.

One thing to understand is that the HTTP protocol needs to be used to build the initial handshake before using the WebSocket protocol. This relies on one mechanism - HTTP setup, request protocol upgrade (or protocol conversion). When the server agrees, it responds with the HTTP status code 101, indicating that it agrees to the switch protocol. Assuming a successful handshake over the TCP socket and an HTTP protocol upgrade request, both the client and server sides can send messages to each other.

A new module, spring-websocket, has been introduced in Spring framework 4.0 or above. It provides support for WebSocket communications. It is compatible with Java WebSocket API specification JSR-356, while providing additional functionality.

When should WebSocket be used

In Web applications, WebSocket is appropriate when the client and server sides need to exchange events at a higher frequency and lower latency. Therefore, WebSocket is suitable for financial, gaming, collaboration and other application scenarios.
It may not be suitable for other application scenarios. For example, if a news subscription needs to display breaking news, it is possible to use long polling intervals of several minutes, where latency is acceptable.
Even in application scenarios that require low latency, if the number of messages being transmitted is low (such as scenarios that monitor network failures), then you should consider using long polling techniques.

The WebSocket protocol is only suitable for low latency and high frequency message communication. Even in this application scenario, there is still the choice of WebSocket communication? Or is it REST HTTP?
The answer depends on the requirements of the application. However, it is also possible to use both techniques to implement data that needs to be exchanged frequently in WebSocket and REST API as the implementation technology for procedural business. In addition, when an REST API call needs to broadcast a message to multiple clients, it can also be done through an WebSocket connection.

The Spring framework provides the @Controller annotation and the @RestController annotation, both of which can be used for processing HTTP requests and WebSocket messages. In addition, the request handling method of Spring MVC, or that of other applications, can easily use the WebSocket protocol to broadcast messages to all interested clients or specified users.


Related articles: