ArcGIS Maritime Server 开发教程(七)Maritime Server 正确的开发模式

本章导读:前面几个章节已经非常细节的分析和测试了 Maritime Server 的相关功能了,在面对重重困难的时候,很多 GIS 开发者甚至在想, Maritime Server 除了发布海图服务之外难道就在开发定制上一筹莫展吗?传统的 ArcGIS Server 功能非常强大,ArcGIS JavaScript API 接口也非常丰富,一旦转入到关于 Maritime 的时候,就显得捉襟见肘了。所以,笔者也在想,ArcGIS Maritime 团队到底是怎样利用其设计的产品完成一个个大型的项目的?可以肯定的是,解决问题的方法不在于 Maritime 产品本身,而在于其开发模式。 BY 李远祥

ArcGIS Maritime Server 你想要的帮助文档

对于开发人员来说,什么是最想要的?那肯定是开发帮助和样例代码,这样就能够以最短的时间最快的方式切入到具体的功能开发中。一般来说,程序员的英文水平都比较高,英文的 SDK 都看得很溜,敲起代码来来比用企鹅聊天还要快。其实大批量出现的都是那几个计算机专业词汇,又或者代码时使用的大量的是程序语言中出现的关键词汇 。总之,习惯就好了。

没有中文帮助,有英文的也不错,就像 ArcGIS Server ,各种产品说明,部署说明,功能说明等都有在中国官网上;开发 API 是全英的,SDK 和 Sample Code 也是全英的,但胜在这一块是程序员的优势,读起来也不算吃力。是在不行的话,国内某知名搜索引擎还是可以检索出前人一堆的代码,还带上中文注释(幸运的话还会在注释出看到程序员诗兴大发编上去的一首打油诗 _

但是,切换到 ArcGIS Maritime 就没有那么幸运了。产品的部署说明还是有的,各种的升级、迁移说明,都能找到。如下图所示:

这就是官方帮助的网址,特别留意一下,是带"zh-cn"的。也就是说,目前还没能像 ArcGIS Server 那样有官方的全中文帮助说明。

尽管如此,笔者还是建议开发人员去看看,这不是了胜于无,而是在专业领域上是在没有办法了,总不能靠猜去完成整个开发过程,必须是实打实的了解产品,了解原理,这样才能从有限的帮助中“感悟”出一些必要的信息出来。也许在项目结束的时候,你还庆幸有这么一丁点的英文资料。

但在 https://developers.arcgis.com/ 上根本上检索不到有任何 Maritime 字样的 API 说明,关于这方面的接口说明,可以肯定是没有的了。那么服务的 REST API 又怎样?前面的文章已经解释过了,如果原始的 REST 页面去访问,提供的输入参数部分,几乎没有一个能够正常返回结果的,所以,无法通过抓取请求/返回的方式去“领悟”并自己构建和解释请求。在这方面,是既没有专门的 Maritime JavaScript API ,也没有最原始的 REST API 说明,完全是处于“你猜猜看”的状态。

通过搬梯子到墙外看看,也没能在 G 姓的搜索引擎中找到一些可用的开发资源。所以,建议开发人员先死了通过搜索去找到帮助的那条心。在这条路中唯一可以依赖的搜索引擎是国内的百度,目前关于 ArcGIS Maritime 开发教程只有中文。没错!真的只有中文,并且跳转的地方是 CSDN 李老师的博客。这个还真只能是苦中作乐。

所以,大篇幅的谈论上述话题,为的只是说明一个问题,你想要的帮助是不存在你最想要的开发帮助这一次非常幸运,就只有中文!

ArcGIS Maritime Server 开发模式猜想

从第一章《ArcGIS Maritime Server 开发教程(一)了解ArcGIS Maritime Server》笔者就已经提到 ArcGIS Maritime Server 的系统架构,架构图上已经写得非常的情况,ArcGIS Maritime Server 实际上是在 ArcGIS Server 上的一个 SOE 扩展,这跟其他的服务器扩展如 Image Server,GeoEvent 等完全不一样。通过 SOE 扩展了海图渲染引擎,对外的服务协议还是全部走 ArcGIS Server 的标准协议,对外接口是保持一致的。尽管实际上的使用有各种问题,其具体的原因笔者在前几章也有非常详细的说明。

按照 ArcGIS Server 的 SOE 扩展模式,它属于在 Server 后台做的功能,原则上是不会作用到前端接口上的。也就是说,从技术路线的选定上,ArcGIS Maritime Server 压根就不会存在像 ImageServer 那样单独的开发接口。

从基本的服务调用、查找、地图交互操作方面,都使用通用的 ArcGIS JavaScript API 去实现,但大部分功能还是不能与传统服务对齐。所以,直接使用 Maritime Server 提供的服务(Maritime Service)功能非常弱。

所以笔者大胆的猜想,ArcGIS Maritime Server 最大的贡献就是能够直接将海图数据 S-57 数据发布成标准的 GIS 服务,并且能够按照 S-52 标准显示出来。这部分的工作如果使用传统的 ETL 以及配图的方式,工作量巨大无比,而且在数据更新以及维护上非常吃力 。至于具体的应用,笔者大胆的猜想,应该不是 ArcGIS Maritime Server 所做的事情,而是返回到传统的 ArcGIS Server 模式,借助成熟的产品和全面的 API ,定制开发应该是轻松的事情。而 ArcGIS Maritime Server 在整个系统的作用,已经就是解决海图数据的支撑以及海图显示的问题。

之前过于依赖 Maritime Service ,那是因为 ArcGIS 在这一块上发力,解决了海图应用中工作量最大也是难度最大的数据发布和海图渲染的问题,让很多人都忽略了最根本的 ArcGIS Server 服务。再大胆一点猜想,在没有 ArcGIS Maritime Server 的时候,海图服务的发布都是通过传统配图方式出来的,发布的数据都已经是从 S-57 转换过来的 Geodatabase 格式的数据。对于这个数据,GIS 开发人员肯定很容易掌握,只要是它发布的服务,ArcGIS JavaScript API 的各种接口都能顺利使用。试想一下,将这两种方式结合起来会是什么样子?

用 Maritime Server 去发布海图服务,海图服务用于前台显示,释放整个电子海图配图的工作;将海图数据转换到 Geodatabase 中,再发布一个没有配图的 MapService ,这个服务不做叠加,只用来在后台做属性查询、空间查询以及地理分析,这种模式可以有效的解决海图显示和开发的所有问题。

使用全新的 Maritime 开发模式

在解决一个问题的时候,往往还会引入另一个新的问题。所以,前面提及到的这种开发模式,会引入另一个工作,就是将 .000 数据转为 GDB 格式。到底怎样转才是正确的,怎样处理才是最高效的,那就值得商榷了。

笔者在前面章节《ArcGIS Maritime Server 开发教程(六)Maritime Service 开发技巧》中介绍过,只要安装了 ArcGIS S-57 Viewer 之后,ArcMap 就能直接识别 S-57 数据,并将其按照 GIS 要素类方式显示。能够通过右键方式将整个 000 数据导出为 GDB 格式,如下图所示:

尽管这个方式是将数据转出来了,但海图数据是分幅的数据,也许每个分幅对应的物标种类不一样,分幅之间接边怎么处理,导出的多个 GDB 如何合并等一系列问题都需要解决。

当然,处理这些工作笔者也可以通过自己编写一些 Python 工具进行扩展。从 000 导出 GDB 然后再去合并所有分幅的 GDB 数据。但这种方法依然很欠妥,每个海图分幅的范围和种类不一样,编写代码要则要考虑比较周全。

在现成的工具下,最有效的管理 S-57 数据的方式是使用 ArcGIS Martime Charting 桌面扩展,通过 NIS 库进行入库管理(非海图生产,只是做数据管理)。安装好 ArcGIS Desktop 软件之后,再单独安装 ArcGIS Martime Charting 扩展模块。其工作方式是以 ArcMap 桌面软件的工具和工具条来实现。

NIS 库是 ArcGIS Maritime Charting 在 Geodatabase 下创建的库结构,主要作用是海图数据存储在 GIS 数据库中,能够使用 GIS 的工具和方法使用这些非 GIS 数据。NIS 的构建方式不在这个章节详细讨论,因为有更好的方式可以实现快速将系列海图数据转存到 NIS 库并制作成地图文档。

通过 GitHub ,检索到 Esri 官方放出的一些海图的工具及代码,有了几个工具一切就简单多了。且看具体的几个工具,这是具体的链接,截图如下

下载下来后最重要的是第一个工具,S57 To GIS 。先来看工具的构成,分别由两个配置好的 MXD 文件,一个 ArcGIS 工具箱,一个 Python 工具脚本以及一个 .zip 压缩包组成,压缩包内其实是预先生成好的空的 NIS 数据库。如下图所示:

从 README文件中可以看到前面有关的重要说明,一是功能,而是工具所需的运行环境。

# S57 To GISS57 to GIS is a python script that allows you to quickly and easily load one, or many, ENC cells into a
geodatabase that is symbolized with S-52.Tool requirements:
* ArcMap 10.4.1 with ArcGIS for Maritime: Charting 10.4.1
* Ensure that the Maritime Charting extension is enabled
* The S57 To GIS.tbx and s57_to_gis Python file must be in the same directory

这个工具是快速的将一个或多个 ENC 数据转为 GDB 格式,并以 S-52 的方式进行符号化。所需的环境是 ArcMap10.4.1 以上,及对应版本的 ArcGIS Maritime Charting 扩展模块。

用法很简单,先将 zip 文件解压,得到一个空的 NIS 库,然后根据数据的情况是否使用带 SCAMIN 的模板,两个 MXD 选定的其中一个。新建一个地图文档(不要使用模板的 mxd 文件来操作,因为最终工具需要将此 mxd 进行覆盖,如果打开了该模板,将无法将信息写入),在 Catalog 中指向 S57 To GIS 工具箱,双击打开该工具,如下图所示

  • 第一个参数是指向 S57 文件所在的目录,该目录中可以含有1个或多个 S57 文件。
  • 第二个参数指向的是解压出来的 NIS 数据库。如果自建有基于 ArcSDE 的 NIS 库也可以。
  • 第三个参数指向是地图模板文件,就是工具目录下的两个 mxd 文件中的其中一个。

为了方便管理,笔者建议是将解压出来的 GDB 文件与地图模板放在同一个目录下,操作完成后打开 ArcMap 将文档的路径改为相对路径。这样方便数据的拷贝和迁移。

执行完之后可以看到工具的执行提示,分别是将 ENC 数据导入到 NIS 库中,然后利用制图表达将其符号化,根据制图模板,将数据源重新设置,并保存了 mxd 文档。

ArcGIS 桌面软件去渲染 NIS 库,使用的并非是传统的符号系统,而是使用制图表达技术,因为 S52 的渲染方式无法通过传统符号系统技术去实现。

完成后打开 Mxd 文件,可以看到地图和数据已经关联,并且以 S52 方式进行显示。

纯桌面的显示效果要比 Maritime Server 输出的效果要差一些,但我们需要的不是桌面显示,而是需要这样的一个 mxd 文件来发布传统的 ArcGIS Server 地图服务。

上面的截图是使用了带 SCAMIN 的模板制作,适合做桌面显示。因为它由多个图层组构成,每个图层组设置好了最大显示比例和最小显示比例,再桌面缩放和浏览有一定的优势。而作为一个查询的不显示的地图服务,还是建议使用 NO_SCAMIN 模板,它只有一个图层组,地图服务中比较容易使用索引指向图层。下图是 NO_SCAMIN 显示的效果。

笔者是推荐使用 NO_SCAMIN 模板来发布用于查询的地图服务。如果用来做切片底图,那么地图服务发布使用 SCAMIN 模板。

接下来就是将 NO_SCAMIN 地图文档发布为地图服务,这个过程就不再多说了。至于这里面包含的图层,显示与不显示都不是重点,因为这个服务是用作查询和空间分析使用的。通过上述的方式,笔者发布一个名为 queryMap 的 MapService,这样就回到熟悉的开发路上了。从这个服务中可以看到加入了 NIS 库中的所有物标对象,但它的命名方式跟前面所说的 S-57 Viewer 呈现的名称不一样,需要做一些适当的对照。不过基本上是大同小异的,使用起来问题也不大。

熟悉的 ArcGIS JavaScript API 开发

使用上述的这种开发模式,立马就可以回归到熟悉的 ArcGIS JavaScript API 开发中去了,通过这种方式,克服了前面所说的种种困难。
前面章节中提及到的空间查找以及图形查找,都可以迎刃而解了,毕竟每一个图层都可以使用传统的开发接口。

根据《ArcGIS Maritime Server 开发教程(五)Maritime Service 系列问题应对》里面提及到的一些问题,例如 不支持Query查找,identify 操作不支持不规则图形等,在新的模式下这些问题都能够迎刃而解。以之前章节的 identify 图形查找为例,现在对其进行有效的改进,使用 QueryTask 做图形查找,其关键代码如下:

加载基础地图部分及海图服务,不需要将 NIS 库发布的服务加载显示。

//加载基础服务WGS 84
var basemap = new DynamicLayer("http://localhost:6080/arcgis/rest/services/SampleWorldCities/MapServer");
map.addLayer(basemap);
//加载海图服务
var enc84 = new DynamicLayer("http://localhost:6080/arcgis/rest/services/SampleWorldCities/MapServer/exts/MaritimeChartService/MapServer");
map.addLayer(enc84);

在绘图完毕之后,调用 QueryByGeometry 函数进行几何图形查找。QueryTask 调用的服务则为使用 NIS 发布的地图服务,索引号为 5 的图层对应的是水深点。

//点击地图,通过屏幕上的点进行查询
function QueryByGeometry(geom) {var queryParams, queryTask;//查找后台不显示的服务,以水深点作为查找queryTask = new QueryTask("http://localhost:6080/arcgis/rest/services/queryMap/MapServer/5");queryParams = new Query();queryParams.geometry = geom;queryParams.returnGeometry = true;queryTask.execute(queryParams, getResult);
}function getResult(results) {//获取并显示查询结果var resultCount = results.features.length;for (var i = 0; i < resultCount; i++) {var feat = results.features[i];setGrapic(feat);}
}

代码片段改动了原来查询的方式,直接使用 QueryTask 来代替原来的 IdentifyTask,实现了精确的对物标要素进行图形查找。这样就不需要像之前那样需要获取物标的属性进行判断,而是在一开始 Query 参数的时候进行了指定。页面代码如下

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" /><title>使用传统服务方式空间查询海图要素(水深点为例)</title><link rel="stylesheet" href="http://localhost/arcgis_js_api/3.19/esri/css/esri.css"><style>html,body,#mapDiv {width: 100%;height: 100%;margin: 0;padding: 0;}</style><script src="http://localhost/arcgis_js_api/3.19/init.js"></script><script>var map, tb;var drawGrapic;require(["esri/map","esri/layers/ArcGISDynamicMapServiceLayer","esri/geometry/Extent","esri/symbols/SimpleMarkerSymbol","esri/symbols/SimpleLineSymbol","esri/symbols/SimpleFillSymbol","esri/tasks/QueryTask","esri/tasks/query","dojo/Deferred","esri/Color", "esri/graphic","esri/toolbars/draw","esri/symbols/PictureFillSymbol", "esri/symbols/CartographicLineSymbol","dojo/on", "dojo/dom","dojo/domReady!"],function (Map, DynamicLayer, Extent,SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol,QueryTask, Query, Deferred,Color, Graphic, Draw,PictureFillSymbol, CartographicLineSymbol,on, dom) {//初始化显示范围var initexten = new Extent({ "xmin": 113.42, "ymin": 22.15, "xmax": 113.58, "ymax": 22.26, "spatialReference": { "wkid": 4326 } });map = new Map("mapDiv", { extent: initexten });//加载基础服务WGS 84var basemap = new DynamicLayer("http://localhost:6080/arcgis/rest/services/SampleWorldCities/MapServer");map.addLayer(basemap);//ENC WGS 84var enc84 = new DynamicLayer("http://localhost:6080/arcgis/rest/services/SampleWorldCities/MapServer/exts/MaritimeChartService/MapServer");map.addLayer(enc84);//注册点击查询事件map.on("load", initToolbar);//简单点符号var markerSymbol = new SimpleMarkerSymbol();markerSymbol.setColor(new Color("#00FFFF"));markerSymbol.setStyle(SimpleMarkerSymbol.STYLE_CIRCLE);markerSymbol.setSize(12);//制图线符号var lineSymbol = new CartographicLineSymbol(CartographicLineSymbol.STYLE_SOLID,new Color([255, 0, 0]), 10,CartographicLineSymbol.CAP_ROUND,CartographicLineSymbol.JOIN_MITER, 5);//图片填充var fillSymbol = new PictureFillSymbol("/mangrove.png",new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,new Color('#000'),1),42,42);//点击地图,通过屏幕上的点进行查询function QueryByGeometry(geom) {var queryParams, queryTask;//查找后台不显示的服务,以水深点作为查找queryTask = new QueryTask("http://localhost:6080/arcgis/rest/services/queryMap/MapServer/5");queryParams = new Query();queryParams.geometry = geom;queryParams.returnGeometry = true;queryTask.execute(queryParams, getResult);}function getResult(results) {//获取并显示查询结果var resultCount = results.features.length;for (var i = 0; i < resultCount; i++) {var feat = results.features[i];setGrapic(feat);}         }//渲染查找结果function setGrapic(gra) {//定义点线面符号var pointSym = new SimpleMarkerSymbol();var lineSym = new SimpleLineSymbol();var polySym = new SimpleFillSymbol();var color = new Color([255, 0, 0, 0.5]);var outColor = new Color([0, 255, 0, 0.5]);//点符号设置pointSym.setColor(color);pointSym.setSize(12);pointSym.outline.setColor(outColor);//线符号设置lineSym.setColor(color);lineSym.setWidth(3);//面符号设置polySym.setColor(color);polySym.outline.setColor(outColor);//对点线面图形设置符号if (gra.geometry.type == "point") {gra.symbol = pointSym;} else if (gra.geometry.type == "polyline") {gra.symbol = lineSym;} else if (gra.geometry.type == "polygon") {gra.symbol = polySym;}map.graphics.add(gra);//跳转到地图位置jumptoMap(gra); }//跳转到要素所在的位置function jumptoMap(gra) {if (gra.geometry.type == "point") {map.centerAndZoom(gra.geometry);} else {map.setLevel(6);map.setExtent(gra.geometry.getExtent());}}//跳转到要素所在的位置function jumptoMap(gra) {if (gra.geometry.type == "point") {map.centerAndZoom(gra.geometry);} else {map.setLevel(6);map.setExtent(gra.geometry.getExtent());}}function initToolbar() {tb = new Draw(map);tb.on("draw-end", addGraphic);on(dom.byId("info"), "click", function (evt) {if (evt.target.id === "info") {return;}var tool = evt.target.id.toLowerCase();map.disableMapNavigation();tb.activate(tool);});}function addGraphic(evt) {tb.deactivate();map.enableMapNavigation();var symbol;if (evt.geometry.type === "point" || evt.geometry.type === "multipoint") {symbol = markerSymbol;} else if (evt.geometry.type === "line" || evt.geometry.type === "polyline") {symbol = lineSymbol;}else {symbol = fillSymbol;}var drawGrapic2 = new Graphic(evt.geometry, symbol);map.graphics.add(drawGrapic2);QueryByGeometry(evt.geometry);}});</script>
</head>
<body><div id="info"><button id="Point">Point</button><button id="Multipoint">Multipoint</button><button id="Line">Line</button><button id="Polyline">Polyline</button><button id="FreehandPolyline">Freehand Polyline</button><button id="Triangle">Triangle</button><button id="Extent">Rectangle</button><button id="Circle">Circle</button><button id="Ellipse">Ellipse</button><button id="Polygon">Polygon</button><button id="FreehandPolygon">Freehand Polygon</button></div><div id="mapDiv"></div>
</body>
</html>

再来看测试结果,通过输入不同的图形进行查询水深点,全部都能满足图形查询要求。如下图所示

总结

通过仔细分析和大胆猜想,基于 SOE 架构的 ArcGIS Maritime Server 是不会带有任何特定的开发 API 的,所以打算直接使用所谓的 Maritime API 去进行开发,这条路从一开始就走不通。ArcGIS Maritime Server 更多是从服务器后端去定制的功能,暴露在前端的则是传统的地图服务接口,使用传统的 ArcGIS JavaScript API 去调用和定制才是唯一可行的道路。通过从 GitHub 上下载下来的 S57 To GDB 工具,很好的封装了 ArcGIS Maritime Charting 扩展的入库工具,给海图数据转到 GDB 中提供了极大的便利,同时也解决了新模式下海图应用开发的所有问题。

更多的GIS主流和非主流技术,可以持续关注CSDN的GIS制图乐园,以及微信公众号【GIS制图乐园】。BY 李远祥

ArcGIS Maritime Server 开发教程(七)Maritime Server 正确的开发模式相关推荐

  1. MongoDB 教程七: MongoDB和PHP结合开发

    视频:MongoDB 教程七: MongoDB和PHP结合开发 Linux上安装 MongoDB PHP扩展 在终端上安装 你可以在linux中执行以下命令来安装MongoDB 的 PHP 扩展驱动 ...

  2. SAP UI5 应用开发教程之八十二 - 采用 OPA5 开发支持页面跳转的 SAP UI5 集成测试用例试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  3. HyperLeger Fabric开发(七)——HyperLeger Fabric链码开发

    HyperLeger Fabric开发(七)--HyperLeger Fabric链码开发 一.链码开发模式 1.链码开发模式简介 Fabric的链码开发调试比较繁琐.在不使用链码开发模式的情况下,链 ...

  4. 小程序云开发教程七:贴子的详情及评论功能

    我们先看看界面: 我们如果要实现评论功能, 先看一下总的数据结构: 那么需要什么参数呢? 参数如下 comment: 评论内容username: 用户名time: 评论时间userId: 用户idid ...

  5. 微信公众号开发教程(七)JSSDK-监听分享朋友圈事件

    作者:陈惠,叩丁狼教育高级讲师.原创文章,转载请注明出处. 微信JS-SDK是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍 ...

  6. python开发软件-七种流行的python开发软件,收藏了!

    Python的应用无处不在,各种流行软件都有Python的身影.相比起最流行的Java.C/C++等语言,Python语言更加简洁,开发更加快速,这对于初学者非常友好,而且Python作为脚本语言,更 ...

  7. Win10+Python+Django+Nginx+MySQL开发教程及实例(1)——开发环境搭建

    Win10+Python+Django+Nginx+MySQL开发教程及实例 PaulTsao 本教程共有三篇内容: 第一篇:Win10+Python+Django+Nginx+MySQL 开发环境搭 ...

  8. 云计算开发教程:Python自动化运维开发实战流程控制

    今天这篇文章是给大家分享一些云计算开发教程,今天讲解的是:Python自动化运维开发实战流程控制. Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. P ...

  9. Python量化交易平台开发教程系列7-顶层GUI界面开发(1)

    原创文章,转载请注明出处:用Python的交易员 前言 终于有时间来写第一篇顶层GUI界面开发相关的教程了,之前实在是事情太多,跟各位读者抱个歉. 整合底层接口的各项功能到中层引擎中后,当我们开发顶层 ...

  10. Luat 功能开发教程(七) 基站 WIFI定位

    目录 基站/WIFI定位 简介 API说明 实现流程 示例 常见问题 1. 如何在网站上查询小区对应的位置信息? 2. wifi定位失败的可能原因有哪些? 3. 基站定位获取的经纬度是什么格式的? 相 ...

最新文章

  1. LeetCode Spiral Matrix II (生成螺旋矩阵)
  2. 查询出的数据记录字段要与实体类中的属性名一致
  3. UA SIE545 优化理论基础4 对偶理论简介1 松弛问题与Lagrange对偶
  4. 关于MyEclipse项目的名字的修改对项目导入导出的影响
  5. Python批量删除错误图片、修改文件名以及删除重复图片
  6. Material Design入门(三)
  7. php 上次登陆时间,php使用cookie显示用户上次访问网站日期的方法
  8. 大数据分析与应用技术国家工程实验室项目通过验收
  9. 拖放获取文件信息的bat代码
  10. ES6高级技巧(五)
  11. 分享一个最新思考的创业项目
  12. ASP.NET错误处理的方式(一)
  13. 不吹不黑,这5款浏览器安全无广告无弹窗,亲测好用
  14. 就百度指数对比分析“微博”与“知乎”搜索人数
  15. 实训-利用HTML和CSS制作一个网页界面
  16. js可以用的万年历API
  17. 计算机二级不能使用快捷键,你不可不知的几个Office2010另类快捷键_计算机二级_Office快捷键_Office考试_课课家...
  18. cad直线和圆弧倒角不相切_CAD圆角、倒角分不清?详细讲解CAD圆角与倒角对象的区别和技巧...
  19. Rust Async: smol源码分析-Executor篇
  20. 第六期 自定义IP添加-PWM 基于ARTY A7的MicroBlaze系统搭建与应用

热门文章

  1. STM32:GPIO配置说明
  2. 在android中使用opencv,在安卓上使用OpenCV的指南 - kdnuggets
  3. python object和type的关系-Python 的 type 和 object 之间是怎么一种关系?
  4. 洛谷——P1427 小鱼的数字游戏
  5. Error: Can’t resolve ‘./src’ in ‘E:\ASUS\Documents\VSCode files\WebPackProject’
  6. 使用IDEA创建Maven项目教程
  7. 复合选择器-链接伪类选择器(HTML、CSS)
  8. python测试udp端口_zabbix上使用外部检查的方式监测公网tcp/udp端口开放情况
  9. potala(5)——Unit Test and Cache
  10. 【编译原理笔记14】中间代码生成:布尔表达式的回填,控制流语句的回填,switch语句的翻译,过程调用语句的翻译