[英]Connection close in Java Servlet and SSE
我嘗試在服務器上使用Java Serlvet在Webapp中實現服務器發送事件。
是否可以在Servlet中檢查客戶端是否關閉了連接? 即使關閉客戶端瀏覽器,Servlet中的while(true)
循環也是無限的。
客戶代碼
function startLogSSE(lastEventId, level) {
var eventSource = new EventSource("log-sse?last-event-id=" + lastEventId + "&level=" + level);
eventSource.onmessage = function (event) {
document.getElementById('log').innerHTML = event.data + "\n" + document.getElementById('log').innerHTML;
};
}
服務器代碼
public class LogSSEServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(LogSSEServlet.class);
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
// get logger purgerDB appender
PurgerDBAppender appender = LogUtils.getPurgerDBAppender();
if (appender == null) {
writer.write("data: [ERROR] Appender 'purgerDB' isn't found for logger 'com.bp3'\n\n");
writer.close();
return;
}
int eventId = 0;
// get last-event-id
String lastEventId = request.getHeader("last-event-id");
if (lastEventId == null) {
// try to get lastEventId from parameter
lastEventId = request.getParameter("last-event-id");
}
if (lastEventId != null) {
try {
eventId = Integer.parseInt(lastEventId);
} catch (NumberFormatException e) {
logger.error("Failed to parse last-event-id: " + lastEventId);
}
}
String minLevel = request.getParameter("level");
if (minLevel == null) {
minLevel = "TRACE";
}
// get logs from purgerDB logger appender
LogServices logServices = new LogServices();
try {
logServices.open();
} catch (SQLException e) {
throw new ServletException(e);
}
try {
while (true) {
List<LogMessage> messages = logServices.getLastMessages(Level.toLevel(minLevel), eventId, 0);
if (messages.size() > 0) {
writer.write("id: " + messages.get(0).getEventId() + "\n");
writer.write("data: " + LogUtils.formatLog(messages) + "\n");
writer.flush();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
} catch (SQLException e) {
throw new ServletException(e);
} finally {
logServices.closeQuietly();
}
}
}
是否可以在Servlet中檢查客戶端是否關閉了連接?
最終將引發異常:如果直接將數據流傳輸到套接字,則拋出IOException: connection reset
如果容器的數據流傳輸到內存,則將OutOfMemoryError
,這是在不使用固定長度或分塊傳輸模式時發生的。 。
即使關閉客戶端瀏覽器,Servlet中的while(true)循環也是無限的。
不,不是。
在Servlet
檢查連接是否關閉的一種方法是使用writer.checkError()
方法。 我在Chrome上測試了此修復程序,並且可以正常工作。 您的代碼為:
boolean error=false;
while (!error) {
//...
writer.write("data: " + /*...*/ "\n");
//writer.flush();
error = writer.checkError(); //internally calls writer.flush()
}
詳細資料 :
此類中的方法永遠不會拋出I / O異常,盡管它的某些構造函數可能會拋出異常。 客戶端可以通過調用
checkError()
來查詢是否發生了任何錯誤。
而checkError()表示:
如果未關閉,則刷新流並檢查其錯誤狀態
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.