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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听