1.websocket是什么?
WebSocket是为解决客户端与服务端实时通信而产生的技术。其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信。
2.websocket的优点
以前我们实现推送技术,用的都是轮询,在特点的时间间隔有浏览器自动发出请求,将服务器的消息主动的拉回来,在这种情况下,我们需要不断的向服务器 发送请求,然而HTTP request 的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。会占用大量的带宽和服务器资源。
WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。在建立连接之后,服务器可以主动传送数据给客户端。
此外,服务器与客户端之间交换的标头信息很小。
WebSocket并不限于以Ajax(或XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;
3.如何使用websocket
下面的代码片段是打开一个连接,为连接创建事件监听器,断开连接,消息时间,发送消息返回到服务器,关闭连接。
<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
<script type="text/javascript" src="js/jquery-1.8.3.js"></script>
<script type="text/javascript" src="js/jquery.serializejson.min.js"></script>
<script type="text/javascript">
var webSocket = new WebSocket('ws://localhost:8080/tProject/websocket');
webSocket.onerror = function(event) {
alert(event.data);
};
webSocket.onclose = function(event) {
document.getElementById('messages').innerHTML = 'onclose';
};
webSocket.onopen = function(event) {
document.getElementById('messages').innerHTML = 'open';
};
webSocket.onmessage = function(event) {
document.getElementById('messages').innerHTML += '<br />' + event.data;
};
function start() {alert("aa");
webSocket.send(JSON.stringify({msgType:1,msgContent:'huang1',msgFromUserID:'huang2',msgFromUserName:'huang1',msgToUserID:'huang2',msgToUserName:'huang2'}));
return false;
}
</script>
</head>
<body>
<div>
<input type="submit" value="Start" οnclick="start()" />
</div>
<div id="messages"></div>
</body>
</html>
让我们来看看上面的初始化片段。参数为URL,ws表示WebSocket协议,url:ws://localhost:8080/byteslounge/websocket。
onOpen 我们创建一个连接到服务器的连接时将会调用此方法。
onClose 我们关闭一个连接到服务器的连接时将会调用此方法。
onError 当客户端-服务器通信发生错误时将会调用此方法。
onMessage事件提供了一个data属性,它可以包含消息的Body部分。消息的Body部分必须是一个字符串,可以进行序列化/反序列化操作,以便传递更多的数据。4.服务器端websocket
package org.jp.websocket;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
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;
import org.jp.util.JsonUtil;
import org.jp.websocket.service.WebSocketService;
import org.springframework.context.ApplicationContext;
//import org.springframework.web.socket.server.endpoint.SpringConfigurator;
import org.springframework.web.context.support.WebApplicationContextUtils;
@ServerEndpoint(value = "/websocket",configurator=GetHttpSessionConfigurator.class)
public class WebSocket{
private WebSocketService webSocketService;
private Session session;
private HttpSession httpSession;
@OnOpen
public void onOpen(Session session, EndpointConfig config) throws IOException, InterruptedException {
this.session = session;
this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
if(httpSession != null){
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(httpSession.getServletContext());
this.webSocketService = (WebSocketService)ctx.getBean("webSocketService");
}
}
@OnClose
public void onClose() throws IOException, InterruptedException {
}
@OnMessage
public void onMessage(String message, EndpointConfig config) throws IOException, InterruptedException {
Map msgMap = JsonUtil.getMapFromJson(message);
Set<Session> sessions = session.getOpenSessions();
for (Session session2 : sessions) {
session2.getBasicRemote().sendText((String)msgMap.get("msgContent"));
}
}
@OnError
public void onError(Throwable t) throws Throwable {
}
}
@ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。
onOpen 和 onClose 方法分别被@OnOpen和@OnClose 所注解。这两个注解的作用不言自明:他们定义了当一个新用户连接和断开的时候所调用的方法。
onMessage 方法被@OnMessage所注解。这个注解定义了当服务器接收到客户端发送的消息时所调用的方法。
注意:这个方法可能包含一个javax.websocket.Session可选参数(在我们的例子里就是session参数)。如果有这个参数,容器将会把当前发送消息客户端的连接Session注入进去。
5.通过GetHttpSessionConfigurator类注入HttpSession
package org.jp.websocket;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
if(httpSession != null){
config.getUserProperties().put(HttpSession.class.getName(), httpSession);
}
}
}
通过GetHttpSessionConfigurator可以在onOpen方法中取得HttpSession,然后通过HttpSession的ServletContext容器可以取得spring的service,实现在websocket中变相注入spring bean。