我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何用JavaEE7、Websockets和GlassFish4打造聊天室(一)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何用JavaEE7、Websockets和GlassFish4打造聊天室(一)

今天就跟大家聊聊有关如何用JavaEE7、Websockets和GlassFish4打造聊天室(一),可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

Java EE 7已经在今年正式发布了,新增加了很多新的功能和特性,如新增或更新了不少的JSR标准。其中特别受到关注的是Websockets。它的一个好处之一是减少了不必要的网络流量。它主要是用于在客户机和服务器之间建立单一的双向连接。这意味着客户只需要发送一个请求到服务端,那么服务端则会进行处理,处理好后则将其返回给客户端,客户端则可以在等待这个时间继续去做其他工作,整个过程是异步的。在本系列教程中,将指导用户如何在JAVA EE 7的容器GlassFish 4中,使用JAVA EE 7中的全新的解析Json  API(JSR-353),以及综合运用jQuery和Bootstrap。本文要求读者有一定的HTML 5 Websocket的基础原理知识。

效果图

我们先来看下在完成这个教程后的效果图,如下所示:

如何用JavaEE7、Websockets和GlassFish4打造聊天室(一)

准备工作

我们使用的是JDK 7 和MAVN 3进行库的构建工作,首先看pom.xml中关于Jave EE 7的部分:

 <properties>     <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>   <dependencies>     <dependency>         <groupId>javax</groupId>         <artifactId>javaee-api</artifactId>         <version>7.0</version>         <scope>provided</scope>     </dependency> </dependencies>   <build>     <plugins>         <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-compiler-plugin</artifactId>             <version>3.1</version>             <configuration>                 <source>1.7</source>                 <target>1.7</target>                 <compilerArguments>                     <endorseddirs>${endorsed.dir}</endorseddirs>                 </compilerArguments>             </configuration>         </plugin>         <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-war-plugin</artifactId>             <version>2.3</version>             <configuration>                 <failOnMissingWebXml>false</failOnMissingWebXml>             </configuration>         </plugin>         <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-dependency-plugin</artifactId>             <version>2.6</version>             [..]         </plugin>     </plugins> </build>

同时,为了能使用GlassFish 4,需要增加如下的插件:

plugin>     <groupId>org.glassfish.embedded</groupId>     <artifactId>maven-embedded-glassfish-plugin</artifactId>     <version>4.0</version>     <configuration>         <goalPrefix>embedded-glassfish</goalPrefix>         <app>${basedir}/target/${project.artifactId}-${project.version}.war</app>         <autoDelete>true</autoDelete>         <port>8080</port>         <name>${project.artifactId}</name>         <contextRoot>hascode</contextRoot>     </configuration>     <executions>         <execution>             <goals>                 <goal>deploy</goal>             </goals>         </execution>     </executions> </plugin>

设置Websocket的Endpoint

我们先来看服务端Websocket的代码如下,然后再做进一步解析:

package com.hascode.tutorial;   import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger;   import javax.websocket.EncodeException; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint;   @ServerEndpoint(value = "/chat/{room}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class) public class ChatEndpoint {     private final Logger log = Logger.getLogger(getClass().getName());       @OnOpen     public void open(final Session session, @PathParam("room") final String room) {         log.info("session openend and bound to room: " + room);         session.getUserProperties().put("room", room);     }       @OnMessage     public void onMessage(final Session session, final ChatMessage chatMessage) {         String room = (String) session.getUserProperties().get("room");         try {             for (Session s : session.getOpenSessions()) {                 if (s.isOpen()                         && room.equals(s.getUserProperties().get("room"))) {                     s.getBasicRemote().sendObject(chatMessage);                 }             }         } catch (IOException | EncodeException e) {             log.log(Level.WARNING, "onMessage failed", e);         }     } }

面分析下上面的代码:

使用@ ServerEndpoint定义一个新的endpoint,其中的值指定了URL并且可以使用PathParams参数,就象在JAX-RS中的用法一样。

所以值“/chat/{room}”允许用户通过如下形式的URL去连接某个聊天室:ws://0.0.0.0:8080/hascode/chat/java

在大括号中的值(即room),可以通过使用javax.websocket.server.PathParam,在endpoint的生命周期回调方法中以参数的方式注入。

此外,我们要使用一个编码和解码的类,因为我们使用的是一个DTO形式的类,用于在服务端和客户端传送数据。

当用户第一次连接到服务端,输入要进入聊天室的房号,则这个房号以参数的方式注入提交,并且使用session.getUserProperties将值保存在用户的属性map中。

当一个聊天参与者通过tcp连接发送信息到服务端,则循环遍历所有已打开的session,每个session被绑定到指定的聊天室中,并且接收编码和解码的信息。

如果我们想发送简单的文本信息或和二进制格式的信息,则可以使用session.getBasicRemote().sendBinary() 或session.getBasicRemote().sendText()

接下来我们看下用于代表信息传递实体(DTO:Data Transfer Object)的代码,如下:

package com.hascode.tutorial;   import java.util.Date;   public class ChatMessage {     private String message;     private String sender;     private Date received;       // 其他getter,setter方法 }

聊天消息的转换

在这个应用中,将编写一个编码和解码类,用于在聊天信息和JSON格式间进行转换。

先来看下解码类的实现,这将会把传递到服务端的聊天信息转换为ChatMessage实体类。在这里,使用的是Java API for JSON Processing(JSR353)(参考:

http://jcp.org/en/jsr/detail?id=353)规范去将JSON格式的信息转换为实体类,代码如下,其中重写的willDecode方法,这里默认返回为true。

package com.hascode.tutorial;   import java.io.StringReader; import java.util.Date;   import javax.json.Json; import javax.json.JsonObject; import javax.websocket.DecodeException; import javax.websocket.Decoder; import javax.websocket.EndpointConfig;   public class ChatMessageDecoder implements Decoder.Text<ChatMessage> {     @Override     public void init(final EndpointConfig config) {     }       @Override     public void destroy() {     }       @Override     public ChatMessage decode(final String textMessage) throws DecodeException {         ChatMessage chatMessage = new ChatMessage();         JsonObject obj = Json.createReader(new StringReader(textMessage))                 .readObject();         chatMessage.setMessage(obj.getString("message"));         chatMessage.setSender(obj.getString("sender"));         chatMessage.setReceived(new Date());         return chatMessage;     }       @Override     public boolean willDecode(final String s) {         return true;     } }

同样再看下编码类的代码,这个类相反,是将ChatMessage类转换为Json格式,代码如下:

package com.hascode.tutorial;   import javax.json.Json; import javax.websocket.EncodeException; import javax.websocket.Encoder; import javax.websocket.EndpointConfig;   public class ChatMessageEncoder implements Encoder.Text<ChatMessage> {     @Override     public void init(final EndpointConfig config) {     }       @Override     public void destroy() {     }       @Override     public String encode(final ChatMessage chatMessage) throws EncodeException {         return Json.createObjectBuilder()                 .add("message", chatMessage.getMessage())                 .add("sender", chatMessage.getSender())                 .add("received", chatMessage.getReceived().toString()).build()                 .toString();     } }

这里可以看到JSR-353的强大威力,只需要调用Json.createObjectBuilder就可以轻易把一个DTO对象转化为JSON了。

通过Bootstrap、Javacsript搭建简易客户端

最后,我们综合运用著名的Bootstrap、jQuery框架和Javascript设计一个简易的客户端。我们在class="lazy" data-src/main/weapp目录下新建立index.html文件,代码如下:

<!DOCTYPE html> <html lang="en"> <head> [..] <script>     var wsocket;     var serviceLocation = "ws://0.0.0.0:8080/hascode/chat/";     var $nickName;     var $message;     var $chatWindow;     var room = '';       function onMessageReceived(evt) {         //var msg = eval('(' + evt.data + ')');         var msg = JSON.parse(evt.data); // native API         var $messageLine = $('<tr><td class="received">' + msg.received                 + '</td><td class="user label label-info">' + msg.sender                 + '</td><td class="message badge">' + msg.message                 + '</td></tr>');         $chatWindow.append($messageLine);     }     function sendMessage() {         var msg = '{"message":"' + $message.val() + '", "sender":"'                 + $nickName.val() + '", "received":""}';         wsocket.send(msg);         $message.val('').focus();     }       function connectToChatserver() {         room = $('#chatroom option:selected').val();         wsocket = new WebSocket(serviceLocation + room);         wsocket.onmessage = onMessageReceived;     }       function leaveRoom() {         wsocket.close();         $chatWindow.empty();         $('.chat-wrapper').hide();         $('.chat-signin').show();         $nickName.focus();     }       $(document).ready(function() {         $nickName = $('#nickname');         $message = $('#message');         $chatWindow = $('#response');         $('.chat-wrapper').hide();         $nickName.focus();           $('#enterRoom').click(function(evt) {             evt.preventDefault();             connectToChatserver();             $('.chat-wrapper h3').text('Chat # '+$nickName.val() + "@" + room);             $('.chat-signin').hide();             $('.chat-wrapper').show();             $message.focus();         });         $('#do-chat').submit(function(evt) {             evt.preventDefault();             sendMessage()         });           $('#leave-room').click(function(){             leaveRoom();         });     }); </script> </head>   <body>       <div class="container chat-signin">         <form class="form-signin">             <h3 class="form-signin-heading">Chat sign in</h3>             <label for="nickname">Nickname</label> <input type="text"                 class="input-block-level" placeholder="Nickname" id="nickname">             <div class="btn-group">                 <label for="chatroom">Chatroom</label> <select size="1"                     id="chatroom">                     <option>arduino</option>                     <option>java</option>                     <option>groovy</option>                     <option>scala</option>                 </select>             </div>             <button class="btn btn-large btn-primary" type="submit"                 id="enterRoom">Sign in</button>         </form>     </div>     <!-- /container -->       <div class="container chat-wrapper">         <form id="do-chat">             <h3 class="alert alert-success"></h3>             <table id="response" class="table table-bordered"></table>             <fieldset>                 <legend>Enter your message..</legend>                 <div class="controls">                     <input type="text" class="input-block-level" placeholder="Your message..." id="message" style="height:60px"/>                     <input type="submit" class="btn btn-large btn-block btn-primary"                         value="Send message" />                     <button class="btn btn-large btn-block" type="button" id="leave-room">Leave                         room</button>                 </div>             </fieldset>         </form>     </div> </body> </html>

在上面的代码中,要注意如下几点:

在Javascript端要调用websocket的话,要用如下的方式发起连接即可:ws://IP:PORT/CONTEXT_PATH/ENDPOINT_URL e.g ws://0.0.0.0:8080/hascode/chat/java

创建一个Websocket连接的方法很简单,使用的是var wsocket = new WebSocket(&lsquo;ws://0.0.0.0:8080/hascode/chat/java&rsquo;);

要获得来自服务端返回的信息,只需要在回调函数wsocket.onmessage中设置对应的获取返回信息的方法即可。

发送一个Websocket消息到服务端,使用的方法是wsocket.send(),其中可以发送的消息可以文本或者二进制数据。

关闭连接使用的是wsocket.close()。

Websocket中还有其他很多种用法,具体的可以参考其标准规范文档(http://tools.ietf.org/html/rfc6455)

最后,我们通过

mvn  package embedded-glassfish:run

进行代码的部署,然后就可以看到本文开始部分截图的效果。

看完上述内容,你们对如何用JavaEE7、Websockets和GlassFish4打造聊天室(一)有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网行业资讯频道,感谢大家的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何用JavaEE7、Websockets和GlassFish4打造聊天室(一)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何用JavaEE7、Websockets和GlassFish4打造聊天室(一)

今天就跟大家聊聊有关如何用JavaEE7、Websockets和GlassFish4打造聊天室(一),可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java EE 7已经在今年正式发布
2023-06-17

如何利用Python打造一个多人聊天室

这篇文章主要介绍如何利用Python打造一个多人聊天室,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、实验名称建立聊天工具二、实验目的掌握Socket编程中流套接字的技术,实现多台电脑之间的聊天。三、实验内容和要求
2023-06-22

如何用webSocket与Swoole打造一个小型聊天室

这篇文章主要介绍了如何用webSocket与Swoole打造一个小型聊天室的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何用webSocket与Swoole打造一个小型聊天室文章都会有所收获,下面我们一起来看
2023-06-29

如何使用MySQL和Java实现一个简单的聊天室功能

要使用MySQL和Java实现一个简单的聊天室功能,你需要进行以下步骤:1. 创建数据库和表:使用MySQL创建一个数据库,并在该数据库中创建一个用于存储聊天记录的表。表的结构可以包括字段如下:- id:聊天记录的唯一标识- sender:
2023-10-10

如何使用MySQL和Java实现一个简单的聊天室功能

使用MySQL和Java实现聊天室本指南将指导您使用MySQL数据库和Java编程语言实现一个简单的聊天室功能。我们将创建一个MySQL表来存储消息,并编写Java代码来连接到数据库、处理消息并创建服务器和客户端。通过遵循本指南,您将学习如何建立一个基本的聊天室应用程序。
如何使用MySQL和Java实现一个简单的聊天室功能
2024-04-10

如何使用Go语言和Redis实现在线聊天室

如何使用Go语言和Redis实现在线聊天室引言:随着互联网的迅速发展,社交网络已经成为人们日常生活中不可或缺的一部分。在线聊天室作为社交网络中的一个重要组成部分,具有便捷、实时、交互性强等特点受到人们的欢迎。本文以Go语言和Redis为基础
2023-10-27

如何利用C++实现一个简单的聊天室程序?

如何利用C++实现一个简单的聊天室程序?在信息时代,人们越来越注重网络交流。而聊天室作为一种常见的沟通工具,具有实时性和交互性的特点,被广泛应用于各个领域。本文将介绍如何利用C++语言实现一个简单的聊天室程序。首先,我们需要建立一个基于客户
如何利用C++实现一个简单的聊天室程序?
2023-11-04

如何用Node.JS打造一个恶劣天气实时预警系统

这篇文章主要讲解了“如何用Node.JS打造一个恶劣天气实时预警系统”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何用Node.JS打造一个恶劣天气实时预警系统”吧!序言:这几日,无论是打
2023-06-25

如何使用MySQL和JavaScript实现一个简单的即时聊天功能

如何使用MySQL和JavaScript实现一个简单的即时聊天功能随着社交媒体的普及,即时聊天已经成为了人们日常生活中必不可少的一部分。在这篇文章中,我们将介绍如何使用MySQL和JavaScript来实现一个简单的即时聊天功能。首先,我们
2023-10-22

如何使用HTML和CSS实现一个简单的聊天页面布局

随着现代科技的发展,人们越来越依赖于互联网来进行沟通和交流。而在网页中,聊天页面是一种非常常见的布局需求。本文将向大家介绍如何使用HTML和CSS来实现一个简单的聊天页面布局,并给出具体的代码示例。首先,我们需要创建一个HTML文件,可以使
2023-10-21

如何使用树莓派和Rocket.Chat构建一个私人聊天服务器

这篇文章主要为大家展示了“如何使用树莓派和Rocket.Chat构建一个私人聊天服务器”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用树莓派和Rocket.Chat构建一个私人聊天服务器”
2023-06-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录