1.pom文件引入依赖:spring.version为对应的spring版本
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
2.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
<!-- 配置webSocket -->
<!-- websocket消息处理bean -->
<bean id="WebsocketHandler" class="com.thinkgem.jeesite.modules.meeting.websocket.WebsocketHandler"/>
<websocket:handlers>
<!-- 配置消息处理bean和路径的映射关系 -->
<websocket:mapping path="/websocket" handler="WebsocketHandler"/>
<!-- 配置握手拦截器 -->
<websocket:handshake-interceptors>
<bean class="com.thinkgem.jeesite.modules.meeting.websocket.HandshakeInterceptor"/>
</websocket:handshake-interceptors>
<!-- 开启sockjs,去掉则关闭sockjs -->
<!--<websocket:sockjs/>-->
</websocket:handlers>
<!-- 配置websocket消息的最大缓冲区长度 -->
<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
<property name="maxTextMessageBufferSize" value="8192"/>
<property name="maxBinaryMessageBufferSize" value="8192"/>
</bean>
</beans>
3.java代码
package com.thinkgem.jeesite.modules.meeting.websocket;
import java.util.Map;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import com.thinkgem.jeesite.modules.meeting.utils.Constant;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
@Service
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("Before Handshake ... 握手前......");
// 解决The extension [x-webkit-deflate-frame] is not supported问题
if (request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}
// 使用userid区分WebSocketHandler,以便定向发送消息(使用shiro获取session)
String userid = UserUtils.getUser().getId();
if (userid == null) {
userid = "default-system";
}
attributes.put(Constant.WEBSOCKET_USERID, userid);
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("After Handshake ... 握手后 ......");
super.afterHandshake(request, response, wsHandler, ex);
}
}
package com.thinkgem.jeesite.modules.meeting.websocket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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;
import com.thinkgem.jeesite.modules.meeting.utils.Constant;
public class WebsocketHandler extends TextWebSocketHandler {
//存储用户
private static final List<WebSocketSession> users = new ArrayList<>();
//接收到客户端消息时调用
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
System.out.println("text message: " + session.getPrincipal() + "-" + message.getPayload());
String text = "get message by "+session.getPrincipal()+":"+message.getPayload();
System.out.println(text);
session.sendMessage(new TextMessage(text.getBytes()));
}
//用户进入系统监听
@Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
users.add(session);
}
// 消息传输出错时调用
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println("handleTransportError");
}
// 一个客户端连接断开时关闭
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
System.out.println("afterConnectionClosed");
if (session.isOpen()) {
session.close();
}
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给所有的用户发送消息
*/
public void sendMessagesToUsers(TextMessage message) {
for (WebSocketSession user : users) {
try {
//isOpen()在线就发送
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 发送消息给指定的用户
*/
public void sendMessageToUser(String userId, TextMessage message) {
for (WebSocketSession user : users) {
if (user.getAttributes().get(Constant.WEBSOCKET_USERID).equals(userId)) {
try {
//isOpen()在线就发送
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.前端页面
<%@ page language="java" import="java.util.*"
contentType="text/html;charset=UTF-8"%>
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
<%@include file="/WEB-INF/views/include/head.jsp"%>
<html>
<head>
<title>test</title>
<meta name="decorator" content="default" />
<meta charset="UTF-8">
<!-- <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
<!-- <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script> -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<title>测试</title>
<script type="text/javascript">
var stomp,sock;
$(document).ready(function () {
if (window.WebSocket){
websocketConfig();
} else {
alert("错误","浏览器不支持websocket技术通讯.");
}
});
//websocket配置
function websocketConfig() {
/* if('WebSocket' in window) {
console.log("此浏览器支持websocket");
sock = new WebSocket("ws://localhost:8080"+ctx+"/webSocket");
} else {
//连接url为endpointChat的endpoint,对应后台WebSoccketConfig的配置
} */
//SockJS所处理的URL是http://或https://,不再是ws://和wss://
//使用相对URL。例如,如果包含JavaScript的页面位于"http://localhost:8080/websocket"的路径下
sock = new SockJS("http://localhost:8080/hprd_business/webSocket");
sockHandle();
stompConfig();
}
function stompConfig() {
//使用STOMP子协议的websocket客户端
console.log("Connection status "+sock.readyState);
stomp = Stomp.over(sock);
stomp.connect({}, function(frame) {
//这里的订阅地址和controller的convertAndSendToUser地址一致,多出的user必须的,指的是用户之间发送消息
//这里的地址和后台的Controller sendChatMsg方法的chatAddress 一致
stomp.subscribe("/user/queue/showQRCode", function (message) {
//处理响应消息
var json = JSON.parse(message.body);
console.log(json);
});
//订阅处理错误的消息地址,接收错误消息
stomp.subscribe("/user/queue/contactErrors${chatId}", function (message) {
var response = JSON.parse(message.body);
var error = response.error;
alert("发送失败"+error);
});
});
}
//发送消息
function sendMessage() {
//文本框的内容
var content = $("#content").val();
if ($.trim($("#content").val()).length <= 0){
return ;
}
//拼接成json传到后台
var data = {
chatId:'${chatId}',
schoolId:'${schoolId}',
toUserId:'${receiverId}',
content:content,
fromUserId:'${accountId}',
appId:'${appId}',
msgType:1
};
//发送
stomp.send("/sendChatMsg",{},JSON.stringify(data) );
}
function sockHandle() {
sock.onopen = function () {
console.log("------连接成功------");
};
sock.onmessage = function (event) {
console.log('-------Received: ' + event.data);
};
sock.onclose = function (event) {
console.log('--------Info: connection closed.------');
};
//连接发生错误
sock.onerror = function () {
alert("连接错误", "网络超时或通讯地址错误.");
disconnect();
};
}
//关闭websocket
function disconnect() {
if (sock != null) {
sock.close();
sock = null;
}
}
</script>
</head>
<body>
<div class="page-header" id="tou">webSocket多终端聊天测试</div>
<div class="well" id="msg"></div>
<div class="col-lg">
<div class="input-group">
<input type="text" class="form-control" placeholder="发送信息..."
width="10" id="message"> <span class="input-group-btn">
<button class="btn btn-default" type="button" id="send">发送</button>
</span>
</div>
</div>
</body>
</html>