HTML5 - WebSocket 简单使用

看到 Tomcat7 支持 WebSocket,对于新东西,总是想先趟一趟水,看能给项目增加点光彩。

简单写了一个 Demo,基础部分还是挺简单。

html & JavaScript :

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSocket</title>
<script type="text/javascript" src="jquery.js"></script>
<style type="text/css">
button{
border: 1px solid #ccc;
background-color: #333;
padding: 3px;
opacity: 0.8;
color: #fff;
}
div{
width:400px;
height:200px;
border:1px solid #cccccc;
border-radius: 3px;
}
div p{
line-height: 20px;
font-size: 12px;
margin: 0;
}
</style>
</head>
<body>
<header></header>
<div id="comand"></div>
<button>OPEN</button><button>NAME</button><button>AGE</button><button>CLOSE</button>
<footer></footer>

</body>
<script>
var host = "ws://localhost:8080/test/wstest";
var socket = null;
function log(msg){
$('#comand').append('<p>'+msg+'</p>');
};
function initpage(){
$('button').click(buttonClick);
}
function buttonClick(e){
var sendText = $(e.currentTarget).text();
log('click:'+sendText);
if(sendText=='OPEN'){
if(socket==null){
socket = new WebSocket(host);
log('WebSocket - status '+socket.readyState);
socket.onopen = function(msg){ log("Welcome - status "+this.readyState); };
socket.onmessage = function(msg){ log("Received: "+msg.data); };
socket.onclose = function(msg){ log("Disconnected - status "+this.readyState); };
}else{
log('WebSocket - was initnailed');
}
}else if(sendText=='CLOSE'){
socket.close();
socket=null;
}else{
socket.send(sendText);
}
}
$(document).ready(initpage);
</script>
</html>

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
package com.xdnote.socket;

import java.io.IOException;

import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/wstest")
public class Socket {

private Session session=null;
@OnOpen
public void onOpen(Session session){
this.session=session;
this.returnMsg("welcome");
}
@OnMessage
public void onMessage(String message){
if(message.equals("NAME")){
this.returnMsg("gaga");
}else if(message.equals("AGE")){
this.returnMsg("15");
}
}
private void returnMsg(String msg){
try {
this.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}

从代码来看,也就这么几步

  1. JavaScript 建立连接,注册onOpen,onMessage,onClose
  2. 执行Java的的注解 @OnOpen / 连接成功后JavaScript的onOpen也会触发
  3. Java处理完后使用session.getBasicRemote().sendText(msg)返回信息
  4. JavaScript 里面的 onMessage接收,处理
  5. JavaScript后续只用调用 socket.send(sendText);就可以了,onMessage会自动接收

对于onmessage方法,注解提供了一些参数规格,可以传文本,二进制和pong消息,可以分别实现命令,上传文件,PING调试等功能,API如下,在下便不翻译了。

  1. if the method is handling text messages:

    • String to receive the whole message
    • Java primitive or class equivalent to receive the whole message converted to that type
    • String and boolean pair to receive the message in parts
    • Reader to receive the whole message as a blocking stream
    • any object parameter for which the endpoint has a text decoder (Decoder.Text or Decoder.TextStream).
  2. if the method is handling binary messages:

    • byte[] or ByteBuffer to receive the whole message
    • byte[] and boolean pair, or ByteBuffer and boolean pair to receive the message in parts
    • InputStream to receive the whole message as a blocking stream
    • any object parameter for which the endpoint has a binary decoder (Decoder.Binary or Decoder.BinaryStream).
  3. if the method is handling pong messages:

    • PongMessage for handling pong messages

Chrome 和 FireFox 现在都支持 WebSocket 了,如果不考虑 IE 用户的话其实是可以用的,但个人感觉有个设计上缺点:对于页面上来说,肯定是希望 WebSocket 对象越少越好,最好一个 WebSocket 能够搞定所有的事情,但对于服务来说,目前没有一个类似 MVC 框架的控制层。也就是说目前如果使用的话,可能 Java 代码会很复杂,只能靠自身的智慧去解决了。