WebSocket的生命周期
WebSocket的端点,以事件的角度看,有四个生命周期事件:
- 打开事件:此事件发生在端点上建立连接时并且在任何其他事件发生之前;
- 消息事件:此事件在接收WebSocket对话中另一端发送的消息。它可以发生在WebSocket端点接收了打开事件之后并且在接收关闭事件关闭之前的任何时刻发生;
- 错误事件:此事件在WebSocket连接或端点发生错误时发生;
- 关闭事件:此事件在WebSocket连接或者端点发生错误时发生;
以注解来声明这的话,可以用@OnOpen、@OnMessage、@OnError和@OnClose这四个注解。
以一个例子来体现WebSocket的生命周期:
点击打开连接按钮,与端点进行连接,这个时候会执行@OnOpen修饰的函数。
点击发送消息,向端点发送文本框中的内容,这个时候会执行@OnMessage修饰的函数。
点击关闭客户端连接按钮,客户端终端与端点的连接,这个时候会调用@OnClick修饰的函数。
点击关闭服务端连接:
端点关闭连接,关闭时大多数会产生一个异常会执行由@OnError修饰的函数,具体代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.net.bysoft</groupId>
<artifactId>websocketapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax/javaee-api -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
服务端代码:
package cn.net.bysoft.websocketapp.lesson2;
import java.io.IOException;
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("/lifecycle")
public class LifeCycle {
private static String START_TIME = "Start Time";
private Session ws_session;
@OnOpen
public void onOpen(Session ws_session) {
// 设置session,并记录建立连接时间
this.ws_session = ws_session;
ws_session.getUserProperties().put(START_TIME, System.currentTimeMillis());
// 通知客户端连接成功
this.sendMessage("success:opened.");
}
@OnMessage
public void onMessage(String message) {
// 如果客户端发送过来close,则关闭连接
if ("close".equals(message)) {
try {
// 关闭前向客户端发送消息
this.sendMessage("danger:server closing after " + this.getConnectionSeconds() + "s.");
// 关闭连接
ws_session.close();
} catch (IOException e) {
System.out.println("Method: onMessage, Error closeing session " + e.getMessage());
}
return;
}
// 如果消息不是close,则正常处理,处理完毕后通知客户端
this.sendMessage("info:processed a message.");
}
@OnError
public void onError(Throwable t) {
// 发生异常时,如果连接还是打开状态,则通知客户端错误信息
if (ws_session.isOpen()) {
this.sendMessage("warning:Error:" + t.getMessage());
}
}
@OnClose
public void onClose() {
// 关闭连接时,需要做的事情在该函数内完成,例如关闭数据库连接等
System.out.println("serivce close.");
}
private void sendMessage(String message) {
try {
// 以同步的方式向客户端发送消息
ws_session.getBasicRemote().sendText(message);
} catch (IOException e) {
System.out.println("Method: sendMessage, Error closeing session " + e.getMessage());
}
}
private int getConnectionSeconds() {
long millis = System.currentTimeMillis() - ((Long) this.ws_session.getUserProperties().get(START_TIME));
return (int) millis / 1000;
}
}
客户端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet"
href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
<!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet"
href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h1>WebSocket的生命周期</h1>
<div class="row">
<div class="col-md-12">
<p>
<button type="button" class="btn btn-primary"
onclick="open_connection()">打开连接</button>
<button type="button" class="btn btn-danger"
onclick="closeServer()">关闭服务端连接</button>
<button type="button" class="btn btn-danger"
onclick="closeClient()">关闭客户端连接</button>
</p>
</div>
</div>
<div class="row">
<form class="form-inline" role="form">
<div class="col-md-12">
<div class="form-group">
<div class="input-group">
<div class="input-group">
<span class="input-group-addon"><span
class="glyphicon glyphicon-send"></span></span> <input id="txtMessage"
type="text" class="form-control" placeholder="Send Message">
</div>
<button type="button" class="btn btn-info"
onclick="messageClick()">发送消息</button>
</div>
</div>
</div>
</form>
</div>
<div class="row">
<div class="col-md-12">
<p id="output">
<br>
</p>
</div>
</div>
</div>
</body>
<script>
var lifecycle_websocket = null;
function init() {
output = document.getElementById("output");
}
function dispose() {
lifecycle_websocket.close();
lifecycle_websocket = null;
}
function open_connection() {
if (lifecycle_websocket == null) {
lifecycle_websocket = new WebSocket(
"ws://localhost:8080/websocketapp/lifecycle");
lifecycle_websocket.onmessage = function(evt) {
displayMessage(evt.data);
}
lifecycle_websocket.onclose = function(evt) {
displayMessage(evt.data);
}
lifecycle_websocket.onerror = function(evt) {
displayMessage(evt.data);
}
}
}
function messageClick() {
send_message(document.getElementById("txtMessage").value);
}
function closeServer() {
send_message("close");
}
function closeClient() {
lifecycle_websocket.close();
displayMessage("danger:client closed.")
}
function send_message(message) {
lifecycle_websocket.send(message);
}
function displayMessage(message) {
var flag = message.substring(0, message.indexOf(':'));
var data = message.substring(message.indexOf(':') + 1);
var pre = document.createElement("p");
// 调用bootstrap样式
pre.className = "text-" + flag;
pre.innerHTML = data;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
window.addEventListener("unload", dispose, false);
</script>
</html>
源码地址:https://github.com/XuePeng87/websocketapp
来源:oschina
链接:https://my.oschina.net/u/2981366/blog/777056