千家信息网

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

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,今天就跟大家聊聊有关如何用JavaEE7、Websockets和GlassFish4打造聊天室(一),可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收
千家信息网最后更新 2024年11月30日如何用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的基础原理知识。

效果图

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

准备工作

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

      ${project.build.directory}/endorsed     UTF-8                  javax         javaee-api         7.0         provided                                    org.apache.maven.plugins             maven-compiler-plugin             3.1                              1.7                 1.7                                      ${endorsed.dir}                                                             org.apache.maven.plugins             maven-war-plugin             2.3                              false                                            org.apache.maven.plugins             maven-dependency-plugin             2.6             [..]               

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

plugin>     org.glassfish.embedded     maven-embedded-glassfish-plugin     4.0              embedded-glassfish         ${basedir}/target/${project.artifactId}-${project.version}.war         true         8080         ${project.artifactId}         hascode                                                 deploy                            

设置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 {     @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 {     @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文件,代码如下:

   [..]                        

Enter your message..

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

在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()。

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

最后,我们通过

mvn package embedded-glassfish:run

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

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

0