服务器推送你还在使用轮询吗本文将带你领略WebSocket的魅力,轻松实现服务器推送功能。本文将以下面两方面让你理解WebSocket并应用到具体的开发中。
WebSocket概述
使用WebSocket实现网页聊天室
二、WebSocket
2.WebSocket介绍
WebSocket是一种网络通信协议。RFC6455定义了它的通信标准。
WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。
HTTP协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。
这种通信模型有一个弊端:HTTP协议无法实现服务器主动向客户端发起消息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数Web应用程序将通过频繁的异步AJAX请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者HTTP连接始终打开)。
websocket协议:
2.websocket协议
本协议有两部分:握手和数据传输。
来自客户端的握手看起来像如下形式:
GETws://localhost/chatHTTP/1.1Host:localhostUpgrade:websocketConnection:UpgradeSec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Extensions:permessage-deflateSec-WebSocket-Version:13来自服务器的握手看起来像如下形式:
HTTP/1.1101SwitchingProtocolsUpgrade:websocketConnection:UpgradeSec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=Sec-WebSocket-Extensions:permessage-deflate字段说明:
|头名称|说明||:------------------------|------------------------------------------------------------||Connection:Upgrade|标识该HTTP请求是一个协议升级请求||Upgrade:WebSocket|协议升级为WebSocket协议||Sec-WebSocket-Version:13|客户端支持WebSocket的版本||Sec-WebSocket-Key:|客户端采用base64编码的24位随机字符序列,服务器接受客户端HTTP协议升级的证明。要求服务端响应一个对应加密的Sec-WebSocket-Accept头信息作为应答||Sec-WebSocket-Extensions|协议扩展类型|3.客户端(浏览器)实现
3.1websocket对象
实现WebSockets的Web浏览器将通过WebSocket对象公开所有必需的客户端功能(主要指支持Html5的浏览器)。
以下API用于创建WebSocket对象:
varws=newWebSocket(url);>参数url格式说明:ws://ip地址:端口号/资源名称
3.2websocket事件
|事件|事件处理程序|描述|
|-------|-----------------------|--------------------------|
|open|websocket对象.onopen|连接建立时触发|
|message|websocket对象.onmessage|客户端接收服务端数据时触发|
|error|websocket对象.onerror|通信发生错误时触发|
|close|websocket对象.onclose|连接关闭时触发|
3.3WebSocket方法
|方法|描述|
|------|----------------|
|send()|使用连接发送数据|
4.服务端实现
Tomcat的7.0.5版本开始支持WebSocket,并且实现了JavaWebSocket规范(JSR356)。
我们可以通过两种方式定义Endpoint:
第一种是编程式,即继承类javax.websocket.Endpoint并实现其方法。
|方法|含义描述|注解|
|-------|------------------------------------------------------------|--------|
|onClose|当会话关闭时调用。|@OnClose|
|onOpen|当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法。|@OnOpen|
|onError|当连接过程中异常时调用。|@OnError|
服务端如何接收客户端发送的数据呢
通过为Session添加MessageHandler消息处理器来接收消息,当采用注解方式定义Endpoint时,我们还可以通过@OnMessage注解指定接收消息的方法。
服务端如何推送数据给客户端呢
发送消息则由RemoteEndpoint完成,其实例由Session维护,根据使用情况,我们可以通过Session.getBasicRemote获取同步消息发送的实例,然后调用其sendXxx()方法就可以发送消息,可以通过Session.getAsyncRemote获取异步消息发送实例。
服务端代码:
@ServerEndpoint("/robin")publicclassChatEndPoint{privatestaticSet
1.需求
通过websocket实现一个简易的聊天室功能。
1).登陆聊天室
2).登陆之后,进入聊天界面进行聊天
登陆成功后,呈现出以后的效果:
当我们想和李四聊天时就可以点击`好友列表`中的`李四`,效果如下:
接下来就可以进行聊天了,“张三”的界面如下:
“李四”的界面如下:
2.实现流程
3.消息格式
客户端-->服务端
{"toName":"张三","message":"你好"}
服务端-->客户端
系统消息格式:{"isSystem":true,"fromName":null,"message":["李四","王五"]}
推送给某一个的消息格式:{"isSystem":false,"fromName":"张三","message":"你好"}
4.功能实现
4.3引入公共资源
pojo类
/***@versionv1.0*@ClassName:MessageUtils*@Description:用来封装消息的工具类*@Author:黑马程序员*/publicclassMessageUtils{publicstaticStringgetMessage(booleanisSystemMessage,StringfromName,Objectmessage){try{ResultMessageresult=newResultMessage();result.setIsSystem(isSystemMessage);result.setMessage(message);if(fromName!=null){result.setFromName(fromName);}ObjectMappermapper=newObjectMapper();returnmapper.writeValueAsString(result);}catch(JsonProcessingExceptione){e.printStackTrace();}returnnull;}}4.4登陆功能实现
login.html:使用异步进行请求发送
@RequestMapping("/getUsername")publicStringgetUsername(HttpSessionsession){Stringusername=(String)session.getAttribute("user");returnusername;}4.6聊天室功能
客户端实现
在main.html页面实现前端代码:
`WebSocketConfig`类实现
开启springboot对websocket的支持
@ConfigurationpublicclassWebSocketConfig{@Bean//注入ServerEndpointExporter,自动注册使用@ServerEndpoint注解的publicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}