什么是websocket 我在这里就不在赘述,网上有很多,可以自行百度,
干脆点直接上代码 部分代码我也是网上找来的
jar 包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
// 注意 websocket 版本应该和你的spring 版本保持一致 否则可能会出现意料之外的错误
配置
以下有三个类 缺一不可 关键地方也都有解释
@Configuration
@EnableWebMvc
@EnableWebSocket
public class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Bean
public TextWebSocketHandler webSocketHandler() {
return new SpringWebSocketHandler();
}
// 地址可以进行自定义 怎么样都可以
// 注意 setAllowedOrigins("*") 这个是允许跨域请求 如果项目启动 前端报了 拒绝连接多半是这个原因
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler(),"/websocket/socketServer")
.addInterceptors(new SpringWebSocketHandlerInterceptor()).setAllowedOrigins("*");
registry.addHandler(webSocketHandler(), "/sockjs/socketServer")
.addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
}
}
public class SpringWebSocketHandler extends TextWebSocketHandler {
//Map来存储WebSocketSession,key用USER_ID 即在线用户列表
private static final Map<String, WebSocketSession> users;
//用户标识
//对应监听器从的key
private static final String USER_ID = "WEBSOCKET_USERID";
static {
users = new HashMap<String, WebSocketSession>();
}
public SpringWebSocketHandler() {}
/**
* 连接成功时候,会触发页面上onopen方法
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("成功建立websocket连接!");
Users user = (Users) session.getAttributes().get("user");
users.put(user.getUserid(),session);
//这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户
//TextMessage returnMessage = new TextMessage("成功建立socket连接,你将收到的离线");
//session.sendMessage(returnMessage);
}
/**
* 关闭连接时触发
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
Users user = (Users) session.getAttributes().get("user");
System.out.println("用户"+user.getUserid()+"已退出!");
users.remove(user.getUserid());
System.out.println("剩余在线用户"+users.size());
}
/**
* js调用websocket.send时候,会调用该方法
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
/**
* 收到消息,自定义处理机制,实现业务
*/
System.out.println("服务器收到消息:"+message);
//单发某人
if(message.getPayload().startsWith("#anyone#")){
Users user = (Users) session.getAttributes().get("user");
sendMessageToUser(user.getUserid(), new TextMessage("服务器单发:" +message.getPayload()));
}else if(message.getPayload().startsWith("#everyone#")){
sendMessageToUsers(new TextMessage("服务器群发:" +message.getPayload()));
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if(session.isOpen()){
session.close();
}
Users user = (Users) session.getAttributes().get("user");
users.remove(user.getUserid());
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给某个用户发送消息
*
* @param userId
* @param message
*/
public void sendMessageToUser(String userId, TextMessage message) {
for (String id : users.keySet()) {
if (id.equals(userId)) {
try {
if (users.get(id).isOpen()) {
users.get(id).sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
for (String userId : users.keySet()) {
try {
if (users.get(userId).isOpen()) {
users.get(userId).sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> 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,以便定向发送消息
//一般直接保存user实体
Users users = (Users) session.getAttribute("user");
if (users!=null) {
attributes.put("WEBSOCKET_USERID",users.getUserid());
}
}
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
super.afterHandshake(request, response, wsHandler, ex);
}
}
前端
// 引入这个外部js
<script type="text/javascript" src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js">
</script>
var websocket = null;
// * 表示和你地址栏上的地址应该是一样的 不然会报404
if ('WebSocket' in window) {
websocket = new WebSocket("ws://*/websocket/socketServer");
}
else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://*/websocket/socketServer");
}
else {
websocket = new SockJS("http://*/sockjs/socketServer");
}
websocket.onopen = onOpen;
websocket.onmessage = onMessage;
websocket.onerror = onError;
websocket.onclose = onClose;
function onOpen(openEvt) {
}
function onMessage(evt) {
// 后端发送消息会在此接收到
}
window.close=function()
{
websocket.onclose();
};
后端发送数据
// 测试类
@Controller
public class WebSocketController {
// webSocket 注入
@Bean
public SpringWebSocketHandler infoHandler() {
return new SpringWebSocketHandler();
}
// 这里就是一个发送某个用户消息的例子!
@RequestMapping("/websocket/send")
@ResponseBody
public String send(HttpServletRequest request,String text) {
String username = request.getParameter("username");
infoHandler().sendMessageToUser(username, new TextMessage(text));
return null;
}
}