项目git地址:https://github.com/Ray8080/RealData.git
一.maven依赖(boot版本2.0.4)
<dependencies>
<!-- springboot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
二.websocket配置bean
package com.zhourui.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
三.抽象session管理类
package com.zhourui.business.websocket.holder;
import com.alibaba.fastjson.JSON;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public abstract class SocketSessionManager {
private ConcurrentHashMap<String, Session> sessions;
public SocketSessionManager(){
this.sessions = new ConcurrentHashMap<>();
}
public Set<String> getUserKeys(){
return this.sessions.keySet();
}
/**
* 用户上线
* @param session
*/
public void online(Session session){
this.sessions.put(session.getId(),session);
}
/**
* 用户下线
* @param sessionId
*/
public void offline(String sessionId){
this.sessions.remove(sessionId);
}
/**
* 获取session数
*/
public int getSessionNum(){
return this.sessions.size();
}
/**
* 发送数据
* @param sessionId
* @param msg
*/
public void sendData(String sessionId,Object msg){
try {
this.sessions.get(sessionId).getBasicRemote().sendText(JSON.toJSONString(msg));
} catch (IOException e) {
e.printStackTrace();
}
}
}
四.真正的session管理类
package com.zhourui.business.websocket.holder;
import org.apache.log4j.Logger;
public class RealDataSocketSessionManager extends SocketSessionManager {
private static Logger log = Logger.getLogger(RealDataSocketSessionManager.class);
private static RealDataSocketSessionManager manager = new RealDataSocketSessionManager();
private RealDataSocketSessionManager(){
super();
}
//单例模式,全局只产生一个 RealDataSocketSessionManager 实例
public static RealDataSocketSessionManager getAlarmSocketSessionManager(){
return manager;
}
}
五.连接建立
package com.zhourui.business.websocket;
import com.zhourui.business.websocket.holder.RealDataSocketSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
@ServerEndpoint("/real")
@Component
public class RealDataSocket {
private static Logger log = LoggerFactory.getLogger(RealDataSocket.class);
@OnOpen
public void onOpen(Session session){
RealDataSocketSessionManager.getAlarmSocketSessionManager().online(session);
log.info("1个用户上线,一共"+(RealDataSocketSessionManager.getAlarmSocketSessionManager().getSessionNum())+"个用户在线");
try {
session.getBasicRemote().sendText("connect success..");
//推送第一屏数据
//session.getBasicRemote().sendText(JSON.toJSONString(RealTimeWarnProcesser.FIRST_BEAN));
} catch (IOException e) {
e.printStackTrace();
}
}
@OnClose
public void onClose(Session session){
RealDataSocketSessionManager.getAlarmSocketSessionManager().offline(session.getId());
log.info("1个用户下线,一共"+(RealDataSocketSessionManager.getAlarmSocketSessionManager().getSessionNum())+"个用户在线");
}
@OnMessage
public void onMessage(String msg, Session session) {
log.info("接收到的消息: msg={} ",msg);
//msg应包含配置信息,模板ID或者配置的内容,然后根据session去更新模板,协议自定义
if(msg != null) {
try {
}catch (Exception e){
e.printStackTrace();
}
}
}
@OnError
public void onError(Session session, Throwable error){
log.error(session.getId()+" error: "+error.getMessage());
}
}
六.对建立连接的客户端实时推送数据
package com.zhourui.business.websocket.process;
import com.zhourui.business.websocket.holder.RealDataSocketSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
public class RealTimeData {
private static final Logger logger = LoggerFactory.getLogger(RealTimeData.class);
private Thread daemon;
private long index;
//public static RealTimeWarnInfoBean FIRST_BEAN = new RealTimeWarnInfoBean();
public void start() {
daemon = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
//这里可以自己去实现数据获取,封装,然后分发出去
Set<String> keys = RealDataSocketSessionManager.getAlarmSocketSessionManager().getUserKeys();
keys.stream().forEach(e -> RealDataSocketSessionManager.getAlarmSocketSessionManager()
.sendData(e, "实时数据"));
logger.info("发送成功msg==={}",keys);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (Exception e) {
logger.error("实时数据返回参数出错========={}" ,e);
e.printStackTrace();
}
try {
Thread.sleep(200);
logger.info("WebSocket线程存活.........");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "RealTimeDataProcesser");
daemon.setDaemon(true);
daemon.start();
}
}
七.启动类开启数据分发线程
package com.zhourui;
import com.zhourui.business.websocket.process.RealTimeData;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"com.zhourui"})
public class StarterServer {
public static void main(String[] args) {
SpringApplication.run(StarterServer.class,args);
try {
Thread.sleep(1000);
new RealTimeData().start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
八.前端页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>websocket</title>
</head>
<body>
<p>websocket.....</p>
<input id="text" type="text"/><br/>
<button onclick="send()">send</button><br/>
<button onclick="close()">close socket</button><br/>
<p id="msg"></p>
<div id="rsvMsg" >收到的信息:</div>
</body>
<script type="text/javascript">
var websocket = null;
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:8888/real");
}else{
alert("浏览器不支持ws");
}
function setMessage2Html(message){
document.getElementById('msg').innerHTML = message;
}
function setRcvMessage2Html(message){
document.getElementById('rsvMsg').innerHTML += message+'<br/>';
}
websocket.onerror = function () {
setMessage2Html("socket error");
};
websocket.onclose = function () {
setMessage2Html("socket close");
};
websocket.onopen = function () {
setMessage2Html("socket open");
};
websocket.onmessage = function (event) {
setRcvMessage2Html(event.data);
};
window.onbeforeunload = function () {
websocket.close();
};
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
function close() {
websocket.close();
}
</script>
</html>
九.启动服务,打开页面测试