/**
* Intended to be overridden by sub-classes that wish to be notified
* when the outbound connection is established. The default implementation
* is a NO-OP.
*
* @param outbound The outbound WebSocket connection.
*/
protected void onOpen(WsOutbound outbound) {
// NO-OP
}
/**
* Intended to be overridden by sub-classes that wish to be notified
* when the outbound connection is closed. The default implementation
* is a NO-OP.
*
* @param status The status code of the close reason.
*/
protected void onClose(int status) {
// NO-OP
}
/**
* This method is called when there is a binary WebSocket message available
* to process. The message is presented via a stream and may be formed from
* one or more frames. The number of frames used to transmit the message is
* not made visible to the application.
*
* @param is The WebSocket message
*
* @throws IOException If a problem occurs processing the message. Any
* exception will trigger the closing of the WebSocket
* connection.
*/
protected abstract void onBinaryData(InputStream is) throws IOException;
/**
* This method is called when there is a textual WebSocket message available
* to process. The message is presented via a reader and may be formed from
* one or more frames. The number of frames used to transmit the message is
* not made visible to the application.
*
* @param r The WebSocket message
*
* @throws IOException If a problem occurs processing the message. Any
* exception will trigger the closing of the WebSocket
* connection.
*/
protected abstract void onTextData(Reader r) throws IOException;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Information required to send the server handshake message
String key;
String subProtocol = null;
List<String> extensions = Collections.emptyList();
if (!headerContainsToken(req, "upgrade", "websocket")) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (!headerContainsToken(req, "connection", "upgrade")) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (!headerContainsToken(req, "sec-websocket-version", "13")) {
resp.setStatus(426);
resp.setHeader("Sec-WebSocket-Version", "13");
return;
}
key = req.getHeader("Sec-WebSocket-Key");
if (key == null) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String origin = req.getHeader("Origin");
if (!verifyOrigin(origin)) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
List<String> subProtocols = getTokensFromHeader(req,
"Sec-WebSocket-Protocol-Client");
if (!subProtocols.isEmpty()) {
subProtocol = selectSubProtocol(subProtocols);
}
// TODO Read client handshake - Sec-WebSocket-Extensions
// TODO Extensions require the ability to specify something (API TBD)
// that can be passed to the Tomcat internals and process extension
// data present when the frame is fragmented.
// If we got this far, all is good. Accept the connection.
resp.setHeader("upgrade", "websocket");
resp.setHeader("connection", "upgrade");
resp.setHeader("Sec-WebSocket-Accept", getWebSocketAccept(key));
if (subProtocol != null) {
resp.setHeader("Sec-WebSocket-Protocol", subProtocol);
}
if (!extensions.isEmpty()) {
// TODO
}
// Small hack until the Servlet API provides a way to do this.
StreamInbound inbound = createWebSocketInbound(subProtocol);
((RequestFacade) req).doUpgrade(inbound);
}
注意倒数第三行,调用了createWebSocketInbound方法,我们重写这个方法。
@Override
protected StreamInbound createWebSocketInbound(String subProtocol) {
return new ChatMessageInbound(theUser);
}
/**
* 前台和后台交互的信息类型常量
*
* @author WangZhenChong
*
*/
public final class MsgTypeConstants {
public static short GET_USER_LIST = 1;// 在线所有用户信息交互
public static short SEND_ONE_TO_ONE = 2;// 对一个用户发送消息
public static short SEND_ONE_TO_ALL = 3;// 对所有用户发送消息
public static short SEND_SERVER_MSG = 4;// 发送系统消息
}