最近,在做项目的时候需要用到Websocket,做到报表的实时更新。在说websocket之前,我们可以先来了解下,websocket到底是个什么东西。
websocket是一种在单个TCP连接上进行全双工通信的协议.
什么是全双工通信,就是说客户端和服务端建立连接之后,可以同时发送消息或者接收消息,如图所示:
至于为什么要用到Websocket,那么就得从项目出发,需求是要做到页面报表的实时更新。假如使用ajax不断的轮询,去请求服务器,是可以达到实时更新的效果,但是这样的弊端是服务器资源消耗过大。但是websocket就不一样,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
客户端代码:
var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8080/websocket"); } else { alert('当前浏览器 Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function() { console.log(("WebSocket连接发生错误"));; }; //连接成功建立的回调方法 websocket.onopen = function() { console.log(("WebSocket连接成功"));; } //接收到消息的回调方法,这里是将数据进行返回的方法 websocket.onmessage = function(event) { console.log((event.data)); } //连接关闭的回调方法 websocket.onclose = function() { console.log(("WebSocket连接关闭"));; } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function() { closeWebSocket(); } //关闭WebSocket连接 function closeWebSocket() { websocket.close(); }
服务端代码:
这里我们使用的框架是使用springboot框架,那么在使用websocket的使用就需要在pom文件添加websocket所对应的依赖,
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
添加完依赖之后,我们就必须要添加配置一个websocket配置处理器,注册所对应的websocket服务:
@Configuration @EnableWebMvc @EnableWebSocket public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer { private final Logger logger = LoggerFactory.getLogger(WebSocketConfig.class); /** * 后台写好服务,项目启动的时候,注册好这两个服务,以供前台调用 */ @Resource private MyWebSocketHandler handler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { // 链接的时候,websocket会自己增加同源检测的功能,需要单独配置是否允许跨域 registry.addHandler(handler, "/websocket").setAllowedOrigins("*"); registry.addHandler(handler, "/websocket/sockjs").setAllowedOrigins("*").withSockJS(); } }
@EnableWebSocket注解:开启websocket
@EnableWebMvc注解 :启用spring mvc的基于java config的配置
@Configuration :用于定义配置类
最后我们在通过配置websocket处理器:
@Component public class MyWebSocketHandler implements WebSocketHandler { private final Logger logger = LoggerFactory.getLogger(MyWebSocketHandler.class); /** * 先注册一个websocket服务器,将连接上的所有用户放进去 */ public static final List<WebSocketSession> users; static { users = new ArrayList<WebSocketSession>(); } /** * 连接已建立 */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { users.add(session); //这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户 //TextMessage returnMessage = new TextMessage("你将收到的离线"); //session.sendMessage(returnMessage); } @Override public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception { } /** * 异常处理 */ @Override public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception { if(session.isOpen()) session.close(); users.remove(session); } /** * 连接已关闭 */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { users.remove(session); } @Override public boolean supportsPartialMessages() { return false; }
}
至此websocket整体集成完成,但是途中出了一些小问题,就是当配置集成好websocket之后,把项目跑起来,结果发现websocket连接失败,抛了一个responsed 404的异常,出现这个问题是因为websocket处理器没有创建,也就是项目启动的时候没有将MyWebSocketHandler创建出来,结果我把包路径给扩大,再将项目跑起来,结果问题就解决了。还有一种情况404是前端的地址给服务器提供给前端注册的地址不一致,也会出现404这种异常。