ArcGIS for JavaScript 开发GP服务思路解析

随着Web GIS的不断发展,让我这个老是墨守成规C/S架构的开发者来说也不得不改变自己的观点,如今web端、移动端的大行其道,让桌面端软件很难有生存之地,尤其是用户只需要使用浏览器就可以参与业务功能的执行,无需安装软件,这让很多人接触所谓的系统而感到便捷。

老实说,我目前的水平只能说稍微看懂ArcGIS的提供的例子,不过有过开发经验或者GIS基础来说,这已经能够让我入门了。现在就将我学习ArcGIS for JavaScript的入门心得以及相关问题给大家介绍一下,也算是给入门者一些经验吧。

------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

建议看到转载,请直接访问正版链接获得最新的ArcGIS技术文章

Blog:               http://blog.csdn.net/linghe301 

------------------------------------------------------------------


要求基础:javascript基础,html基础、css基础、ArcGIS二次开发经验,ArcGIS基础等,其实最主要的就是JS基础,因为ArcGIS提供的例子核心都是JS代码,我们无需了解更为详细的html和css知识,当然,如果你有dojo的经验就更好了,因为arcgis for js就是使用dojo框架。


其实我个人理解,如果想看懂arcgis for js代码最起码的js基础要求包括:js基础语法,dom知识,匿名函数、回调函数概念等。


其实我觉得对于开发者来说最核心的东西要懂得怎么来看帮助,之所以这样说,我觉得以前我做开发可能就没有认真或者说就没有正确的方法来看帮助,所有你在开发中遇到的问题,帮助上都会给你做详细的介绍。

ArcGIS for JS的官方帮助:https://developers.arcgis.com/javascript/

包括一些概念性的介绍,API介绍,Sample例子,这些例子都是可以直接运行的,因为例子的服务都是来自于ArcGIS Online上,所以只要有互联网和浏览器就可以直接查看功能效果,这个是桌面程序无法比拟的。


关于ArcGIS for JS开发环境的介绍:https://developers.arcgis.com/javascript/jshelp/intro_devenv.html

如果你的开发环境是VS2010、VS2012、Aptana2等,可以参考如下链接获得ArcGIS for JS的代码提示组件:https://developers.arcgis.com/javascript/jsapi/api_codeassist.html

------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

建议看到转载,请直接访问正版链接获得最新的ArcGIS技术文章

Blog:               http://blog.csdn.net/linghe301 

------------------------------------------------------------------


环境:ArcGIS 10.2.2 for Desktop、ArcSDE10.1、Oracle11.2.0.1、ArcGIS for JS 3.9


1:目标

我有一个subway的点数据图层,我希望能够使用属性条件查询某个地铁站,然后以这个点为中心,做一个缓冲区半径5000的buffer,要求比较简单,主要想介绍相关的步骤。


2:制作modelbuilder

制作modelbuilder我就不在多说了,我使用了select和buffer工具,添加了条件选择参数和缓冲区半径参数,先测试有数据情况下(有颜色标识)是否可以运行正常。


确保运行正常好,删除subway、条件、缓冲区半径、输出结果的具体信息,而且将其设置为变量,执行完毕如下所示:


保存到某个FGDB中,打开运行再次测试,确保没有任何问题。


------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

建议看到转载,请直接访问正版链接获得最新的ArcGIS技术文章

Blog:               http://blog.csdn.net/linghe301 

------------------------------------------------------------------


3:发布GP Service

将上面的Arctoolbox添加数据运行,如果运行成功后,在相关的运行日志可以看到相关信息,然后选择运行model发布相关的GP Service即可。


发布选择前需要用户了解几个知识点

a:GP服务的同步和异步,因为用户选择不同的运行方式在编写JS代码是不一样的

b:熟知job目录和output目录,这个是在调试程序时候需要开发者实时查看该目录的信息是否正确。


还有就是对相关参数的中文描述,养成好习惯,这样方便开发人员对参数的理解,也便于其他开发者如果接手调试你的程序会很快的进入状态。

PS:大家其实都很讨厌接手别人的代码,都说看不懂,没有代码注释,文档写的不明确,但是你们有没有想象你自己当前编写的代码是否有这些信息,一个合格的程序员编写的代码是会让接手人员赶到非常的惬意和舒服,其实这就是细节的力量,程序员的职业道德!


发布完毕之后,我们可以查看如下链接:http://localhost:6080/arcgis/rest/services/GP/GPServer/Model/submitJob

查看到如下界面

PS :发布异步是submitJob,发布同步是ExcuteTask。


点击submit job(GET)进行测试,可以得到如下结果,获得想的JobID



我们可以在ArcGIS Server的目录就是前面所述的job目录查看相关



从上面的几次验证,都可以确认发布的GP Service 没有问题,这样我们在开发调用才肯定不会再GP Service方面费太多时间。

------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

建议看到转载,请直接访问正版链接获得最新的ArcGIS技术文章

Blog:               http://blog.csdn.net/linghe301 

------------------------------------------------------------------


开发思路

a:首先去看关键性API

Represents a GP Task resource exposed by the ArcGIS Server REST API. A GP Task resource represents a single task in a GP service published using the ArcGIS Server and it supports one of the following operations:
"execute" - performed on a GP Task resource when the execution type is synchronous.
"submitJob" - performed on an asynchronous GP Task resource.

通过帮助查看

submitJob(inputParameters,callback?,statusCallback?,errback?)

里面传入GP参数、gp完成、gp运行状态、gp失败等,关于GP参数,我们在创建GP时候已经确定了三个参数,运行图层(subway)、选择条件、缓冲半径,那么通过这三个参数来构造inputParameters。
那么获得图层我们可以直接使用mapservice获得图层,选择条件直接写一个函数也可以,其实也可以使用QueryTask+过滤条件直接获得选择数据,但是这个不太符合GP的思想,缓冲半径可以调用esri/tasks/LinearUnit即可。

源代码展示
其实也就是通过Sample的示例进行修改
<!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>Simple Map</title>
    <link rel="stylesheet" type="text/css" href="http://localhost/arcgis_js_v39_api/arcgis_js_api/library/3.9/3.9/js/dojo/dijit/themes/tundra/tundra.css" />
    <link rel="stylesheet" type="text/css" href="http://localhost/arcgis_js_v39_api/arcgis_js_api/library/3.9/3.9/js/esri/css/esri.css" />
    <script type="text/javascript" src="http://localhost/arcgis_js_v39_api/arcgis_js_api/library/3.9/3.9"> </script>
    <style>
        html, body {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        #map {
            margin: 0;
            padding: 0;
        }
        #status {
            background-color: #E0E0E0;
            color: #707070;
            font-weight: bold;
            padding: 3px;
            border: solid 1px #707070;
            -moz-border-radius: 5px;
            -webkit-border-radius: 5px;
            border-radius: 5px;
            position: absolute;
            top: 50%;
            right: 50%;
            z-index: 100;
            display: none;
            height: 20px;
        }
    </style>
    <script>
        /*
            该程序实现了GP Service,生成一个结果图层以MapService显示
            使用了FeatureLayer.QueryFeatures获得相关的输入图层
        */
        require(["dojo/dom",
            "dojo/_base/array",
            "dojo/date/locale",
            "dojo/parser",
            "dijit/registry",
            "esri/domUtils",
            "esri/map",
            "esri/graphic",
            "esri/layers/ArcGISDynamicMapServiceLayer",
            "esri/layers/FeatureLayer",
            "esri/tasks/Geoprocessor",
            "esri/config", "esri/tasks/query",
            "esri/tasks/QueryTask", "esri/tasks/FeatureSet",
            "esri/tasks/LinearUnit",
            "dijit/form/DateTextBox",
            "dijit/layout/BorderContainer",
            "dijit/layout/ContentPane"],
      function (dom, array, locale, parser, registry,
               domUtils, Map, Graphic,
               ArcGISDynamicMapServiceLayer,
               FeatureLayer, Geoprocessor,  esriConfig,
               Query, QueryTask, FeatureSet, LinearUnit) {
          //配置代理------------------------------------------A
         esriConfig.defaults.io.proxyUrl = "/proxy.ashx";
          domUtils.show(dom.byId('status'));
          var gpServiceUrl = "http://localhost:6080/arcgis/rest/services/GP/GPServer/Model",
              mapserviceurl = "http://localhost:6080/arcgis/rest/services/GP/MapServer/jobs";
          //显示dojo控件                    
          parser.parse();
          //设置底图------------------------------------------B
          var map = new Map("map", {
              basemap: "streets",
              center: [116.341095, 39.925535],
              zoom: 13
          });
          //Run the gp task when the app loads to display default incidents
          map.on("load", findHotspot);
          var featureSet;
          var featureLayer;
          var query ;
         
          function findHotspot() {
              query = new Query();
              featureLayer = new FeatureLayer("http://lishaohua:6080/arcgis/rest/services/JS/MapServer/0");
              query.returnGeometry = true;
              query.outFields = ["*"];
              query.where = "1=1";
              featureLayer.queryFeatures(query, function (fs) {
                  featureSet = fs;
                  var gp = new Geoprocessor(gpServiceUrl);
                  var vsDistance = new LinearUnit();
                  vsDistance.distance = 50000;
                  //该单位根据GP发布的单位进行选择
                  vsDistance.units = "esriFeet";
                  //设置GP参数
                  var params = {
                      SDE_subway: featureSet,
                      Expression: buildDefinitionQuery(),
                      Distance__value_or_field_: vsDistance

                  };
                  //cleanup any results from previous runs
                  cleanup();
                  gp.submitJob(params, gpJobComplete, gpJobStatus, gpJobFailed);
              });
              
          }
          //GP完成之后加载结果图层
          function gpJobComplete(jobinfo) {
              //construct the result map service url using the id from jobinfo we'll add a new layer to the map
              var mapurl = mapserviceurl + "/" + jobinfo.jobId;
              var hotspotLayer = new ArcGISDynamicMapServiceLayer(mapurl, {
                  "id": "bufferlayer"
              });

              //add the hotspot layer to the map
              map.addLayers([hotspotLayer]);

            
          }
          //获得GP运行状态
          function gpJobStatus(jobinfo) {
              domUtils.show(dom.byId('status'));
              var jobstatus = '';
              switch (jobinfo.jobStatus) {
                  case 'esriJobSubmitted':
                      jobstatus = 'Submitted...';
                      break;
                  case 'esriJobExecuting':
                      jobstatus = 'Executing...';
                      break;
                  case 'esriJobFailed':
                      jobstatus = 'Failed...';
                      break;
                  case 'esriJobSucceeded':
                      domUtils.hide(dom.byId('status'));
                      break;
              }
              dom.byId('status').innerHTML = jobstatus;
          }
          //获得GP失败信息
          function gpJobFailed(error) {
              dom.byId('status').innerHTML = error;
              domUtils.hide(dom.byId('status'));
          }
          //获得条件参数
          function buildDefinitionQuery() {             
              return   "NAME = '北京站'";
          }
          function cleanup() {
              //hide the legend and remove the existing hotspot layer
          
              var hotspotLayer = map.getLayer('bufferlayer');
              if (hotspotLayer) {
                  map.removeLayer(hotspotLayer);
              }
          }
          app = {
              findHotspot: findHotspot
          };
          return app;
      });
    </script>
</head>
<body class="tundra">
            <div id="map" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center'">
            <span id="status" style='position:absolute;bottom:5px;'></span>
        </div>
</body>
</html>

里面有几个知识点:
A:关于设置代理: https://developers.arcgis.com/javascript/jshelp/ags_proxy.html
B:关于设置目标经纬度坐标: http://zhaoziang.com/amap/picpoint.html

------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

建议看到转载,请直接访问正版链接获得最新的ArcGIS技术文章

Blog:               http://blog.csdn.net/linghe301 

------------------------------------------------------------------


关于代码调试

我是使用Chrome进行代码调试的,也是同事介绍的,如果需要web开发,是一个很好的选择,点击F12,选择源代码,设置断点即可。



从上图所示,我们可以选择F10或者F11进行断点调试,而且在Console输入或者鼠标点击获得每一个参数的值,比如上述生成一个jobid,那么我就可以到相关的AGS的job目录里面查看是否该id的文件夹,然后再分析问题。


当然,也可以查看network查看GP运行的每一个步骤,从获得submitjob的页面,到执行gp 服务,到生成结果,都一目了然。

当然也有相关的软件比如fiddler会有更加详细的信息可以参考。




------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

建议看到转载,请直接访问正版链接获得最新的ArcGIS技术文章

Blog:               http://blog.csdn.net/linghe301 

------------------------------------------------------------------


最后,以上是个人在学习JS开发中可能遇到的困难和需要了解的知识,如果你有一定的基础,会看帮助,懂得调试,入门ArcGIS for JS开发应该没有问题,但是如何编写一个项目或者工程、将更加绚丽的页面加入进去,能够获得高性能的能力这个可能需要更长的路要走!



你可能感兴趣的:(ArcGIS for JavaScript 开发GP服务思路解析)