如果不是很清楚WebSocket协议,可以参考这篇博客。
包结构
Servlet 3.1以上的版本制定了WebSocket的编程规范,位于包javax.servlet
中:
javax.servlet.websocket
下包含了客户端和服务器端公用的注解、接口、类和异常
javax.servlet.websocket.server
下包含了创建和配置WebSocket服务端所需的注解、接口和类。
Maven依赖:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
关于WebSocket的简易Demo网上已经有很多了,这里就不介绍这些了。
Endpoint
WebSocket是一个建立在TCP基础上的双向通信应用层协议,Endpoint
的概念类似于一个Servlet
实现类,用于实现WebSocket相关业务逻辑,区别在于Servlet
是处理HTTP请求,而EndPoint
是处理WebSocket数据帧。例如javax.servlet.websocket.RemoteEndpoint
实例代表客户端。
在实际编程中,Endpoint
的编写有两种方式:
-
基于注解(常用)
Servlet提供了4个用于修饰方法的注解:@OnOpen
、@OnMessage
、@OnError
、@OnClose
,其修饰的方法分别用于在连接建立时回调、收到数据帧时回调、处理逻辑发生异常时回调、连接关闭时回调。例如:@ServerEndpoint("/ws/chart") public class ChartEndpointImpl { @OnOpen public void open(Session session, EndpointConfig conf) { } @OnMessage public void message(Session session, String message) { } @OnError public void error(Session session, Throwable error) { } @OnClose public void close(Session session, CloseReason reason) { } }
@ServletEndpoint
需要指定一个URI,在上述例子中,当客户端向/ws/chart
发起WebSocket握手HTTP请求时,默认情况下会创建一个新的ChartEndpointImpl
实例,并调用@OnOpen
修饰的方法(如果存在的话)。
此外,各个方法的参数列表并不是固定的,具体规则如下:- 用户可以在任何方法中的参数列表指定一个
Session
类型的参数。 - 在
@OnMessage
修饰的方法中,可以传入消息对象(类型由Decoder
决定,我们稍作讨论),一个ServerEndpoint
可以具有多个@OnMessage
修饰的方法,前提是它们的参数列表互不相同,并且有对应的Docoder
。 - 在
@OnError
方法中,可以传入异常Throwable
类型的参数。 - 在
@OnClose
方法中,可以传入CloseReason
类型的参数,以分析WebSocket连接关闭的具体原因。
- 用户可以在任何方法中的参数列表指定一个
-
基于
javax.servlet.websocket.Endpoint
抽象类(较少使用)
我们可以通过继承EndPoint
方式来重写控制WebSocket连接生命周期相关的回调方法,例如我们实现一个EndpointImpl
:public class EndpointImpl extends Endpoint { @Override public void onOpen(Session session, EndpointConfig config) { //连接建立时回调 } public void onClose(Session session, CloseReason closeReason) { // 连接被关闭时回调 } public void onError(Session session, Throwable throwable) { // 连接发生异常时回调 } }
虽然
Endpoint
没有定义onMessage
处理方法,但是我们可以通过在onOpen
方法通过Session
对象添加MessageHandler
对象来实现onMessage
相关的逻辑。
@ServerEndpoint
注解除了可以指定URI以外,还可以定义以下内容:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ServerEndpoint {
String value(); //对应的URI
String[] subprotocols() default {
}; //对应的子协议,由握手请求头Sec-WebSocket-Protocol指定
Class