(九)ArcGIS Server之介绍SOE(上)

1.引言

      在看博客之前,首先重点说明,本博客中使用的软件版本:

  • ArcGIS Server10.2
  • ArcGIS Object10.2

      如果你的版本是10.0,本博客中的代码肯定不可以用(10.0版本到10.1版本是一个大的提升)
      如果你的版本是10.1,本博客中的代码需要稍微修改(10.1版本到10.2版本会有小部分的修改)

2. 什么是SOE?

      我们开发SOE之前首先要弄明白什么是SOE?SOE的全称为:服务器对象扩展(Server Object Extension)。一个SOE简单的来说 就是一组包含方法的类(注意这里是一组方法的类),Server Objects 是粗粒度的AO 组件,是一个可以执行特定操作的高级对象,它隐藏了细粒度的ArcObject。Server Objects的粗粒度接口支持对于像绘制地图或地理编码等整体性任务。Server objects 也有SOAP接口,可以把 Server objects暴露成Web Service,从而可以被客户端使用。

3. SOE的优势

  • SOE可以作为SOAP或REST Web服务,使得用ArcGIS Web APIs 建立的客户(用 于Javascript、Flex、Silverlight、iOS等)以便调用这些应用程序。事实上,您的 SOE将出 现在ArcGIS Services Directory 之内,并将提供特性设置、基本类型等ArcGIS APIs能够理 解的典型对象类型。
  • SOE能够对ArcObjects进行有效封装,提供理想环境以快速执行您的指令。 . 可以建立一个SOE,使用动态分段获取里程标志位置,或者实现几何网络分析(在ArcGIS 10 的时候,因为工具箱中没有提供几何网络的 GP,因此要实现几何网络的分析,可以通过 这种办法)

4. SOE过程(图像解释)

      SOE开发需要 ArcObjects和.NET或者Java(Java或者C#二选一)以及 REST 与SOAP 等Web 服务通信技术的知识。ArcObjects SDK 具有多种可供您进行校验的样本,即可用于Java也可用于.NET。
      在SOE的开发过程中,我们必须清楚,我们需要在 SOE中将请求获取,然后将传入的参数 转化为AO,然后通过AO 处理,再将处理的结果转成json格式,传给客户端,客户端得到json 格式的结果,然后解析

下图描述了请求响应的整个过程,如下图:

这里写图片描述

上面这个图片可能会涉及一些细节(数据类型),如果大家看不懂,大家可以看下面这个简单的图:

这里写图片描述

在上图我们需要解决的三个问题:

  • 如何在SOE中获取客户端传来的数据
  • 如何在服务器端读取地图服务数据
  • 如何将运行后的结果传回客户端

5. SOE需要的接口

5.1 必选接口IRESTRequestHandler

这个接口主要有两种方法:

  • string GetSchema();
  • byte[] HandleRESTRequest();

其中byte[] HandleRESTRequest();方法主要有两个作用:

  • 回调资源和操作的方法
  • 获取资源在实例级别的描述

该方法在识别这两个作用的时候是通过operationName参数,如果该参数是空字符产那就是第二个作用,否则是第一个作用。

byte[] HandleRESTRequest();的参数:

  • String capabilities:一组被资源授权的操作,可以为空字符串
  • String resourceName: 资源名称. 空字符串表示根级别,子资源会通过‘/’ 表示
  • String operationName:操作名称
  • String operationInput:操作的参数,JSON格式
  • String outputFormat:客户端请求的输出格式,如JSON,AMF
  • String[] responseProperties: 通过操作返回的一组键值对,逗号分开

5.2 必选接口IServerObjectExtension

这个接口实现的方法:Init(IServerObjectHelper pSOH)void Shutdown();

  • init() 方法:当Server启动的时候会调用该方法,并将IServerObjectHelper对象传入,该接口是对Server对象的弱引用,可以通过IServerObjectHelper.ServerObject得到服务器对象。
  • Shutdown方法:用在服务器关闭时调用,经常我们在该方法中释放SOE中使用的资源。

5.3 可选接口IObjectConstruct

      该接口只有一个方法Construct,该方法在Init方法执行后,立即被执行,如果我们的SOE有配置属性,就可通过该方法的参数得到,该方法只调用1次,我们可以将SOE中用的的比较耗费资源的逻辑写在该方法中,比如:获取地图代码,或者你始终操作某一个图层,就可以把获取该图层的代码写在这里。

5.4 可选接口IObjectActivate

      当initConstruct调用后,SOE的对象已经被创建,并且相应的配置信息也得到了,如果SOE的整个逻辑中需要不停的获取和释放服务器上下文,那么就必须实现改接口,改接口有两个方法: activate()deactivate(),当客户端调用CreateServerContext()的时候activate()方法被调用,当客户端释放服务器上下文对象时deactivate()方法被调用。

5.5 SOE接口执行顺序

这里写图片描述

5.5 SOE接口说明

      前面我们说过,SOE开发我们要面对三个问题:

  • 如何在SOE中获取客户端传来的数据
  • 如何在服务器端读取地图服务数据
  • 如何将运行后的结果传回客户端

如果利用上面的接口,解决这三个问题可能大家还不是特别的清楚,接下来我们要通过一个简单的demo来介绍一下接口的具体使用。

6. SOE开发的步骤

介绍完了一些SOE的理论东西,我们就要开发我们的SOE程序,开发SOE程序的过程为(五步):

  • 发布我们的地图服务(以MapServer为例)
  • 根据我们的地图服务编写SOE代码
  • 发布我们的SOE扩展
  • 将SOE扩展和我们的地图服务绑定
  • 客户端调用SOE扩展

7. SOE之Hello World程序

7.1 HelloWorld程序的解释

      在本篇博客中SOE实例是最简单的,在这个代码中解决的问题主要有两个:

  • 如何从客户端接受数据
  • 如何将结果返回给客户端

7.2 发布我们的地图服务(MapServer)

  • 因为我们在本次SOE实例中没有读取地图服务信息,所以使用ArcGIS Server自带的地图服务(当ArcGIS Server安装成功之后自带一个服务)

这里写图片描述

7.3 创建SOE程序(C#版本)

7.3.1 使用VS 创建SOE程序

这里写图片描述

7.3.2 默认的SOE模版有5个属性,有9个方法(代码截图,具体属性方法的作用等会解释

这里写图片描述

7.3.3 填写SOE扩展的服务类型

  • 因为我们的SOE是基于MapServer开发的(虽然我们的代码没有修改,假设我们的SOE就是基于MapServer开发的,因为Hello World程序太简单,不需要读取MapServer数据,所以也就不需要修改代码),所以修改我们SOE的类型。注意:新建的SOE程序,这个地方是空字符串,必须要修改为MapServer或者ImageServer,不然SOE发布不成功

这里写图片描述

7.3.4 生成soe文件

  • 右击项目:重新生成。在debug文件夹下面会出现SOE文件(此文件是发布soe扩展使用的)

这里写图片描述

7.3.5 将SOE扩展发布到ArcGIS Server

这里写图片描述

这里写图片描述

这里写图片描述

7.3.6 将SOE和地图服务绑定

  • 选择RestSOE重新启动地图服务

这里写图片描述

  • 绑定成功

这里写图片描述

7.4 客户端调用SOE功能

  • 访问生成的网址(绑定生成的url,7.3.6绑定成功之后生成了一个url):http://localhost:6080/arcgis/rest/services/SampleWorldCities/MapServer/exts/RestSOE

这里写图片描述

前面我们说了 SOE是包含一组方法的类(我们发布的Hello World程序只有一个方法)。

  • 访问sampleOperation方法

这里写图片描述

我们调用了sampleOperation方法,传过去两个参数

  • 返回值

这里写图片描述

方法调用成功:并且取得了相应的结果

7.5 解释默认的SOE模版

在这里我们将详细解释一下SOE默认模版的一些属性和方法。在这里主要解决一下问题:

  • SOE如何接受客户端传来的参数
  • SOE如何将结果返回给客户端
  • SOE的方法是如何添加的(SOE是一组方法的类)
  • SOE如何读取地图服务的信息(这个问题,在这里不解决,只是稍微提一下,重点将在下一篇博客中说明)

7.5.1 SOE中的属性

在SOE中一个最重要的属性是:serverObjectHelper,我们可以通过这个属性获得地图服务中的信息,具体这个属性怎么使用将在下一篇博客中使用

7.5.2 SOE中的方法

在SOE开发中,我们要着重的关注CreateRestSchema 方法,首先我们看一下这个方法中的代码

  private RestResource CreateRestSchema()
        {
            RestResource rootRes = new RestResource(soe_name, false, RootResHandler);

            RestOperation sampleOper = new RestOperation("sampleOperation",
                                                      new string[] { "parm1", "parm2" },
                                                      new string[] { "json" },
                                                      SampleOperHandler);

            rootRes.operations.Add(sampleOper);

            return rootRes;
        }
  • 在该函数中创建了Rest资源和Rest资源的操作,并且资源和Rest操作都对应一个处理函数。
  • Rest资源对应的函数为RootResHandler
  • Rest操作对应的函数为SampleOperHandler
  • RootResHandler在什么时候被触发?是在访问这个url(http://localhost:6080/arcgis/rest/services/SampleWorldCities/MapServer/exts/RestSOE)的时候被触发
  • 我们可以看到Rest资源可以添加多个Rest操作,也就是说一个SOE可以有多个方法,每一个方法对应着一个Rest操作
  • rest操作体现在什么地方?体现在这里:

这里写图片描述

  • 我们看rest资源所对应的方法(注意:我方法中返回了hello world,然后在rest资源那里显示hello world)
  private byte[] RootResHandler(NameValueCollection boundVariables, string outputFormat, string requestProperties, out string responseProperties)
        {
            responseProperties = null;

            JsonObject result = new JsonObject();
            result.AddString("hello", "world");

            return Encoding.UTF8.GetBytes(result.ToJson());
        }
  • 我们在看rest操作的定义

这里写图片描述

对应着

这里写图片描述

这里写图片描述

  • rest操作函数的实现
  private byte[] SampleOperHandler(NameValueCollection boundVariables,
                                                  JsonObject operationInput,
                                                      string outputFormat,
                                                      string requestProperties,
                                                  out string responseProperties)
        {
            responseProperties = null;

            string parm1Value;
            //将客户端parm1传给parm1Value变量
            bool found = operationInput.TryGetString("parm1", out parm1Value);
            if (!found || string.IsNullOrEmpty(parm1Value))
                throw new ArgumentNullException("parm1");

            string parm2Value;
            //将客户端parm2传给parm2Value变量
            found = operationInput.TryGetString("parm2", out parm2Value);
            if (!found || string.IsNullOrEmpty(parm2Value))
                throw new ArgumentNullException("parm2");
            //创建jsonObject对象,用于将结果传给客户端。在这里,我们将客户端传来的数据,原封不懂的返还给客户端
            JsonObject result = new JsonObject();

            result.AddString("parm1", parm1Value);
            result.AddString("parm2", parm2Value);

            return Encoding.UTF8.GetBytes(result.ToJson());
        }

7.8 代码总结

  • 一个SOE服务对应一个rest资源
  • 一个rest资源可以拥有多个rest操作
  • 一个rest资源对应一个方法(此方法作用不是很大)
  • 一个rest操作对应一个方法(这个方法很重要,一般是soe的核心方法)
  • 在rest操作对应的方法中可以获得客户端传来的参数,同时也可以给客户端发送信息
  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值