注:需spring4.0及以上版本。
步骤:
1、导入jar包(maven方式)
<!-- Spring websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
2、编写WebSocketConfig类,用于配置websocket
package com.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.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//允许连接的域;只能以http或https开头
String[] allowsOrigins = {"https://www.xxx.com"};
//WebIM WebSocket通道
registry.addHandler(WebSocketHandler(), "/websocket").addInterceptors(WebScoketInterceptor());
}
@Bean
public WebSocketHandler WebSocketHandler() {
return WebSocketHandler();
}
@Bean
public WebScoketInterceptor WebScoketInterceptor() {
return new WebScoketInterceptor();
}
}
也可用spring的配置文件:
文件头部添加websocket的xsd文件:
xmlns:websocket="http://www.springframework.org/schema/websocket"
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd
<!-- websocket处理器 -->
<bean id="websocket" class="com.websocket.WebSocketHandler"></bean>
<websocket:handlers>
<websocket:mapping path="/websocket" handler="websocket"></websocket:mapping>
<!-- websocket拦截器 -->
<websocket:handshake-interceptors>
<bean class="com.websocket.WebScoketInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
3、编写WebScoketInterceptor,拦截器的作用是将此连接与用户对应
package com.websocket;
import java.util.Map;
import javax.servlet.http.HttpSession;
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.HandshakeInterceptor;
public class WebScoketInterceptor implements HandshakeInterceptor{
@Override
public void afterHandshake(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse, WebSocketHandler handler, Exception e) {
}
@Override
public boolean beforeHandshake(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse, WebSocketHandler handler,
Map<String, Object> map) throws Exception {
ServletServerHttpRequest request = (ServletServerHttpRequest) httpRequest;
//获取httpSession拿到此链接对应的用户,websocket中可以拿到http协议对应的httpSession
HttpSession session = request.getServletRequest().getSession();
if (session != null) {
map.put("userId", session.getAttribute("userId"));
}
return true;
}
}
4、编写WebSocketHandler,继承自AbstractWebSocketHandler,提供了建立连接,关闭连接,连接发生错误等回调方法,用于实现自己的业务逻辑
package com.websocket;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
/**
* websocket处理器
* @author Administrator
*
*/
public class WebSocketHandler extends AbstractWebSocketHandler {
private static final Map<Integer, WebSocketSession> wsUserMap = new HashMap<Integer, WebSocketSession>();
/**
* 处理前端发送的文本信息
* @throws IOException
*/
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
Integer userId = getUserIdBySession(session);
System.out.println("收到userId为:" + userId + "的用户发的消息" + message.toString());
//给用户回复一条消息
// session.sendMessage(new TextMessage("reply msg:" + message.getPayload()));
}
/**
* 成功建立连接
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Integer userId = getUserIdBySession(session);
wsUserMap.put(userId, session);
super.afterConnectionEstablished(session);
System.out.println("用户id为" + userId + "的用户建立连接");
}
/**
* 关闭连接
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
Integer userId = getUserIdBySession(session);
wsUserMap.remove(userId);
super.afterConnectionClosed(session, status);
System.out.println("用户id为" + userId + "的用户关闭了连接");
}
/**
* 连接发生错误
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
exception.printStackTrace();
Integer userId = getUserIdBySession(session);
wsUserMap.remove(userId);
super.handleTransportError(session, exception);
}
/**
* 给某个用户发送消息
*/
public static boolean sendMessageToUser(Integer userId,Integer toUserId, TextMessage message) {
WebSocketSession tosession = wsUserMap.get(toUserId);
if (tosession != null && tosession.isOpen()) {
try {
tosession.sendMessage(new TextMessage("{" + userId + ":" + message.getPayload()+ "}"));
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
} else {
return false;
}
}
/**
* 给全部用户发送消息
*/
public static void sendMessageToAllUser(TextMessage message) {
Set<Integer> userSet = wsUserMap.keySet();
for (Integer i : userSet) {
WebSocketSession session = wsUserMap.get(i);
if (session != null && !session.isOpen()) {
try {
session.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Integer getUserIdBySession(WebSocketSession session) {
Integer userId = (Integer) session.getAttributes().get("userId");
return userId;
}
}
5、配置SpringWebSocketConfig了配置类随spring容器启动,此步骤为使用WebSocketConfig类做配置是使用,用spring配置文件做websocket的配置时可省略。
<!-- websocket配置扫描 -->
<context:component-scan base-package="com.websocket"/>
6、创建controller,仅简单测试。
package com.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.socket.TextMessage;
import com.websocket.WebSocketHandler;
@Controller
public class WebSocketController {
//模拟登录
@RequestMapping("login")
public void login(HttpServletRequest request, HttpServletResponse response) {
int userId = Integer.parseInt(request.getParameter("userId"));
HttpSession session = request.getSession();
session.setAttribute("userId", userId);
}
//用户给另一用户发送消息
@RequestMapping("sendMessageToUser")
public void sendMessageToUser(HttpServletRequest request, HttpServletResponse response) {
int toUserId = Integer.parseInt(request.getParameter("toUserId"));
int userId = Integer.parseInt(request.getParameter("userId"));
CharSequence message = request.getParameter("message");
TextMessage mess = new TextMessage(message);
WebSocketHandler.sendMessageToUser(userId, toUserId, mess);
}
//给当前所有在线用户发送消息
}
7、客户端代码(创建连接部分)
var ws;
function websocketTest() {
ws = new WebSocket("ws://localhost:8080/websocketTest/websocket");
ws.open = function() {
console.log("open");
}
ws.onclose = function() {
console.log("onclose");
}
ws.onmessage = function(evt) {
console.log(evt);
alert(evt.data);
};
}