Tomcat Websocket应用实例研究

news2024/11/25 3:04:38

概述

本文介绍了如何根据Tomcat给出的websocket实例,通过对实例的学习,定制自己基于websocket的应用。

环境及版本:

  1. Ubuntu 22.04.4 LTS
  2. Apache Tomcat/10.1.20
  3. openjdk 11.0.23 2024-04-16
  4. 浏览器:Chrome

相关资源及链接

Class Loader How-To:

Apache Tomcat 11 (11.0.0-M20) - Class Loader How-To

推荐几篇本站内介绍Websocket原理及tomcat附带的实例的文章,可作为参考:

Websocket原理-CSDN博客

看完让你彻底理解 WebSocket 原理_websocket原理-CSDN博客

Tomcat实现Web Socket_tomcat 9 wss服务配置-CSDN博客

Tomcat提供的websocket实例

Tomcat安装完成后给出的Examples中,包括了有关websocket的例子。

如上图,点击‘Examples’,进入如下界面:

继续点击‘WebSocket Examples’,进入如下界面:

点击‘Echo example’,进入如下界面:

从界面可以看出,Tomcat提供以下三种方式与服务器建立websocket双向通信:

  1. programmatic API
  2. annotation API (basic)
  3. annotation API (stream)

programmatic:编程式,即编写一个Java类继承javax.websocket.Endpoint(根据tomcat及openjdk的版本不同,或继承jakarta.websocket.Endpoint,本文中为jakarta),并实现它的onOpen、onClose和onError等方法。

annotation:注解式,实现一个业务类并给其添加websocket相关的注解(通过@ServerEndpoint(...)),注解表明当前业务类是已经实现了WebSocket规范的Endpoint。根据上面tomcat给出的实例界面显示,注解式又分为basic和stream两种模式。

本文不对上述三种方式展开详细讨论。

点击上面(tomcat)界面的三种websocket的实现方式,下方的编辑框中会同步显示将实际在代码中用到的websocket URL,例如点击‘annotation API (basic)’,下面编辑框的内容同步更新为‘ws://host/examples/websocket/echoAnnotation’,其中host为服务器的URL(含端口),以下均使用‘127.0.0.1:8080’作为默认值,例如:

ws://127.0.0.1:8080/examples/websocket/echoAnnotation

客户端浏览器将使用该URL串作为目标websocket服务器地址。

点击‘Connect’按钮,再点击‘Echo message’按钮,界面如下:

依葫芦画瓢

now,我们照着tomcat给出的实例依葫芦画瓢建立自己的websocket应用,并试图在这一过程中逐步理解tomcat的websocket实现原理以及相关的配置。

新建一个自己的webapp,例如命名为myws:

  1. 在目录‘opt/tomcat/webapps’新建目录‘myws’;
  2. 将examples实例下‘websocket’目录及其文件拷贝到‘myws’目录下;
  3. 在‘myws’目录下新建目录‘WEB-INF’;进入新建的‘WEB-INF’目录,继续创建目录‘classes’,此目录为本文涉及的tomcat 11加载Java类的默认目录!
  4. 将examples实例下的‘WEB-INF/classes/websocket’目录及其文件拷贝到myws应用下新建的‘classes’目录。

依葫芦画瓢(文件拷贝)暂时到此。

在新建的myws应用根目录下新建一个index.html文件,内容如下:

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<title>项目测试首页列表</title>

<style>

  body {

    background-color: lightblue;

  }

  h1 {

    text-align: center;

  }

  div.exam_list {

    font-family: verdana;

    font-size: 18px;

    margin-left: 100px;

    margin-top:5px;

  }

</style>

</head>

<body>

<h1>tomcat websocket应用学习</h1>

<p>

<div class="exam_list"><li><a href="/myws/websocket/index.xhtml">examples实例学习</a></li></div>

</p>

</body>

</html>

启动浏览器,输入URL,例如:http://hostname/myws,出现如下界面:

点击页面链接,进入如下界面(此界面与之前的完全相同):

点击‘Echo example’,进入如下界面(此界面与之前的完全相同):

分别点击tomcat下websocket的三种通信实现方式,下方编辑框的链接URI为:

  1. ws://127.0.0.1:8080/examples/websocket/echoProgrammatic
  2. ws://127.0.0.1:8080/examples/websocket/echoAnnotation
  3. ws://127.0.0.1:8080/examples/websocket/echoStreamAnnotation

点击页面其他按钮,并操作,一切正常,注意观察三个URL,其仍然连接的是安装包默认提供的examples项目上了,故一切正常

打开并编辑文件‘echo.xhtml’,注意如下代码行:

<div>

    <div id="connect-container">

        <div>

            <span>Connect to service implemented using:</span>

            <br/>

            <!-- echo example using new programmatic API on the server side -->

            <input id="radio1" type="radio" name="group1" value="/examples/websocket/echoProgrammatic"

                   onclick="updateTarget(this.value);"/> <label for="radio1">programmatic API</label>

            <br/>

            <!-- echo example using new annotation API on the server side -->

            <input id="radio2" type="radio" name="group1" value="/examples/websocket/echoAnnotation"

                   onclick="updateTarget(this.value);"/> <label for="radio2">annotation API (basic)</label>

            <br/>

            <!-- echo example using new annotation API on the server side -->

            <input id="radio3" type="radio" name="group1" value="/examples/websocket/echoStreamAnnotation"

                   onclick="updateTarget(this.value);"/> <label for="radio3">annotation API (stream)</label>

            <br/>

            <!-- echo example using new annotation API on the server side -->

            <!-- Disabled by default -->

            <!--

            <input id="radio4" type="radio" name="group1" value="/examples/websocket/echoAsyncAnnotation"

                   οnclick="updateTarget(this.value);"/> <label for="radio4">annotation API (async)</label>

            -->

        </div>

根据代码,如前所述,每当用户点击了不同的通信方式,页面会自动更新websocket连接,其中实例代码还注释掉了第四种方式‘AsynAnntation’。

将上述代码中高亮的‘examples’替换为本项目名称‘myws’。刷新页面,点击选择不同的通信方式,确认编辑框中websocket连接URL更新。

回到页面进行操作,OK!一切正常!!!

温馨提示(重要的问题说三遍),在测试页面之前务必通过tomcat的管理页面重新启动web应用,界面如下:

点击‘停止’按钮,再点击‘启动’按钮。

不知道如何配置管理页面的,可直接重启tomcat服务。

重要的事情说三遍!!!一定记得重启应用!

tomcat三种websocket通信方式测试

一个小测试:

查看目录‘myws/WEB-INF/classes/websocket’,除了四个子目录,注意该目录下有两个文件,一个是‘ExamplesConfig.java’,另一个是对应的class文件。

从项目目录中删除该两个文件,重新启动web应用,再次进入Echo example界面,同样进行三种方式的通信测试,其中后两种(基础注解式/annotation API (basic)和流式注解式/annotation API (stream))正常,第一种‘编程式’连接失败,连接失败界面如下。

查看目录‘myws/WEB-INF/classes/websocket/echo’,该目录下文件列表如下图。

再次回顾前文提到的三种通信方式的URL,如下:

  1. ws://127.0.0.1:8080/examples/websocket/echoProgrammatic
  2. ws://127.0.0.1:8080/examples/websocket/echoAnnotation
  3. ws://127.0.0.1:8080/examples/websocket/echoStreamAnnotation

查看文件EchoAnnotation.java,在类定义之前有一处申明,代码如下:

注解式下,通过‘@ServerEndpoint’添加注解后,在项目(网站)启动时tomcat服务会自动扫描(WEB-INF/calsses目录下)java类,并将注解类与ws服务关联。

查看文件EchoStreamAnnotation.java,同样有一处类似的申明,如下:

在EchoEndpoint.java文件中,没有发现类似的注解。

所以,在删除了文件ExampleConfig(并重新启动应用)后,注解式的方式依然有效,编程式的方式连接失败。

重新拷贝ExampleConfig.java/.class到应用目录,查看ExampleConfig.java,内容如下:

package websocket;

import java.util.HashSet;

import java.util.Set;

import jakarta.websocket.Endpoint;

import jakarta.websocket.server.ServerApplicationConfig;

import jakarta.websocket.server.ServerEndpointConfig;

import websocket.drawboard.DrawboardEndpoint;

import websocket.echo.EchoEndpoint;

public class ExamplesConfig implements ServerApplicationConfig {

    @Override

    public Set<ServerEndpointConfig> getEndpointConfigs(

            Set<Class<? extends Endpoint>> scanned) {

        Set<ServerEndpointConfig> result = new HashSet<>();

        if (scanned.contains(EchoEndpoint.class)) {

            result.add(ServerEndpointConfig.Builder.create(

                    EchoEndpoint.class,

                    "/websocket/echoProgrammatic").build());

        }

        if (scanned.contains(DrawboardEndpoint.class)) {

            result.add(ServerEndpointConfig.Builder.create(

                    DrawboardEndpoint.class,

                    "/websocket/drawboard").build());

        }

        return result;

    }

    @Override

    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {

        // Deploy all WebSocket endpoints defined by annotations in the examples

        // web application. Filter out all others to avoid issues when running

        // tests on Gump

        Set<Class<?>> results = new HashSet<>();

        for (Class<?> clazz : scanned) {

            if (clazz.getPackage().getName().startsWith("websocket.")) {

                results.add(clazz);

            }

        }

        return results;

    }

}

首先类ExampleConfig继承自ServerApplicationConfig,该类会执行目录自动扫描,对于目录(及子目录)下所有继承自‘Endpoint’的类进行处理,并分别映射了两个ws服务:

  1. "/websocket/echoProgrammatic"
  2. "/websocket/drawboard"

其中第一个正是echo测试中的第一种基于编程式的通信方式所对应的服务,第二个为多人协同画板应用的实例服务(对应的注册名称)。

对于所有注解式实现的websocket服务(类),示例代码中进行了过滤操作,即任何不是以‘websocket.’开头的服务,都将被屏蔽。上面的实际测试中(删除ExamplesConfig),注解式的不需要代码中的add(clazz)操作也可以正常工作。

另外,在自己的应用中,可将配置文件/类(ExamplesConfig)更改为项目对应的名称,例如本例中更改为MywsConfig.java/class,记得类名与文件一致,重新编译.java,并重启web应用。

记录一下ubuntu下成功编译MywsConfig.java的命令(好记性不如烂笔头),主要是指定import的相关库/类的路径,如下:

javac -cp /opt/tomcat/webapps/myws/WEB-INF/classes:/opt/tomcat/lib/* MywsConfig.java

其他

Tomcat有关websocket实现的包在目录$CATALINA_HOME/lib($CATALINA_HOME的默认安装目录为‘/opt/tomcat’)下,包含三个文件,如下图:

本文未涉及注解式以及编程式websocket通信的各接口的分析,相关文章可在站内搜索。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大模型精调:实现高效迁移学习的艺术

在人工智能领域&#xff0c;大型预训练模型&#xff08;以下简称“大模型”&#xff09;已经取得了令人瞩目的成果。这些模型通过在海量数据上进行预训练&#xff0c;能够捕捉到丰富的特征信息&#xff0c;为各种下游任务提供强大的支持。然而&#xff0c;如何将这些大模型应用…

如何用Vue3打造一个炫酷的树状图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 Vue.js 的 Treemap 可视化组件 应用场景介绍 Treemap 可视化组件是一种强大的工具&#xff0c;用于以直观的方式展示分层数据。它将数据点绘制为矩形&#xff0c;其中每个矩形的大小与数据点的大小成正比…

【牛客面试必刷TOP101】Day33.BM70 兑换零钱(一)和BM71 最长上升子序列(一)

文章目录 前言一、BM70 兑换零钱(一)题目描述题目解析二、BM71 最长上升子序列(一)题目描述题目解析总结 前言 一、BM70 兑换零钱(一) 题目描述 描述&#xff1a; 给定数组arr&#xff0c;arr中所有的值都为正整数且不重复。每个值代表一种面值的货币&#xff0c;每种面值的货币…

C++ 60 之 虚析构和纯虚析构

#include <iostream> #include <string> #include <cstring> using namespace std;class Animal13{ public:Animal13(){cout << "Animal的默认构造函数" << endl;}virtual void speak(){cout << "动物叫" << en…

SD卡可以格式化成NTFS吗 SD卡Mac怎么读取内容

SD卡作为便携式存储媒介&#xff0c;广泛应用于我们的日常生活与工作之中。而NTFS&#xff0c;作为一种先进的文件系统&#xff0c;因其强大的功能和安全性&#xff0c;在Windows平台备受青睐。然而&#xff0c;当谈及将SD卡格式化为NTFS这一话题时&#xff0c;用户的疑惑随之而…

每日一练:攻防世界:Ditf

这是难度1的题吗&#xff1f;&#xff1f;&#xff1f; 拿到一个png图片&#xff0c;第一反应就是CRC爆破&#xff0c;结果还真的是高度被修改了 这里拿到一个字符串&#xff0c;提交flag结果发现不是&#xff0c;那么只可能是密钥之类的了 看看有没有压缩包&#xff0c;搜索…

超图论文细品——2019年AAAI《Hypergraph Neural Networks》

我是“导航” 1 摘要1.1 简介1.2 问题描述 2 超图2.1 图和超图对比 参考 1 摘要 1.1 简介 文章提出了一种名为超图神经网络的框架&#xff0c;用于高维数据的表示学习。 该方法英文称呼为 Hypergraph Neural Networks&#xff0c;简写为 HGNN。 1.2 问题描述 传统的 GNN 是…

多模态大模型通用模式

MM-LLMs&#xff08;多模态大模型&#xff09;是目前比较新的和实用价值越发显著的方向。其指的是基于LLM的模型&#xff0c;具有接收、推理和输出多模态信息的能力。这里主要指图文的多模态。 代表模型&#xff1a;GPT-4o、Gemini-1.5-Pro、GPT-4v、Qwen-VL、CogVLM2、GLM4V、…

服务器测试之硬盘规格扫盲贴

最近整理了AVL系统里的SSD相关规格信息&#xff0c;来个了解硬盘规格信息的扫盲贴,过程很曲折&#xff0c;但是认为学习一下相关规格参数还是很有用的 1.什么是硬盘 硬盘是计算机最主要的存储设备&#xff0c;平常买电脑的时候看到的配置24G1T里的1T就是硬盘&#xff0c;计算机…

ECharts 词云案例三:2024年阅读关键词

ECharts 词云案例三&#xff1a;2024年阅读关键词 引言 在数据可视化领域&#xff0c;ECharts 以其强大的功能性和灵活性&#xff0c;成为开发者和设计师的首选工具之一。继上一篇关于 ECharts 词云图的详细介绍后&#xff0c;本文将探索词云图的进阶应用——使用蒙版来创造更…

【Linux】—在Linux中搭建Python环境

文章目录 前言一、检查Linux系统是否自带Python版本。二、安装依赖包(重要)三、下载Python-3.9.5安装包四、下载完成后&#xff0c;通过xftp6上传到Linux服务器上五、解压Python安装包六、编译安装Python七、配置Python环境变量八、运行Python&#xff0c;查看是否可用九、pyth…

如何用Excel随机抽取幸运儿

在举行年会等活动&#xff0c;会在大屏幕互动随机滚动抽取幸运观众&#xff0c;有专门开发的软件或程序&#xff1b; 对于我们日常工作中有时会遇到&#xff0c;如何在群体中随机抽取部分幸运儿的问题&#xff1f; 除了抓阄&#xff0c;当然也可以用Excel解决哦&#xff0c;今…

适合小白学习的项目1906java Web智慧食堂管理系统idea开发mysql数据库web结构java编程计算机网页源码servlet项目

一、源码特点 java Web智慧食堂管理系统是一套完善的信息管理系统&#xff0c;结合java 开发技术和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 前段主要技术 bootstra…

现在市面上哪个大大数据信用查询平台比较好用?

在当今信息化和数字化的时代&#xff0c;信用查询平台的重要性愈发突出&#xff0c;特别是在个人贷款、信用卡申请和金融服务领域。选择一个优秀的大数据信用查询平台&#xff0c;不仅可以帮助用户全面了解自己的信用状况&#xff0c;还能提供针对性的解读和建议&#xff0c;帮…

中国天辰×蓝卓丨共创行业级工业操作系统,加速培育新质生产力!

6月17日&#xff0c;中国天辰工程有限公司&#xff08;以下简称“中国天辰”&#xff09;党委委员、总经理梁军湘一行莅临蓝卓&#xff0c;双方就工业互联网平台合作进行座谈交流。蓝卓总经理谭彰、副总经理蓝照斌、总经理助理俞益标&#xff0c;以及中控技术副总裁吴才宝、大客…

阿里又出AI神器,颠覆传统图像编辑,免费开源!

文章首发于公众号&#xff1a;X小鹿AI副业 大家好&#xff0c;我是程序员X小鹿&#xff0c;前互联网大厂程序员&#xff0c;自由职业2年&#xff0c;也一名 AIGC 爱好者&#xff0c;持续分享更多前沿的「AI 工具」和「AI副业玩法」&#xff0c;欢迎一起交流~ 最近阿里开源了 Mi…

玩转编程的终极挑战,C++究竟有多难?

C是一门非常强大和灵活的编程语言&#xff0c;它可以实现面向对象、泛型、元编程等多种编程范式&#xff0c;可以开发高性能的系统软件、游戏、图形、网络等各种应用。但是&#xff0c;C也是一门非常复杂和难学的语言&#xff0c;很多初学者在学习C的过程中会遇到很多困难和挫折…

YOLOv8目标检测算法在地平线Bernoulli2架构BPU上高效部署参考(PTQ方案)30fps!

—— 以RDK X3为例&#xff0c;修改Head部分&#xff0c;8ms疾速Python后处理程序&#xff0c;30fps稳稳当当 本文在地平线对YOLOv8s的Backbone修改的基础上&#xff0c;提出一种在地平线Bernoulli2架构BPU上部署YOLOv8的后处理思路。使用640640分辨率&#xff0c;80类别基于C…

【STM32入门学习】定时器与PWM的LED控制

目录 一、定时器与PWM介绍 1.1定时器 1.1.1定时器分类简介 1.1.2STM32定时器分类比较表 1.1.3定时器启动操作&#xff1a; 1.2 PWM 1.2.1 简介&#xff1a; 1.2.2PWM工作原理 1.2.3使用步骤&#xff1a; 二、定时器计数控制LED灯亮灭 2.1HAL库 2.1.1使用HAL库创建…

如何选择适合自己的收银系统源码?

提到收银系统源码&#xff0c;想必很多企业都为此头疼&#xff0c;收银系统厂商五花八门&#xff0c;价格从几千元&#xff0c;到几十万元&#xff0c;甚至上百万元不等。到底如何选择一套适合自己的收银系统源码呢&#xff1f;本文我将结合自己8年从业经验展推荐大家从以下几个…