使用java websocket简单实现即时聊天

本文介绍了一个简单的WebSocket聊天应用程序,包括服务器端Java代码和客户端HTML代码。服务器端使用了Java的WebSocket API进行消息处理,并实现了基本的连接管理和消息广播功能。客户端采用HTML与JavaScript,通过WebSocket与服务器交互,实现了消息发送与接收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、服务器端代码

package com.chhuang.websocket;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

/**
 * websocket
 * 
 * @author CHHUANG
 *
 */
@ServerEndpoint("/chat/{userId}") // 该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
public class ChatAnnotation {

    // 用来存放每个客户端对应的ChatAnnotation对象,实现服务端与单一客户端通信的话,使用Map来存放,其中Key可以为用户标识,hashtable比hashmap线程安全
    private static Map<String, ChatAnnotation> webSocketMap = new Hashtable<String, ChatAnnotation>();

    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    /**
     * 连接建立成功调用的方法
     * 
     * @param session
     *            可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam(value="userId") String userId, Session session) {
        this.session = session;
        webSocketMap.put(userId, this);//加入map中
        System.out.println(userId+"连接加入!当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam(value="userId") String userId) {
        webSocketMap.remove(userId);
        System.out.println(userId+"关闭连接!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     * 
     * @param message
     *            客户端发送过来的消息
     * @param session
     *            可选的参数
     */
    @OnMessage
    public void onMessage(@PathParam(value="userId") String userId, String message, Session session) {
        System.out.println("来自客户端"+userId+"的消息:" + message);

        // 群发消息
        for (Map.Entry<String, ChatAnnotation> entry : webSocketMap.entrySet()) {
            ChatAnnotation item = entry.getValue();
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发生错误时调用
     * 
     * @param session
     * @param error
     */
    @OnError
    public void onError(@PathParam(value="userId") String userId, Session session, Throwable error) {
        System.out.println(userId+"发生错误");
        error.printStackTrace();
    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
     * 
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
        // this.session.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        return webSocketMap.size();
    }
}

二、客户端html代码

<!doctype html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <style type="text/css">
        input#chat {  
            width: 410px  
        }
         #console-container {  
            width: 400px;  
        }  

        #console {  
            border: 1px solid #CCCCCC;  
            border-right-color: #999999;  
            border-bottom-color: #999999;  
            height: 170px;  
            overflow-y: scroll;  
            padding: 5px;  
            width: 100%;  
        }  

        #console p {  
            padding: 0;  
            margin: 0;  
        }
    </style>
</head>

<body>

     <p>  
        <input type="text" placeholder="type and press enter to chat" id="chat" />  
    </p>  
    <div id="console-container">  
        <div id="console"></div>  
    </div>

    <script type="text/javascript">
        var Console = {};  

        Console.log = (function(message) {  
            var console = document.getElementById('console');  
            var p = document.createElement('p');  
            p.style.wordWrap = 'break-word';  
            p.innerHTML = message;  
            console.appendChild(p);  
            while (console.childNodes.length > 25) {  
                console.removeChild(console.firstChild);  
            }  
            console.scrollTop = console.scrollHeight;  
        });

        var Chat = {};

        Chat.socket = null;

        Chat.connect = (function(host) {
            if ('WebSocket' in window) {
                Chat.socket = new WebSocket(host);
            } else if ('MozWebSocket' in window) {
                Chat.socket = new MozWebSocket(host);
            } else {
                Console.log('Error: WebSocket is not supported by this browser.');
                return;
            }

            Chat.socket.onopen = function() {
                Console.log('Info: WebSocket connection opened.');
                document.getElementById('chat').onkeydown = function(event) {
                    if (event.keyCode == 13) {
                        Chat.sendMessage();
                    }
                };
            };

            Chat.socket.onclose = function() {
                document.getElementById('chat').onkeydown = null;
                Console.log('Info: WebSocket closed.');
            };

            Chat.socket.onmessage = function(message) {
                Console.log(message.data);
            };
        });

        Chat.initialize = function() {
            Chat.connect('ws://localhost:8080/websocket/chat/123456789');
        };

        Chat.sendMessage = (function() {
            var message = document.getElementById('chat').value;
            if (message != '') {
                Chat.socket.send(message);
                document.getElementById('chat').value = '';
            }
        });

        Chat.initialize();
    </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值