<!-- WebSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
前端代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
var userID="888";
var websocket=null;
$(function(){
connectWebSocket();
})
//建立WebSocket连接
function connectWebSocket(){
console.log("开始...");
//建立webSocket连接
websocket = new WebSocket("ws://127.0.0.1:8010/websocket/socketServer?user="+userID);
//打开webSokcet连接时,回调该函数
websocket.onopen = function () {
console.log("onpen");
}
//关闭webSocket连接时,回调该函数
websocket.onclose = function () {
//关闭连接
console.log("onclose");
}
//接收信息
websocket.onmessage = function (msg) {
console.log(msg.data);
}
}
//发送消息
function send(){
var postValue={};
postValue.id=userID;
postValue.message=$("#text").val();
websocket.send(JSON.stringify(postValue));
}
//关闭连接
function closeWebSocket(){
if(websocket != null) {
websocket.close();
}
}
</script>
</body>
</html>
后端代码
**
* 注册处理类及握手接口
* 这个有两种方式:
* 1.创建一个类来实现注册
* 2.使用xml配置文件实现
*
* @author lhb
*/
@Configuration
@EnableWebSocket
public class SpringWebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//前台 可以使用websocket环境
registry.addHandler(myHandler(), "websocket/socketServer").addInterceptors(new SpringWebSocketHandlerInterceptor()).setAllowedOrigins("*");
//前台 不可以使用websocket环境,则使用sockjs进行模拟连接
registry.addHandler(myHandler(), "sockjs/socketServer").addInterceptors(new SpringWebSocketHandlerInterceptor()).setAllowedOrigins("*").withSockJS();
}
public WebSocketHandler myHandler() {
return new SpringWebSocketHandler();
}
}
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;
/**
* 相当于controller的处理器
*/
@Slf4j
public class SpringWebSocketHandler extends TextWebSocketHandler {
// 保存所有的用户session
private static final Map<String, WebSocketSession> users = new HashMap<>();//这个会出现性能问题,最好用Map来存储,key用userid
/**
* 连接成功时候,会触发页面上onopen方法
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
users.put(session.getAttributes().get("userNo").toString(), session);
System.out.println("connect to the websocket success......当前数量:" + users.size());
//这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户
//TextMessage returnMessage = new TextMessage("你将收到的离线");
//session.sendMessage(returnMessage);
}
/**
* 关闭连接时触发
*/
@Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) throws Exception {
log.info("connect websocket closed.......");
users.remove(session.getAttributes().get("userNo"));
}
// 处理信息
/**
* js调用websocket.send时候,会调用该方法
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {// super.handleTextMessage(session, message);
Gson gson = new Gson();
// 将消息JSON格式通过Gson转换成Map
// message.getPayload().toString() 获取消息具体内容
Map<String, Object> msg = gson.fromJson(message.getPayload().toString(),
new TypeToken<Map<String, Object>>() {
}.getType());
log.info("handleMessage......." + message.getPayload() + "..........." + msg);
// session.sendMessage(message);
// 处理消息 msgContent消息内容
TextMessage textMessage = new TextMessage(msg.toString(), true);
// 调用方法(发送消息给所有人)
sendMessageToUsers(textMessage);
}
// 处理传输时异常
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
log.debug("websocket connection closed......");
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
return false;
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
*/
public void sendMessageToUser(String userName, TextMessage message) {
Iterator<String> iterator = users.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
WebSocketSession webSocketSession = users.get(key);
if (webSocketSession.getAttributes().get("userNo").equals(userName)) {
try {
if (webSocketSession.isOpen()) {
webSocketSession.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
Iterator<String> iterator = users.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
WebSocketSession webSocketSession = users.get(key);
try {
if (webSocketSession.isOpen()) {
webSocketSession.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.util.Map;
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;
/**
* 创建握手(handshake)接口/拦截器
*
* @author lhb
*/
public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
// 握手前
/**
* handler处理前调用,attributes属性最终在WebSocketSession里,可能通过webSocketSession.getAttributes().get(key值)获得
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler
wsHandler, Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
// 获取请求路径携带的参数
String user = serverHttpRequest.getServletRequest().getParameter("user");
attributes.put("userNo", user);
return true;
} else {
return false;
}
}
// 握手后
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
// TODO Auto-generated method stub
super.afterHandshake(request, response, wsHandler, ex);
}
}