本文摘自classinstance.cn。
上一篇关于使用spring4实现websocket连接的问题,我只是分享了大致如何实现,要想应用到实际项目中,还要考虑2个问题:
1.是否区分用户,用户连上websocket时,每次发消息给用户时,是否要区分用户,是不是每个人收到的消息不一样,这里就涉及获取httpSession的问题了。
2.我们项目中一般不会只有一个websocket收发消息,有时一个是处理用户消息,一个是处理其他的,举个例子:批处理时的进度实时反馈等,都会用到websocket。
所以针对上面这两个问题,我决定再深入研究了下,pom文件还是参考上一篇文章里的,并没有新加入jar包,下面直接上代码吧,类也是上一篇里的那两个类,只是新加入了一些完善的代码,代码里都有提到上面这两个问题:
HandshakeInterceptor.java
package com.solr.websocket;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{
//websocket握手时处理httpsession,取用户标识,如果你的应用不区分用户,当然这里就可以不用取sesion了
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("Before Handshake");
//演示怎么把httpsession放入websocketsession里,区分用户
HttpSession session = getSession(request);
if (session != null) {
String userId = session.getId();
attributes.put("userId", userId);
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
}
//取httpSession
private HttpSession getSession(ServerHttpRequest request) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
return serverRequest.getServletRequest().getSession();
}
return null;
}
}
WebsocketHandler.java
package com.solr.websocket;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class WebsocketHandler extends TextWebSocketHandler {
private final static Map<String, WebSocketSession> users = new ConcurrentHashMap<String, WebSocketSession>();
public static Map<String, WebSocketSession> getUsers() {
return users;
}
static{
SendMessageThread sendThread = new SendMessageThread();
Thread t = new Thread(sendThread);
t.start();
}
/**
* 连接成功时候,会触发页面上的onopen方法
*/
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
Map<String, Object> attributes = session.getHandshakeAttributes();
if (attributes != null && attributes.size() > 0) {
String userId = attributes.get("userId").toString();//只是为了演示这里可以取httpsession的id,如果你的应用要区分用户,就可以在此处取httpsession
System.out.println("userId:" + userId);
String websocketId = session.getId();//websocket id
users.put(websocketId, session);
}
System.out.println("connect to the websocket success......当前数量:"+ users.size());
}
/**
* 关闭连接时触发(关闭掉页面也会触发)
*/
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) throws Exception {
System.out.println("websocket connection closed......");
String websocketId = session.getId();//websocket id
users.remove(websocketId);
System.out.println("剩余在线用户" + users.size());
}
/**
* 异常处理
*/
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
System.out.println("websocket connection closed......");
String websocketId = session.getId();//websocket id
users.remove(websocketId);
}
// 收消息
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
super.handleTextMessage(session, message);
System.out.println("收到消息:" + message.getPayload());
}
static class SendMessageThread implements Runnable {
public void run() {
while (true) {
try {
Map<String, WebSocketSession> map = WebsocketHandler.getUsers();
Set<String> keySet = map.keySet();
for (String key : keySet) {
WebSocketSession webSocketSession = map.get(key);
if (webSocketSession.isOpen()) {
String message = "现在时间:"+ new Date().toLocaleString();
TextMessage textMessage = new TextMessage(message);
webSocketSession.sendMessage(textMessage);
}
}
//定时5秒发一次消息
Thread.sleep(5000l);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
这样就是比较接近实际项目里的应用了,触发发送消息我上面的代码是定时5秒发一次消息,你也可以根据你的项目把调用发送消息的代码写在service或者springmvc的controller里,关键是看你的具体业务。
相关阅读 >>
spring如何获取配置在application.properties文件中属性的值?
spring、springmvc、springboot和springcloud的区别
更多相关阅读请进入《spring4》频道 >>
深入理解Java虚拟机 JVM高级特性与实践 周志明 第3版
这是一部从工作原理和工程实践两个维度深入剖析JVM的著作,是计算机领域公认的经典。