https://blog.csdn.net/u014377655/article/details/81332959
结构如下图
Hello World!
WebSocket测试页
Input:
public class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements
WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler(),"/websocket/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor());
registry.addHandler(webSocketHandler(), "/sockjs/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
}
@Bean
public TextWebSocketHandler webSocketHandler(){
return new SpringWebSocketHandler();
}
}
public class SpringWebSocketHandler extends TextWebSocketHandler {
//在线用户列表
private static final Map users;
static {
users = new HashMap<>();
}
public SpringWebSocketHandler() { }
/**
* 建立连接后触发的回调
* 记录用户的连接标识,便于后面发信息,
* 这里我是记录将id记录在Map集合中。
* 一个Map中不能包含相同的key,每个key只能映射一个value,根据先后put的顺序覆盖
* @param session
* @throws Exception
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("成功建立连接");
String userName = getClientId(session);
if (userName != null) {
System.out.println("用户"+userName+"登录!");
users.put(userName, session);
session.sendMessage(new TextMessage("server:成功建立socket连接"));
System.out.println("当前在线用户"+users.size()+": "+users);
}
//userName为空时,不存储该用户,不与该用户交互
}
/**
* 断开连接后触发的回调
* 连接已关闭,移除在Map集合中的记录。
* @param session
* @param closeStatus
* @throws Exception
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
String userName = getClientId(session);
System.out.println("\n用户"+userName+"已退出: " + closeStatus);
users.remove(userName);
System.out.println("剩余在线用户"+users.size()+": "+users);
}
/**
* 收到消息时触发的回调
* 对H5 Websocket的send方法进行处理
* @param session
* @param message
*/
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
//显示客户端发送过来的消息内容
System.out.println("client:"+message.getPayload());
WebSocketMessage message1 = new TextMessage("server:"+message);
try {
session.sendMessage(message1);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 传输消息出错时触发的回调
* 连接出错处理,主要是关闭出错会话的连接,和删除在Map集合中的记录
* @param session
* @param exception
* @throws Exception
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
System.out.println("连接出错");
users.remove(getClientId(session));
}
/**
* 是否处理分片消息
* @return
*/
public boolean supportsPartialMessages() {
return false;
}
/**
* 发送信息给指定用户
* 传入用户标识和消息体
* @param clientId
* @param message
* @return
*/
public boolean sendMessageToUser(String clientId, TextMessage message) {
if (users.get(clientId) == null) return false;
WebSocketSession session = users.get(clientId);
System.out.println("sendMessage:" + session);
if (!session.isOpen()) return false;
try {
session.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 广播信息
* 只需要传入消息体
* @param message
* @return
*/
public boolean sendMessageToAllUsers(TextMessage message) {
boolean allSendSuccess = true;
Set clientIds = users.keySet();
WebSocketSession session = null;
for (String clientId : clientIds) {
try {
session = users.get(clientId);
if (session.isOpen()) {
session.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
allSendSuccess = false;
}
}
return allSendSuccess;
}
/**
* 获取用户标识
* @param session
* @return
*/
private String getClientId(WebSocketSession session) {
try {
String clientId = (String)session.getAttributes().get(Const.CLIENT_NAME);
return clientId;
} catch (Exception e) {
return null;
}
}
}
public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map attributes) throws Exception
System.out.println("Before Handshake");
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession(false);
if (session != null) {
//使用userName区分WebSocketHandler,以便定向发送消息
String userName = (String) session.getAttribute("userName");
if (userName==null) {
userName="default-system";
}
attributes.put("userName",userName);
}else{
System.out.println("beforeHandshake 没有获取到 session");
}
}
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);
}
}
@Controller
public class WebsocketController {
@Bean
public SpringWebSocketHandler infoHandler() {
return new SpringWebSocketHandler();
}
@RequestMapping("/websocket/login")
public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
String userName = request.getParameter("userName");
System.out.println(userName+"登录");
HttpSession session = request.getSession(false);
session.setAttribute(Const.CLIENT_NAME, userName);
ModelAndView mv = new ModelAndView();
mv.setViewName("ws");
return mv;
}}
输入用户名,点击login
跳转至
发送消息测试
参考博文
spring配置websocket并实现群发/单独发送消息
https://blog.csdn.net/u014520745/article/details/62046396
https://www.cnblogs.com/3dianpomian/p/5902084.html