在现代Web应用中,服务器主动推送数据到客户端的需求越来越普遍,Java服务器可以通过多种方式实现这种功能,例如使用WebSocket、ServerSent Events(SSE)和长轮询等技术,本文将详细介绍这些技术,并提供示例代码以帮助理解其实现过程。

1. WebSocket
什么是WebSocket?
WebSocket是一种在单个TCP连接上进行全双工通信的协议,它允许服务器和客户端之间建立一个持久的连接,从而实现实时双向数据传输。
如何实现WebSocket?
服务器端
在Java中,可以使用Java API for WebSocket(JSR 356)来实现WebSocket服务器,以下是一个简单的例子:
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/websocket")
public class MyWebSocketServer {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connected ... " + session.getId());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Received: " + message);
try {
session.getBasicRemote().sendText("Echo: " + message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
@OnClose
public void onClose(Session session) {
System.out.println("Disconnected ... " + session.getId());
}
@OnError
public void onError(Session session, Throwable throwable) {
throwable.printStackTrace();
}
}
客户端
客户端可以使用JavaScript来连接到WebSocket服务器:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Example</title>
</head>
<body>
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:8080/websocket");
ws.onopen = function() {
console.log("Connected to the server");
ws.send("Hello Server!");
};
ws.onmessage = function(evt) {
console.log("Message from server: " + evt.data);
};
ws.onclose = function() {
console.log("Connection closed");
};
</script>
</body>
</html>
2. ServerSent Events (SSE)

什么是ServerSent Events?
ServerSent Events(SSE)是一种用于从服务器向客户端发送单向消息的技术,SSE使用HTTP协议,但保持连接不断开,从而能够持续发送数据。
如何实现SSE?
服务器端
在Java中,可以使用Servlet来实现SSE,以下是一个简单示例:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/sse")
public class SSEServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/eventstream");
response.setCharacterEncoding("UTF8");
PrintWriter out = response.getWriter();
while (true) {
out.print("data: " + System.currentTimeMillis() + "
");
out.flush();
try {
Thread.sleep(1000); // 每秒发送一次数据
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
客户端
客户端可以使用JavaScript来接收SSE事件:
<!DOCTYPE html>
<html>
<head>
<title>SSE Example</title>
</head>
<body>
<div id="result"></div>
<script type="text/javascript">
var evtSource = new EventSource("http://localhost:8080/sse");
evtSource.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
</script>
</body>
</html>
长轮询(Long Polling)
什么是长轮询?
长轮询是一种模拟服务器推送的技术,通过让客户端发起请求并保持连接,直到有新数据可返回为止,这种方式虽然不如WebSocket和SSE高效,但兼容性更好。

如何实现长轮询?
服务器端
在Java中,可以使用Servlet来实现长轮询,以下是一个简单示例:
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/longpolling")
public class LongPollingServlet extends HttpServlet {
private BlockingQueue<String> queue = new LinkedBlockingQueue<>();
public void addMessage(String message) {
queue.add(message);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF8");
PrintWriter out = response.getWriter();
String message = queue.take(); // 阻塞直到有新消息
out.print(message);
out.flush();
out.close();
}
}
客户端
客户端可以使用JavaScript来实现长轮询:
<!DOCTYPE html>
<html>
<head>
<title>Long Polling Example</title>
</head>
<body>
<div id="result"></div>
<script type="text/javascript">
function longPolling() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("result").innerHTML += xhr.responseText + "<br>";
longPolling(); // 继续下一次轮询
}
};
xhr.open("GET", "http://localhost:8080/longpolling", true);
xhr.send();
}
longPolling(); // 开始第一次轮询
</script>
</body>
</html>
归纳与比较
| 技术 | 优点 | 缺点 | 适用场景 |
| WebSocket | 全双工通信,低延迟,适合实时应用 | 需要浏览器支持,较复杂 | 聊天应用,实时游戏,金融交易平台等 |
| SSE | 单向通信,简单易用,适合广播消息 | 仅支持单向通信,浏览器支持有限 | 新闻更新,股票行情,社交媒体通知等 |
| 长轮询 | 兼容性好,不需要特殊协议,易于实现 | 效率较低,不适合高频率更新 | 简单的实时数据更新,旧系统兼容 |
小伙伴们,上文介绍了“java服务器怎么主动推送数据”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。














