在webSocket还未引入前,许多开发人员通过各种非正规手段来完成更新网站的最新信息和到所有当前访问者的任务,其中一种手段就是通过浏览器向服务器轮询更新,但这种手段的网络延迟比较明显,其用户体验比较差。而webSocket协议的引入比较好的解决这种问题,webSocket是一种网络协议,它允许两个相连的端在一个TCP连接上进行全双工通讯。它主要用来作为托管在Web服务器上的Web应用和浏览器之间的通讯机制,同样,WebSocket可以在网络间的任意两端建立,而不一定要在浏览器和服务器上。Java Web Socket API 是JavaEE7平台的核心特性。端点是Java WebSocket API组件模型的中心,而创建端点的方式有注解式和编程式。下面的内容都是关于WebSocket注解式编程。

WebSocket端点的4个生命周期事件

  • 打开事件 
    此事件发生在端点上建立新连接时并且在任何其他事件之前
  • 消息事件 
    此事件接收WebSocket对话的另外一端发送的消息。它可以发生在WebSocket端点接收了打开事件后并且在接收关闭事件关闭连接之前的任意时刻
  • 错误事件 
    此事件在WebSocket连接或者端点发生错误时产生
  • 关闭事件 
    此事件表示WebSocket端点的连接目前正在部分的关闭,它可以由参与连接的任意一个端点发出

注解式端点事件处理

将Java类声明成WebSocket端点,在服务器端端点用@ServerEndpoint来注解,在客户端可以使用@ClientEndpoint来注解。对于端点的四个生命周期事件: 
打开事件@OnOpen

@OnOpen
public void init(Session session,EndpointConfig config){
/*
*方法名任意,参数两个任选,可要可不要,其他事件也一样
**/
}

消息事件@OnMessage

@OnMessage
public void message(String textMessage,Session session){//处理文本信息,Session参数可选
}@OnMessage
public void message(byte[] messageData,Session session){//处理二进制信息,Session参数可选
}@OnMessage
public void message(String textMessage,boolean isLast){//处理分片段的文本信息,isLast 为false表示信息没有接收完整,true则表示最后一条信息
}//所有的@OnMessage 也可以有返回值相当于发送消息的功能
@OnMessage
public String message(String textMessage,Session session){//处理文本信息,Session参数可选return "I got it";
}

错误事件@OnError

@OnError
public void errorHandler(Throwable t){//log error here
}

关闭事件@OnClose

@OnClose
public void goodbye(){//
}

发送信息

1.发送字符串消息

RemoteEndpoint.Basic发送文本信息:public void sendText(String text) throws IOEcxeption 
RemoteEndpoint.Basic发送文本信息到流:public Writer getSendStream() throws IOEcxeption 
RemoteEndpoint以片段形式发送文本消息:public void sendText(String partialMessage,boolean isLast) throws IOException 
以小片段序列的形式发送大的字符串消息,调用时isLast参数一般设为false,直到最后一个片段才设为true,表明消息发送完毕。

2.发送二进制消息

对于大多数应用,发送文本形式消息已经足够,对于有特殊格式例如小图像文件,以二进制形式发送消息则更合适 
RemoteEndpoint发送二进制消息: 
public void sendBinary(ByteBuffer data) throws IOException 
public void sendBinary(ByteBuffer partialByte,boolean isLast) throws IOException 以分片的形式发送,调用时isLast参数一般设为false,直到最后一个片段才设为true,表明消息发送完毕。 
RemoteEndpoint.Basic使用流发送二进制消息: 
public OutputStream getSendStream() throws IOException

基于Java WebSocket 编写的简易聊天室

服务端采用注解式编写

package server;
import java.io.IOException;
import java.util.HashMap;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/echo")//注解使得此Java类声明成WebSocket的端点
public class EchoServer {private boolean first = true;private String name;//用户昵称//connect key为session的ID,value为此对象thisprivate static final HashMap<String,Object> connect = new HashMap<String,Object>();//userMap key为session的ID,value为用户名private static final HashMap<String,String> userMap = new HashMap<String,String>();private Session session;@OnOpenpublic void start(Session session){this.session = session; //获取Seession,存入SashMapconnect.put(session.getId(),this);}@OnMessagepublic void echo( String incomingMessage,Session session){EchoServer client = null ;//first 判断是否第一次传值,第一次的值是昵称,由web端的OnOpen传入if(first){this.name = incomingMessage;String message ="系统:欢迎"+name;//昵称和session的Id一一对应存储在HashMapuserMap.put(session.getId(), name);//将message广播给所有用户for (String key : connect.keySet()) {  try {  client = (EchoServer) connect.get(key);  synchronized (client) {  //给对应的Web端发送一个文本消息client.session.getBasicRemote().sendText(message);  }  } catch (IOException e) {   connect.remove(client);  try {  client.session.close();  } catch (IOException e1) {  }  }  }  //输入昵称后,往后的交互传值都不是第一次first = false;}else{/*** incomingMessage的值为xxx@xxxxx的形式xxx为要发给的用户昵称,all则表示发给所有人* incomingMessage.split("@",2);以@为分隔符把字符串分为xxx和xxxxx两部分*/String [] list = incomingMessage.split("@",2);if(list[0].equalsIgnoreCase("all")){ //all广播全部人sendAll(list[1],session);}else{boolean you = false;//标记是否找到发送的用户for(String key : userMap.keySet()){if(list[0].equalsIgnoreCase(userMap.get(key))){client = (EchoServer) connect.get(key);  synchronized (client) {  try {//发送信息给指定的用户client.session.getBasicRemote().sendText(userMap.get(session.getId())+"对你说:"+list[1]);} catch (IOException e) {e.printStackTrace();}  } you = true;//找到指定用户标记为truebreak;}}//you为true则在自己页面显示自己对xxx说xxxxx,否则显示系统:无此用户if(you){try {session.getBasicRemote().sendText("自己对"+ list[0]+"说:"+list[1]);} catch (IOException e) {e.printStackTrace();}}else{try {session.getBasicRemote().sendText("系统:无此用户");} catch (IOException e) {e.printStackTrace();}}}}}@OnClosepublic void close(Session session){//当一用户退出时,对其他用户进行广播String message ="系统:"+userMap.get(session.getId()) +"退出群聊";userMap.remove(session.getId());connect.remove(session.getId());for (String key : connect.keySet()) {  EchoServer client = null ;  try {  client = (EchoServer) connect.get(key);  synchronized (client) {  client.session.getBasicRemote().sendText(message);  }  } catch (IOException e) {   connect.remove(client);  try {  client.session.close();  } catch (IOException e1) {  }  }  }  }//对信息进行全体广播public static void sendAll(String mess,Session session){  String who = null;for (String key : connect.keySet()) {  EchoServer client = null ;  try {  client = (EchoServer) connect.get(key);  if(key.equalsIgnoreCase(session.getId())){who = "自己对大家说 : ";}else{who = userMap.get(session.getId())+"对大家说 : ";}synchronized (client) {  client.session.getBasicRemote().sendText(who+mess);  }  } catch (IOException e) {   connect.remove(client);  try {  client.session.close();  } catch (IOException e1) {  }  }  }  }  public String getName(){return this.name;}
}

web端

<!DOCTYPE html>
<html><head><title>简易聊天室</title><meta name="keywords" content="keyword1,keyword2,keyword3"><meta name="description" content="this is my page"><meta name="content-type" content="text/html; charset=UTF-8"><script  type="text/javascript">var ws;var wsUri = "ws://localhost:8080/Socket/echo";ws = new WebSocket(wsUri);ws.onopen = function(){n=prompt('请给自己取一个昵称:');n=n.substr(0,16);ws.send(n);//在服务端必须由OnMessage接收此消息};//处理连接后的信息处理ws.onmessage = function(message){writeToScreen(message.data); };//对发送按钮进行监听,获取发送的信息和发送对象function button(){message = document.getElementById('in').value;towho = document.getElementById('towho').value + "@";ws.send(towho+message);}   //发生错误时,处理错误ws.onerror = function (evt){ writeToScreen('<span style="color:red;">ERROR:</span>'+evt.data);ws.close();};//把信息显示到当前屏幕function writeToScreen(message){var pre = document.createElement("p");pre.style.wordWrap = "break-word";pre.innerHTML = message;output.appendChild(pre);}   //当关闭页面时执行ws.closewindow.onbeforeunload=function (){ ws.close();}; </script></head><body><h1>简易聊天室</h1><div style="width:400px;height:260px; overflow:scroll; border:3px solid; " id="output"> </div>  <br>    <div style="text-align:left;"><form action=""><input id="in" name="message" value="" type="text" style="width:400px;height:60px;  border:3px solid; " ><br><br><input onclick="button()" value="发送" type="button"/>发送对象:<input id="towho" name="towho" value="all"><br></form></div></body>
</html>

部署程序,Tomcat从7.0.27开始支持WebSocket,从7.0.47开始支持JSR-356,上述代码也是需要部署在Tomcat7.0.47上,JDK1.7以上才能运行。当浏览器或者Tomcat或者jdk不支持的时候会报undefined的错误 
 

Java WebSocket编程与网页简易聊天室相关推荐

  1. WebSocket+Tomcat实现网页简易聊天室

    简单的说一下什么是websocket,它是基于TCP的服务器与客户端之间全双工通信的一种协议,允许服务端主动推送消息给客户端,只需要一次握手,就可以在服务端和客户端之间建立持久相连接,在这里我们只用到 ...

  2. HTML5 之WebSocket入门demo和简易聊天室

    HTML5 WebSocket WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. 在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏 ...

  3. WebSocket原生JavaScript实现简易聊天室

    WebSocket原生实现 WebSocket-Vue2 WebSocket-Vue3 基本介绍 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. Web ...

  4. 【第98题】JAVA高级技术-网络编程17(简易聊天室12:实现客户端一对一聊天)

    回城传送–><JAVA筑基100例> 文章目录 零.前言 一.题目描述 二.解题思路 三.代码详解 多学一个知识点 四.推荐专栏 五.示例源码下载 零.前言 ​ 今天是学习 JAVA ...

  5. 【第99题】JAVA高级技术-网络编程18(简易聊天室13:聊天室服务端)

    回城传送–><JAVA筑基100例> 文章目录 零.前言 一.题目描述 二.解题思路 三.代码详解 多学一个知识点 四.推荐专栏 五.示例源码下载 零.前言 ​ 今天是学习 JAVA ...

  6. 【第90题】JAVA高级技术-网络编程9(简易聊天室4:获得Socket)

    回城传送–><JAVA筑基100例> 文章目录 零.前言 一.题目描述 二.解题思路 三.代码详解 四.推荐专栏 五.示例源码下载 零.前言 ​ 今天是学习 JAVA语言 打卡的第9 ...

  7. 【第91题】JAVA高级技术-网络编程10(简易聊天室5:接收和发送Socket)

    回城传送–><JAVA筑基100例> 文章目录 零.前言 一.题目描述 二.解题思路 三.代码详解 四.推荐专栏 五.示例源码下载 零.前言 ​ 今天是学习 JAVA语言 打卡的第9 ...

  8. 【第87题】JAVA高级技术-网络编程6(简易聊天室1:运行服务器程序,等待客户端连接)

    回城传送–><JAVA筑基100例> 文章目录 零.前言 一.题目描述 二.解题思路 三.代码详解 四.推荐专栏 五.示例源码下载 零.前言 ​ 今天是学习 JAVA语言 打卡的第8 ...

  9. 【第94题】JAVA高级技术-网络编程13(简易聊天室8:使用Socket传递图片)

    回城传送–><JAVA筑基100例> 文章目录 零.前言 一.题目描述 二.解题思路 三.代码详解 四.推荐专栏 五.示例源码下载 零.前言 ​ 今天是学习 JAVA语言 打卡的第9 ...

最新文章

  1. OO第一单元总结博客
  2. 作为iOS开发者不得不follow的52人
  3. 【原创】数据库中时间字段的值读取到DataSet中后,毫秒部分丢失。
  4. 腾讯云服务器部署FTP
  5. extern 定义_Essential Cython - 2.7 - 定义并使用模板函数
  6. 如何利用python在一个文档里写入长须_Python语法入门—文件处理
  7. Linux加法简单程序,Android应用程序的开发目录——简单的加法计算示例
  8. Windows 10下,anaconda (conda) 虚拟环境的创建,jupyter notebook如何使用虚拟环境
  9. combobox异步加载 easyui_如何解决多条数据加载easyui-combobox样式反应慢的问题
  10. 客户成功已死,客户服务还活着
  11. 财务人员工资那么低,财务工作真的有价值吗?
  12. 1021 个位数统计 (15 分)—PAT (Basic Level) Practice (中文)
  13. 最实用的网上赚钱方法:这7个方法真的很实用哦!
  14. 一元三次、四次方程求解
  15. 正点原子stmf103zet6代码移植为stm32f103c8t6(库函数版)
  16. 【python爬虫】爬取Bing词典的单词存到SQLite数据库
  17. 系统中IDE硬盘与SCSI硬盘的区别
  18. python+appium 实现抖音自动化浏览
  19. 在ubuntu20.04环境下安装opencv教程并测试
  20. 【模型加速】自定义TensorRT NMS3D插件(1)

热门文章

  1. K8S调试工具之--nsenter
  2. 全民健身时代到来,运动类APP如何秀出肌肉?
  3. Freeswitch智能语音开发之TTS
  4. 网站访问流程及原理分析
  5. 基于WT588F02B语音芯片的智能语音感应洗手液器设计方案
  6. 超级干货 :一文总览数据科学全景:定律、算法、问题类型...
  7. 惠海半导体H7230直接替换BP1371 BP1361方案设计
  8. 思科交换机指示灯全解
  9. java-php-python-ssm新生报到管理计算机毕业设计
  10. PlayMaker 1.9 烦人的小提示