JavaEE7+Websockets+GlassFish4打造聊天室

在客户机和服务器之间建立单一的双向连接,这就意味着客户只需要发送一个请求到服务端,那么服务端则会进行处理,处理好后则将其返回给客户端,客户端则可以在等待这个时间继续去做其他工作,整个过程是异步的。在本系列教程中,将指导用户如何在JAVA EE 7的容器GlassFish 4中,使用JAVA EE 7中的全新的解析Json API(JSR-353),以及综合运用jQuery和Bootstrap。本文要求读者有一定的HTML 5 Websocket的基础原理知识。

效果图

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

准备工作

我们使用的是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)规范去将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设计一个简易的客户端。我们在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 h2').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">
   <h2 class="form-signin-heading">Chat sign in</h2>
   <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">
   <h2 class="alert alert-success"></h2>
   <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(‘ws://0.0.0.0:8080/hascode/chat/java');

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

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

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

最后,我们通过mvn package embedded-glassfish:run进行代码的部署,然后就可以看到本文开始部分截图的效果。

以上就是用JavaEE7、Websockets和GlassFish4实现的聊天室,希望对大家的学习有所帮助。

(0)

相关推荐

  • 使用Java和WebSocket实现网页聊天室实例代码

    在没介绍正文之前,先给大家介绍下websocket的背景和原理: 背景 在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更

  • 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室

    一,利用Node搭建静态服务器 这个是这个项目的底层支撑部分.用来支持静态资源文件像html, css, gif, jpg, png, javascript, json, plain text等等静态资源的访问.这里面是有一个mime类型的文件映射. mime.js /** * mime类型的 map * @ author Cheng Liufeng * @ date 2014/8/30 * 当请求静态服务器文件的类型 html, css, gif, jpg, png, javascript,

  • php+html5基于websocket实现聊天室的方法

    本文实例讲述了php+html5基于websocket实现聊天室的方法.分享给大家供大家参考.具体如下: html5的websocket 实现了双向通信,折腾了几天弄了个聊天室,分享给大家 <?php error_reporting(E_ALL); ob_implicit_flush(); $sk=new Sock('127.0.0.1',8000); $sk->run(); class Sock{ public $sockets; public $users; public $master;

  • nodejs实现的一个简单聊天室功能分享

    今天我来实现一个简单的聊天室,后台用nodejs, 客户端与服务端通信用socket.io,这是一个比较成熟的websocket框架. 初始工作 1.安装express, 用这个来托管socket.io,以及静态页面,命令npm install express --save,--save可以使包添加到package.json文件里. 2.安装socket.io,命令npm install socket.io --save. 编写服务端代码 首先我们通过express来托管网站,并附加到socke

  • WebSocket+node.js创建即时通信的Web聊天服务器

    本文实例node.js创建即时通信的Web聊天服务器,供大家参考,具体内容如下 1.使用nodejs-websocket  nodejs-websocket是基于node.js编写的一个后端实现websocket协议的库,  连接:https://github.com/sitegui/nodejs-websocket.  (1)安装  在项目目录下通过npm安装:npm install nodejs-websocket  (2)创建服务器 //引入nodejs-websocket var ws

  • php基于websocket搭建简易聊天室实践

    本文实例讲述了php基于websocket搭建简易聊天室实践.分享给大家供大家参考.具体如下: 1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短连接和长连接.短连接一般可以用ajax实现,长连接就是websocket.短连接实现起来比较简单,但是太过于消耗资源.websocket高效不过兼容存在点问题.websocket是html5的资源 2.前

  • 使用JavaWeb webSocket实现简易的点对点聊天功能实例代码

    首先给大家声明一点:需要 jdk 7 , tomcat需要支持websocket的版本  1.InitServlet 该类主要是用来初始化构造将来存储用户身份信息的map仓库,利用其初始化方法Init 初始化仓库, 利用其静态方法getSocketList 获得对应的用户身份信息. webSocket ,我认为MessageInbound 用来识别登录人的信息,用它来找到对应的人,推送消息.每次登录都会产生一个MessageInbound. 这里的 HashMap<String,MessageI

  • websocket+node.js实现实时聊天系统问题咨询

    1.最近新学习websocket.做了一个实时聊天.用Node.js搭建的服务:serevr.js. 两个相互通信页面:client.html 和server.html 但是就是有很多问题,想让知道的人帮我看看哈: 我先把代码贴出来: server.js: var ws=require("nodejs-websocket"); console.log("开始建立连接..."); var str1=null,str2=null, clientReady=false,s

  • HTML5基于Tomcat 7.0实现WebSocket连接并实现简单的实时聊天

    1.什么是WebSocket? WebSocket 是一种自然的全双工.双向.单套接字连接.使用WebSocket,你的HTTP 请求变成打开WebSocket 连接(WebSocket 或者WebSocket over TLS(TransportLayer Security,传输层安全性,原称"SSL"))的单一请求,并且重用从客户端到服务器以及服务器到客户端的同一连接.WebSocket 减少了延迟,因为一旦建立起WebSocket 连接,服务器可以在消息可用时发送它们.例如,和轮

  • JavaEE7+Websockets+GlassFish4打造聊天室

    在客户机和服务器之间建立单一的双向连接,这就意味着客户只需要发送一个请求到服务端,那么服务端则会进行处理,处理好后则将其返回给客户端,客户端则可以在等待这个时间继续去做其他工作,整个过程是异步的.在本系列教程中,将指导用户如何在JAVA EE 7的容器GlassFish 4中,使用JAVA EE 7中的全新的解析Json API(JSR-353),以及综合运用jQuery和Bootstrap.本文要求读者有一定的HTML 5 Websocket的基础原理知识. 效果图 我们先来看下在完成这个教程

  • 使用WebSocket实现即时通讯(一个群聊的聊天室)

    随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据. 传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据:这种客户端是主动方,服务端是被动方的传统Web模式对于信息变化不频繁的Web应用来说造成的麻烦

  • Django使用channels + websocket打造在线聊天室

    Channels是Django团队研发的一个给Django提供websocket支持的框架,它同时支持http和websocket多种协议.使用channels可以让你的Django应用拥有实时通讯和给用户主动推送信息的功能. 演示效果如下所示: 什么是websocket? WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 WebSocket API

  • 利用Python打造一个多人聊天室的示例详解

    一.实验名称 建立聊天工具 二.实验目的 掌握Socket编程中流套接字的技术,实现多台电脑之间的聊天. 三.实验内容和要求 vii.掌握利用Socket进行编程的技术 viii.必须掌握多线程技术,保证双方可以同时发送 ix.建立聊天工具 x.可以和多个人同时进行聊天 xi.必须使用图形界面,显示双方的语录 四.实验环境 PC多台,操作系统Win7,win10(32位.64位) 具备软件python3.6 . 五.操作方法与实验步骤 服务端 1.调入多线程.与scoket包,用于实现多线程连接

  • .NET Core 基于Websocket的在线聊天室实现

    什么是Websocket 我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后就会断开连接. 在没有websocket之前web系统如果要做双工通讯往往使用http long polling技术.http long polling 每次往服务器发送请求后,服务端不会立刻返回信息来结束请求,而是一直挂着直到有数据需要返回,或者等待超时了才会返回.客户端在结束上一次请求后立刻再发

  • ASP.NET MVC4异步聊天室的示例代码

    本文介绍了ASP.NET MVC4异步聊天室的示例代码,分享给大家,具体如下: 类图: Domain层 IChatRoom.cs using System; using System.Collections.Generic; namespace MvcAsyncChat.Domain { public interface IChatRoom { void AddMessage(string message); void AddParticipant(string name); void GetM

  • Python实现的使用telnet登陆聊天室实例

    本文实例讲述了Python实现的使用telnet登陆聊天室.分享给大家供大家参考.具体如下: 前久在家学习Python的时候写的一个简单的聊天室,可以使用telnet来登陆. 遗憾的是现在对中文的支持很差,英文聊天倒是没什么问题了. 功能很简单的,应该没有你想象的那么强大,但是你如果有兴趣的话可以试试的. 另外,让我惊奇的是它可以在Android的平板上运行SL4A的Python解释器上运行(需要稍微改几句代码,貌似是编码的那个地方,我记不清了). 现在这个是可以在PC上跑起来的. 废话不多,直

  • vue组件父子间通信之综合练习(聊天室)

    本文实例为大家分享了vue组件父子间通信之聊天室的具体代码,供大家参考,具体内容如下 <!doctype html> <html> <head> <meta charset="UTF-8"> <title>组件父子间通信之综合练习</title> <script src="js/vue.js"></script> </head> <body> &l

  • 用Flash和XML来构造一个聊天室

    点击这里下载源文件 前面的教程我们介绍了Flash与XML结合使用的原理以及一个论坛的实现,下面我们继续结合Flash与XML来实现一个简单的聊天室,有在线聊天.在线人员名单.在线时间.简单的管理操作等功能.根据需要在此基础上稍作修改,就可以实现一个功能比较完备的聊天室了. 一.原理 用Flash和XML来构造聊天室,跟直接用Flash和Asp来构造聊天室的基本原理是一样的.都是先在Flash端发送一个XML请求到服务器端,然后等待从服务器端的XML返回值,当值返回Flash端后,解释所返回的X

随机推荐