杰瑞科技汇

Java与HTML5 WebSocket如何实现实时通信?

Of course! This is a very common and powerful combination for building modern, real-time web applications. Here’s a comprehensive guide covering both the Java (Server) and HTML5 (Client) sides of a WebSocket connection, complete with code examples.

What is WebSocket?

WebSocket is a computer communication protocol that provides full-duplex communication channels over a single, long-lived TCP connection. Unlike traditional HTTP, which is request-response-based, WebSocket allows the server to push data to the client at any time.

Key Advantages:

  • Real-time: True bi-directional communication.
  • Efficient: No repeated HTTP request/response headers, reducing overhead.
  • Low Latency: Data is sent as soon as it's available.

The Client-Side: HTML5 & JavaScript

The client-side implementation is straightforward using the browser's built-in WebSocket API.

Key Concepts:

  • new WebSocket(url): Creates a new WebSocket connection.
  • onopen: A function called when the connection is successfully established.
  • onmessage: A function called when a message is received from the server.
  • onerror: A function called when an error occurs.
  • onclose: A function called when the connection is closed.
  • send(data): Sends data to the server.
  • close(): Closes the connection.

Example: index.html

This simple web page will connect to our Java server, send a message, and display messages received from the server.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">Java WebSocket Client</title>
    <style>
        body { font-family: sans-serif; }
        #messages { border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: scroll; margin-bottom: 10px; }
        #input { width: 80%; padding: 5px; }
        #sendButton { padding: 5px 10px; }
    </style>
</head>
<body>
    <h1>Java WebSocket Chat</h1>
    <div id="messages"></div>
    <div>
        <input type="text" id="input" placeholder="Type a message...">
        <button id="sendButton">Send</button>
    </div>
    <script>
        // 1. Create a new WebSocket connection.
        // 'ws://' for non-secure, 'wss://' for secure (HTTPS)
        const socket = new WebSocket('ws://localhost:8080/websocket/chat');
        const messagesDiv = document.getElementById('messages');
        const inputElement = document.getElementById('input');
        const sendButton = document.getElementById('sendButton');
        // 2. Connection opened
        socket.onopen = function(event) {
            console.log("Connection established!");
            appendMessage("System: Connected to the server.");
        };
        // 3. Listen for messages
        socket.onmessage = function(event) {
            console.log("Message from server: ", event.data);
            appendMessage(event.data);
        };
        // 4. Handle errors
        socket.onerror = function(error) {
            console.error("WebSocket Error: ", error);
            appendMessage("System: An error occurred.");
        };
        // 5. Connection closed
        socket.onclose = function(event) {
            if (event.wasClean) {
                console.log(`Connection closed cleanly, code=${event.code} reason=${event.reason}`);
            } else {
                console.error('Connection died');
            }
            appendMessage("System: Connection closed.");
        };
        // Function to append a message to the div
        function appendMessage(message) {
            const p = document.createElement('p');
            p.textContent = message;
            messagesDiv.appendChild(p);
            messagesDiv.scrollTop = messagesDiv.scrollHeight; // Auto-scroll
        }
        // Send message when the button is clicked or Enter is pressed
        function sendMessage() {
            const message = inputElement.value;
            if (message) {
                console.log("Sending message: ", message);
                socket.send(message);
                inputElement.value = '';
            }
        }
        sendButton.addEventListener('click', sendMessage);
        inputElement.addEventListener('keypress', function(event) {
            if (event.key === 'Enter') {
                sendMessage();
            }
        });
    </script>
</body>
</html>

The Server-Side: Java

For Java, the modern and standard way to handle WebSockets is using the Jakarta WebSocket (formerly Java WebSocket) API. We'll use a simple Servlet-based approach, which is easy to set up in any standard Java web server (like Tomcat, Jetty, etc.).

Java与HTML5 WebSocket如何实现实时通信?-图1

Java与HTML5 WebSocket如何实现实时通信?-图2

Key Concepts:

  • @ServerEndpoint: An annotation that marks a class as a WebSocket endpoint. The value is the URL path for the endpoint.
  • @OnOpen: A method annotated with this will be called when a new WebSocket connection is established.
  • @OnClose: Called when a connection is closed.
  • @OnMessage: Called when a message is received from a client.
  • @OnError: Called when an error occurs.
  • Session: Represents the two-way communication channel with a client. It's used to send messages back (session.getBasicRemote().sendText(...)).

Project Setup (using Maven)

You'll need the Jakarta WebSocket API dependency. For a server like Tomcat 10 or newer, this is usually included, but it's good to be explicit.

<dependencies>
    <!-- Jakarta WebSocket API -->
    <dependency>
        <groupId>jakarta.platform</groupId>
        <artifactId>jakarta.jakartaee-web-api</artifactId>
        <version>10.0.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

Example: ChatEndpoint.java

This is the main WebSocket endpoint class.

import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
 * WebSocket endpoint for a simple chat application.
 * The path "/websocket/chat" must match the client's WebSocket URL.
 */
@ServerEndpoint("/websocket/chat")
public class ChatEndpoint {
    // A thread-safe Set to store all active sessions.
    // This allows us to broadcast messages to all connected clients.
    private static final Set<Session> chatroomUsers = Collections.synchronizedSet(new HashSet<>());
    /**
     * Called when a new WebSocket connection is opened.
     * @param session The session for the new connection.
     */
    @OnOpen
    public void onOpen(Session session) {
        chatroomUsers.add(session);
        System.out.println("New connection opened. Session ID: " + session.getId());
        // Broadcast a message to all users that someone joined
        broadcast("System: User " + session.getId() + " has joined the chat.");
    }
    /**
     * Called when a message is received from a client.
     * @param message The message received from the client.
     * @param session The session of the client who sent the message.
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Message from " + session.getId() + ": " + message);
        // Broadcast the received message to all other users
        broadcast("User " + session.getId() + ": " + message);
    }
    /**
     * Called when a WebSocket connection is closed.
     * @param session The session that is being closed.
     * @param closeReason The reason for the closure.
     */
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        chatroomUsers.remove(session);
        System.out.println("Connection closed. Session ID: " + session.getId() + ", Reason: " + closeReason.getReasonPhrase());
        // Broadcast a message to all users that someone left
        broadcast("System: User " + session.getId() + " has left the chat.");
    }
    /**
     * Called when an error occurs during the WebSocket communication.
     * @param session The session where the error occurred.
     * @param throwable The throwable that was thrown.
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println("Error on session " + session.getId());
        throwable.printStackTrace();
        chatroomUsers.remove(session);
    }
    /**
     * Helper method to send a message to all connected clients.
     * @param message The message to broadcast.
     */
    private void broadcast(String message) {
        // Iterate over a copy of the set to avoid ConcurrentModificationException
        Set<Session> usersCopy = new HashSet<>(chatroomUsers);
        for (Session user : usersCopy) {
            try {
                // Check if the session is still open
                if (user.isOpen()) {
                    user.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                System.err.println("Error broadcasting message to user " + user.getId());
                e.printStackTrace();
                // If an error occurs sending to a user, remove them from the set
                chatroomUsers.remove(user);
            }
        }
    }
}

Putting It All Together: Running the Application

Java与HTML5 WebSocket如何实现实时通信?-图3

分享:
扫描分享到社交APP
上一篇
下一篇