1.在pom文件中添加依赖
<properties>
<spring.version>4.3.20.RELEASE</spring.version>
</properties>
<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.注册处理适配器
MyWebSocketConfig.java
package com.myc.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebMvc
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 前台 可以使用websocket环境
registry.addHandler(myWebSocketHandler(), "/websocket").addInterceptors(new HandshakeInterceptor())
.setAllowedOrigins("*");
// 前台 不可以使用websocket环境,则使用sockjs进行模拟连接
registry.addHandler(myWebSocketHandler(), "/sockjs/websocket").addInterceptors(new HandshakeInterceptor())
.setAllowedOrigins("*").withSockJS();
}
// websocket 处理类
@Bean
public WebSocketHandler myWebSocketHandler() {
return new MyWebSocketHandler();
}
}
3.添加拦截器
HandshakeInterceptor.java
package com.myc.websocket;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
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 {
// 握手前
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("++++++++++++++++ HandshakeInterceptor: beforeHandshake ++++++++++++++" + attributes);
HttpServletRequest httpRequest = ((ServletServerHttpRequest) request).getServletRequest();
String uid = httpRequest.getParameter("uid");
if (StringUtils.isNoneBlank(uid)) {
attributes.put("uid", uid);
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
// 握手后
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("++++++++++++++++ HandshakeInterceptor: afterHandshake ++++++++++++++");
super.afterHandshake(request, response, wsHandler, ex);
}
}
4.添加处理适配器
MyWebSocketHandler.java
package com.myc.websocket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import com.alibaba.fastjson.JSON;
public class MyWebSocketHandler implements WebSocketHandler {
private static final Logger log = LoggerFactory.getLogger(MyWebSocketHandler.class);
// 保存未登录用户session
private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();
// 保存登录用户session
private static final HashMap<Long, WebSocketSession> uidUsers = new HashMap<>();
// 连接 就绪时
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Map<String, Object> map = session.getAttributes();
if (map != null) {
String uid = (String) map.get("uid");
if (uid != null) {
uidUsers.put(Long.valueOf(uid), session);
} else {
users.add(session);
}
} else {
users.add(session);
}
log.info("connect websocket success.......");
}
// 处理信息
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
// 将消息JSON格式通过Gson转换成Map
// message.getPayload().toString() 获取消息具体内容
Map<String, Object> msg = JSON.parseObject(message.getPayload().toString(), HashMap.class);
log.info("handleMessage......." + message.getPayload() + "..........." + msg);
// session.sendMessage(message);
// 处理消息 msgContent消息内容
TextMessage textMessage = new TextMessage(msg.get("msgContent").toString(), true);
// 调用方法(发送消息给所有人)
sendMsgToAllUsers(textMessage);
}
// 处理传输时异常
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// TODO Auto-generated method stub
}
// 关闭 连接时
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
log.info("connect websocket closed.......");
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
return false;
}
// 给所有用户发送 信息
public void sendMsgToAllUsers(WebSocketMessage<?> message) throws Exception {
for (WebSocketSession user : users) {
user.sendMessage(message);
}
}
public void sendMsgToAllUsers(TextMessage msg) throws IOException {
for (WebSocketSession user : users) {
user.sendMessage(msg);
}
for (WebSocketSession user : uidUsers.values()) {
user.sendMessage(msg);
}
}
public void sendMsgToUser(Long uid, TextMessage msg) throws IOException {
for (Long key : uidUsers.keySet()) {
if (key.equals(uid)) {
uidUsers.get(uid).sendMessage(msg);
break;
}
}
}
}
5.控制器
TestSocketController.java
package com.myc.controller;
import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.socket.TextMessage;
import com.myc.websocket.MyWebSocketHandler;
@RestController
@RequestMapping("/api")
public class TestSocketController {
@Autowired
MyWebSocketHandler myHandler;
@GetMapping("/websocket")
public String handle(String uid) throws IOException {
if (StringUtils.isEmpty(uid)) {
myHandler.sendMsgToAllUsers(new TextMessage("我是群发"));
}else {
myHandler.sendMsgToUser(Long.valueOf(uid),new TextMessage("我是私发"));
}
return "ok";
}
}
6.测试页面
websocket.html
<!DOCTYPE HTML>
<html>
<head>
<title>首页</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<!-- 引入 JQuery -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<!-- 引入 sockJS -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js" ></script>
<!-- 自定义JS文件 -->
<script type="text/javascript">
window.onload = function() {
var websocket;
var uid =116;
// 首先判断是否 支持 WebSocket
if('WebSocket' in window) {
<!-- websocket = new WebSocket("ws://localhost:8081/websocket?uid="+uid);-->
websocket = new WebSocket("ws://localhost:8081/websocket");
console.log("type=1");
} else if('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8081/websocket"+uid);
console.log("type=2");
} else {
websocket = new SockJS("http://localhost:8081/sockjs/websocket"+uid);
console.log("type=3");
}
// 打开时
websocket.onopen = function(evnt) {
console.log(" websocket.onopen ");
};
// 处理消息时
websocket.onmessage = function(evnt) {
$("#msg").append("<p>(<font color='red'>" + evnt.data + "</font>)</p>");
console.log(" websocket.onmessage ");
};
websocket.onerror = function(evnt) {
console.log(" websocket.onerror ");
};
websocket.onclose = function(evnt) {
console.log(" websocket.onclose ");
};
// 点击了发送消息按钮的响应事件
$("#group").click(function(){
htmlobj=$.ajax({url:"http://localhost:8081/api/websocket",async:false});
});
$("#single").click(function(){
htmlobj=$.ajax({url:"http://localhost:8081/api/websocket?uid="+uid,async:false});
});
// 点击了发送消息按钮的响应事件
$("#TXBTN").click(function(){
// 获取消息内容
var text = $("#tx").val();
// 判断
if(text == null || text == ""){
alert(" content can not empty!!");
return false;
}
var msg = {
msgContent: text,
uid: 116
};
// 发送消息
websocket.send(JSON.stringify(msg));
});
};
</script>
</head>
<body>
<!-- 最外边框 -->
<div style="margin: 20px auto; border: 1px solid blue; width: 300px; height: 500px;">
<!-- 消息展示框 -->
<div id="msg" style="width: 100%; height: 56%; border: 1px solid yellow;overflow: auto;"></div>
<!-- 消息编辑框 -->
<textarea id="tx" style="width: 100%; height: 20%;"></textarea>
<!-- 消息发送按钮 -->
<button id="TXBTN" style="width: 100%; height: 8%;">发送数据</button>
<!-- 消息发送按钮 -->
<button id="group" style="width: 100%; height: 8%;">群发</button>
<button id="single" style="width: 100%; height: 8%;">私发</button>
</div>
</body>
</html>
7.web.xml配置
在原来的xml中添加
<async-supported>true</async-supported>
8.websocket配置
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
<!-- websocket处理类 -->
<bean id="myHandler" class="com.myc.websocket.MyWebSocketHandler"/>
<!-- 握手接口/拦截器 -->
<bean id="myInterceptor" class="com.myc.websocket.HandshakeInterceptor"/>
<websocket:handlers >
<websocket:mapping path="/websocket" handler="myHandler"/>
<websocket:handshake-interceptors>
<ref bean="myInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
<!-- 注册 sockJS -->
<websocket:handlers>
<websocket:mapping path="/sockjs/websocket" handler="myHandler"/>
<websocket:handshake-interceptors>
<ref bean="myInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs />
</websocket:handlers>
</beans>
9.效果如下
这是依次点了下群发、私发、发送数据的按钮,群发可以打开多个页面测试