前段时间写了个一对一实时聊天,且将数据保存到数据库,所以需将websocket与ssm整合,方便使用注解。
1、在pom.xml中添加需要的jar文件
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
2、创建拦截器类
public class MyHandShakeInterceptor implements HandshakeInterceptor {
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse,
WebSocketHandler webSocketHandler, Map<String, Object> map)
throws Exception {
if (serverHttpRequest instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) serverHttpRequest;
HttpSession session = servletRequest.getServletRequest()
.getSession(false);
// 获取登录时保存到session中的用户信息
UserInfo userInfo = (UserInfo) session.getAttribute("userInfo");
if (userInfo != null) {
map.put("userId", userInfo.getId());//为服务器创建WebSocketSession做准备
} else {
return false;
}
}
return true;
}
public void afterHandshake(ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse,
WebSocketHandler webSocketHandler, Exception e) {
}
}
3、创建WebSocketMap工具类
public class WebSocketMapService {
public static final ConcurrentMap<Integer, WebSocketSession> webSocketSessionMap;
static {
webSocketSessionMap = new ConcurrentHashMap<Integer, WebSocketSession>();
}
public static void put(Integer key, WebSocketSession myWebSocket) {
webSocketSessionMap.put(key, myWebSocket);
}
public static WebSocketSession get(Integer key) {
return webSocketSessionMap.get(key);
}
public static void remove(Integer key) {
webSocketSessionMap.remove(key);
}
public static Collection<WebSocketSession> getValues() {
return webSocketSessionMap.values();
}
public static Set<Entry<Integer, WebSocketSession>> entrySet() {
return webSocketSessionMap.entrySet();
}
}
4、创建websocket处理类
@Component
public class MyWebSocketHandler implements WebSocketHandler {
@Autowired
private MessageInfoService messageInfoService;
//握手实现连接后
public void afterConnectionEstablished(WebSocketSession webSocketSession)
throws Exception {
int userId = (Integer) webSocketSession.getAttributes().get("userId");
if (WebSocketMapService.get(userId) == null) {
WebSocketMapService.put(userId, webSocketSession);
}
}
//发送信息前的处理
public void handleMessage(WebSocketSession webSocketSession,
WebSocketMessage<?> webSocketMessage) throws Exception {
if (webSocketMessage.getPayloadLength() == 0)
return;
//获取Socket通道中的数据
JSONObject object = JSONObject
.parseObject(webSocketMessage.getPayload().toString());
MessageInfo messageInfo = new MessageInfo();
//...
//将信息保存至数据库
messageInfoService.insertMessage(messageInfo);
// 给自己发送消息
sendMessageToUser(messageInfo.getSenduserid(),
new TextMessage(
new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
.create().toJson(messageInfo)));
// 给对方发送消息
sendMessageToUser(messageInfo.getReuserid(),
new TextMessage(
new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
.create().toJson(messageInfo)));
}
public void handleTransportError(WebSocketSession webSocketSession,
Throwable throwable) throws Exception {
}
public void afterConnectionClosed(WebSocketSession webSocketSession,
CloseStatus closeStatus) throws Exception {
//断开连接即将此用户对应的WebSocketSession移除,以便再次连接时添加新的WebSocketSession
Iterator<Map.Entry<Integer, WebSocketSession>> iterator = WebSocketMapService
.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, WebSocketSession> entry = iterator.next();
if (entry.getValue().getAttributes()
.get("userId") == webSocketSession.getAttributes()
.get("userId")) {
WebSocketMapService.remove((Integer) webSocketSession
.getAttributes().get("userId"));
}
}
}
public boolean supportsPartialMessages() {
return false;
}
//发送信息的实现
public void sendMessageToUser(Integer userId, TextMessage message)
throws IOException {
WebSocketSession session = WebSocketMapService.get(userId);
if (session != null && session.isOpen()) {
session.sendMessage(message);
}
}
}
5、创建配置类 (也可使用配置文件)
@Component
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter
implements WebSocketConfigurer {
@Autowired
MyWebSocketHandler handler;
public void registerWebSocketHandlers(
WebSocketHandlerRegistry webSocketHandlerRegistry) {
//添加websocket处理器,添加握手拦截器
webSocketHandlerRegistry.addHandler(handler, "/ws")
.addInterceptors(new MyHandShakeInterceptor());
//添加websocket处理器,添加握手拦截器
webSocketHandlerRegistry.addHandler(handler, "/ws/sockjs")
.addInterceptors(new MyHandShakeInterceptor()).withSockJS();
}
}
6、添加前端(客户端)连接(主要代码)
<script src="../../assets/js/plugins/sockjs/sockjs.js"></script>
var wsServer = null;
var ws = null;
wsServer = "ws://ip:端口/项目名/ws";
ws = new WebSocket(wsServer); //创建WebSocket对象
ws.onopen = function(evt) {
layer.msg("已经建立连接", {
offset : 0
});
};
ws.onmessage = function(evt) {
var message = JSON.parse(evt.data);//将数据解析成JSON形式
showMess(message);//展示消息
};
ws.onerror = function(evt) {
layer.msg("产生异常", {
offset : 0
});
};
ws.onclose = function(evt) {
layer.msg("已经关闭连接", {
offset : 0
});
};
...
//发送消息
var data = {};//新建data对象,并规定属性名与相应的值
ws.send(JSON.stringify(data));//将对象封装成JSON后发送至服务器