您好,登錄后才能下訂單哦!
這篇文章給大家介紹SpringMVC中怎么開(kāi)放WebSocket接口,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
1)首先創(chuàng)建websocket專屬的package(規(guī)范問(wèn)題,實(shí)現(xiàn)某一功能的源碼應(yīng)放到統(tǒng)一路徑下)。
2)創(chuàng)建WebSocketConfig類,繼承WebMvcConfigurationSupport類,實(shí)現(xiàn)WebSocketConfigurer接口并實(shí)現(xiàn)其定義的方法。添加類注解
@Configuration
@EnableWebMvc
@EnableWebSocket
3)實(shí)現(xiàn)的registerWebSocketHandlers方法中,使用參數(shù)WebSocketHandlerRegistry的對(duì)象開(kāi)放WebSocket接口。
registry.addHandler(websocket消息處理實(shí)現(xiàn)類實(shí)例,websocket地址).setAllowedOrigins("*").addInterceptors(攔截器實(shí)例);
其中setAllowedOrigins為設(shè)置訪問(wèn)權(quán)限,通常不限制訪問(wèn)時(shí)使用“*”;addInterceptors為添加攔截器,如果不需要攔截器則可不調(diào)用此方法。
通常開(kāi)放WebSocket接口開(kāi)放兩個(gè),因?yàn)g覽器支持的問(wèn)題,前端只能使用SockJS插件實(shí)現(xiàn)WebSocket連接,所以我們還要開(kāi)放一個(gè)專為SockJS服務(wù)的WebSocket接口,只需調(diào)用withSockJS接口即可。
registry.addHandler(websocket消息處理實(shí)現(xiàn)類實(shí)例,websocket地址).setAllowedOrigins("*").addInterceptors(攔截器實(shí)例).withSockJS();
至此,第一步,配置WebSocket信息已完成。
1)創(chuàng)建WebSocket消息處理接口,繼承WebSocketHandler接口(為開(kāi)放操作接口給其他服務(wù)調(diào)用,一般與業(yè)務(wù)相關(guān),服務(wù)端希望推送消息時(shí)調(diào)用此接口,同樣關(guān)乎規(guī)范,亦可使用其他方式實(shí)現(xiàn))。
2)創(chuàng)建WebSocket消息處理實(shí)現(xiàn)類,實(shí)現(xiàn)第一步創(chuàng)建的接口。其中,業(yè)務(wù)接口請(qǐng)自行實(shí)現(xiàn),從WebSocketHandler繼承實(shí)現(xiàn)的接口有:
afterConnectionEstablished:建立WebSocket連接成功時(shí)觸發(fā)。
handleMessage:收到客戶端發(fā)送的消息時(shí)觸發(fā)。
handleTransportError:發(fā)生異常時(shí)觸發(fā)。
afterConnectionClosed:與客戶端斷開(kāi)連接時(shí)觸發(fā)。
supportsPartialMessages:是否支持部分消息處理(一般返回false,此標(biāo)志一般用來(lái)拆分大型或未知大小的WebSocket消息,當(dāng)支持部分消息時(shí),一個(gè)消息會(huì)拆分成多個(gè)消息調(diào)用handleMessage,可以利用WebSocketMessage的isLast方法判斷是否最后一次消息)。
1)創(chuàng)建WebSocket攔截器,實(shí)現(xiàn)HandshakeInterceptor接口。實(shí)現(xiàn)方法有:
beforeHandshake:消息處理前。
afterHandshake:消息處理后。
此處使用配置掃描包的形式,在配置文件中添加<context:component-scan base-package="com.???.???.???.websocket" />
其中base-package可以根據(jù)自己項(xiàng)目的實(shí)際包路徑配置。
下面就是實(shí)例代碼,細(xì)節(jié)處可根據(jù)實(shí)際項(xiàng)目修改:
WebSocket配置信息
package com.???.???.???.websocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowire; 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.WebMvcConfigurationSupport; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; /** * websocket配置類 * * @author Heller.Zhang * @since 2018年11月8日 上午10:23:04 */ @Configuration @EnableWebMvc @EnableWebSocket public class MyWebSocketConfig extends WebMvcConfigurationSupport implements WebSocketConfigurer { private Logger logger = LoggerFactory.getLogger(MyWebSocketConfig.class); /* (non-Javadoc) * @see org.springframework.web.socket.config.annotation.WebSocketConfigurer#registerWebSocketHandlers(org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry) */ @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { logger.debug("----------開(kāi)始注冊(cè)MyWebSocketConfig----------"); logger.debug("----------注冊(cè)普通websocket----------"); registry.addHandler(msgSocketHandle(), "/websocket/myWebSocketServer").setAllowedOrigins("*"); logger.debug("----------注冊(cè)sockjs/websocket----------"); registry.addHandler(msgSocketHandle(), "/websocket/sockjs/myWebSocketServer").setAllowedOrigins("*").withSockJS(); } @Bean(name = "myMsgScoketHandle", autowire = Autowire.BY_NAME) public MyMsgScoketHandle msgSocketHandle() { return new MyMsgScoketHandleImpl(); } }
自定義WebSocket消息處理接口
package com.???.???.???.websocket; import org.springframework.web.socket.WebSocketHandler; /** * websocket消息處理器 * * @author Heller.Zhang * @since 2018年11月13日 下午5:13:20 */ public interface MyMsgScoketHandle extends WebSocketHandler { public void sendMessage(Long userId, Integer num); }
自定義WebSocket消息處理接口實(shí)現(xiàn)
package com.???.???.???.websocket; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; import com.hzsparrow.framework.common.exception.ServiceException; import com.hzsparrow.framework.utils.JsonUtils; import com.hzsparrow.framework.utils.NumberUtils; /** * websocket消息處理類 * * @author Heller.Zhang * @since 2018年11月8日 上午11:15:22 */ public class MyMsgScoketHandleImpl implements MyMsgScoketHandle { private Logger logger = LoggerFactory.getLogger(MyMsgScoketHandleImpl.class); private ConcurrentMap<String, List<WebSocketSession>> webSocketMap = new ConcurrentHashMap<>(); public MyMsgScoketHandleImpl() { logger.debug("--------init MyMsgScoketHandle-----------"); } /* (non-Javadoc) * @see org.springframework.web.socket.WebSocketHandler#afterConnectionEstablished(org.springframework.web.socket.WebSocketSession) */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.debug("-----------建立websocket連接---------"); } /* (non-Javadoc) * @see org.springframework.web.socket.WebSocketHandler#handleMessage(org.springframework.web.socket.WebSocketSession, org.springframework.web.socket.WebSocketMessage) */ @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { logger.debug("-----------處理消息---------"); TextMessage msg = (TextMessage) message; //建立連接發(fā)送的用戶id String msgStr= msg.getPayload(); logger.debug("----------msg:" + msgStr); if (StringUtils.equals(msgStr, "heartbeat")) { // 心跳消息,不予處理 return; } session.getAttributes().put("mykey", msgStr + "|" + UUID.randomUUID().toString()); //通過(guò)用戶id獲取session集合 List<WebSocketSession> list = webSocketMap.get(msgStr); //判斷集合是否為空 if (CollectionUtils.isNotEmpty(list)) { list.add(session); } else { list = new ArrayList<WebSocketSession>(); list.add(session); } //將用戶id和session集合綁定到map webSocketMap.put(msgStr, list); logger.debug("消息處理完畢"); } /* (non-Javadoc) * @see org.springframework.web.socket.WebSocketHandler#handleTransportError(org.springframework.web.socket.WebSocketSession, java.lang.Throwable) */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { logger.debug("-----------處理異常---------"); } /* (non-Javadoc) * @see org.springframework.web.socket.WebSocketHandler#afterConnectionClosed(org.springframework.web.socket.WebSocketSession, org.springframework.web.socket.CloseStatus) */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { logger.debug("-----------斷開(kāi)連接---------"); String myKey = session.getAttributes().get("mykey").toString(); String userId = myKey.split("|")[0]; List<WebSocketSession> list = webSocketMap.get(userId); WebSocketSession delSession = null; if (CollectionUtils.isNotEmpty(list)) { for (WebSocketSession webSocketSession : list) { String delKey = webSocketSession.getAttributes().get("mykey").toString(); if (StringUtils.equals(myKey, delKey)) { delSession = webSocketSession; break; } } } if (delSession != null) { list.remove(delSession); } } /* (non-Javadoc) * @see org.springframework.web.socket.WebSocketHandler#supportsPartialMessages() */ @Override public boolean supportsPartialMessages() { return false; } /** * 給單個(gè)用戶發(fā)送消息 * * @param session * @param type * @param data * @throws IOException * @author Heller.Zhang * @since 2018年11月8日 下午2:05:32 */ public void sendMessage(WebSocketSession session, Object data) throws IOException { if (session.isOpen()) { String json = JsonUtils.serialize(data); TextMessage outMsg = new TextMessage(json); session.sendMessage(outMsg); } } /** * 發(fā)送鏈接成功消息 * * @param session * @throws IOException * @author Heller.Zhang * @since 2018年11月10日 下午3:16:35 */ public void sendSuccessMsg(WebSocketSession session, Integer type) throws IOException { logger.debug("---------發(fā)送鏈接成功消息-----------"); TextMessage outMsg = new TextMessage(""); session.sendMessage(outMsg); } @Override public void sendMessage(Long userId, Integer num) { //獲取用戶下的session集合 List<WebSocketSession> list = webSocketMap.get(NumberUtils.num2Str(userId)); //向每一條session中發(fā)送數(shù)據(jù) if (CollectionUtils.isNotEmpty(list)) { for (WebSocketSession webSocketSession : list) { try { sendMessage(webSocketSession, num); } catch (IOException e) { throw new ServiceException("發(fā)送消息失敗"); } } } } }
攔截器
package com.???.???.???.websocket; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.HandshakeInterceptor; /** * websocket攔截器 * * @author Heller.Zhang * @since 2018年11月8日 上午10:40:51 */ public class MyWebSocketHandshakeInterceptor implements HandshakeInterceptor { private Logger logger = LoggerFactory.getLogger(MyWebSocketHandshakeInterceptor.class); /* (non-Javadoc) * @see org.springframework.web.socket.server.HandshakeInterceptor#beforeHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.util.Map) */ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { logger.debug("---------websocket 攔截器 握手前------------"); return true; } /* (non-Javadoc) * @see org.springframework.web.socket.server.HandshakeInterceptor#afterHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.lang.Exception) */ @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { logger.debug("---------websocket 攔截器 握手后------------"); } }
掃描包配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="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 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <context:component-scan base-package="com.???.???.???.websocket" /> </beans>
關(guān)于SpringMVC中怎么開(kāi)放WebSocket接口就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。