美文网首页java填坑之路
在springBoot框架下利用websocket实现消息推送(

在springBoot框架下利用websocket实现消息推送(

作者: 郭小颖在2018 | 来源:发表于2018-09-20 19:54 被阅读262次

    websocket实现消息推送

    1、添加Spring WebSocket的依赖jar包

    <!-- https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket -->
            <dependency>
                <groupId>org.java-websocket</groupId>
                <artifactId>Java-WebSocket</artifactId>
                <version>1.3.0</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-messaging -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-messaging</artifactId>
                <version>4.3.18.RELEASE</version>
            </dependency>
    

    2、建立一个类实现websocketconfigurer接口

    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Autowired
        WebSocketUtil webSocketUtil;
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(webSocketUtil,"/webSocket").addInterceptors(new SpringWebSocketHandlerInterceptor());
            registry.addHandler(webSocketUtil,"/sockJs").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
        }
    }
    

    3、继承WebSocketHandler对象

    • 该对象提供了客户端连接,关闭,错误,发送等方法,重写这几个方法即可实现自定义业务逻辑
    @Component
    public class WebSocketUtil extends TextWebSocketHandler {
        private Map<String, WebSocketSession> socketCache = new ConcurrentHashMap<>();
        //private static final ArrayList<WebSocketSession> users;//这个会出现性能问题,最好用Map来存储,key用userid
        private static Logger logger = LoggerFactory.getLogger(WebSocketUtil.class);
        /*static {
            users = new ArrayList<WebSocketSession>();
        }*/
        public WebSocketUtil() {
            // TODO Auto-generated constructor stub
        }
    
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("connect to the websocket success......当前数量:" + socketCache.size());
            String token = (String) session.getAttributes().get("token");
            System.out.println(token);
            socketCache.put(token, session);
            System.out.println("连接后的数量为:" + socketCache.size());
        }
    
    
        public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
            logger.debug("websocket connection closed......");
            String token = (String) session.getAttributes().get("token");
            System.out.println("用户" + token + "已退出!");
            socketCache.remove(token);
            System.out.println(socketCache.get(token));
            System.out.println("剩余在线用户" + socketCache.size());
        }
    
    
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            super.handleTextMessage(session, message);
        }
    
        public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
            if (session.isOpen()) {
                session.close();
            }
            logger.debug("websocket connection closed......");
            String token = (String) session.getAttributes().get("token");
            socketCache.remove(token);
        }
    
        public boolean supportsPartialMessages() {
            return false;
        }
    
    
        public boolean send(String token, TextMessage message) {
            if (socketCache.containsKey(token)) {
                return send(socketCache.get(token), message);
            }
            logger.info("socketCache   is  not  key ");
            return false;
        }
    
        public void sendAll(TextMessage message) {
            if (message == null) return;
            for (WebSocketSession webSocketSession : socketCache.values()) {
                send(webSocketSession, message);
            }
        }
    
        public boolean send(WebSocketSession webSocketSession, TextMessage message) {
            String token = (String) webSocketSession.getAttributes().get("token");
            if (token==null){
                return false;
            }
            try {
                webSocketSession.sendMessage(message);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
                logger.info("websocket 数据发送异常 !");
                return false;
            }
        }
    }
    

    4、继承HttpSessionHandshakeInterceptor对象

    • 该对象作为页面连接websocket服务的拦截器,代码如下
    /**
     * websocket拦截器
     */
    public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
        @Autowired
        UserService userService;
    
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                                       Map<String, Object> attributes) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("Before Handshake");
            if (request instanceof ServletServerHttpRequest) {
                ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
                //1.拿去前段请求中携带的token
                String token = servletRequest.getServletRequest().getParameter("token");
                //2.对token进行判断,如果token不存在,则进行拦截
                if (token==null){
                    return false;
                }
                UserInfo userInfo = userService.getloginuserinfo(token);
                if (userInfo==null){
                    return false;
                }
                attributes.put("token",token);
               /* if (token!=null){
                    UserInfo userInfo = userService.getloginuserinfo(token);
                    if (userInfo!=null){
                        attributes.put("token",token);
                    }
                }*/
            }
            System.out.println("handshake...");
            return super.beforeHandshake(request, response, wsHandler, attributes);
        }
    
        @Override
        public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
                                   Exception ex) {
            // TODO Auto-generated method stub
            System.out.println("afterHandshake...");
            super.afterHandshake(request, response, wsHandler, ex);
        }
    }
    

    1.定义一个控制器用来做连接标识和发送消息

    @RestController
    public class MessagePushController {
    
    
        @Autowired
        private WebSocketUtil webSocketUtil;
    
        /**
         * 给某个用户发送消息
         *
         * @param token
         * @param message
         * @return
         */
        @PostMapping("/push")
        public String tokenPush(String token, String message) {
            return  webSocketUtil.send(token,new TextMessage(message))?"success":"fail";
        }
    
        /**
         * 广播,给所有在线用户发送广播
         *
         * @param message
         * @return
         */
        @PostMapping("/broadcast")
        public String Push(String message) {
            try {
                webSocketUtil.sendAll(new TextMessage(message));
                return "success";
            } catch (Exception e) {
                e.printStackTrace();
                return "false";
            }
        }
    }
    

    2、建立发消息页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta name="viewport" content="width=device-width" charset="UTF-8"/>
        <title>WebSocket 客户端</title>
    </head>
    
    <body>
    <div>
    
        token:<input type="text" id="token"/>
        <input type="button" id="btnConnection" value="连接到服务器"/><br/>
        <input type="text" id="inputMsg"/>
        <input type="button" id="btnSend" value="客户端发送消息" /><br/>
        <input type="button" id="btnClose" value="客户端关闭连接" /><br/>
    
    </div>
    <script src="js/jquery-1.8.3.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        var websocket = null;
        if (typeof(WebSocket) == "undefined") {
            alert("您的浏览器不支持WebSocket");
        }
    
         //连接到ws服务器
         $("#btnConnection").click(function () {
             var token=document.getElementById("token").value;
             //实现化WebSocket对象,指定要连接的服务器地址与端口
             websocket = new WebSocket("ws://localhost:8210/webSocket?token="+token);
             //打开事件
             websocket.onopen = function () {
                 alert("Socket 已打开");
                 websocket.send("这是来自客户端的消息:" + location.href + new Date());
             };
             //获得消息事件
             websocket.onmessage = function (msg) {
                 alert(msg.data);
             };
             //关闭事件
             websocket.onclose = function () {
                 alert("Socket已关闭");
             };
             //发生了错误事件
             websocket.onerror = function () {
                 alert("发生了错误");
             }
         });
    
         //发送消息
         $("#btnSend").click(function () {
             var msg = document.getElementById("inputMsg").value;
             websocket.send("这是来自客户端的消息:" +msg+new Date());
             alert("客户端发送了消息");
         });
    
    
         //关闭
         $("#btnClose").click(function () {
             websocket.close();
             alert("客户端关闭了连接");
         });
    </script>
    </body>
    
    </html>
    

    相关文章

      网友评论

        本文标题:在springBoot框架下利用websocket实现消息推送(

        本文链接:https://www.haomeiwen.com/subject/qdannftx.html