跳到主要内容

WebSocket接口

WebSocket接口配置说明

选中组件(本文以百分比条形图为例说明),在操作界面右侧,点击图标,并选择WebSocket,如下图

1、配置接口地址

在接口地址一栏填写我们制作的接口地址,并点击刷新应用接口,如下图

接口地址示例:ws://localhost:8080/jeecg-boot/websocket/refreshChart

https使用wss

2、编写WebSocket服务端

示例代码如下:

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

package org.jeecg.modules.jmreport.visual.websocket;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;

/**
* 大屏websocket服务端
* @author zyf
*/
@Component
@Slf4j
@ServerEndpoint("/websocket/refreshChart/{chartId}")
public class BigScreenWebSocket {
/**
* 链接会话
*/
private Session session;
/**
* 图表ID
*/
private String chartId;
/**
* redis队列名称
*/
private static final String REDIS_TOPIC_NAME = "bigScreenSocketHandler";

@Resource
private JeecgRedisClient jeecgRedisClient;

/**
* 缓存 webSocket连接到单机服务class中(整体方案支持集群)
*/
private static CopyOnWriteArraySet<BigScreenWebSocket> webSockets = new CopyOnWriteArraySet<>();
private static Map<String, Session> sessionPool = new HashMap<String, Session>();


@OnOpen
public void onOpen(Session session, @PathParam(value = "chartId") String chartId) {
try {
this.session = session;
this.chartId = chartId;
webSockets.add(this);
sessionPool.put(chartId, session);
log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());
} catch (Exception e) {
}
}

@OnClose
public void onClose() {
try {
webSockets.remove(this);
sessionPool.remove(this.chartId);
log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
} catch (Exception e) {
}
}


/**
* 服务端推送消息
*
* @param chartId
* @param message
*/
public void pushMessage(String chartId, String message) {
Session session = sessionPool.get(chartId);
if (session != null && session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:" + message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 服务器端推送消息
*/
public void pushMessage(String message) {
try {
webSockets.forEach(ws -> ws.session.getAsyncRemote().sendText(message));
} catch (Exception e) {
e.printStackTrace();
}
}


@OnMessage
public void onMessage(String message) {
//todo 现在有个定时任务刷,应该去掉
log.debug("【websocket消息】收到客户端消息:" + message);
JSONObject obj = new JSONObject();
//业务类型
obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK);
//消息内容
obj.put(WebsocketConst.MSG_TXT, "心跳响应");
for (BigScreenWebSocket webSocket : webSockets) {
webSocket.pushMessage(message);
}
}

/**
* 后台发送消息到redis
*
* @param message
*/
public void sendMessage(String message) {
log.info("【websocket消息】广播消息:" + message);
BaseMap baseMap = new BaseMap();
baseMap.put("chartId", "");
baseMap.put("message", message);
jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME, baseMap);
}

/**
* 此为单点消息
*
* @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(REDIS_TOPIC_NAME, baseMap);
}

/**
* 此为单点消息(多组件)
*
* @param chartIds
* @param message
*/
public void sendMessage(String[] chartIds, String message) {
for (String chartId : chartIds) {
sendMessage(chartId, message);
}
}

}

3、编写消息推送测试方法

/**
* 测试大屏websocket接口
*/
@RestController
@Api(tags="大屏WebSocket测试")
@RequestMapping("/bigscreen/websocket")
public class WebSocketController {

@Autowired
private BigScreenWebSocket webSocket;

@PostMapping("/sendData")
@ApiOperation(value="测试大屏组件更新", notes="测试大屏组件更新")
public Result<String> sendData() {
Result<String> result = new Result<String>();
//需要推送数据的组件ID
String chartId="listab18b33f-1b10-45ea-9621-7d32d802f084";
String message = "[{\"country\":\"Asia\",\"year\":\"1750\",\"value\":1502},{\"country\":\"Asia\",\"year\":\"1800\",\"value\":1635},{\"country\":\"Asia\",\"year\":\"1850\",\"value\":1809},{\"country\":\"Asia\",\"year\":\"1900\",\"value\":1947},{\"country\":\"Asia\",\"year\":\"1950\",\"value\":1402},{\"country\":\"Asia\",\"year\":\"1999\",\"value\":3634},{\"country\":\"Asia\",\"year\":\"2050\",\"value\":5268},{\"country\":\"Africa\",\"year\":\"1750\",\"value\":106},{\"country\":\"Africa\",\"year\":\"1800\",\"value\":107},{\"country\":\"Africa\",\"year\":\"1850\",\"value\":111},{\"country\":\"Africa\",\"year\":\"1900\",\"value\":133},{\"country\":\"Africa\",\"year\":\"1950\",\"value\":221},{\"country\":\"Africa\",\"year\":\"1999\",\"value\":767},{\"country\":\"Africa\",\"year\":\"2050\",\"value\":1766},{\"country\":\"Europe\",\"year\":\"1750\",\"value\":163},{\"country\":\"Europe\",\"year\":\"1800\",\"value\":203},{\"country\":\"Europe\",\"year\":\"1850\",\"value\":276},{\"country\":\"Europe\",\"year\":\"1900\",\"value\":408},{\"country\":\"Europe\",\"year\":\"1950\",\"value\":547},{\"country\":\"Europe\",\"year\":\"1999\",\"value\":729},{\"country\":\"Europe\",\"year\":\"2050\",\"value\":628}]";
JSONObject obj = new JSONObject();
obj.put("chartId",chartId);
obj.put("result", message);
webSocket.sendMessage(chartId, obj.toJSONString());
result.setResult("单发");
return result;
}

}

4、返回JSON数据格式

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