知道WebSocket挺久了,但是一直没提起兴趣去了解它。

今天听@成熟的毛毛虫 说到slack。小小的试用了一下,发现slack的聊天功能做得相当强大,看了下网络请求,发现是基于WebSocket实现的。顿时提起兴趣,想了解下这强大的WebSocket

先了解下WebSocket。

--开源中国的介绍:http://www.oschina.net/p/websocket

--百度百科的介绍:http://baike.baidu.com/link?url=yMTBVobtkp1E1a0wrRJlnEXzREuPQFF3psqG6wKJsSxY0_QVpKdEPZ5AyxQfn6TbfdYrRe3aGyak9hEBF6279K

网上关于WebSocket的例子貌似不多,但最好的例子已经有了。偶然间发现tomcat的自带的例子中,已经有了基于WebSocket实现的聊天室例子。这里就不献丑,直接拿来用了。

首先,服务端的实现ChatAnnotation.java

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package websocket.chat;
 
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
 
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;
 
@ServerEndpoint(value = "/chat")
public class ChatAnnotation {
 
    private static final String GUEST_PREFIX = "Guest";
    private static final AtomicInteger connectionIds = new AtomicInteger(0);
    private static final Set connections =
            new CopyOnWriteArraySet<>();
 
    private final String nickname;
    private Session session;
 
    public ChatAnnotation() {
        nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
    }
 
    @OnOpen
    public void start(Session session) {
        this.session = session;
        connections.add(this);
        String message = String.format("* %s %s", nickname, "has joined.");
        broadcast(message);
    }
 
    @OnClose
    public void end() {
        connections.remove(this);
        String message = String.format("* %s %s",
                nickname, "has disconnected.");
        broadcast(message);
    }
 
    @OnMessage
    public void incoming(String message) {
        // Never trust the client
        // TODO: 过滤输入的内容
        broadcast(message);
    }
 
    @OnError
    public void onError(Throwable t) throws Throwable {
        System.out.println("Chat Error: " + t.toString());
    }
 
    private static void broadcast(String msg) {
        for (ChatAnnotation client : connections) {
            try {
                synchronized (client) {
                    client.session.getBasicRemote().sendText(msg);
                }
            } catch (IOException e) {
                System.out.println("Chat Error: Failed to send message to client");
                connections.remove(client);
                try {
                    client.session.close();
                } catch (IOException e1) {
                    // Ignore
                }
                String message = String.format("* %s %s",
                        client.nickname, "has been disconnected.");
                broadcast(message);
            }
        }
    }
}

稍微解释下上面这段代码。

1、@ServerEndpoint(value = "/websocket/chat")定义一个WebSocket服务端。value即访问地址。这个例子中:客户端通过 ws://{domain}/{context}/chat 来进行连接

2、Set connections用于存储聊天室中的连接实例

3、@OnPen,连接创建时调用的方法

4、@OnClose,连接关闭时调用的方法

5、@OnMessage,传输信息过程中调用的方法

6、@OnError,发生错误时调用的方法

7、broadcast(String msg),通过connections,对所有其他用户推送信息的方法


客户端的实现chat.xhtml





    Apache Tomcat WebSocket Examples: Chat
    
     25) {
                console.removeChild(console.firstChild);
            }
            console.scrollTop = console.scrollHeight;
        });
 
        Chat.initialize();
 
        document.addEventListener("DOMContentLoaded", function() {
            // Remove elements with "noscript" class -