spring websocket實現
阿新 • • 發佈:2018-11-20
注:需spring4.0及以上版本。
步驟:
1、匯入jar包(maven方式)
<!-- Spring websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
2、編寫WebSocketConfig類,用於配置websocket
package com.websocket; 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.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{ @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { //允許連線的域;只能以http或https開頭 String[] allowsOrigins = {"https://www.xxx.com"}; //WebIM WebSocket通道 registry.addHandler(WebSocketHandler(), "/websocket").addInterceptors(WebScoketInterceptor()); } @Bean public WebSocketHandler WebSocketHandler() { return WebSocketHandler(); } @Bean public WebScoketInterceptor WebScoketInterceptor() { return new WebScoketInterceptor(); } }
也可用spring的配置檔案:
檔案頭部新增websocket的xsd檔案:
xmlns:websocket="http://www.springframework.org/schema/websocket"
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd
<!-- websocket處理器 --> <bean id="websocket" class="com.websocket.WebSocketHandler"></bean> <websocket:handlers> <websocket:mapping path="/websocket" handler="websocket"></websocket:mapping> <!-- websocket攔截器 --> <websocket:handshake-interceptors> <bean class="com.websocket.WebScoketInterceptor"/> </websocket:handshake-interceptors> </websocket:handlers>
3、編寫WebScoketInterceptor,攔截器的作用是將此連線與使用者對應
package com.websocket;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
public class WebScoketInterceptor implements HandshakeInterceptor{
@Override
public void afterHandshake(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse, WebSocketHandler handler, Exception e) {
}
@Override
public boolean beforeHandshake(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse, WebSocketHandler handler,
Map<String, Object> map) throws Exception {
ServletServerHttpRequest request = (ServletServerHttpRequest) httpRequest;
//獲取httpSession拿到此連結對應的使用者,websocket中可以拿到http協議對應的httpSession
HttpSession session = request.getServletRequest().getSession();
if (session != null) {
map.put("userId", session.getAttribute("userId"));
}
return true;
}
}
4、編寫WebSocketHandler,繼承自AbstractWebSocketHandler,提供了建立連線,關閉連線,連線發生錯誤等回撥方法,用於實現自己的業務邏輯
package com.websocket;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
/**
* websocket處理器
* @author Administrator
*
*/
public class WebSocketHandler extends AbstractWebSocketHandler {
private static final Map<Integer, WebSocketSession> wsUserMap = new HashMap<Integer, WebSocketSession>();
/**
* 處理前端傳送的文字資訊
* @throws IOException
*/
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
Integer userId = getUserIdBySession(session);
System.out.println("收到userId為:" + userId + "的使用者發的訊息" + message.toString());
//給使用者回覆一條訊息
// session.sendMessage(new TextMessage("reply msg:" + message.getPayload()));
}
/**
* 成功建立連線
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Integer userId = getUserIdBySession(session);
wsUserMap.put(userId, session);
super.afterConnectionEstablished(session);
System.out.println("使用者id為" + userId + "的使用者建立連線");
}
/**
* 關閉連線
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
Integer userId = getUserIdBySession(session);
wsUserMap.remove(userId);
super.afterConnectionClosed(session, status);
System.out.println("使用者id為" + userId + "的使用者關閉了連線");
}
/**
* 連線發生錯誤
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
exception.printStackTrace();
Integer userId = getUserIdBySession(session);
wsUserMap.remove(userId);
super.handleTransportError(session, exception);
}
/**
* 給某個使用者傳送訊息
*/
public static boolean sendMessageToUser(Integer userId,Integer toUserId, TextMessage message) {
WebSocketSession tosession = wsUserMap.get(toUserId);
if (tosession != null && tosession.isOpen()) {
try {
tosession.sendMessage(new TextMessage("{" + userId + ":" + message.getPayload()+ "}"));
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
} else {
return false;
}
}
/**
* 給全部使用者傳送訊息
*/
public static void sendMessageToAllUser(TextMessage message) {
Set<Integer> userSet = wsUserMap.keySet();
for (Integer i : userSet) {
WebSocketSession session = wsUserMap.get(i);
if (session != null && !session.isOpen()) {
try {
session.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Integer getUserIdBySession(WebSocketSession session) {
Integer userId = (Integer) session.getAttributes().get("userId");
return userId;
}
}
5、配置SpringWebSocketConfig了配置類隨spring容器啟動,此步驟為使用WebSocketConfig類做配置是使用,用spring配置檔案做websocket的配置時可省略。
<!-- websocket配置掃描 -->
<context:component-scan base-package="com.websocket"/>
6、建立controller,僅簡單測試。
package com.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.socket.TextMessage;
import com.websocket.WebSocketHandler;
@Controller
public class WebSocketController {
//模擬登入
@RequestMapping("login")
public void login(HttpServletRequest request, HttpServletResponse response) {
int userId = Integer.parseInt(request.getParameter("userId"));
HttpSession session = request.getSession();
session.setAttribute("userId", userId);
}
//使用者給另一使用者傳送訊息
@RequestMapping("sendMessageToUser")
public void sendMessageToUser(HttpServletRequest request, HttpServletResponse response) {
int toUserId = Integer.parseInt(request.getParameter("toUserId"));
int userId = Integer.parseInt(request.getParameter("userId"));
CharSequence message = request.getParameter("message");
TextMessage mess = new TextMessage(message);
WebSocketHandler.sendMessageToUser(userId, toUserId, mess);
}
//給當前所有線上使用者傳送訊息
}
7、客戶端程式碼(建立連線部分)
var ws;
function websocketTest() {
ws = new WebSocket("ws://localhost:8080/websocketTest/websocket");
ws.open = function() {
console.log("open");
}
ws.onclose = function() {
console.log("onclose");
}
ws.onmessage = function(evt) {
console.log(evt);
alert(evt.data);
};
}