初识WebSocket
一、WebSocket的用途
参考:
https://blog.csdn.net/qq_43842093/article/details/123158436
https://cloud.tencent.com/developer/article/2028722
大致可以分为以下几点:
一、通知功能
保持长连接,例如微信qq等在平台上的社交软件或共同协作的地方
二、数据收集
一些次优级别的数据,比如行为日志、trace、异常执栈收集等,都可以开辟专门的WebSocket通道进行传输。这能够增加信息的集中度,并能及时的针对用户的行为进行合适的配置推送。由于大多数浏览器内核都支持,它将使客户端APM编程模型变得简单。
三、加密&&认证
虽然使用Fiddler、Charles等能够抓到很多WebSocket包。但如果同时开启SSL,传输加密后的二进制数据,会大幅增加破解的成本,会安全的多。
二、WebSocket的生命周期
参考:
https://blog.csdn.net/batter_hwb/article/details/82379692
-
打开事件
-
此事件发生在端点上建立新连接时并且在任何其他事件发生之前
-
注解形式为@OnOpen
注解在方法上,指示此端点建立新的连接时调用此方法。
需要一个方法来处理打开事件的主要原因是,使得开发人员能够设置在WebSocket对话时可能需要的任何信息(打开数据库连接)。
此事件伴随三部分信息:WebSocket Session对象,用于表示已经建立好的连接
配置对象(EndpointConfig的实例),包含了用来配置端点的信息
一组路径参数,用于打开阶段握手时WebSocket端点匹配入站URI
使用注解的好处是如果你不需要的话,不必使用此事件的所有信息。
因此@OnOpen注解的方法是没有任何返回值的公有方法,这些方法有一个可选的Session参数,一个可选的EndpointConfig参数,以及任意数量的被@PathParam注解的String参数,这些参数的顺序可以任意排列。@OnOpen public void init(Session session, EndpointConfig config) { }
-
-
消息事件
-
此事件接收WebSocket对话中另一端发送的消息。它可以发生在WebSocket端点接收了打开事件之后且在接收关闭事件关闭连接之前的任意时刻
-
注解形式为@OnMessage
在建立连接后处理入站信息。
消息事件伴随的信息是Session对象,EndpointConfig对象,打开握手阶段中从匹配入站URI过程中获取的路径参数以及最重要的消息本身。与@OnOpen注解一样,方法参数可以任意选择任意顺序排列连接上的消息将以文本消息、二进制消息或Pong消息三种形式抵达。JavaWebSocket API提供了一系列的选项使得能够以这些形式接收消息。最基本的形式是选择使用带String参数的方法来处理文本消息;使用带ByteBuffer或者是byte[]参数的方法来处理二进制消息;若你的消息将仅仅处理Pong消息,则可以使用JavaWebSocket API中的PongMessage接口的一个实例。
文本消息例子:
@OnMessage public String echo(String incomingMessage) { return "I got this (" + incomingMessage + ")!!"; }
对于二进制和文本消息,你可以选择在消息到来时分批的接收。可以使用一对参数来表示到来的消息分片(partial message)。对文本消息分片来说是String和boolean,其中String参数表示文本消息分片,boolean参数表示该分片是否是序列中的最后一个消息分片;对二进制消息分片来说,可以选择一对参数ByteBuffer(或者byte[])和boolean,其中ByteBuffer(或者byte[])表示二进制消息分片,boolean参数表示该分片是否是序列中的最后一个消息分片。
@OnMessage public void echo(byte[] partialData, boolean isLast) { if (!isLast) { // 序列中还有更多的消息分片进来 } else { // 最后一个消息分片 } }
还可以使用Java I/O流处理:
使用Reader接收文本消息,使用InputStream接收二进制消息@OnMessage public void handleBinary(InputStream is) { }
WebSocket应用一般是异步的双向消息。一般情况下的 WebSocket 应用并不总是立即响应入站消息。如果想要立刻响应入站消息,可以通过将 @OnMessage 注解的方法的返回类型设置为有返回类型,那么 WebSocket 实现立即将返回值作为消息返回给刚刚在方法中处理的消息的发送者。
-
-
错误事件
-
此事件在WebSocket连接或者端点发生错误时产生
-
注解形式为@OnError
@OnError 可以用来注解 WebSocket 端点的方法,使其可以处理 WebSocket 实现处理入站消息时发生的任何错误。伴随错误事件的信息是错误信息、发生错误的会话以及与建立连接打开阶段握手相关联的任何一个路径参数。
@OnError public void errorHandler(Throwable throwable) { // 错误处理方法 }
-
-
关闭事件
-
此事件表示 WebSocket 端点的连接目前正在部分地关闭,它可以由参与连接的任意一个端点发出。
-
注解形式为@OnClose
该注解对应拦截关闭事件。伴随关闭事件的信息:关闭信息、与建立连接的打开阶段握手相关联的任意一个路径参数,以及描述连接关闭原因的信息。
@OnClose public void closeHandler(CloseReason closeReason) { // 关闭事件处理 }
三、入门代码练习
-
首先创建一个maven的web项目需要添加tomcat和maven坐标
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build>
-
添加websocket的maven坐标
<dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1</version> <scope>provided</scope> </dependency>
-
类文件代码如下:
package com.lq.zhicheng; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.HashMap; import java.util.Map; import java.util.Set; @ServerEndpoint("/ws/{id}") public class TestWebSocket { //生命周期 open,close,message,error Session session; //用户身份令牌 String id; //用户id static Map<String,TestWebSocket> map=new HashMap<String, TestWebSocket>(); @OnOpen public void onOpen(Session session, @PathParam("id") String id){ //回调参数 this.session=session; this.id=id; map.put(id,this); System.out.println(id+"加入房间"); } @OnClose public void onClose(){ map.remove(id); System.out.println(id+"退出房间"); } @OnMessage public void OnMessage(String msg){ Set<String> key = map.keySet(); for (String s : key) { if(!map.get(s).id.equals(id)){ map.get(s).session.getAsyncRemote().sendText(msg); } } } }
-
通过在线websocket测试结果展示可以看到a1用户发送的消息a2的用户可以实时看到
-