赞
踩
在实现尝试实现的过程中,观察和遇到了这样几个问题。第一个问题是基于jsr-356标准的websocket实现与spring整合的问题,如果不解决这个问题就会导致在websocket的接口里无法自动组装(@Autowired)在spring context里的Bean。第二个问题是当用户离开当前页面时,普通浏览器会立即断开当前页发起的websocket链接,而在微信中的网页不会。在微信中websocket长连接会一直保持链接,直至用户锁屏,或再次发起另一个websocket握手请求时,上一个连接才会断开。这样的现象导致我们不得不在服务端实现心跳检测来侦测用户是否真的离开了目标页面。
OK, SHOW ME THE CODE!
- /**
- *
- * websocket heart break endpoint
- * client side viewing-time count
- *
- * @author zhiheng
- *
- */
-
- @ServerEndpoint(value = "/websocket/count")
- public class HeartBreakEndpoint {
-
- private Timer timer;
- private volatile boolean isPong;
- private long startTime;
-
- @OnOpen
- public void start(final Session localSession) {
- this.startTime = System.currentTimeMillis();
-
- timer.schedule(new TimerTask() {
-
- @Override
- public void run() {
- try {
- if(isPong) {
- System.out.println("Timer - Say hi");
- localSession.getBasicRemote().sendText("hi");
- isPong = false;
- } else {
- System.out.println("INFO - Check the time.");
- try {
- localSession.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- this.cancel();
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- this.cancel();
- }
- }
-
- }, 2000, 2000);
-
- }
-
- @OnClose
- public void onClose() {
- long currTime = System.currentTimeMillis();
- System.out.println("OnClose - view time " + (currTime - this.startTime)/1000 + " sec.");
- }
-
- @OnMessage
- public void onMessage(String msg) {
- System.out.println("OnMessage - " + msg);
- if(msg.equals("yes")) {
- this.isPong = true;
- }
- }
-
- @OnError
- public void onError(Throwable t) throws Throwable {
-
- }
-
- public HeartBreakEndpoint() {
- this.timer = new Timer();
- this.isPong = true;
- }
-
- }
首先需要明确的一点是,如果在不加其他的配置的前提下,websocket的服务端endpoint默认是多例模式——一个握手连接就会
- <html>
- <body>
- <h2>Hello See heartBreak</h2>
-
- <script>
- var socket = new WebSocket("ws://" + location.host + '/websocket/count'); socket.onmessage = function(e) {
- var msg = e.data;
- var socket = e.target;
- if(msg === 'hi') {
- socket.send('yes');
- }
- }
- </script>
- </body>
- </html>
- import org.springframework.web.socket.server.endpoint.SpringConfigurator;
-
-
- @ServerEndpoint(value = "/websocket/count", configurator = SpringConfigurator.class)
在endpoint类上导入这个包,并改一下annotation就可以了。
- package com.zhheng.nosencebase.wshandler;
-
- 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 org.springframework.web.socket.handler.TextWebSocketHandler;
-
- import com.zhheng.nosencebase.dao.CitiesDao;
-
-
- public class GreetHandler extends TextWebSocketHandler {
-
- private final CitiesDao citiesDao;
-
- @Override
- protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
- String msg = citiesDao.selectCitiesList().get(0).getCity();
- session.sendMessage(new TextMessage(msg));
- }
-
- @Override
- public void afterConnectionEstablished(WebSocketSession session) throws Exception {
-
- }
-
- @Override
- public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
- super.handleMessage(session, message);
- }
-
- @Override
- public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
- super.handleTransportError(session, exception);
- }
-
- @Override
- public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
- super.afterConnectionClosed(session, status);
- }
-
- public GreetHandler(CitiesDao citiesDao) {
- this.citiesDao = citiesDao;
- }
-
- }
- package com.zhheng.nosencebase;
-
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.socket.WebSocketHandler;
- import org.springframework.web.socket.config.annotation.EnableWebSocket;
- import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
- import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
-
- import com.zhheng.nosencebase.dao.CitiesDao;
- import com.zhheng.nosencebase.wshandler.GreetHandler;
-
- @Configuration
- @EnableWebSocket
- public class WebSocketConfig implements WebSocketConfigurer {
-
- @Autowired
- private CitiesDao citiesDao;
-
- public WebSocketConfig() {
-
- }
-
- @Override
- public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
- registry.addHandler(greetingHandler(), "/wstest");
- }
-
- @Bean
- public WebSocketHandler greetingHandler() {
- return new GreetHandler(citiesDao);
- }
-
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。