- 浏览: 181519 次
- 性别:
- 来自: 北京
文章分类
最新评论
今天心情不错,公司终于签下了一个综合业务监控系统的大单。到底有多大我也不知道,反正连软件带硬件不算小。按照销售的说法,拿下这个项目一个重要的因素就是要提供一个吸引眼球的demo,而我们做的不错!今天和大家分享一下喜悦和经验!
这个项目是一个省级电信运营商的综合业务监控系统。公司跟了好长时间了。由于是一个综合的业务监控系统,涉及的管理资源非常多,又要提供大屏幕显示,所以对系统的呈现效果要求非常高(“政绩工程”么)。前前后后提了很多“无礼”要求,陆续提过的有3D电子地图、3D机房监控、场景仿真、全动画、Google Earth、全Flash等等....弄的我们晕头转向、焦头烂额。其实很多时候,用户自己也不知道想要什么,反正对厂商的要求就是一个字:“炫”,两个字“好看”,三个字:“一定好好看!”(不对,好像是四个字哦)。
言归正传,项目跟踪过程中,商务始终告诉我们研发一定要做好一件事:如何做好呈现,尤其是综合的业务监控和呈现,这是获得项目的关键,一定要“出彩”。这个“综合呈现”说起来容易,做起来难。作为省级的电信运营商,内部的各种软硬件系统无数,要监控从上到下、从软到硬,真是烦不胜烦:
- 基础设施层:主要是网络上的硬件设备,包括交换机、路由器、防火墙、各种主机设备服务器等等;
- 软件层:这一层主要是主机上面运行的操作系统和各类业务软件系统,例如操作系统(Windows、AIX/HP-UX/LINUX/SOLARIS)、各种中间件(WebLogic、JBoss、IIS、WebSphere等)、数据库(Oracle、Sybase、MySQL)等;
- 应用层:这一层是指运行在软件层内部的一些细粒度资源,包括一些关键的软件进程、数据库表空间、业务连接、消息队列等等。这一层数量繁杂、数量众多。不过这些资源的状态直接会影响其上层支撑的业务。
- 业务层:业务层是最顶层,由以上底层资源所共同支撑起来的面向用户的各种业务。对业务最容易理解的描述就是电信提供给客户的具体“服务”。例如视频业务、短信业务、WAP业务、专网业务等等。这些业务才是用户最终关心的东西,因为这些业务才是客户的核心资产,是拿来卖钱的最终产品。一旦出问题,将直接影响money!
此外,还有一大堆机房环境监控的要求,什么配电柜供电、开关状态、UPS、蓄电池、空调、适度温度漏水效仿通风门禁视频.........一大堆。所以,要对业务进行监控,就必须对业务所支撑的各个底层资源进行监控。另外,还要能够对这些资源的关系进行连接和定义,一旦发生故障和问题,能够从上到下迅速定位故障起源,在最短时间内发现问题、解决问题。如何呈现这些依赖关系,并对故障和告警进行纵向定位,是软件呈现的一个核心问题,也是用户最关心的一个问题。
用户要求我们先制作一个demo程序,看我们将如何呈现“综合监控”的效果。在充分了解了用户需求之后,经过讨论,我们想做一个完全图形化的分层、跨层的综合监控界面。界面要美观,有动画效果,能够清晰的显示资源依赖关系和告警传播定位。
需要监控和管理的资源
接下来要写代码了。肯定先用我熟悉的TWaver试试。研究了一下,TWaver中有一个平行四边形的Group对象,适合做上图中的“层”的概念。先如下封装并设置属性:
- package demo;
- import java.awt.Color;
- import twaver.Group;
- import twaver.TWaverConst;
- public class LayerGroup extends Group {
- public LayerGroup() {
- init();
- }
- public LayerGroup(Object id) {
- super(id);
- init();
- }
- private void init() {
- this.setGroupType(TWaverConst.GROUP_TYPE_PARALLELOGRAM);
- this.putGroupAngle(45);
- this.putGroup3D(true);
- this.putGroupDeep(10);
- this.putGroupOutline(false);
- this.putGroupFillColor(Color.green.darker());
- this.putGroupGradient(true);
- this.putGroupGradientFactory(TWaverConst.GRADIENT_LINE_E);
- this.putGroupHandlerVisible(false);
- this.putGroupDoubleClickEnabled(false);
- this.putBorderColor(Color.white);
- this.putBorderInsets(3);
- this.putBorderAntialias(true);
- this.putBorderStroke(TWaverConst.STROKE_SOLID_4);
- this.putBorderVisible(false);
- this.putLabelHighlightable(false);
- this.setEnableAlarmPropagationFromChildren(false);
- }
- }
package demo; import java.awt.Color; import twaver.Group; import twaver.TWaverConst; public class LayerGroup extends Group { public LayerGroup() { init(); } public LayerGroup(Object id) { super(id); init(); } private void init() { this.setGroupType(TWaverConst.GROUP_TYPE_PARALLELOGRAM); this.putGroupAngle(45); this.putGroup3D(true); this.putGroupDeep(10); this.putGroupOutline(false); this.putGroupFillColor(Color.green.darker()); this.putGroupGradient(true); this.putGroupGradientFactory(TWaverConst.GRADIENT_LINE_E); this.putGroupHandlerVisible(false); this.putGroupDoubleClickEnabled(false); this.putBorderColor(Color.white); this.putBorderInsets(3); this.putBorderAntialias(true); this.putBorderStroke(TWaverConst.STROKE_SOLID_4); this.putBorderVisible(false); this.putLabelHighlightable(false); this.setEnableAlarmPropagationFromChildren(false); } }
通过这个简单的封装,再往Group里头放几个节点和连线,显示效果如下:
用Group制作的“层”效果
怎么样,有点意思吧?开头不错,继续改进!再依次排列4个Group,用不同颜色,试试效果:
- createLayer(Color.orange, 50, 0, 10, "7.png", "<html><center>软件<br>业务层</center></html>");
- createLayer(Color.green.darker(),180, 200, 15, "8.png", "<html><center>技术<br>应用层</center></html>");
- createLayer(Color.magenta.darker(),280, 350, 5, "5.png", "<html><center>技术<br>软件层</center></html>");
- createLayer(Color.cyan.darker(),400, 570, 7, "1.png", "<html><center>基础<br>设施层</center></html>");
createLayer(Color.orange, 50, 0, 10, "7.png", "<html><center>软件<br>业务层</center></html>"); createLayer(Color.green.darker(),180, 200, 15, "8.png", "<html><center>技术<br>应用层</center></html>"); createLayer(Color.magenta.darker(),280, 350, 5, "5.png", "<html><center>技术<br>软件层</center></html>"); createLayer(Color.cyan.darker(),400, 570, 7, "1.png", "<html><center>基础<br>设施层</center></html>");
以上代码封装了创建一个层的函数,给定颜色、坐标位置、内部节点数量、图标、文字等等。上面代码中的HTML风格字符串是为了在TWaver中(好像Swing中也是这样的)显示换行的标签。每一个层作为容器包含了很多不同类型的资源。显示效果如下图:
四层拓扑图显示效果
注意其中的连线有下垂的弯曲效果。这是我以前在做项目封装过的一个TWaver技巧:通过重写twaver的Link的UI类,重新指定path走向实现的。其实也很简单,首先获得link的from点和to点,取值中间点,再把y纵向增加20,把这个点作为quadTo的控制点画曲线即可。对TWaver熟悉的朋友可以看一下这段代码(其实这个效果也是从TWaver Java的demo源代码中学习到的):
- package demo;
- import java.awt.Point;
- import java.awt.geom.GeneralPath;
- import twaver.network.TNetwork;
- import twaver.network.ui.LinkUI;
- public class InnerLinkUI extends LinkUI {
- public InnerLinkUI(TNetwork network, InnerLink link) {
- super(network, link);
- }
- @Override
- public GeneralPath getPath() {
- GeneralPath customPath = new GeneralPath();
- Point p1 = this.getFromPoint();
- Point p2 = this.getToPoint();
- customPath.moveTo(p1.x, p1.y);
- int offset = 20;
- customPath.quadTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2 + offset, p2.x, p2.y);
- return customPath;
- }
- }
package demo; import java.awt.Point; import java.awt.geom.GeneralPath; import twaver.network.TNetwork; import twaver.network.ui.LinkUI; public class InnerLinkUI extends LinkUI { public InnerLinkUI(TNetwork network, InnerLink link) { super(network, link); } @Override public GeneralPath getPath() { GeneralPath customPath = new GeneralPath(); Point p1 = this.getFromPoint(); Point p2 = this.getToPoint(); customPath.moveTo(p1.x, p1.y); int offset = 20; customPath.quadTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2 + offset, p2.x, p2.y); return customPath; } }
用这种link做出的拓扑图比较生动美观。多加几个节点连线就能看出来了:
四层复杂拓扑图显示效果
不过发现平行四边形Group一个问题:当两个Layer叠加后,下面的节点会被完全覆盖,看不见了。用户说:能不能也能看见?(晕,盖住了也要看见。谁让人家是甲方呢?)于是询问TWaver的人,一个哥们说Group有透明属性。于是试了一下,效果不还错:
this.putGroupOpaque(false);
层的透明与覆盖
下一步,关键了:要增加层与层之间资源的“依赖关系”。例如一个Oracle跑在一台主机上,而Oracle中的一个关键表空间需要重点监控,它决定了上层一个视频点播业务是否能够正常。为了体现这个依赖关系,在跨层的节点中间建立link。这个link和层内部link显示上应当有所区别:
- package demo;
- import java.awt.Color;
- import twaver.Link;
- import twaver.Node;
- import twaver.TWaverConst;
- import twaver.base.OrthogonalLinkDirectionType;
- public class LayerLink extends Link {
- public LayerLink(Node from, Node to) {
- super(from, to);
- init();
- }
- public LayerLink(Object id, Node from, Node to) {
- super(id, from, to);
- init();
- }
- private void init() {
- this.putLink3D(true);
- this.putLinkWidth(4);
- this.putLinkOutlineWidth(0);
- this.putLinkColor(Color.lightGray);
- this.putLinkAntialias(false);
- this.setLinkType(TWaverConst.LINK_TYPE_ORTHOGONAL);
- }
- }
package demo; import java.awt.Color; import twaver.Link; import twaver.Node; import twaver.TWaverConst; import twaver.base.OrthogonalLinkDirectionType; public class LayerLink extends Link { public LayerLink(Node from, Node to) { super(from, to); init(); } public LayerLink(Object id, Node from, Node to) { super(id, from, to); init(); } private void init() { this.putLink3D(true); this.putLinkWidth(4); this.putLinkOutlineWidth(0); this.putLinkColor(Color.lightGray); this.putLinkAntialias(false); this.setLinkType(TWaverConst.LINK_TYPE_ORTHOGONAL); } }
显示出来后,效果并不理想,有点乱。主要是没有“跨层”的立体感。
跨层连线效果
图中跨层的link没有呈现出“穿透层”的感觉,多了以后反而破坏了整个拓扑图的立体感和生动感,需要再改进。最好能够显示“穿层而过”的效果。需求变态么?不弄点猛药还想拿单子么,程序员就是要与各种“不可能”说“不”嘛!经过反复研究和实验,终于做出了一个更好的效果,如下图:
连线的跨层穿透效果
注意观察其中穿层效果,不知大家是否喜欢?
连线的透明穿透
怎么做到的呢?其实也简单,一点就破,我就不点破了吧,卖个关子先。大家可以先猜猜看,源代码里头也能看到答案。接下来,可以增加一些跨层连线了!看看下图效果:
跨层连线的综合效果图
效果还不错吧?销售看过后非常满意,连说有新意。不过还有最后一个很头大的问题:需要显示告警及其传播路线,也就是告警发生后,要从底层一直沿着依赖关系传播到上层。于是开始研究TWaver的AlarmPropagator告警传播器。通过研究发现,其实告警传播也不复杂,主要原理是当告警发生后,它会根据AlarmPropagator的“指示”和定义的规则,沿着一个特定的“路径”进行告警传播。被传播过的地方,会显示一个有告警颜色的外框,标志其告警状态。
但是问题是,TWaver的告警传播器是按照“父子关系”进行传播的。也就是默认情况下,告警总是从孩子传给父亲,一直到没有parent为止。按照这个规则,这个demo中一个节点发生告警后,会传播给平行四边形这个层对象,这显然是没有意义的,不符合我的要求。我们需要告警沿着层的“依赖关系”进行跨层传播。于是重写AlarmPropagator!也不难,调试了几个小时,用一个递归法总算搞定了。代码如下:
- package demo;
- import java.util.Collection;
- import java.util.Iterator;
- import twaver.AlarmSeverity;
- import twaver.Element;
- import twaver.Node;
- public class DemoPropagator {
- public void propagate(Element element) {
- AlarmSeverity severity = element.getAlarmState().getHighestNativeAlarmSeverity();
- if (element instanceof Node) {
- Node node = (Node) element;
- Collection links = node.getAllLinks();
- if (links != null && !links.isEmpty()) {
- Iterator it = links.iterator();
- while (it.hasNext()) {
- Object o = it.next();
- if (o instanceof LayerLink) {
- LayerLink link = (LayerLink) o;
- if (link.getAlarmState().isEmpty()) {
- link.getAlarmState().addAcknowledgedAlarm(severity);
- Node anotherNode = link.getFrom();
- if (anotherNode.getAlarmState().isEmpty()) {
- anotherNode.getAlarmState().addAcknowledgedAlarm(severity);
- if (anotherNode != node) {
- propagate(anotherNode);//这里递归!
- }
- }
- }
- }
- }
- }
- }
- }
- }
package demo; import java.util.Collection; import java.util.Iterator; import twaver.AlarmSeverity; import twaver.Element; import twaver.Node; public class DemoPropagator { public void propagate(Element element) { AlarmSeverity severity = element.getAlarmState().getHighestNativeAlarmSeverity(); if (element instanceof Node) { Node node = (Node) element; Collection links = node.getAllLinks(); if (links != null && !links.isEmpty()) { Iterator it = links.iterator(); while (it.hasNext()) { Object o = it.next(); if (o instanceof LayerLink) { LayerLink link = (LayerLink) o; if (link.getAlarmState().isEmpty()) { link.getAlarmState().addAcknowledgedAlarm(severity); Node anotherNode = link.getFrom(); if (anotherNode.getAlarmState().isEmpty()) { anotherNode.getAlarmState().addAcknowledgedAlarm(severity); if (anotherNode != node) { propagate(anotherNode);//这里递归! } } } } } } } } }
这里代码的逻辑主要是判断是不是跨层link,如果是就沿着它进行传播。噢吼!上面代码好像泄露了上面“穿透Layer”的秘密了,呵呵。最后,再来一个“告警模拟器”来模拟随机、随时发生告警,也就是用一个单独的线程在里面sleep然后生成Alarm并发送到拓扑图的节点上。直接上代码:
- package demo;
- import java.util.Iterator;
- import javax.swing.SwingUtilities;
- import twaver.AlarmSeverity;
- import twaver.Element;
- import twaver.TDataBox;
- import twaver.TWaverUtil;
- public class AlarmMocker extends Thread {
- private TDataBox box = null;
- private DemoPropagator propagator = new DemoPropagator();
- public AlarmMocker(TDataBox box) {
- this.box = box;
- }
- @Override
- public void run() {
- while (true) {
- try {
- Thread.sleep(1 * 1000);
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- if (TWaverUtil.getRandomInt(5) == 1) {
- //clear all alarm and propagation.
- Iterator it = box.iterator();
- while (it.hasNext()) {
- Element e = (Element) it.next();
- e.getAlarmState().clear();
- }
- }
- Element element = box.getElementByID("4." + TWaverUtil.getRandomInt(10));
- if (element != null) {
- element.getAlarmState().addNewAlarm(AlarmSeverity.getRandomSeverity());
- propagator.propagate(element);
- }
- }
- });
- }
- }
- }
package demo; import java.util.Iterator; import javax.swing.SwingUtilities; import twaver.AlarmSeverity; import twaver.Element; import twaver.TDataBox; import twaver.TWaverUtil; public class AlarmMocker extends Thread { private TDataBox box = null; private DemoPropagator propagator = new DemoPropagator(); public AlarmMocker(TDataBox box) { this.box = box; } @Override public void run() { while (true) { try { Thread.sleep(1 * 1000); } catch (InterruptedException ex) { ex.printStackTrace(); } SwingUtilities.invokeLater(new Runnable() { public void run() { if (TWaverUtil.getRandomInt(5) == 1) { //clear all alarm and propagation. Iterator it = box.iterator(); while (it.hasNext()) { Element e = (Element) it.next(); e.getAlarmState().clear(); } } Element element = box.getElementByID("4." + TWaverUtil.getRandomInt(10)); if (element != null) { element.getAlarmState().addNewAlarm(AlarmSeverity.getRandomSeverity()); propagator.propagate(element); } } }); } } }
告警模拟器把最底层的里面的节点随机产生告警,再随机的清除,模拟现实网络的监控状态。然后运行demo,观察其告警传播的路线是否符合预期,也就是沿着层进行传播。
注意一个细节:由于上面告警模拟器在一个单独的Thread线程中运行,在产生告警并更改界面时候,需要用SwingUtilities.invokeLater进行代码封装调用,保证它在Swing线程中执行,避免屏幕和界面“花”或不可预知的显示结果。唉,谁让Swing是单线程而且是线程不安全呢?这是个古老话题,就不罗嗦了。
废话不多说,直接上最终效果图:
demo最终效果图
双击层动画旋转并放大
看到告警跨层传播的效果了吗?最后,根据客户的要求,又增加了一些动画效果:双击平行四边形后,平行四边形会动画变成矩形、动画飞到屏幕中间,然后动画放大内部拓扑图,供用户查看细节;再次双击,平行四边形快速旋转缩小并回到原来位置。demo程序交付并演示后,获得客户高度评价。用我们商务人员的话来说就是:“我们的demo最出彩!”作为程序员,自己做的东西能为公司创造价值和利润就是最大的肯定和成就感!
由于demo掺杂了不少公司的代码,我会花一点时间整理一下,弄出一个干净的demo代码贴出来,请感兴趣的朋友留意。我这里也有可以直接运行的jar包,感兴趣的朋友可以留下邮箱。对了,以上信息仅供技术交流之用,请勿用于其它商业用途。
评论
258026921@qq.com
非常感谢
xzy_07@163.com
非常感谢
发表评论
-
人民币转换数字
2012-11-07 15:14 1115该贴原因: ... -
个人收集的java精品网站
2012-05-30 08:19 0java进阶网 http://www.javady.com ... -
JVM(java 虚拟机)内存设置
2011-06-02 16:37 15176JVM(java 虚拟机)内存 ... -
汉字全半角转化程序
2011-02-25 08:52 1473转载一个牛人的。方便以后查看使用: 也许. 这个代码对很多人 ... -
md5JAVA实现
2010-06-07 22:43 1200MD5算法研究 MD5的 ... -
在Java中操作串口实现短信收发2
2010-06-07 22:08 14024.发送数据成功进行初 ... -
在Java中操作串口实现短信收发1
2010-06-07 22:06 1601在Java中操作串口实现短信收发 采用串口操作进行短信收发 ... -
JVM内存参数调优
2010-06-07 22:03 1950JVM内存参数调优 我们前面所提到的堆内存(heap)是由 ... -
多线程程序设计的要点
2010-06-07 22:00 853多线程中有主内存和工 ... -
Java 处理事务精要
2010-06-07 21:58 988简单事务的概念 我 ... -
如何开公司及手续过程
2010-06-07 21:55 1213注册一个公司,首先想好经营什么,怎样经营好,再来注册。要不,注 ... -
运用加密技术保护Java源代码
2010-06-07 21:52 942Java程序的源代码很容易被别人偷看,只要有一个反编译器,任何 ... -
连接池的基本工作原理
2010-06-07 21:39 840连接池的基本工作原理 1、基本概念及原理 由上面的分析可以 ... -
高效的Java音乐播放类
2010-06-07 21:34 1528/** *//** * 自动播放,循环停止后结束。 ... -
高效的Java音乐播放类 2
2010-06-07 21:32 1191/** *//** * 直接播放url文件 * ... -
高效的Java音乐播放类
2010-06-07 21:26 1372Java音频播放,因为必须依赖到本地环境,所以JAVA在音频处 ... -
用开源的 InnoSetup 为 Java 应用制作 Windows 安装程序
2010-04-24 11:30 1678在这个例子里, 我将给大家展示如何使用 InnoSetup 自 ... -
Swing: 用 GlassPane 显示一个透明的正在操作框
2010-04-24 10:25 2029这个组件可以让用户看到界面里的显示但是无法操作. 需要的图: ... -
文本放大器
2010-04-24 10:06 1270/** * @(#)Text2Image.java 1.0 D ... -
在自定义 JToolTip 里面显示组件
2010-04-24 10:03 2316在自定义 JToolTip 里面显示组件 我们经常可以看 ...
相关推荐
综上所述,"java+jtopo"是一个强大的Java拓扑图插件,它结合了Java的灵活性和JTopo的可视化能力,为开发者提供了一种高效的方式来创建和展示拓扑图。通过学习和应用这些知识点,开发者可以在自己的项目中实现功能...
java拓扑图第三方包(twaver.jar)试用版
Java网络拓扑图的实现通常是通过编程语言(如Java)与前端框架(如Vue.js)结合来完成的,以创建交互式的、可自定义的拓扑图管理界面。以下是对这些知识点的详细说明: 1. **Java网络拓扑图**:Java是多平台的编程...
在Java中,实现这样的拓扑图插件可以帮助开发者更好地理解和管理复杂项目。本篇文章将详细介绍如何利用Java来创建拓扑图插件,并探讨相关的核心知识点。 首先,拓扑图插件通常涉及图形用户界面(GUI)的设计,这...
基于swing的拓扑图第三方包,可以快速实现网络拓扑结构的动态图形。
Java拓扑图插件是一种用于在Java应用程序中绘制和展示网络、系统或流程拓扑结构的工具。这种插件通常提供了丰富的图形库和API,使得开发者可以方便地创建交互式的图表,以直观地表示复杂的系统关系。在给定的描述中...
Java 拓扑图在 IT 领域,特别是电信行业,是一种重要的系统设计和管理工具。它通过图形化的方式,清晰地展示了系统的组件、它们之间的连接以及数据流的方向,帮助开发者、运维人员以及管理者理解复杂的系统架构。...
jtopo就是这样一个专用于绘制Java拓扑图的库,它提供了丰富的API和功能,使得开发者可以轻松创建出复杂的网络拓扑模型。 jtopo库的设计目标是提供一种简单、高效的方式来构建和操作拓扑图。它支持动态更新,可以...
"拓扑发现"是SNMP应用的一个关键领域,它涉及到自动识别网络中的设备,了解它们之间的连接关系,形成一个可视化拓扑图。这个过程通常包括以下步骤: 1. **设备发现**:通过发送SNMP GET请求到预定义的IP地址范围,...
在IT行业中,Flex和Java的组合常常用于构建交互式的、图形化的用户界面,尤其是在需要展示复杂数据关系或网络拓扑图的场景下。本项目"Flex+Java开发拓扑图"是一个利用Flex作为前端展示层,Java作为后端数据处理层来...
在IT领域,网络拓扑图是一种重要的工具,用于可视化网络结构和设备间的连接关系。本文将深入探讨如何利用JavaScript(JS)和HTML5技术,特别是借助Qunee库,来实现网络拓扑图的自动排列展示。 首先,HTML5是现代...
3. **拓扑图构建**:根据提取的关键信息,使用Java图形库或其他可视化工具构建网络拓扑图。 4. **拓扑图优化**:进一步优化拓扑图,确保其准确性并提高可读性。 #### 结论 本文介绍的基于SNMP和Java的网络拓扑发现...
`jtopo` 是一款基于 Java 开发的网络拓扑图绘制软件,它具有强大的功能,可以满足各种网络设计和教学需求。 **jtopo 的主要特性:** 1. **图形化界面**:jtopo 提供了用户友好的图形界面,使得用户可以方便地拖放...
这段代码主要用于在Web页面上显示一个网络连接的拓扑图。 #### 代码结构解析 - **JSP 导入声明**:通过 `<%@ page import="..." %>` 语法导入所需的 Java 类库,如 `NetworkStatus`、`ArrayList` 和 `List`。 - **...
Java知识体系架构,java开发使用到的相关的知识技术。
Java开发拓扑图涉及到的是在Java环境中创建和展示网络、系统或者应用的图形化表示,这对于监控、管理和故障排查有着重要的作用。在这个上下文中,"TWaver" 和 "iTop" 是两个关键工具,用于创建复杂的拓扑图表。 ...
在这个"Gojs设备拓扑图Demo实例"中,它被用来展示设备及其端口的拓扑结构,允许用户点击设备和端口来查询它们之间的链路连接。这个实例是Web开发中的一个常见应用场景,尤其是在网络管理和监控、物联网(IoT)系统或...
"Python思维拓扑图"旨在帮助学习者构建一个清晰的知识框架,以便更好地理解和掌握Python编程的核心概念。以下是对这些文件名称中所包含的Python知识点的详细解读: 1. **标准库**:Python的标准库是其内置的一系列...
JTopo 是一款强大的、开源的Java拓扑图绘制工具,适用于网络、系统和应用的可视化设计。它提供了丰富的API和组件,使得开发者可以方便地创建复杂的拓扑图,包括网络设备、服务器、链路等元素,并能进行动态交互。本...