百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

01_tomcat 通过websocket 实现一个简易聊天室功能-项目-教程(一)

zhezhongyun 2025-01-14 19:05 90 浏览

01_tomcat 通过 websocket 实现一个简易的聊天室功能-项目-教程(一)

## 一、Tomcat专题 - WebSocket - 介绍

### 1、Tomcat 附加功能:websocket 介绍

1)websocket :是 HTML5 新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,

比如说,服务器可以在任意时刻发送消息给浏览器。

2)为什么传统的 HTTP 协议不能做到 websocket 实现的功能?

- 这是因为 HTTP 协议是一个请求-响应协议,请求必须先由浏览器发给服务器服务器才能响应这个请求,再把数据发送给浏览器。

换句话说,浏览器不主动请求,服务器是没法主动发数据给浏览器的,

- 这样一来,要在浏览器中搞一个实时聊天,或者在线多人游戏的话就没法实现了,只能借助 Elash 这些插件,

3)也有人说,HTTP 协议其实也能实现啊,比如用轮询或者 comet。

- 轮询:是指浏览器通过 Javascript 启动一个定时器,然后以固定的间隔给服务器发请求,询问服务器有没有新消息。

这个机制的缺点一是实时性不够,二是频繁的请求会给服务器带来极大的压力。

- comet 本质上也是轮询,但是在没有消息的情况下,服务器先拖一段时间,等到有消息了再回复,这个机制暂时地解决了实时性问题,

但是它带来了新的问题:

以多线程模式运行的服务器会让大部分线程大部分时间都处于挂起状态,极大地浪费服务器资源。

另外,一个 HTTP 连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能关闭这个连接,

而网关是我们不可控的,这就要求 comet 连接必须定期发一些 ping 数据表示连接“正常工作"。

### 2、以上两种机制都治标不治本,所以,HTML5 推出了 websocket 标准,让浏览器和服务器之间可以建立无限制的全双工通信,任何一方都可以主动发消息给对方。websocket 并不是全新的协议,而是利用了 HTTP 协议来建立连接。

### 3、websocket 连接是如何创建的。

1)首先,websocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

2)该请求和普通的HTTP请求有几点不同:

- 1.GET请求的地址不是类似 http://,而是以 ws:// 开头的地址;

- 2.请求头 connection:upgrade 和 请求头 upgrade:websocket 表示这个连接将要被转换为 websocket 连接;

- 3.sec-websocket-Key 是用于标识这个连接, 是一个BASE64编码的密文,要求服务端响应一个对应加密的sec-websocket-Accept头信息作为应答。

- 4.sec-websocket-version 指定了 websocket 的协议版本;

- 5.HTTP101 状态码表明服务端已经识别并切换为 Websocket 协议,sec-websocket-Accept 是服务端与客户端一致的秘钥计算出来的信息。

## 二、Tomcat专题 - WebSocket - Tomcat的支持

### 1、Tomcat 的 Websocket

Tomcat 的 7.0.5 版本开始支持 websocket,并且实现了 Java websocket 规范(JSR356),而在7.0.5版本之前(7.0.2之后)则采用自定义 API,即 websocketservlet 实现。

### 2、Java websocket 应用由一系列的 nebsocketEndpoint 组成。Endpoint 是一个 Java 对象,代表 websocket 链接的一端,对于服务端,可以视为处理具体 websocket 消息的接口,就像 servlet 之与 http 请求一样。

### 3、可以通过两种方式定义 Endpoint:

1)第一种是编程式,即继承类 javax.websocket.Endpoint 并实现其方法。

2)第二种是注解式,即定义一个POJO,并添加 @serverEndpoint 相关注解。

### 4、Endpoint 实例在 websocket 握手时创建,并在客户端与服务端链接过程中有效,最后在链接关闭时结束,在 Endpoint 接口中明确定义了与其生命周期相关的方法, 规范实现者确保生命周期的各个阶段调用实例的相关方法。生命周期方法如下:

| 方法 | 含义描述 | 注解 | |

|--|--|--|--|

| onOpen | 当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法。 | @onopen | |

| onClose | 当会话关闭时调用。 | @onClose | |

| onError | 当连接过程中异常时调用。 | @onError | |

| | | | |

### 5、编程式 和 注解式 接收和发送消息。

- 编程式通过为 session 添加 Messagexandler 消息处理器来接收消息。

- 采用注解方式定义 Endpoint 时,可以通过 @onMessage 注解指定接收消息的方法。发送消息则由 RemoteEndpoint 完成,其实例由 session 维护。

- 根据使用情况, 可以通过 session.getBasicRemote 获取同步消息发送的实例,然后调用其 sendxxx() 方法就可以发送消息,可以通过 session.getAsyncRemote 获取异步消息发送实例。

### 6、...\apache-tomcat-8.5.42-src\java\javax\websocket\Endpoint.java 类,源码:

```bash

package javax.websocket;

public abstract class Endpoint {

public abstract void onOpen(Session session, EndpointConfig config);

public void onClose(Session session, CloseReason closeReason) {

// NO-OP by default

}

public void onError(Session session, Throwable throwable) {

// NO-OP by default

}

}

```

## 三、 Tomcat专题 - WebSocket - 案例 - 需求及流程分析

### 1、WebSocket DEMO 案例需求:通过 websocket 实现一个简易的聊天室功能。

### 2、WebSocket DEMO 案例流程

1)登录聊天室

2)登录后,进入聊天界面,进行聊天。

3)用户1 聊天界面,用户2 聊天界面。

4)好友列表、单独聊天模式与广播模式。

### 3、WebSocket DEMO 案例 实现流程

### 4、消息格式

客户端 --> 服务端: {"fromName":"Deng","toName":"HEIMA","content":"约会呀"}

服务端 --> 客户端:

1)如果 type 为 user,则说明返回的是用户列表

{"data" : "HEIMA, Deng, ITCAST" ,"toName" :"" ,"fromName" :"","type" :"user" }

2)如果 type 为 message,则说明返回的是消息内容

{"data" : "你好" ,"toName" : "HE IMA" , " fromName" : "Deng" ,"type" : "message" }

## 四、Tomcat专题 - WebSocket - 案例 - 准备工作

### 1、打开 idea 创建 名为 dzs168_chat_room 的 Web Application 项目

```java

--> idea --> File

--> New --> Project

--> Java

Project SDK: ( 1.8(java version "1.8.0_131" )

--> Java EE : 勾选 ( Web Application )

--> Next

--> Project Name: ( dzs168_chat_room )

Project Location: ( ...\dzs168_chat_room\ )

--> Finish

```

### 2、在项目 dzs168_chat_room 中,导入项目依赖( dzs168_chat_room/web/lib/ ),Add as Library...

fastjson-1.2.5.jar

tomcat-websocket.jar

websocket-api.jar

### 3、在项目 dzs168_chat_room 中,导入静态资源文件。

dzs168_chat_room/web/css/

dzs168_chat_room/web/img/

dzs168_chat_room/web/js/

dzs168_chat_room/web/chat.jsp

dzs168_chat_room/web/login.jsp

### 4、在项目 dzs168_chat_room 中, Web 应用配置欢迎页面为 login.jsp

(project_tomcat\dzs168_chat_room\web\WEB-INF\web.xml)

```java

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

version="3.1">

<welcome-file-list>

<welcome-file>login.jsp</welcome-file>

</welcome-file-list>

</web-app>

<!-- project_tomcat\dzs168_chat_room\web\WEB-INF\web.xml -->

```

### 5、配置 dzs168_chat_room 应用,进行测试。

```java

idea ---> Run/Debug Configurations

---> 点击 应用 Tomcat 8.5.47

---> Deployment

删除已经存在的应用。

---> 点击 + 添加新应用 Artifact... ,选择我们的项目 dzs168_chat_room.war exploded

---> Application context: ( / )

---> Apply

---> Server

---> On'Update'action: ( Update classes and resources )

---> On frame deactivation: ( Update classes and resources )

---> Apply

---> OK 。

```

### 6、运行 tomcat 服务器,自动打开欢迎页面,localhost:8080

相关推荐

3 分钟!AI 从零开发五子棋全过程曝光,网友:这效率我服了

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8...

一行代码实现display&quot;过渡动画&quot;原理

作者:Peter谭老师转发链接:https://mp.weixin.qq.com/s/XhwPOv62gypzq5MhhP-5vg写本文的起因上篇文章,提到如何让display出现过渡动画,却没有仔...

脑洞:琼恩·雪诺、蝙蝠侠和魔形女的灵魂宠物了解一下

AlekseiVinogradovisaRussianfreelancedigitalartistwhoshareshisskillsandtalentwith120k...

浏览器的渲染机制、重绘、重排

1、什么是重排和重绘网页生成过程:HTML被HTML解析器解析成DOM树css则被css解析器解析成CSSOM树结合DOM树和CSSOM树,生成一棵渲染树(RenderTree)生成布局(flo...

托福写作高频考题写作思路&amp;词汇丨考虫独家

科技话题与媒体话题是托福写作的常考话题很多考生对这两类话题里的专有词汇表达也许很不了解所以今天就跟随考虫托福写作老师刘云龙老师一起来学习在这些话题的写作里你可以使用哪些有用的表达。希望大家有收获!记得...

在优麒麟上使用 Electron 开发桌面应用

使用Web标准来创建桌面GUI,上手快、成本低、跨平台、自适应分辨率,这些都是Electron的优势。作者/来源:优麒麟Electron是由Github开发,用HTML、CSS和...

php手把手教你做网站(三十八)jquery 转轮盘抽奖,开盲盒

抽奖和开盲盒性质一样的都是通过ajax读取后台的随机数据。1、转轮盘本来是想直接绘图实现轮盘,但是没有找到怎么填充文字,只好把轮盘弄成了背景图,通常用于游戏抽道具,商城积分抽奖,公司年末员工抽奖点击抽...

用 CSS 整活!3D 轮播图手把手教学,快乐代码敲出来

兄弟们,今天咱来搞点好玩的——用CSS整一个3D轮播图!咱野生程序员就是要在代码里找乐子,技术和快乐咱都得要!代码是写不完的,但咱能自己敲出快乐来,走起!一、先整个容器,搭个舞台咋先写一个...

实现一个超酷的 3D 立体卡片效 #前端开发

今天我们来实现一个超酷的3D立体卡片效果。正常情况下就是一个普通的图片展示卡片,鼠标悬停的时候图片会跳出卡片,并将影子投射到背景卡片上,在视觉上有一个3D立体感。html主要分成3个部分:容器→背景层...

Vue 3 Teleport与Suspense:解决UI难题的两个&quot;隐藏大招&quot;

模态框的"层级噩梦"与Teleport的救赎"这个模态框怎么又被父容器截断了?"团队协作开发后台系统时,小张第N次遇到这个问题。多层嵌套的组件结构里,弹窗被overfl...

让交互更加生动!有意思的鼠标跟随 3D 旋转动效

今天,群友问了这样一个问题,如下所示的鼠标跟随交互效果,如何实现:简单分析一下,这个交互效果主要有两个核心:借助了CSS3D的能力元素的旋转需要和鼠标的移动相结合本文,就将讲述如何使用纯CSS...

填坑:transform元素导致zindex失效终极方法

今天遇到了使用css3动画的元素层级被放大置顶的问题,ios浏览器上没问题,安卓原生浏览器和安卓微信上有问题。使用了css3动画的元素z-index失效,兄弟元素设置多高的z-index都盖不住解决办...

诡异的层级错乱:一个被transform隐藏的CSS陷阱

周五下午三点十七分,设计部突然发来紧急截图——原本应该悬浮在顶部的导航菜单,此刻正诡异地被下方的轮播图遮挡。我盯着屏幕上错乱的层级关系,手指下意识地敲下z-index:9999,心里清楚这不过是程序...

动画篇--碎片动画

本文授权转载,作者:Sindri的小巢(简书)前言从最开始动笔动画篇的博客,至今已经过去了四个多月。这段时间回头看了看自己之前的动画文章,发现用来讲解动画的例子确实不那么的赏心悦目。于是这段时间总是想...

Nature:大洋转换断层处的拉张构造与两阶段地壳增生

Nature:大洋转换断层处的拉张构造与两阶段地壳增生转换断层是三种基本的板块边界之一,全球总长度超过48000km(Bird,2003),它们的发现为板块构造理论的建立奠定了重要的基础(Wil...