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 ${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);
- }
- }
- }
#p#
面分析下上面的代码:
使用@ 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了。
#p#
通过Bootstrap、Javacsript搭建简易客户端
最后,我们综合运用著名的Bootstrap、jQuery框架和Javascript设计一个简易的客户端。我们在src/main/weapp目录下新建立index.html文件,代码如下:
- [..]
- 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 = $('
'); ' + msg.received - + '
' + msg.sender - + '
' + msg.message - + '
- $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();
- });
- });
Chat sign in
- class="input-block-level" placeholder="Nickname" id="nickname">
- value="Send message" />
- room
在上面的代码中,要注意如下几点:
在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
进行代码的部署,然后就可以看到本文开始部分截图的效果。
本文的代码可以通过git获得:
git clone https://bitbucket.org/hascode/javaee7-websocket-chat.git
读者也可以通过这个地址下载可部署的war包:
标题名称:用JavaEE7、Websockets和GlassFish4打造聊天室(一)
文章来源:http://www.shufengxianlan.com/qtweb/news11/74511.html
成都网站建设公司_创新互联,为您提供手机网站建设、网站收录、python、全网营销推广、外贸建站、移动网站建设
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联