跳到主要内容

WEBSOCKET

大屏设计器数据集支持WEBSOCKET数据集,通过WEBSOCKET推送,将数据展示在图表中

  • 点击组件栏右上角的数据集或者“数据”中数据集后的均可打开数据集管理界面

  • 点击“新增”,即可打开数据集新增界面

一、基本信息

  • 数据集名称:自定义即可
  • 分组:直接选择对应分组 分组维护参考
  • 数据集类型:选择“WebSocket”类型

二、接口地址配置

在接口地址一栏填写我们制作的接口地址,接口代码详见第六步 接口地址示例:

ws://localhost:8080/jeecg-boot/websocket/drag

https使用wss

填写完此信息后,即可保存数据集,无需解析

三、获取组件id

选中组件,点击“

① 数据类型:选择动态数据
② 数据集:选择刚刚新建的“websocket”数据集
③ 组件ID:②数据集选择为“websocket”数据集时,自动会出现组件ID,可进行复制
④ 映射关系:“websocket”数据集选择后,映射关系字段暂时不存在,需要访问websocket数据推送接口


四、获取组件映射关系

  • 访问websocket数据推送接口,访问一次后,映射关系即推送至组件中了,如下图

http://localhost:8080/jeecg-boot/drag/websocket/sendData?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzkyMzEzNzUsInVzZXJuYW1lIjoiYWRtaW4ifQ.QceTlZLlivKrQWwlStY6OiREfTqMqAbW7X1wmS-EWZo&chartId=cdbde743-3f3d-4131-a05d-a83077bd9c47
  • websocket数据推送接口上传参数 token:项目的token信息(必传) chartId:第三步获取的组件ID(必传)

注:访问接口时可使用postman,如果是get接口也可以在浏览器中直接访问

  • 此时映射关系即可选择字段了

五、图表展示

当webSocket进行数据推送时,即可展示数据了

六、编写WebSocket服务端

此WebSocket服务端为创建WebSocket数据集时使用的Websocket地址,默认项目中已存在,可直接使用;也可根据自己的需求重新定义其他服务端;如下图:

示例代码如下: 示例中使用了(redis订阅发布)机制解决消息集群问题

package org.jeecg.modules.drag.config.websocket;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
import org.jeecg.common.modules.redis.listener.JeecgRedisListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;

/**
*websocket服务端
*
*/
@Component
@Slf4j
@ServerEndpoint("/websocket/drag/{chartId}")
public class DragWebSocket {
/**线程安全Map*/
private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();

/**
* redis队列名称
*/
public static final String REDIS_TOPIC_NAME = "dragSocketHandler";

@Autowired
private JeecgRedisClient jeecgRedisClient;

@OnOpen
public void onOpen(Session session, @PathParam(value = "chartId") String chartId) {
try {
sessionPool.put(chartId, session);
log.debug("【BI大屏设计器 WebSocket】有新的连接,总数为:" + sessionPool.size());
} catch (Exception e) {
}
}

@OnClose
public void onClose(@PathParam("chartId") String chartId) {
try {
sessionPool.remove(chartId);
log.debug("【BI大屏设计器 WebSocket】连接断开,总数为:" + sessionPool.size());
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 推送消息
*
* @param chartId
* @param message
*/
public void pushMessage(String chartId, String message) {
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
if (item.getKey().contains(chartId)) {
Session session = item.getValue();
try {
synchronized (session){
log.debug("【BI大屏设计器 WebSocket】推送单人消息:" + message);
session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
log.error(e.getMessage(),e);
}
}
}
}

@OnMessage
public void onMessage(String message) {
if(!"ping".equals(message) && !WebsocketConst.CMD_CHECK.equals(message)){
log.debug("【BI大屏设计器 WebSocket】收到客户端消息:" + message);
}else{
log.debug("【BI大屏设计器 WebSocket】收到客户端消息:" + message);
}
}

/**
* 配置错误信息处理
*
* @param session
* @param t
*/
@OnError
public void onError(Session session, Throwable t) {
log.warn("【BI大屏设计器 WebSocket】消息出现错误");
t.printStackTrace();
}

/**
* 此为单点消息
*
* @param chartId
* @param message
*/
public void sendMessage(String chartId, String message) {
BaseMap baseMap = new BaseMap();
baseMap.put("chartId", chartId);
baseMap.put("message", message);
jeecgRedisClient.sendMessage(DragWebSocket.REDIS_TOPIC_NAME, baseMap);
}

@Component(REDIS_TOPIC_NAME)
class RedisSocketHandler implements JeecgRedisListener {

private final DragWebSocket dragWebSocket;

private RedisSocketHandler(DragWebSocket dragWebSocket) {
this.dragWebSocket = dragWebSocket;
}

@Override
public void onMessage(BaseMap map) {
log.debug("【BI大屏设计器 WebSocket】redis {},参数:{}", REDIS_TOPIC_NAME, map.toString());
String chartId = map.get("chartId");
String message = map.get("message");
dragWebSocket.pushMessage(chartId, message);
}
}

}

七、编写消息推送方法

此方法为业务数据推送接口

package org.jeecg.modules.drag.controller;

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.drag.config.websocket.DragWebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* websocket数据接口
*
*/
@RestController
@RequestMapping("/drag/websocket")
public class DragWebSocketController {

@Autowired
private DragWebSocket webSocket;

/**
* 大屏设计器webSocket数据推送接口
* @param chartId
* @return
*/
@GetMapping("/sendData")
public Result<String> sendData(@RequestParam(name = "chartId", required = false)String chartId) {
Result<String> result = new Result<>();
//推送数据,实际使用时改成自己的业务数据
String message = "[{\"value\":1048,\"name\":\"波导\"},{\"value\":735,\"name\":\"oppo\"},{\"value\":580,\"name\":\"华为\"},{\"value\":484,\"name\":\"小米\"},{\"value\":300,\"name\":\"魅族\"}]";
JSONObject obj = new JSONObject();
obj.put("chartId", chartId);
obj.put("result", message);
webSocket.sendMessage(chartId, obj.toJSONString());
result.setResult("单发");
return result;
}

}

业务数据JSON格式:

[
    {
        "value": 1048,
        "name": "波导"
    },
    {
        "value": 735,
        "name": "oppo"
    },
    {
        "value": 580,
        "name": "华为"
    },
    {
        "value": 484,
        "name": "小米"
    },
    {
        "value": 300,
        "name": "魅族"
    }
]