这篇文章给大家介绍SpringMVC中怎么开放WebSocket接口,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
1)首先创建websocket专属的package(规范问题,实现某一功能的源码应放到统一路径下)。
2)创建WebSocketConfig类,继承WebMvcConfigurationSupport类,实现WebSocketConfigurer接口并实现其定义的方法。添加类注解
@Configuration
@EnableWebMvc
@EnableWebSocket
3)实现的registerWebSocketHandlers方法中,使用参数WebSocketHandlerRegistry的对象开放WebSocket接口。
registry.addHandler(websocket消息处理实现类实例,websocket地址).setAllowedOrigins("*").addInterceptors(拦截器实例);
其中setAllowedOrigins为设置访问权限,通常不限制访问时使用“*”;addInterceptors为添加拦截器,如果不需要拦截器则可不调用此方法。
通常开放WebSocket接口开放两个,因浏览器支持的问题,前端只能使用SockJS插件实现WebSocket连接,所以我们还要开放一个专为SockJS服务的WebSocket接口,只需调用withSockJS接口即可。
registry.addHandler(websocket消息处理实现类实例,websocket地址).setAllowedOrigins("*").addInterceptors(拦截器实例).withSockJS();
至此,第一步,配置WebSocket信息已完成。
1)创建WebSocket消息处理接口,继承WebSocketHandler接口(为开放操作接口给其他服务调用,一般与业务相关,服务端希望推送消息时调用此接口,同样关乎规范,亦可使用其他方式实现)。
2)创建WebSocket消息处理实现类,实现第一步创建的接口。其中,业务接口请自行实现,从WebSocketHandler继承实现的接口有:
afterConnectionEstablished:建立WebSocket连接成功时触发。
handleMessage:收到客户端发送的消息时触发。
handleTransportError:发生异常时触发。
afterConnectionClosed:与客户端断开连接时触发。
supportsPartialMessages:是否支持部分消息处理(一般返回false,此标志一般用来拆分大型或未知大小的WebSocket消息,当支持部分消息时,一个消息会拆分成多个消息调用handleMessage,可以利用WebSocketMessage的isLast方法判断是否最后一次消息)。
1)创建WebSocket拦截器,实现HandshakeInterceptor接口。实现方法有:
beforeHandshake:消息处理前。
afterHandshake:消息处理后。
此处使用配置扫描包的形式,在配置文件中添加<context:component-scan base-package="com.???.???.???.websocket" />
其中base-package可以根据自己项目的实际包路径配置。
下面就是实例代码,细节处可根据实际项目修改:
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("----------开始注册MyWebSocketConfig----------"); logger.debug("----------注册普通websocket----------"); registry.addHandler(msgSocketHandle(), "/websocket/myWebSocketServer").setAllowedOrigins("*"); logger.debug("----------注册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消息处理接口实现
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; //建立连接发送的用户id String msgStr= msg.getPayload(); logger.debug("----------msg:" + msgStr); if (StringUtils.equals(msgStr, "heartbeat")) { // 心跳消息,不予处理 return; } session.getAttributes().put("mykey", msgStr + "|" + UUID.randomUUID().toString()); //通过用户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("-----------断开连接---------"); 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; } /** * 给单个用户发送消息 * * @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); } } /** * 发送链接成功消息 * * @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("---------发送链接成功消息-----------"); 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中发送数据 if (CollectionUtils.isNotEmpty(list)) { for (WebSocketSession webSocketSession : list) { try { sendMessage(webSocketSession, num); } catch (IOException e) { throw new ServiceException("发送消息失败"); } } } } }
拦截器
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>
关于SpringMVC中怎么开放WebSocket接口就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。