基于WebSocket实现网页聊天室
背景在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定
背景
在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。
在JavaEE7中也实现了WebSocket协议。
原理
WebSocket protocol 。
现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏览器需要不断的向服务器发出请求,然而HTTP request 的header是非常长的,里面包含的有用数据可能只是一个很小的值,这样会占用很多的带宽。
而比较新的技术去做轮询的效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。
在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此WebSocket 协议中,为我们实现即时服务带来了两大好处:
1. Header
互相沟通的Header是很小的-大概只有 2 Bytes
2. Server Push
服务器的推送,服务器不再被动的接收到浏览器的request之后才返回数据,而是在有新数据时就主动推送给浏览器。
一、项目简介
WebSocket是HTML5一种新的协议,它实现了浏览器与服务器全双工通信,这里就将使用WebSocket来开发网页聊天室,前端框架会使用AmazeUI,后台使用Java,编辑器使用UMEditor。
二、涉及知识点
网页前端(HTML+CSS+JS)和JavaSE
三、软件环境 Tomcat 7 JDK 7 Eclipse JavaEE 现代浏览器
四、效果截图
效果1
效果2
五、项目实战
1. 新建项目
打开Eclipse JavaEE,新建一个名为Chat的Dynamic Web Project,然后导入处理JSON格式字符串所需要的包,把commons-beanutils-1.8.0.jar、commons-collections-3.2.1.jar、commons-lang-2.5.jar、commons-logging-1.1.1.jar、ezmorph-1.0.6.jar和json-lib-2.4-jdk15.jar这几个包放在WebContent/WEB-INF/lib目录下,最后把项目发布到Tomcat服务器上,到此空项目就搭建完成了。
2. 编写前端页面
在WebContent目录下新建一个名为index.jsp的页面,这里使用了AmazeUI框架,它是一个跨屏自适应的前端框架,消息输入框使用了UMEditor,它是一个富文本在线编辑器,能让我们的消息内容多姿多彩。
首先从 AmazeUI官网 下载压缩包,然后解压把assets文件夹拷贝到WebContent目录下,这样我们就能使用AmazeUI了。
再从 UEditer官网 下载Mini版的JSP版本压缩包,解压后把整个目录拷贝到WebContent目录下,接下来就可以编写前端代码了,代码如下(你可以按照自己的喜好编写):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
<%@ page language=
"java"
contentType=
"text/html; charset=UTF-8"
pageEncoding=
"UTF-8"
%>
<!DOCTYPE html>
<html lang=
"zh"
>
<head>
<meta charset=
"utf-8"
>
<meta http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<meta name=
"viewport"
content=
"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
>
<title>ShiYanLou Chat</title>
<!-- Set render engine
for
360 browser -->
<meta name=
"renderer"
content=
"webkit"
>
<!-- No Baidu Siteapp-->
<meta http-equiv=
"Cache-Control"
content=
"no-siteapp"
/>
<link rel=
"alternate icon"
href=
"assets/i/favicon.ico"
>
<link rel=
"stylesheet"
href=
"assets/css/amazeui.min.css"
>
<link rel=
"stylesheet"
href=
"assets/css/app.css"
>
<!-- umeditor css -->
<link href=
"umeditor/themes/default/css/umeditor.css"
rel=
"stylesheet"
>
<style>
.title {
text-align: center;
}
.chat-content-container {
height: 29rem;
overflow-y: scroll;
border: 1px solid silver;
}
</style>
</head>
<body>
<!-- title start -->
<div
class
=
"title"
>
<div
class
=
"am-g am-g-fixed"
>
<div
class
=
"am-u-sm-12"
>
<h1
class
=
"am-text-primary"
>ShiYanLou Chat</h1>
</div>
</div>
</div>
<!-- title
end
-->
<!-- chat content start -->
<div
class
=
"chat-content"
>
<div
class
=
"am-g am-g-fixed chat-content-container"
>
<div
class
=
"am-u-sm-12"
>
<ul id=
"message-list"
class
=
"am-comments-list am-comments-list-flip"
></ul>
</div>
</div>
</div>
<!-- chat content start -->
<!-- message input start -->
<div
class
=
"message-input am-margin-top"
>
<div
class
=
"am-g am-g-fixed"
>
<div
class
=
"am-u-sm-12"
>
<form
class
=
"am-form"
>
<div
class
=
"am-form-group"
>
<script type=
"text/plain"
id=
"myEditor"
style=
"width: 100%;height: 8rem;"
></script>
</div>
</form>
</div>
</div>
<div
class
=
"am-g am-g-fixed am-margin-top"
>
<div
class
=
"am-u-sm-6"
>
<div id=
"message-input-nickname"
class
=
"am-input-group am-input-group-primary"
>
<span
class
=
"am-input-group-label"
><i
class
=
"am-icon-user"
></i></span>
<input id=
"nickname"
type=
"text"
class
=
"am-form-field"
placeholder=
"Please enter nickname"
/>
</div>
</div>
<div
class
=
"am-u-sm-6"
>
<button id=
"send"
type=
"button"
class
=
"am-btn am-btn-primary"
>
<i
class
=
"am-icon-send"
></i> Send
</button>
</div>
</div>
</div>
<!-- message input
end
-->
<!--[
if
(gte IE 9)|!(IE)]><!-->
<script src=
"assets/js/jquery.min.js"
></script>
<!--<![
endif
]-->
<!--[
if
lte IE 8 ]>
<![
endif
]-->
<!-- umeditor js -->
<script charset=
"utf-8"
src=
"umeditor/umeditor.config.js"
></script>
<script charset=
"utf-8"
src=
"umeditor/umeditor.min.js"
></script>
<script src=
"umeditor/lang/zh-cn/zh-cn.js"
></script>
<script>
$(
function
() {
// 初始化消息输入框
var
um = UM.getEditor(
'myEditor'
);
// 使昵称框获取焦点
$(
'#nickname'
)[0].focus();
});
</script>
</body>
</html>
|
编写完成之后启动Tomcat服务器,然后访问 http://localhost:8080/Chat/index.jsp ,会看到如下界面。
3. 编写后台代码
新建一个com.shiyanlou.chat的包,在包中创建一个名为ChatServer的类,从JavaEE 7开始就统一了WebSocket的API,因此无论是什么服务器,用Java写的代码都是一样的,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
package com.shiyanlou.chat;
import java.text.SimpleDateFormat;
import java.util.
Date
;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import net.sf.json.JSONObject;
/**
* 聊天服务器类
* @author shiyanlou
*
*/
@ServerEndpoint(
"/websocket"
)
public
class
ChatServer {
private
static
final
SimpleDateFormat DATE_FORMAT =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm"
);
// 日期格式化
@OnOpen
public
void open(Session session) {
// 添加初始化操作
}
/**
* 接受客户端的消息,并把消息发送给所有连接的会话
* @param message 客户端发来的消息
* @param session 客户端的会话
*/
@OnMessage
public
void getMessage(String message, Session session) {
// 把客户端的消息解析为JSON对象
JSONObject jsonObject = JSONObject.fromObject(message);
// 在消息中添加发送日期
jsonObject.put(
"date"
, DATE_FORMAT.format(
new
Date
()));
// 把消息发送给所有连接的会话
for
(Session openSession : session.getOpenSessions()) {
// 添加本条消息是否为当前会话本身发的标志
jsonObject.put(
"isSelf"
, openSession.equals(session));
// 发送JSON格式的消息
openSession.getAsyncRemote().sendText(jsonObject.toString());
}
}
@OnClose
public
void close() {
// 添加关闭会话时的操作
}
@OnError
public
void error(Throwable t) {
// 添加处理错误的操作
}
}
|
稍微解释下上面这段代码。
- @ServerEndpoint(value = "/websocket")定义一个WebSocket服务端。value即访问地址。这个例子中:客户端通过 ws://{domain}/{context}来进行连接
- Set<ChatAnnotation> connections用于存储聊天室中的连接实例
- @OnPen,连接创建时调用的方法
- @OnClose,连接关闭时调用的方法
- @OnMessage,传输信息过程中调用的方法
- @OnError,发生错误时调用的方法
- broadcast(String msg),通过connections,对所有其他用户推送信息的方法
4. 前后台交互
后台写完了,前台要用WebSocket连接后台,需要新建一个WebSocket对象,然后就可以和服务器端进行交互,从浏览器发送消息给服务器端,同时要验证输入框的内容是否为空,然后接受服务端发送的消息,把它们动态地添加到聊天内容框中,在
到这步,简单的网页聊天室就完成了。
六、小结
本次项目课使用WebSocket实现了简单的网页聊天室,其实WebSocket不仅可以应用于浏览器,也可以应用于桌面客户端。
更多推荐
所有评论(0)