开发ws链接

This commit is contained in:
huangdeliang 2021-06-02 14:06:21 +08:00
parent d7368a2e0e
commit cfe970bd45
8 changed files with 286 additions and 6 deletions

View File

@ -0,0 +1,54 @@
package com.stdiet.web.controller.custom;
import com.alibaba.fastjson.JSONObject;
import com.stdiet.common.core.controller.BaseController;
import com.stdiet.custom.utils.WsUtils;
import com.stdiet.web.server.WebSocketServer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Controller
@EnableScheduling
@RequestMapping("/ws/api")
public class WebSocketController extends BaseController {
@ResponseBody
@RequestMapping("/push/{cid}")
public Map pushToWeb(@PathVariable String cid, String message) {
if (message == null) {
message = "我是消息44";
}
Map result = new HashMap();
try {
WebSocketServer.sendInfo(message, cid);
result.put("code", 200);
result.put("msg", "success");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Scheduled(fixedRate = 30000)
public void boardCast() {
try {
JSONObject heartBeat = new JSONObject();
heartBeat.put("type", WsUtils.WS_TYPE_HEART_BEAT);
heartBeat.put("msg", "ping");
WebSocketServer.sendInfo(heartBeat.toJSONString(), null);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,122 @@
package com.stdiet.web.server;
import com.alibaba.fastjson.JSONObject;
import com.stdiet.common.core.domain.model.LoginUser;
import com.stdiet.custom.utils.WsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint(value = "/ws")
@Component
@Slf4j
public class WebSocketServer {
// concurrent包的线程安全Set用来存放每个客户端对应的MyWebSocket对象
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//private static ConcurrentHashMap<String,WebSocketServer> websocketList = new ConcurrentHashMap<>();
// 与某个客户端的连接会话需要通过它来给客户端发送数据
private Session session;
// 接收sid
private String sid = "";
public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
return webSocketSet;
}
/**
* 群发自定义消息
*/
public static void sendInfo(String message, String sid) throws IOException {
log.info("推送消息到窗口" + sid + ",推送内容:" + message + "目标:" + webSocketSet.size());
for (WebSocketServer item : webSocketSet) {
try {
// 这里可以设定只推送给这个sid的为null则全部推送
if (sid == null) {
item.sendMessage(message);
} else if (item.sid.equals(sid)) {
item.sendMessage(message);
}
} catch (IOException e) {
// 清理断开的连接
webSocketSet.remove(item);
continue;
}
}
}
// * 连接建立成功调用的方法*
@OnOpen
public void onOpen(Session session) {
this.session = session;
this.sid = String.valueOf(getUserId(session));
webSocketSet.add(this); // 加入set中
try {
JSONObject object = new JSONObject();
object.put("type", WsUtils.WS_TYPE_SYSTEM_MESSAGE);
object.put("msg", "连接成功");
sendMessage(object.toJSONString());
} catch (IOException e) {
log.error("websocket IO异常");
}
}
@OnClose
public void onClose() {
webSocketSet.remove(this); // 从set中删除
log.info("有一连接关闭!");
}
// */
/// **
// * 收到客户端消息后调用的方法
// *
// * @param message 客户端发送过来的消息*//*
@OnMessage
public void onMessage(String message, Session session) {
log.info("收到来自窗口" + sid + "的信息:" + message);
// // 群发消息
// for (WebSocketServer item : webSocketSet) {
// try {
// item.sendMessage(message);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
}
/**
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
log.info("服务器消息推送:" + message);
this.session.getBasicRemote().sendText(message);
}
public Long getUserId(Session session) {
try {
return ((LoginUser) ((UsernamePasswordAuthenticationToken) session.getUserPrincipal()).getPrincipal()).getUser().getUserId();
} catch (Exception e) {
return 0L;
}
}
}

View File

@ -0,0 +1,8 @@
package com.stdiet.custom.utils;
public class WsUtils {
public static final String WS_TYPE_HEART_BEAT = "WS_TYPE_HEART_BEAT";
public static final String WS_TYPE_SYSTEM_MESSAGE = "WS_TYPE_SYSTEM_MESSAGE";
}

View File

@ -59,6 +59,23 @@
<artifactId>stdiet-system</artifactId>
</dependency>
<!-- websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -102,6 +102,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
"/custom/wxUserInfo/wx/**",
"/custom/wxUserLog/wx/**",
"/wx/**",
// "/ws/**",
"/wap/**",
"/investigate/**",
"/common/customerUploadFile",

View File

@ -0,0 +1,18 @@
package com.stdiet.framework.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
@ConditionalOnWebApplication
public class WebsocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

View File

@ -18,12 +18,15 @@ import "./permission"; // permission control
import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config";
import VueScrollTo from "vue-scrollto";
import VueResource from "vue-resource"
import HighchartsVue from 'highcharts-vue'
import Highcharts from 'highcharts'
import VueResource from "vue-resource";
import HighchartsVue from "highcharts-vue";
import Highcharts from "highcharts";
import { init } from "@/utils/websocket";
//图片导出模块
import exportingInit from 'highcharts/modules/exporting'
exportingInit(Highcharts)
import exportingInit from "highcharts/modules/exporting";
exportingInit(Highcharts);
init();
import {
addDateRange,
@ -111,7 +114,7 @@ Vue.use(VueScrollTo, {
y: true
});
Vue.use(VueResource)
Vue.use(VueResource);
new Vue({
el: "#app",

View File

@ -0,0 +1,57 @@
import { getToken } from "./auth";
const { protocol, hostname, origin, port } = window.location;
const wsProtocol = protocol.startsWith("https") ? "wss" : "ws";
const url = `${wsProtocol}://${hostname}${
port === "80" || port === "443" ? "" : `:${8091}`
}/ws`;
let ws = undefined;
let intervalRef = undefined;
function handleOnMessageReceive(event) {
console.log({ event });
}
function connect() {
try {
ws = new WebSocket(url);
ws.onopen = event => {
console.log("ws连接成功");
intervalRef && clearInterval(intervalRef);
document.addEventListener("message", handleOnMessageReceive);
};
ws.onmessage = event => {
console.log({ event });
const dataObj = JSON.parse(event.data || "{}");
if (dataObj.type && dataObj.type !== "WS_TYPE_HEART_BEAT") {
window.postMessage(dataObj, origin);
}
};
ws.onerror = event => {
console.log({ event });
ws = undefined;
document.removeEventListener("message", handleOnMessageReceive);
};
ws.onclose = event => {
ws = undefined;
document.removeEventListener("message", handleOnMessageReceive);
};
} catch (error) {
console.log(error);
console.log("浏览器不支持websocket");
}
}
export function init() {
intervalRef = setInterval(() => {
console.log("尝试连接websocket");
!ws && connect();
}, 10000);
}