程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Spring整合WebSocket運用示例(上)

Spring整合WebSocket運用示例(上)

編輯:關於JAVA

Spring整合WebSocket運用示例(上)。本站提示廣大學習愛好者:(Spring整合WebSocket運用示例(上))文章只能為提供參考,不一定能成為您想要的結果。以下是Spring整合WebSocket運用示例(上)正文


以下教程是小編在介入開辟公司的一個crm體系,整頓些相干材料,在該體系中有許多新聞推送功效,在個中用到了websocket技巧。上面小編整頓分享到平台供年夜家參考

1. maven依附

<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的設置裝備擺設

<?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>

個中,path對應的途徑就是前段經由過程ws協定調的接口途徑

3. 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 :創立握手(handshake)接口
* @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("樹立握手前...");
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("樹立握手後...");
super.afterHandshake(request, response, wsHandler, ex);
}
}

由於老漢不是很懂,所以最年夜限制的保存原代碼,這其實就是從單點登錄中掏出以後登錄用戶,轉成UserSocketVo對象,放到Map中。所以接上去我們看看UserSocketVo對象的界說

4. UserSocketVo的界說

package cn.bridgeli.websocket;
import org.springframework.web.socket.WebSocketSession;
import java.util.Date;
/**
* @Description : 用戶socket銜接實體
* @Date : 16-3-7
*/
public class UserSocketVo {
private String userEmail; //用戶郵箱
private Date connectionTime; //勝利銜接時光
private Date preRequestTime; //前次要求時光
private Date newRequestTime; //新要求時光
private Date lastSendTime = new Date(); //下架新聞比來一次發送時光
private Date lastTaskSendTime = new Date(); //待處置義務比來一次發送時光
private WebSocketSession webSocketSession; //用戶對應的wsSession 默許僅緩存一個
// getXX and setXX 
}

個中最主要的就是這個WebSocketSession這個屬性了,前面我們要用到

5. 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處置類
* @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 : 樹立銜接後
* @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勝利樹立銜接...");
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勝利封閉銜接...");
super.afterConnectionClosed(session, status);
}
}

6. WSSessionLocalCache的完成

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 :當地緩存WebSocketSession實例
* @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());
}
}

看了其完成,感化就比擬顯著了吧,寄存每一個UserSocketVo的最新數據,其實到這裡我們websocket的完成曾經算完了,但還有一個焦點類(關於營業邏輯查理的類)沒有完成,下篇Spring整合WebSocket運用示例(下),我們就看怎樣完成這個類。

WebSocket協定引見

WebSocket協定是RFC-6455標准界說的一個Web范疇的主要的功效:全雙工,即客戶端和辦事器之間的雙向通訊。它是一個使人高興的功效,業界在此范疇上曾經摸索良久,應用的技巧包含Java Applet、XMLHttpRequest、Adobe Flash、ActiveXObject、各類Comet技巧、辦事器真個發送事宜等。

須要懂得一點,在應用WebSocket協定前,須要先應用HTTP協定用於構建最後的握手。這依附於一個機制——樹立HTTP,要求協定進級(或叫協定轉換)。當辦事器贊成後,它會呼應HTTP狀況碼101,表現贊成切換協定。假定經由過程TCP套接字勝利握手,HTTP協定進級要求經由過程,那末客戶端和辦事器端都可以彼此互發新聞。

Spring框架4.0以上版本引入了一個新模塊,即spring-websocket模塊。它對WebSocket通訊供給了支撐。它兼容Java WebSocket API標准JSR-356,同時供給了額定的功效。

甚麼場景下該應用WebSocket

在Web運用中,客戶端和辦事器端須要以較高頻率和較低延遲來交流事宜時,合適用WebSocket。是以WebSocket合適財經、游戲、協作等運用場景。
關於其他運用場景則未必合適。例如,某個消息定閱須要顯示突發消息,應用距離幾分鐘的長輪詢也是可以的,這裡的延遲可以接收。
即便在請求低延遲的運用場景,假如傳輸的新聞數很低(好比監測收集毛病的場景),那末應當斟酌應用長輪詢技巧。

而只要在低延遲和高頻新聞通訊的場景下,選用WebSocket協定才長短常合適的。即便是如許的運用場景,依然存在是選擇WebSocket通訊呢?又或許是選擇REST HTTP通訊呢?
謎底是會依據運用法式的需求而定。然則,也能夠同時應用這兩種技巧,把須要頻仍交流的數據放到WebSocket中完成,而把REST API作為進程性的營業的完成技巧。別的,當REST API的挪用中須要把某個信息播送給多個客戶端是,也能夠經由過程WebSocket銜接來完成。

Spring框架供給了@Controller正文和@RestController正文,二者都可以用於HTTP要求的處置和WebSocket新聞的處置。別的,Spring MVC的要求處置辦法,或其它運用法式的要求處置辦法,都可以很輕易地應用WebSocket協定來播送新聞到一切感興致的客戶端或指定用戶。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved