在springBoot框架下利用websocket实现消息推送(
2018-09-20 本文已影响262人
郭小颖在2018
websocket实现消息推送
1、添加Spring WebSocket的依赖jar包
<!-- https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket -->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-messaging -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
2、建立一个类实现websocketconfigurer接口
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
WebSocketUtil webSocketUtil;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketUtil,"/webSocket").addInterceptors(new SpringWebSocketHandlerInterceptor());
registry.addHandler(webSocketUtil,"/sockJs").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
}
}
3、继承WebSocketHandler对象
- 该对象提供了客户端连接,关闭,错误,发送等方法,重写这几个方法即可实现自定义业务逻辑
@Component
public class WebSocketUtil extends TextWebSocketHandler {
private Map<String, WebSocketSession> socketCache = new ConcurrentHashMap<>();
//private static final ArrayList<WebSocketSession> users;//这个会出现性能问题,最好用Map来存储,key用userid
private static Logger logger = LoggerFactory.getLogger(WebSocketUtil.class);
/*static {
users = new ArrayList<WebSocketSession>();
}*/
public WebSocketUtil() {
// TODO Auto-generated constructor stub
}
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// TODO Auto-generated method stub
System.out.println("connect to the websocket success......当前数量:" + socketCache.size());
String token = (String) session.getAttributes().get("token");
System.out.println(token);
socketCache.put(token, session);
System.out.println("连接后的数量为:" + socketCache.size());
}
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("websocket connection closed......");
String token = (String) session.getAttributes().get("token");
System.out.println("用户" + token + "已退出!");
socketCache.remove(token);
System.out.println(socketCache.get(token));
System.out.println("剩余在线用户" + socketCache.size());
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
}
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
logger.debug("websocket connection closed......");
String token = (String) session.getAttributes().get("token");
socketCache.remove(token);
}
public boolean supportsPartialMessages() {
return false;
}
public boolean send(String token, TextMessage message) {
if (socketCache.containsKey(token)) {
return send(socketCache.get(token), message);
}
logger.info("socketCache is not key ");
return false;
}
public void sendAll(TextMessage message) {
if (message == null) return;
for (WebSocketSession webSocketSession : socketCache.values()) {
send(webSocketSession, message);
}
}
public boolean send(WebSocketSession webSocketSession, TextMessage message) {
String token = (String) webSocketSession.getAttributes().get("token");
if (token==null){
return false;
}
try {
webSocketSession.sendMessage(message);
return true;
} catch (IOException e) {
e.printStackTrace();
logger.info("websocket 数据发送异常 !");
return false;
}
}
}
4、继承HttpSessionHandshakeInterceptor对象
- 该对象作为页面连接websocket服务的拦截器,代码如下
/**
* websocket拦截器
*/
public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
@Autowired
UserService userService;
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
// TODO Auto-generated method stub
System.out.println("Before Handshake");
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
//1.拿去前段请求中携带的token
String token = servletRequest.getServletRequest().getParameter("token");
//2.对token进行判断,如果token不存在,则进行拦截
if (token==null){
return false;
}
UserInfo userInfo = userService.getloginuserinfo(token);
if (userInfo==null){
return false;
}
attributes.put("token",token);
/* if (token!=null){
UserInfo userInfo = userService.getloginuserinfo(token);
if (userInfo!=null){
attributes.put("token",token);
}
}*/
}
System.out.println("handshake...");
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
// TODO Auto-generated method stub
System.out.println("afterHandshake...");
super.afterHandshake(request, response, wsHandler, ex);
}
}
1.定义一个控制器用来做连接标识和发送消息
@RestController
public class MessagePushController {
@Autowired
private WebSocketUtil webSocketUtil;
/**
* 给某个用户发送消息
*
* @param token
* @param message
* @return
*/
@PostMapping("/push")
public String tokenPush(String token, String message) {
return webSocketUtil.send(token,new TextMessage(message))?"success":"fail";
}
/**
* 广播,给所有在线用户发送广播
*
* @param message
* @return
*/
@PostMapping("/broadcast")
public String Push(String message) {
try {
webSocketUtil.sendAll(new TextMessage(message));
return "success";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}
2、建立发消息页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width" charset="UTF-8"/>
<title>WebSocket 客户端</title>
</head>
<body>
<div>
token:<input type="text" id="token"/>
<input type="button" id="btnConnection" value="连接到服务器"/><br/>
<input type="text" id="inputMsg"/>
<input type="button" id="btnSend" value="客户端发送消息" /><br/>
<input type="button" id="btnClose" value="客户端关闭连接" /><br/>
</div>
<script src="js/jquery-1.8.3.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var websocket = null;
if (typeof(WebSocket) == "undefined") {
alert("您的浏览器不支持WebSocket");
}
//连接到ws服务器
$("#btnConnection").click(function () {
var token=document.getElementById("token").value;
//实现化WebSocket对象,指定要连接的服务器地址与端口
websocket = new WebSocket("ws://localhost:8210/webSocket?token="+token);
//打开事件
websocket.onopen = function () {
alert("Socket 已打开");
websocket.send("这是来自客户端的消息:" + location.href + new Date());
};
//获得消息事件
websocket.onmessage = function (msg) {
alert(msg.data);
};
//关闭事件
websocket.onclose = function () {
alert("Socket已关闭");
};
//发生了错误事件
websocket.onerror = function () {
alert("发生了错误");
}
});
//发送消息
$("#btnSend").click(function () {
var msg = document.getElementById("inputMsg").value;
websocket.send("这是来自客户端的消息:" +msg+new Date());
alert("客户端发送了消息");
});
//关闭
$("#btnClose").click(function () {
websocket.close();
alert("客户端关闭了连接");
});
</script>
</body>
</html>