编译环境:jdk1.8 , tomcat8.0+ , IDEA
这里主要讲一下websocket的信息传递,以如何实现多人实时在线聊天为例:
websocket主要的三个类
MyWebSocketConfig主要负责配置websocket的处理器和握手拦截器
MyHandShakeInterceptor 是websocket的拦截器
MyWebSocketHander是websocket的处理器
@Component
@EnableWebSocket
public class MyWebSocketConfig implements WebSocketConfigurer {
@Autowired
private MyWebSocketHander myWebSocketHander;
private static final String LINK_URI = "websocket.do";
//添加websocket处理器,添加握手拦截器 拦截器先执行 然后到处理器
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(myWebSocketHander,LINK_URI).addInterceptors(new MyHandShakeInterceptor());
}
}
/* private static Map map = new HashMap();
* websocket握手拦截器
* 拦截握手前,握手后的两个切面
*/
@Component
public class MyHandShakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map map) throws Exception {
if(serverHttpRequest instanceof ServletServerHttpRequest){
HttpServletRequest servletRequest = ((ServletServerHttpRequest)serverHttpRequest).getServletRequest();
User user = (User)servletRequest.getSession().getAttribute("user");
//这里给map赋值 相当于websockethandler的afterConnectionEstablished方法里的WebSocketSession
//key是session,value是变量
map.put("ws_user", user);
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
}
实时通信的具体流程:
前端
<% String path = request.getContextPath();%>
link rel="stylesheet" href="<%=path%>/static/css/bootstrap.min.css"
type="text/css">
chat-room
后台MyWebSocketHander接受数据
@Component
public class MyWebSocketHander implements WebSocketHandler {
private final static List USERS = new ArrayList<>();
private final static List USER_ONLINE = new ArrayList<>();
/*
*在链接创建完后就在前端显示在线用户
*/
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
USERS.add(webSocketSession);
//每次有新的连接,就加入到user集合中
User user = (User) webSocketSession.getAttributes().get("ws_user");
USER_ONLINE.add(user);
List userNamelist = new ArrayList<>();
for (User u : USER_ONLINE) {
String userName = u.getUserName();
userNamelist.add(userName);
}
//String类的format()方法用于创建格式化的字符串以及连接多个字符串对象。
//这里传到前端的应该是JSON格式
String messageFormat = "{onlineNum:\"%d\",userName:\"%s\" , msgTyp " +
":\"%s\"}";
String msg = String.format(messageFormat, USERS.size(), userNamelist,
"notice");
TextMessage testMsg = new TextMessage(msg + "");
//确保每个用户信息都能同步到
for (WebSocketSession wss : USERS) {
wss.sendMessage(testMsg);
}
}
/**
* 客户端发送服务器的消息时的处理函数,在这里收到消息之后可以分发消息
*/
@Autowired
private ChatService chatService;
@Override
public void handleMessage(WebSocketSession webSocketSession,
WebSocketMessage> webSocketMessage) throws Exception {
String messageFormat = null;
//发送消息的时间
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String sentMsgDate = dateFormat.format(new Date());
User user = (User) webSocketSession.getAttributes().get("ws_user");
String msgContent = webSocketMessage.getPayload() + "";
JSONObject chat = JSON.parseObject(msgContent);
//消息的内容
String msgJSON = chat.get("message").toString();
//消息的样式
String msgJSONType = chat.get("type").toString();
String chatMsg = "chatMsg";
if (msgJSONType.equals(chatMsg)) {
//将消息保存到数据库
ChatMsg chatMessage = new ChatMsg(user.getId(), sentMsgDate,
msgJSON);
chatService.addMessage(chatMessage);
messageFormat = "{user:\"%s\",sendDate:\"%s\" ," +
"sendContent:\"%s\" , msgTyp :\"%s\"}";
String message = String.format(messageFormat, user.getUserName(),
sentMsgDate, msgJSON , "msg");
TextMessage toMsg = new TextMessage(message + "");
//遍历所有的用户,发信息,这个要注意哦,要不然不能做到多人同时聊天
for (WebSocketSession wss : USERS) {
wss.sendMessage(toMsg);
}
}
}
@Override
public void handleTransportError(WebSocketSession webSocketSession,
Throwable throwable) throws Exception {
USERS.remove(webSocketSession);
}
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession,
CloseStatus closeStatus) throws Exception {
User userRemove = (User) webSocketSession.getAttributes().get(
"ws_user");
USER_ONLINE.remove(userRemove);
USERS.remove(webSocketSession);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
所以websocket消息传送流程大致是
websocket.onopen打开链接 --> websocket.send()发送数据 -->后台的MyWebSocketHander接收数据-->WebSocketSession.sendMessage将消息发送给前端 --> 前端websocket.onmessage()接收数据并显示。
github地址:https://github.com/androidlearner2017/simple-chatroom.git
很简单的一个demon,里面有些功能还没有完全实现,继续修改中 ing