基于spring實現(xiàn)websocket實時推送實例
基于spring框架來寫的,websocket實時推送例子,具體內(nèi)容如下
第一步:自己搭建一個springmvc項目,很簡單,網(wǎng)上百度都有;pom文件添加以下:
<!-- WebSocket --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>4.2.4.RELEASE</version> </dependency>
我的spring版本是4.2.4的,所以websocket也是4.2.4的;websocket最好和spring版本保持一致
第二步:編寫消息處理器
/**
* Project Name:springRabbitMQ
* File Name:MyMessageHandler.java
* Package Name:com.zsy.websocket
* Date:2018年1月31日上午11:10:03
* Copyright (c) 2018, zhaoshouyun All Rights Reserved.
*
*/
package com.zsy.websocket;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.StringUtils;
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;
/**
* ClassName: MyMessageHandler
* Function: 實現(xiàn)webscoket接口
* date: 2018年1月31日 上午11:10:03
* @author zhaoshouyun
* @version
* @since JDK 1.7
*/
public class MyMessageHandler implements WebSocketHandler {
//用戶key
public static final String USER_KEY = "current_user";
/**
* userMap:存儲用戶連接webscoket信息
* @since JDK 1.7
*/
private final static Map<String, WebSocketSession> userMap;
static {
userMap = new ConcurrentHashMap<String,WebSocketSession>(30);
}
/**
* 關(guān)閉websocket時調(diào)用該方法
* @see org.springframework.web.socket.WebSocketHandler#afterConnectionClosed(org.springframework.web.socket.WebSocketSession, org.springframework.web.socket.CloseStatus)
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
String userId = this.getUserId(session);
if(StringUtils.isNoneBlank(userId)){
userMap.remove(userId);
System.err.println("該" + userId +"用戶已成功關(guān)閉");
}else{
System.err.println("關(guān)閉時,獲取用戶id為空");
}
}
/**
* 建立websocket連接時調(diào)用該方法
* @see org.springframework.web.socket.WebSocketHandler#afterConnectionEstablished(org.springframework.web.socket.WebSocketSession)
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String userId = this.getUserId(session);
if(StringUtils.isNoneBlank(userId)){
userMap.put(userId, session);
session.sendMessage(new TextMessage("建立WebSocket連接成功!"));
}
}
/**
* 客戶端調(diào)用websocket.send時候,會調(diào)用該方法,進(jìn)行數(shù)據(jù)通信
* @see org.springframework.web.socket.WebSocketHandler#handleMessage(org.springframework.web.socket.WebSocketSession, org.springframework.web.socket.WebSocketMessage)
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
String msg = message.toString();
String userId = this.getUserId(session);
System.err.println("該"+userId+"用戶發(fā)送的消息是:"+msg);
message = new TextMessage("服務(wù)端已經(jīng)接收到消息,msg="+msg);
session.sendMessage(message);
}
/**
* 傳輸過程出現(xiàn)異常時,調(diào)用該方法
* @see org.springframework.web.socket.WebSocketHandler#handleTransportError(org.springframework.web.socket.WebSocketSession, java.lang.Throwable)
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable e) throws Exception {
WebSocketMessage<String> message = new TextMessage("異常信息:"+e.getMessage());
session.sendMessage(message);
}
/**
*
* @see org.springframework.web.socket.WebSocketHandler#supportsPartialMessages()
*/
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* sendMessageToUser:發(fā)給指定用戶
* @author zhaoshouyun
* @param userId
* @param contents
* @since JDK 1.7
*/
public void sendMessageToUser(String userId,String contents) {
WebSocketSession session = userMap.get(userId);
if(session !=null && session.isOpen()) {
try {
TextMessage message = new TextMessage(contents);
session.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* sendMessageToAllUsers:發(fā)給所有的用戶
* @author zhaoshouyun
* @param contents
* @since JDK 1.7
*/
public void sendMessageToAllUsers(String contents) {
Set<String> userIds = userMap.keySet();
for(String userId: userIds) {
this.sendMessageToUser(userId, contents);
}
}
/**
* getUserId:獲取用戶id
* @author zhaoshouyun
* @param session
* @return
* @since JDK 1.7
*/
private String getUserId(WebSocketSession session){
try {
String userId = (String)session.getAttributes().get(USER_KEY);
return userId;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
第三步:編寫websocket相關(guān)配置,當(dāng)然可以在xml配置;我現(xiàn)在沒有使用xml配置,使用代碼配置,需要在xml里添加掃描包<context:component-scan base-package="com.zsy.websocket" />
/**
* Project Name:springRabbitMQ
* File Name:WebSocketConfig.java
* Package Name:com.zsy.websocket
* Date:2018年1月31日下午1:10:33
* Copyright (c) 2018, zhaoshouyun All Rights Reserved.
*
*/
/**
* Project Name:springRabbitMQ
* File Name:WebSocketConfig.java
* Package Name:com.zsy.websocket
* Date:2018年1月31日下午1:10:33
* Copyright (c) 2018, zhaoshouyun All Rights Reserved.
*
*/
package com.zsy.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
/**
* ClassName: WebSocketConfig
* Function: TODO ADD FUNCTION.
* date: 2018年1月31日 下午1:10:33
* @author zhaoshouyun
* @version
* @since JDK 1.7
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
/**
* 注冊handle
* @see org.springframework.web.socket.config.annotation.WebSocketConfigurer#registerWebSocketHandlers(org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry)
*/
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/testHandler").addInterceptors(new WebSocketInterceptor());
registry.addHandler(myHandler(), "/socketJs/testHandler").addInterceptors(new WebSocketInterceptor()).withSockJS();
}
@Bean
public WebSocketHandler myHandler(){
return new MyMessageHandler();
}
}
第四步:編寫websocket適配器
package com.zsy.websocket;
import java.util.Map;
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;
/**
* ClassName: WebSocketInterceptor
* Function: TODO ADD FUNCTION.
* date: 2018年1月31日 上午11:42:34
* @author zhaoshouyun
* @version
* @since JDK 1.7
*/
public class WebSocketInterceptor extends HttpSessionHandshakeInterceptor {
/**
* TODO 簡單描述該方法的實現(xiàn)功能(可選).
* @see org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor#beforeHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.util.Map)
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
if(request instanceof ServletServerHttpRequest){
ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest)request;
//獲取參數(shù)
String userId = serverHttpRequest .getServletRequest().getParameter("userId");
attributes.put(MyMessageHandler.USER_KEY, userId);
}
return true;
}
}
第五步對應(yīng)的js:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript">
var websocket;
// 首先判斷是否 支持 WebSocket
if('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8085/springTest/testHandler?userId=zhaoshouyun");
} else if('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8085/springTest/testHandler?userId=zhaoshouyun");
} else {
websocket = new SockJS("http://localhost:8085/springTest/socketJs/testHandler?userId=zhaoshouyun");
}
// 打開連接時
websocket.onopen = function(evnt) {
console.log(" websocket.onopen ");
};
// 收到消息時
websocket.onmessage = function(evnt) {
alert(evnt.data);
};
websocket.onerror = function(evnt) {
console.log(" websocket.onerror ");
};
websocket.onclose = function(evnt) {
console.log(" websocket.onclose ");
};
function say(){
//客戶端主動發(fā)消息
websocket.send(document.getElementById('msg').value);
}
</script>
</head>
<body>
<input type="text" value="" id="msg"><button onclick="say()"></button>
</body>
</html>
第六步測試:
package com.zsy.test.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.zsy.websocket.MyMessageHandler;
/**
* ClassName: TestController
* Function: TODO ADD FUNCTION.
* date: 2017年12月14日 上午11:11:23
* @author zhaoshouyun
* @version
* @since JDK 1.7
*/
@Controller
public class TestController {
@Autowired
MyMessageHandler handler;
@RequestMapping("/get")
public String get(){
return "index";
}
@ResponseBody
@RequestMapping("/get1")
public String send(String name){
handler.sendMessageToUser("zhaoshouyun", "服務(wù)端發(fā)送的內(nèi)容:"+name);
return "success";
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java對象序列化與反序列化的默認(rèn)格式和json格式使用示例
這篇文章主要介紹了java對象序列化與反序列化的默認(rèn)格式和json格式使用示例,需要的朋友可以參考下2014-02-02
Spring配置文件解析之BeanDefinitionReader詳解
這篇文章主要介紹了Spring配置文件解析之BeanDefinitionReader詳解,ApplicationContext.xml配置文件解析成Document對象,真正對xml中元素解析的類是在BeanDefinitionDocumentReader的實現(xiàn)類中來完成的,需要的朋友可以參考下2024-02-02
Java中BeanUtils.copyProperties基本用法與小坑
本文主要介紹了Java中BeanUtils.copyProperties基本用法與小坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04

