初始化数据
在servlet构造中,我们添加了些模拟数据,在客户端建立连接时(AlarmWebSocket#onOpen(Connection connection)),后台将节点连线和告警信息以JSON格式发送到前台(sendMessage(this, "reload", loadDatas());)
1 public AlarmServlet() {
2 initDatas();
3 4 }
5 6 public
void initDatas() {
7 int i = 0;
8 double cx = 350, cy = 230, a = 250, b = 180;
9 nodes.add(
new Node("center", cx, cy));
10
double angle = 0, perAngle = 2 * Math.PI/10;
11 while(i++ < 10){
12 Node node =
new Node("node_" + i, cx + a * Math.cos(angle), cy + b * Math.sin(angle));
13 elementMap.put(node.name, node);
14 nodes.add(node);
15 angle += perAngle;
16 }
17 i = 0;
18 while(i++ < 10){
19 Link link =
new Link("link_" + i, "center", "node_" + i, 1 + random.nextInt(10));
20 elementMap.put(link.name, link);
21 links.add(link);
22 }
23 }
24 25 private String loadDatas(){
26 StringBuffer result =
new StringBuffer();
27 result.append("{\"nodes\":");
28 listToJSON(nodes, result);
29 result.append(", \"links\":");
30 listToJSON(links, result);
31 result.append(", \"alarms\":");
32 listToJSON(alarms, result);
33 result.append("}");
34 return result.toString();
35 }
36 37 class AlarmWebSocket implements org.eclipse.jetty.websocket.WebSocket.OnTextMessage
38 {
39 40 @Override
41 public
void onOpen(Connection connect) {
42 this.connection = connect;
43 clients.add(
this);
44 sendMessage(
this, "reload", loadDatas());
45 }
46 47 }
初始数据前台展示
初始数据通过后台的sendMessage(...)方法推送到客户端,客户端可以在onmessage回调函数中收到,本例我们使用twaver html5组件来展示这些信息。TWaver组件的使用流程一如既往,先作数据转换,将JSON数据转换成TWaver的网元类型,然后填充到ElementBox数据容器,最后关联上Network拓扑图组件,代码如下:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>TWaver HTML5 Demo - Alarm</title>
5 <script type="text/javascript" src="./twaver.js"></script>
6 <script type="text/javascript">
7 var box, network, nameFinder;
8 function init(){
9 network =
new twaver.network.Network();
10 box = network.getElementBox();
11 nameFinder =
new twaver.QuickFinder(box, "name");
12 13 var networkDom = network.getView();
14 networkDom.style.width = "100%";
15 networkDom.style.height = "100%";
16 document.body.appendChild(networkDom);
17 18 window.WebSocket = window.WebSocket || window.MozWebSocket;
19 if (!window.WebSocket){
20 alert("WebSocket not supported by this browser");
21 return;
22 }
23 var websocket =
new WebSocket("ws://127.0.0.1:8080/alarm/alarmServer");
24 25 websocket.onmessage = onmessage;
26 27 }
28 29 function onmessage(evt){
30 var data = evt.data;
31 if(!data){
32 return;
33 }
34 data = stringToJson(data);
35 if(!data){
36 return;
37 }
38 var action = data.action;
39 if(!action){
40 return;
41 }
42 if(action == "alarm.clear"){
43 box.getAlarmBox().clear();
44 return;
45 }
46 data = data.data;
47 if(!data){
48 return;
49 }
50 if(action == "reload"){
51 reloadDatas(data);
52 return;
53 }
54 if(action == "alarm.add"){
55 newAlarm(data)
56 return;
57 }
58 if(action == "node.move"){
59 modeMove(data);
60 return;
61 }
62 }
63 64 function reloadDatas(datas){
65 box.clear();
66 var nodes = datas.nodes;
67 var links = datas.links;
68 var alarms = datas.alarms;
69 70 for(
var i=0,l=nodes.length; i < l; i++){
71 var data = nodes[i];
72 var node =
new twaver.Node();
73 node.setName(data.name);
74 node.setCenterLocation(parseFloat(data.x), parseFloat(data.y));
75 box.add(node);
76 }
77 78 for(
var i=0,l=links.length; i < l; i++){
79 var data = links[i];
80 var from = findFirst(data.from);
81 var to = findFirst(data.to);
82 var link =
new twaver.Link(from, to);
83 link.setName(data.name);
84 link.setStyle("link.width", parseInt(data.width));
85 box.add(link);
86 }
87 88 var alarmBox = box.getAlarmBox();
89 for(
var i=0,l=alarms.length; i < l; i++){
90 newAlarm(alarms[i]);
91 }
92 }
93 function findFirst(name){
94 return nameFinder.findFirst(name);
95 }
96 function newAlarm(data){
97 var element = findFirst(data.elementName);
98 var alarmSeverity = twaver.AlarmSeverity.getByName(data.alarmSeverity);
99 if(!element || !alarmSeverity){
100 return;
101 }
102 addAlarm(element.getId(), alarmSeverity, box.getAlarmBox());
103 }
104 function addAlarm(elementID,alarmSeverity,alarmBox){
105 var alarm =
new twaver.Alarm(
null, elementID,alarmSeverity);
106 alarmBox.add(alarm);
107 }
108 function modeMove(datas){
109 for(
var i=0,l=datas.length; i<l; i++){
110 var data = datas[i];
111 var node = findFirst(data.name);
112 if(node){
113 var x = parseFloat(data.x);
114 var y = parseFloat(data.y);
115 node.setCenterLocation(x, y);
116 }
117 }
118 }
119 120 </script>
121 </head>
122 <body onload="init()" style="margin:0;"></body>
123 </html>
界面效果

后台推送告警,前台实时更新
增加后台推送告警的代码,这里我们在后台起了一个定时器,每隔两秒产生一条随机告警,或者清除所有告警,并将信息推送给所有的客户端
后台代码如下:
1 public AlarmServlet() {
2 3 Timer timer =
new Timer();
4 timer.schedule(
new TimerTask() {
5 @Override
6 public
void run() {
7 if(random.nextInt(10) == 9){
8 alarms.clear();
9 sendMessage ("alarm.clear", "");
10 return;
11 }
12 sendMessage("alarm.add", randomAlarm());
13 }
14 }, 0, 2000);
15 }
16 public
void sendMessage(String action, String message) {
17 for(AlarmWebSocket client : clients){
18 sendMessage(client, action, message);
19 }
20 }
21 private Random random =
new Random();
22 private Data getRandomElement(){
23 if(random.nextBoolean()){
24 return nodes.get(random.nextInt(nodes.size()));
25 }
26 return links.get(random.nextInt(links.size()));
27 }
28 String[] alarmSeverities =
new String[]{"Critical", "Major", "Minor", "Warning", "Indeterminate"};
29 private String randomAlarm(){
30 Alarm alarm =
new Alarm(getRandomElement().name, alarmSeverities[random.nextInt(alarmSeverities.length)]);
31 alarms.add(alarm);
32 return alarm.toJSON();
33 }
34
前台代码:
客户端接收到消息后,需要对应的处理,增加对"alarm.clear"和"alarm.add"的处理,这样告警就能实时更新了
1 function onmessage(evt){
2 3 if(action == "alarm.clear"){
4 box.getAlarmBox().clear();
5 return;
6 }
7 data = data.data;
8 if(!data){
9 return;
10 }
11 12 if(action == "alarm.add"){
13 newAlarm(data)
14 return;
15 }
16 17 }
客户端拖拽节点,同步到其他客户端
最后增加拖拽同步,监听network网元拖拽监听,在网元拖拽放手后,将节点位置信息发送给后台
前台代码:
1 network.addInteractionListener(function(evt){
2 var moveEnd = "MoveEnd";
3 if(evt.kind.substr(-moveEnd.length) == moveEnd){
4 var nodes = [];
5 var selection = box.getSelectionModel().getSelection();
6 selection.forEach(function(element){
7 if(element instanceof twaver.Node){
8 var xy = element.getCenterLocation();
9 nodes.push({name: element.getName(), x: xy.x, y: xy.y});
10 }
11 });
12 websocket.send(jsonToString({action: "node.move", data: nodes}));
13 }
14 });
后台接收到节点位置信息后,首先更新后台数据(节点位置),然后将消息转发给其他客户端,这样各个客户端就实现了同步操作
后台代码
1 class AlarmWebSocket implements org.eclipse.jetty.websocket.WebSocket.OnTextMessage
2 {
3 4 @Override
5 public
void onMessage(String message) {
6 Object json = JSON.parse(message);
7 if(!(json
instanceof Map)){
8 return;
9 }
10 Map map = (Map)json;
11 Object action = map.get("action");
12 Object data = map.get("data");
13 if("node.move".equals(action)){
14 if(!(data
instanceof Object[])){
15 return;
16 }
17 Object[] nodes = (Object[])data;
18 for(Object nodeData : nodes){
19 if(!(nodeData
instanceof Map) || !((Map)nodeData).containsKey("name") || !((Map)nodeData).containsKey("x") || !((Map)nodeData).containsKey("y")){
20 continue;
21 }
22 String name = ((Map)nodeData).get("name").toString();
23 Data element = elementMap.get(name);
24 if(!(element
instanceof Node)){
25 continue;
26 }
27 double x = Double.parseDouble(((Map)nodeData).get("x").toString());
28 double y = Double.parseDouble(((Map)nodeData).get("y").toString());
29 ((Node)element).x = x;
30 ((Node)element).y = y;
31 }
32 33 }
else{
34 return;
35 }
36 for(AlarmWebSocket client : clients){
37 if(
this.equals(client)){
38 continue;
39 }
40 sendMessage(client,
null, message);
41 }
42 }
43 }
完整代码
代码:webSocketDemo
结构: