Java Websocket实例【服务端与客户端实现全双工通讯】

2024-09-09 05:08

本文主要是介绍Java Websocket实例【服务端与客户端实现全双工通讯】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Java Websocket实例【服务端与客户端实现全双工通讯】


现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发

HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏

览器需要不断的向服务器发出请求,然而HTTP request header是非常长的,里面包含的数据可能只是一个很小的值,这样会占

用很多的带宽。WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的Ajax技术。

一、什么是WebSocket API?

WebSocket API是下一代客户端-服务器的异步通信方法。该通信取代了单个的TCP套接字,使用wswss协议,可用于任意的

客户端和服务器程序。WebSocket目前由W3C进行标准化。WebSocket已经受到Firefox 4Chrome 4Opera 10.70以及Safari 5

浏览器的支持。

WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket并不限于以

Ajax(XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;XHR受到域

的限制,而WebSocket允许跨域通信。

Ajax技术很聪明的一点是没有设计要使用的方式。WebSocket为指定目标创建,用于双向推送消息。

那么我就开始我在项目中对websocket的使用,首先使用的是J2EE7的架包。

 

架包加完之后,只需要再添加2个类就可以实现使用的功能了。

首先添加一个Java类,WebsocketController.java

[java]  view plain copy
  1. package com.lwl.activemq.controller.websocket;  
  2.   
  3. import java.util.Map;  
  4. import java.util.concurrent.ConcurrentHashMap;  
  5.   
  6. import javax.websocket.*;  
  7. import javax.websocket.server.PathParam;  
  8. import javax.websocket.server.ServerEndpoint;  
  9.   
  10.   
  11. import org.slf4j.Logger;  
  12. import org.slf4j.LoggerFactory;  
  13. /** 
  14.  * 功能说明:websocket处理类, 使用J2EE7的标准 
  15.  * @author Administrator 
  16.  * @create 2016-8-11 下午4:08:35 
  17.  * @version 1.0 
  18.  */  
  19. @ServerEndpoint("/websocket/{myWebsocket}")  
  20. public class WebsocketController {  
  21.     private static final Logger logger = LoggerFactory.getLogger(WebsocketController.class);  
  22.   
  23.     public static Map<String, Session> clients = new ConcurrentHashMap<String, Session>();  
  24.   
  25.     /** 
  26.      * 打开连接时触发 
  27.      * @param myWebsocket 
  28.      * @param session 
  29.      */  
  30.     @OnOpen  
  31.     public void onOpen(@PathParam("myWebsocket") String myWebsocket, Session session){  
  32.         logger.info("Websocket Start Connecting:" + myWebsocket);  
  33.         System.out.println("进入:"+myWebsocket);  
  34.         clients.put(myWebsocket, session);  
  35.     }  
  36.   
  37.     /** 
  38.      * 收到客户端消息时触发 
  39.      * @param myWebsocket 
  40.      * @param message 
  41.      * @return 
  42.      */  
  43.     @OnMessage  
  44.     public String onMessage(@PathParam("myWebsocket") String myWebsocket, String message) {  
  45.         return "Got your message ("+ message +").Thanks !";  
  46.     }  
  47.   
  48.     /** 
  49.      * 异常时触发 
  50.      * @param myWebsocket 
  51.      * @param throwable 
  52.      */  
  53.     @OnError  
  54.     public void onError(@PathParam("myWebsocket") String myWebsocket, Throwable throwable) {  
  55.         logger.info("Websocket Connection Exception:" + myWebsocket);  
  56.         logger.info(throwable.getMessage(), throwable);  
  57.         clients.remove(myWebsocket);  
  58.     }  
  59.   
  60.     /** 
  61.      * 关闭连接时触发 
  62.      * @param myWebsocket 
  63.      */  
  64.     @OnClose  
  65.     public void onClose(@PathParam("myWebsocket") String myWebsocket) {  
  66.         logger.info("Websocket Close Connection:" + myWebsocket);  
  67.         clients.remove(myWebsocket);  
  68.     }  
  69.   
  70.   
  71.     /** 
  72.      * 将数据传回客户端 
  73.      * 异步的方式 
  74.      * @param myWebsocket 
  75.      * @param message 
  76.      */  
  77.     public static void broadcast(String myWebsocket, String message) {  
  78.         if (clients.containsKey(myWebsocket)) {  
  79.             clients.get(myWebsocket).getAsyncRemote().sendText(message);  
  80.         } else {  
  81.             throw new NullPointerException("[" + myWebsocket +"]Connection does not exist");  
  82.         }  
  83.     }  
  84.   
  85. }  

然后添加相应的接受页面index.html:

[html]  view plain copy
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  2. <html>  
  3.     <head>  
  4.         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  5.         <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  6.         <meta name="viewport" content="width=device-width, initial-scale=1">  
  7.           <script type="text/javascript" src="resources/jquery-1.8.3.min.js"></script>  
  8.      </head>     
  9. <body>  
  10.   
  11.    
  12. <script type="text/javascript">  
  13.  //测试controller是否可以进入  
  14. // ajaxDo("/activemq-client/index",null);  
  15.    
  16. // function ajaxDo(url,data){  
  17. //   $.ajax({  
  18. //          url:url ,  
  19. //          type: "post",  
  20. //          dataType: "json",  
  21. //          data: data,  
  22. //          success:function(result){  
  23. //             if(result.success){  
  24. //                 alert(result.data);  
  25. //             }else{  
  26. //                 alert(result.msg);  
  27. //             }  
  28. //          }  
  29. //      });  
  30. // }      
  31.   
  32.   
  33. //--------------------------------- webSocket ----------------------------------------------  
  34.   initSocket("user");  
  35.   initSocket("news");  
  36.   initSocket("client");  
  37.     
  38.   
  39. function initSocket(myWebsocket) {  
  40.       
  41.     var webSocket = null;  
  42.       
  43.     window.onbeforeunload = function () {  
  44.         //离开页面时的其他操作  
  45.     };  
  46.   
  47.     if (!window.WebSocket) {  
  48.         console("您的浏览器不支持websocket!");  
  49.         return false;  
  50.     }  
  51.   
  52.     var target = 'ws://' + window.location.host + "/activemq-client/websocket/"+myWebsocket;    
  53.             
  54.         if ('WebSocket' in window) {    
  55.             webSocket = new WebSocket(target);    
  56.         } else if ('MozWebSocket' in window) {    
  57.             webSocket = new MozWebSocket(target);    
  58.         } else {    
  59.             alert('WebSocket is not supported by this browser.');    
  60.             return;    
  61.         }    
  62.       
  63.       
  64.     // 收到服务端消息  
  65.     webSocket.onmessage = function (msg) {  
  66.             alert(msg.data);  
  67.         // 关闭连接  
  68.         webSocket.onclose();  
  69.         console.log(msg);  
  70.     };  
  71.   
  72.     // 异常  
  73.     webSocket.onerror = function (event) {  
  74.         console.log(event);  
  75.     };  
  76.   
  77.     // 建立连接  
  78.     webSocket.onopen = function (event) {  
  79.         console.log(event);  
  80.     };  
  81.   
  82.     // 断线  
  83.     webSocket.onclose = function () {  
  84.           
  85.         console.log("websocket断开连接");  
  86.     };  
  87. }  
  88.   
  89.   
  90. </script>  
  91.   
  92. </body>  
  93. </html>  

好了,websocket已经实现了,现在最重要的是我们要在哪儿监听哪些变动,在推送给前端的问题了,这里我监听了MQ消息队

列中的某个Queen,如果获取到消息就推送给前端展示,稍后我会把MQ的消息队列也写给大家看,做个参考。(当然你也可以

监听属于你自己的对象,主要是调用 WebsocketController.broadcast("client", jsonStr);第一个参数和前端的参数一

致,第二个参数是你想推送给前端的内容)。

[java]  view plain copy
  1. <span style="font-size:14px;"><span style="font-family:宋体;">package com.lwl.activemq.listener;  
  2.   
  3. import javax.jms.JMSException;  
  4. import javax.jms.Message;  
  5. import javax.jms.MessageListener;  
  6. import javax.jms.TextMessage;  
  7.   
  8. import org.apache.log4j.Logger;  
  9. import org.springframework.stereotype.Component;  
  10.   
  11. import com.alibaba.fastjson.JSON;  
  12. import com.lwl.activemq.domain.Client;  
  13. import com.lwl.activemq.controller.websocket.WebsocketController;  
  14.   
  15. @Component("clientPushListener")  
  16. public class ClientPushListener implements MessageListener {  
  17.      protected static final Logger logger = Logger.getLogger(ClientPushListener.class);  
  18.     @Override  
  19.     public void onMessage(Message message) {  
  20.          logger.info("[ClientPushListener.onMessage]:begin onMessage.");  
  21.             TextMessage textMessage = (TextMessage) message;  
  22.             try {  
  23.                 String jsonStr = textMessage.getText();  
  24.                 logger.info("[ClientPushListener.onMessage]:receive message is,"+ jsonStr);  
  25.                 if (jsonStr != null) {  
  26.                     Client info = JSON.parseObject(jsonStr, Client.class);  
  27.                     System.out.println("==============================接受到的客户信息 开始====================================");  
  28.                     System.out.println(info.toString());  
  29.                     System.out.println("==============================接受到的客户信息 结束====================================");  
  30.                     WebsocketController.broadcast("client", jsonStr);  
  31.                 }  
  32.             } catch (JMSException e) {  
  33.                 logger.error("[ClientPushListener.onMessage]:receive message occured an exception",e);  
  34.             }  
  35.             logger.info("[ClientPushListener.onMessage]:end onMessage.");  
  36.         }  
  37. }</span></span>  
转自: http://blog.csdn.net/LOVELONG8808/article/details/52277029

这篇关于Java Websocket实例【服务端与客户端实现全双工通讯】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1150242

相关文章

Java中Arrays类和Collections类常用方法示例详解

《Java中Arrays类和Collections类常用方法示例详解》本文总结了Java中Arrays和Collections类的常用方法,涵盖数组填充、排序、搜索、复制、列表转换等操作,帮助开发者高... 目录Arrays.fill()相关用法Arrays.toString()Arrays.sort()A

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

Java堆转储文件之1.6G大文件处理完整指南

《Java堆转储文件之1.6G大文件处理完整指南》堆转储文件是优化、分析内存消耗的重要工具,:本文主要介绍Java堆转储文件之1.6G大文件处理的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言文件为什么这么大?如何处理这个文件?分析文件内容(推荐)删除文件(如果不需要)查看错误来源如何避

SpringBoot整合Dubbo+ZK注册失败的坑及解决

《SpringBoot整合Dubbo+ZK注册失败的坑及解决》使用Dubbo框架时,需在公共pom添加依赖,启动类加@EnableDubbo,实现类用@DubboService替代@Service,配... 目录1.先看下公共的pom(maven创建的pom工程)2.启动类上加@EnableDubbo3.实

SpringBoot整合(ES)ElasticSearch7.8实践

《SpringBoot整合(ES)ElasticSearch7.8实践》本文详细介绍了SpringBoot整合ElasticSearch7.8的教程,涵盖依赖添加、客户端初始化、索引创建与获取、批量插... 目录SpringBoot整合ElasticSearch7.8添加依赖初始化创建SpringBoot项

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法