在Java7与Tomcat8环境下使用WebSocket实现聊天的示例

文中案例在apache-tomcat-8.0.15和jdk1.8.0_25环境下开发,运行。不过标题上是Java7,并不造成影响,代码中没有涉及任何与jdk1.8.x相关的代码。另外之所以要讲清软件版本,一是为了保证案例能够有个明确的实现背景,二是websocket实现tomcat7.x与tomcat8.x有很大差异。

在JavaEE规范集中我们这里主要看Java API for WebSocket(JSR 356)。Websocket-api提供了Java实现Websocket的接口,其中最重要的几个类和注解如下图:

上图解释:

1.最上面4个注解OnClose,OnError, OnOpen, OnMessage用来标注一个POJO用来处理WebSocket请求的方法;

2.Endpoint和EndpointConfig分别定义了端点和端点相关配置的接口方法;

3.ClientEndpoint和ServerEndpoint分别定义了客户端和服务器端端点的接口方法;

4.Decoder和Encoder分别是解码和编码的接口方法定义;

5.Session是与Endpoint相关的WebSocket Session接口方法定义。

另外还有其它接口,这里作为初步了解Java websocket api仅列出最有必要的一些。

Tomcat8.x提供了JavaEE7的标准实现,其中WebSocket 1.1规范给予实现。在使用其开发的依赖环境是Tomcat8.x JDK7。Tomcat8.x提供了服务器端的实现,客户端实现需要借助其他实现如java_websocket。

Tomcat8.x对WebSocket实现感觉很明朗化了,既然API中定义了WebSocket相关的注解和Session那么Tomcat8.x实现中自然会有相应的处理和实现,下图是简单的关系描述。

 

上图解释:

  1. tomcat的WsSession类实现了Java WebSocket API中的Session接口
  2. PojoEndpointBase以及其子类处理与Endpoint相关的类或注解
  3. EndpointConfig,Endpoint都与Session的实现类之间存在依赖关系

通过了解Java Websocket API和Tomcat8.x对其的实现,认为使用Java WebSocket需要熟悉其中关键类或接口如:Endpoint,EndpointConfig,Client和Server,Encoder和Decoder,Session,MessageHandler。

上面大致介绍了Tomcat8.x对Java Websocket的实现,有关WebSocket规范的了解信息可以参考:

RFC6455: http://tools.ietf.org/html/rfc6455

WebSocket服务器端实现:https://java.net/projects/websocket-spec/pages/WebSocketAPIs

下面是通过代码示例来展示基于WebSocket的实时聊天

1.服务器端实现

package t8j8.examples;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/ws/chat/{nickName}")
public class Chat {

    /**
     * 连接对象集合
     */
    private static final Set<Chat> connections = new CopyOnWriteArraySet<Chat>();

    private String nickName;

    /**
     * WebSocket Session
     */
    private Session session;

    public Chat() {
    }

    /**
     * 打开连接
     * 
     * @param session
     * @param nickName
     */
    @OnOpen
    public void onOpen(Session session,
            @PathParam(value = "nickName") String nickName) {

        this.session = session;
        this.nickName = nickName;

        connections.add(this);
        String message = String.format("System> %s %s", this.nickName,
                " has joined.");
        Chat.broadCast(message);
    }

    /**
     * 关闭连接
     */
    @OnClose
    public void onClose() {
        connections.remove(this);
        String message = String.format("System> %s, %s", this.nickName,
                " has disconnection.");
        Chat.broadCast(message);
    }

    /**
     * 接收信息
     * 
     * @param message
     * @param nickName
     */
    @OnMessage
    public void onMessage(String message,
            @PathParam(value = "nickName") String nickName) {
        Chat.broadCast(nickName + ">" + message);
    }

    /**
     * 错误信息响应
     * 
     * @param throwable
     */
    @OnError
    public void onError(Throwable throwable) {
        System.out.println(throwable.getMessage());
    }

    /**
     * 发送或广播信息
     * 
     * @param message
     */
    private static void broadCast(String message) {
        for (Chat chat : connections) {
            try {
                synchronized (chat) {
                    chat.session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                connections.remove(chat);
                try {
                    chat.session.close();
                } catch (IOException e1) {
                }
                Chat.broadCast(String.format("System> %s %s", chat.nickName,
                        " has bean disconnection."));
            }
        }
    }
}

说明:

代码中ServerEndpoint注解的value值中有个nickName的参数占位符,该参数占位符称为路径参数,路径参数可以通过方法参数注解(@PathParam)进行设置并且获取;

在Endpoint注解的类中OnClose,OnOpen,OnError注解的方法只有一个,OnMessage注解的方法可以有多个这个容易理解因为WebSocket可能处理的信息有text,binary,textStream等。

2.客户端实现

如果使用Maven的话,可以添加java_websocket jar的依赖。

<dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.0</version>
            <scope>runtime</scope>
        </dependency>

如果开发Web客户端则可以选择支持WebSocket的浏览器,使用HTML5技术。

下面是使用java_websocket来实现客户端的代码:

package t8j8.examples.client;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Scanner;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.handshake.ServerHandshake;

public class TestTocatWebSocket {

    public static void main(String[] args) throws URISyntaxException {

        String url = "ws://localhost:8080/t8j8/ws/chat/" + args[0];
        WebSocketClient wc = new WebSocketClient(new URI(url), new Draft_17()) {

            @Override
            public void onOpen(ServerHandshake handshakedata) {
                System.out.println(handshakedata.getHttpStatusMessage());
            }

            @Override
            public void onMessage(String message) {
                System.out.println(message);
            }

            @Override
            public void onError(Exception ex) {
            }

            @Override
            public void onClose(int code, String reason, boolean remote) {
            }
        };

        wc.connect();

        while (true) {
            Scanner scanner = new Scanner(System.in);
            String message = scanner.nextLine();
            if (message.equals("q")) {
                wc.close();
                break;
            }
            scanner.close();
            wc.send(message);
        }
    }
}

说明:

客户端中要说明的是new Draft_17()对象的创建,通过类名可以得知草案的意思。由于Websocket标准迟迟没有发布,因而之前实现都是依据草案进行,而这里的Draft_17对应的WebSocket版本正是:【"Sec-WebSocket-Version", "13"  】可惜,java_websocket包迟迟没有更新内容,名称出现误解人的地方。

3.开始聊天

部署服务器端程序,启动客户端程序(需要添加nickName的参数)。

下面是聊天的截图,分别为Tom和Jack。

至此,关于使用Tomcat8和JDK7基于WebSocket实现的聊天示例就结束了。

时间: 2024-10-09 20:29:39

在Java7与Tomcat8环境下使用WebSocket实现聊天的示例的相关文章

【Spring Boot项目】Win7+JDK8+Tomcat8环境下的War包部署

一.pom.xml及启动类修改 pom.xml Step1:指定打包类型 <!-- 打包类型 jar 或 war --> <packaging>war</packaging> Step2:移除嵌入式tomcat插件 <!-- 支持web的模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-

脱离Tomcat环境下使用WebSocket即时通讯聊天的示例

A 代码生成器(开发利器);     增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面 都生成   就不用写搬砖的代码了,生成的放到项目里,可以直接运行B 阿里巴巴数据库连接池druid;  数据库连接池  阿里巴巴的 druid.Druid在监控.可扩展性.稳定性和性能方面都有明显的优势C 安全权限框架shiro ;  Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权,更安

并发环境下,不安全发布对象示例代码

package com.mm.concurrent; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestConcurrent { public static 

Solr6.0与Jetty、Tomcat在Win环境下搭建/部署

摘要: Solr6的新特性包括增强的edismax,对SQL更好的支持--并行SQL.JDBC驱动.更多的SQL语法支持等,并且在Solr6发布以后,Solr5还在持续更新,对于想尝鲜Solr6的用户来说,与之前版本有什么不同,让我们一起来探究一下. Solr6用默认的Jetty启动 需要的软件支持 JDK1.8以上 Solr6的安装包(solr-6.0.0.zip 大约140M) Solr自带一个Jetty环境,可以很方便的运行Solr. 直接到解压缩的solr/bin目录运行solr sta

window环境下将solr6.3部署到tomcat中

1.我下载的solr是6.3版本的,需要jdk1.8及以上,tomcat8 JDK1.8的下载地址:http://www.Oracle.com/technetwork/Java/javase/downloads/jdk8-downloads-2133151.html tomcat8的下载地址:http://tomcat.apache.org/download-80.cgi 注意:Window环境下下载的都是zip包 2.安装jdk,这里就省略了,参考其他文章 3.solr6.3发布版本本身就有一

Windows Azure+Windows+Linux多环境下Tomcat服务的安装及配置集合

Windows Azure+Windows+Linux多环境下的Tomcat服务的安装及配置集合 说到Tomcat服务,相信大家都很熟悉了,当然也这包括安装及配置:我们都知道Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求.实际上To

利用Redis实现集群或开发环境下SnowFlake自动配置机器号

前言: SnowFlake 雪花ID 算法是推特公司推出的著名分布式ID生成算法.利用预先分配好的机器ID,工作区ID,机器时间可以生成全局唯一的随时间趋势递增的Long类型ID.长度在17-19位.随着时间的增长而递增,在MySQL数据库中,InnoDB存储引擎可以更快的插入递增的主键.而不像UUID那样因为写入是乱序的,InnoDB不得不频繁的做页分裂操作,耗时且容易产生碎片. 对于SnowFlake 的原理介绍,可以参考该文章:理解分布式id生成算法SnowFlake 理解了雪花的基本原理

定制windows环境下cmd替代软件ConEmu

定制windows环境下cmd替代软件ConEmu 公认的是Windows环境下命令行界面太难用. 不管是cmd还是powershell都不顺手!!窗口宽度不能全屏,字体太难看还不能调整,窗口背景不能更换,永远的黑白配,最痛苦的是复制和粘贴.都不知道MS是怎么想的?搞个这么个反人类的东西出来,还万年不变,从Windows诞生到Windows7不论是桌面版还是服务器版都一样,到了windows8/windows10换成powershell一样的鸡肋. 在百度搜了一下,找到cmd的替代软件conem

《高可用MySQL》1 – Windows环境下压缩版MySQL安装

近日在读O'REILIY系列的<高可用MySQL>, 自然少不了主从(Master-Slave)配置和横向扩展相关的内容. Master-Slave这东西吧.在很多公司都是标配.开发中基本天天都用.遇到的问题自然也不少(如主从不同步,Master宕机).但操作权限很有限.有些东西,仅仅有自己看了.做了,才干真正知道原理是什么,也才干更好的去把握. 本文是高可用MySQL的第一篇读书笔记,主要记录Windows环境下压缩版MySQL(基于安装版的傻瓜式安装过程这里不再提及)的安装过程. 1. 从