




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、产品应用与技术推广部ArcGIS 10.1 for ServerSOE介绍及开发Esri中国信息技术有限公司2012年6月版权声明本文档版权为Esri中国信息技术有限公司所有。未经本公司书面许可,任何单位和个人不得以任何形式摘抄、复制本文档的部分或全部,并以任何形式传播。制定及修订记录版本完成日期编写/修订纪要编写者备 注V0.12012-6-4刘宇V0.22012-6-11刘宇目 录SOE介绍及开发1第一章SOE由来1第二章SOE使用31.1必选接口31.1.1IRESTRequestHandler 接口31.1.2IServerObjectExtension41.2可选接口51.2.1IO
2、bjectConstruct51.2.2IObjectActivate51.3创建SOE61.4部署SOE111.5使用SOE18II第一章 SOE由来在ArcGIS 10.1中ArcGIS Server不在支持DCOM方式的连接,这也就意味着我们不能通过本地方式的连接使用ArcObjects提供的更多功能,所以我们推荐一种新的方式来实现这些功能,这种方式就是SOE服务器对象扩展,一个SOE(Server Object Extension)就是一个包含一组方法的类,这个类可以在SOC(ArcGIS 10.1 for Server进程,全称是ArcSOC.exe)中运行,并且可以被web应用程序
3、调用。Server Objects是粗粒度的AO组件,是一个可以执行特定操作的高级对象,它隐藏了细粒度的ArcObject。Server Objects的粗粒度接口支持对于像绘制地图或地理编码等整体性任务。Server objects也有SOAP接口,可以把server objects暴露成Web Service,从而可以被客户端使用。SOE是开发者的一个高级选项,使您能够将ArcGIS Server服务基本功能进行扩展。SOE具有两大优势:1.SOE可以作为SOAP或REST Web服务,使得用ArcGIS Web APIs建立的客户(用于JavaScript、Flex、Silverligh
4、t、iOS等)以便调用这些应用程序。事实上,您的SOE将出现在ArcGIS Services Directory之内,并将提供特性设置、基本类型等ArcGIS APIs能够理解的典型对象类型。2.SOE能够对ArcObjects进行有效封装,提供理想环境以快速执行您的指令。.可以建立一个SOE,使用动态分段获取里程标志位置,或者实现几何网络分析(在ArcGIS 10的时候,因为工具箱中没有提供几何网络的GP,因此要实现几何网络的分析,可以通过这种办法)SOE开发需要ArcObjects、.NET或Java以及REST与SOAP等Web服务通信技术的知识。ArcObjects SDK具有多种可供
5、您进行校验的样本,即可用于Java也可用于.NET。在SOE的开发过程中,我们必须清楚,我们需要在SOE中将请求获取,然后将传入的参数转化为AO,然后通过AO处理,再将处理的结果转成json格式,传给客户端,客户端得到json格式的结果,然后解析。下图描述了请求响应的整个过程,如下图:下图描述了请求回复的整个过程,如下图:第二章 SOE使用122.1 必选接口2.1.1 IRESTRequestHandler 接口该接口主要有下面两个方法: string GetSchema(); byte HandleRESTRequest() IRESTRequestHandler.handl
6、eRESTREquest() 方法主要有下面两个作用:Ø 回调资源和操作的方法Ø 获取资源在实例级别的描述该方法在识别这两个作用的时候是通过operationName参数,如果该参数是空字符产那就是第二个作用,否则是第一个作用。该方法的参数如下: 1. String capabilities:一组被资源授权的操作,可以为空字符串 2. String resourceName: 资源名称. 空字符串表示根级别,子资源会通过/ 表示 3. String operationName: 操作名称4. String operationInput: 操作的参数,JSON格式5. Str
7、ing outputFormat:客户端请求的输出格式,如JSON,AMF 6. String responseProperties: 通过操作返回的一组键值对,逗号分开 IRESTRequestHandler.getSchema() 方法以JSON格式返回SOE的资源列表2.1.2 IServerObjectExtension该接口主要有个方法:Init(IServerObjectHelper pSOH)和void Shutdown();当Server启动的时候会调用该方法,并将IServerObjectHelper对象传入,该接口是对Server对象的弱引用,可以通过ISer
8、verObjectHelper.ServerObject得到服务器对象。Shutdown方法用在服务器关闭时调用,经常我们在该方法中释放SOE中使用的资源。2.2 可选接口2.2.1 IObjectConstruct该接口只有一个方法Construct,该方法在Init方法执行后,立即被执行,如果我们的SOE有配置属性,就可通过该方法的参数得到,该方法只调用1次,我们可以将SOE中用的的比较耗费资源的逻辑写在该方法中,比如:获取地图代码,或者你始终操作某一个图层,就可以把获取该图层的代码写在这里。2.2.2 IObjectActivate当init和Construct调用后,SOE的对象已经被
9、创建,并且相应的配置信息也得到了,如果SOE的整个逻辑中需要不停的获取和释放服务器上下文,那么就必须实现改接口,改接口有两个方法: activate()和deactivate(),当客户端调用CreateServerContext()的时候activate()方法被调用,当客户端释放服务器上下文对象时deactivate()方法被调用。SOE的执行过程在对接口介绍的时候,我们已经提到了SOE的的运行过程,我们通过下面的图可进一步了解:2.3 创建SOE现在我们创建一个完整的SOE,在VS2010中新建一个项目,选择Server Object Extention,并在右边选择REST 模板,如下
10、图:当点了确定之后,我们可以看到VS已经为我们生成了一个RestSOETest的类,该类已经实现了了我们前面介绍过的接口,如下:public class RestSOETest : IServerObjectExtension, IObjectConstruct, IRESTRequestHandler private string soe_name; private IPropertySet configProps; private IServerObjectHelper serverObjectHelper; private ServerLogger logger; private IRE
11、STRequestHandler reqHandler; public RestSOETest() soe_name = this.GetType().Name; logger = new ServerLogger(); reqHandler = new SoeRestImpl(soe_name, CreateRestSchema() as IRESTRequestHandler; #region IServerObjectExtension Members public void Init(IServerObjectHelper pSOH) serverObjectHelper = pSOH
12、; public void Shutdown() #endregion #region IObjectConstruct Members public void Construct(IPropertySet props) configProps = props; #endregion #region IRESTRequestHandler Members public string GetSchema() return reqHandler.GetSchema(); public byte HandleRESTRequest(string Capabilities, string resour
13、ceName, string operationName, string operationInput, string outputFormat, string requestProperties, out string responseProperties) return reqHandler.HandleRESTRequest(Capabilities, resourceName, operationName, operationInput, outputFormat, requestProperties, out responseProperties); 在构造函数中多了一个Server
14、Logger的对象,通过名称我们就可知道,该对象是一个日志记录对象,用该对象可以对我们的SOE进行信息记录,记录后的信息,最后可以通过Manager的日志查看。在构造函数中还调用了CreateRestSchema函数,如下: private RestResource CreateRestSchema() RestResource rootRes = new RestResource(soe_name, false, RootResHandler); RestOperation sampleOper = new RestOperation("sampleOperation",
15、 new string "parm1", "parm2" , new string "json" , SampleOperHandler); rootRes.operations.Add(sampleOper); return rootRes; 在该函数中创建了Rest资源和Rest资源的操作,并且资源和Rest操作都对应一个处理函数,我们一般称作Resthandler,这里的资源和操作可能比较抽象,我们举一个例子,比如说MapService就是一个资源,而查询就是一个操作,当我们执行操作的时候,处理整个逻辑的就是Resthandle
16、r,如上图的RootResHandler和SampleOperHandler分别是处理资源和资源操作的方法,这些handler的具体实现如下: private byte RootResHandler(NameValueCollection boundVariables, string outputFormat, string requestProperties, out string responseProperties) responseProperties = null; JsonObject result = new JsonObject(); result.AddString(&quo
17、t;hello", "world"); return Encoding.UTF8.GetBytes(result.ToJson(); private byte SampleOperHandler(NameValueCollection boundVariables, JsonObject operationInput, string outputFormat, string requestProperties, out string responseProperties) responseProperties = null; string parm1Value;
18、bool found = operationInput.TryGetString("parm1", out parm1Value); if (!found | string.IsNullOrEmpty(parm1Value) throw new ArgumentNullException("parm1"); string parm2Value; found = operationInput.TryGetString("parm2", out parm2Value); if (!found | string.IsNullOrEmpty(
19、parm2Value) throw new ArgumentNullException("parm2"); JsonObject result = new JsonObject(); result.AddString("parm1", parm1Value); result.AddString("parm2", parm2Value); return Encoding.UTF8.GetBytes(result.ToJson(); 在这里我们要注意RestOperation类,该类对应了我们SOE的一个操作,该类的参数如下:RestOp
20、eration (string name, string parameters, string supportedFormats, OperationHandler handler),这些参数分别对应了操作的名称,参数,支持的格式,以及该操作的处理函数。一个资源可以有子资源,并且一个资源可以对应多个操作,对于资源的handler我们可以不用关注,但是操作的handler是我们整个SOE的核心部分。下面是我们自定义的一个操作,其中pLineOperHandler是对应我们的handler 定义的操作: RestOperation pLineOper = new RestOperation(&qu
21、ot;pLineOperation", new string "RouteFieldName", "RouteID", "Stationfrom", "Stationto" , new string "json" , pLineOperHandler);当定义好了RestOperation之后,并且成功部署,那么可以在服务目录中看到下面的页面:我们可以看出,RestOperation类中的参数和这个对应,当我们点了GET或者POST操作之后,这个时候就执行PlineOperHandle
22、r操作,该函数的定义如下: private byte pLineOperHandler(NameValueCollection boundVariables, JsonObject operationInput, string outputFormat, string requestProperties, out string responseProperties) responseProperties = "" if (serverObjectHelper.ServerObject is IMapServer) mapServer = (IMapServer3)serve
23、rObjectHelper.ServerObject; / IMapServerObjects pMSO = serverObjectHelper.ServerObject as IMapServerObjects; IMapServerDataAccess pMapServerDataAcc = null; IFeatureClass pFeatureClass = null; if (serverObjectHelper.ServerObject is IMapServerDataAccess) pMapServerDataAcc = serverObjectHelper.ServerOb
24、ject as IMapServerDataAccess; pFeatureClass = pMapServerDataAcc.GetDataSource(mapServer.DefaultMapName, 0) as IFeatureClass; / / IMapServer.DefaultMapName / IMap map = pMSO.get_Map(mapServer.DefaultMapName); / /返回参与线性参考 / / routeFeatureLayer = (IFeatureLayer)map.get_Layer(0); / /线性参考代码 / IFeatureLay
25、er featureLayer = routeFeatureLayer; string _pPKName; operationInput.TryGetString("RouteFieldName", out _pPKName); if (_pPKName=null) throw new ArgumentNullException("StationMeasure"); long? _pID; operationInput.TryGetAsLong("RouteID", out _pID); if (_pID = null) throw
26、new ArgumentNullException("RouteID"); double ? _pFrom; operationInput.TryGetAsDouble("Stationfrom", out _pFrom); if (_pFrom = null) throw new ArgumentNullException("Stationfrom"); double? _pTo; operationInput.TryGetAsDouble("Stationto", out _pTo); if (_pTo = n
27、ull) throw new ArgumentNullException("Stationto"); IPolyline pointColl = FindRoutByMeasure(pFeatureClass, _pPKName.Substring(1, _pPKName.Length - 2), _pID.Value, _pFrom.Value, _pTo.Value); JsonObject featureJson = new JsonObject(); featureJson.AddJsonObject("geometry", Conversion
28、.ToJsonObject(pointColl as IGeometry); return Encoding.UTF8.GetBytes( featureJson.ToJson(); 在前面已经介绍过,SOE里面的很大一部分代码是和AO对象打交道,而这部分也是我们的核心功能,当我们使用Esri提供给的SOE模板之后,我们要核心要做的就是写SOE请求函数,在这个请求函数也就是handler中,我们的核心AO代码就在这里,我这个函数的核心代码如下:IPolyline FindRoutByMeasure(IFeatureClass _pRouteFC, string _pPKName, object
29、 _pID, double _pFrom, double _pTo) IDataset pDataset = (IDataset)_pRouteFC; IName pName = pDataset.FullName; IRouteLocatorName pRouteLocatorName = new RouteMeasureLocatorNameClass(); pRouteLocatorName.RouteFeatureClassName = pName; pRouteLocatorName.RouteIDFieldName = _pPKName; pRouteLocatorName.Rou
30、teMeasureUnit = esriUnits.esriFeet; pName = (IName)pRouteLocatorName; IRouteLocator2 pRouteLocator = (IRouteLocator2)pName.Open(); IRouteLocation pRouteLoc = new RouteMeasureLineLocationClass(); pRouteLoc.MeasureUnit = esriUnits.esriFeet; pRouteLoc.RouteID = _pID; IRouteMeasureLineLocation rMLineLoc
31、 = (IRouteMeasureLineLocation)pRouteLoc; rMLineLoc.FromMeasure = _pFrom; rMLineLoc.ToMeasure = _pTo; IGeometry pGeo = null; esriLocatingError locError; pRouteLocator.Locate(pRouteLoc, out pGeo, out locError); return pGeo as IPolyline; 其实如果在ArcGIS Engine中做过和线性参考相关的工作,那么这端代码是完全可以在ArcGIS Engine中使用的,所以说
32、SOE的开发并不是想象中的困难,相反如果有了AO基础的话,的确是很简单。注意:在这里我将自己遇到的问题说一下,如果在ArcGIS 10或者之前的版本中使用过SOE,那么发现下面的代码是可以运行的,而且没有问题:IMapServer mapServer = (IMapServer3)serverObjectHelper.ServerObject; IMapServerObjects3 pMSO = mapServer as IMapServerObjects3; IMap map = pMSO.get_Map(mapServer.DefaultMapName);但是在10.1的时候,这句代码是不
33、会成功的,错误的地方在IMapServerObjects3,这是因为10.1中发布的服务是使用MSD文档,而IMapServerObjects3是针对MXD文档的,因此在10.1中应避免,避免IMap,Ilayer等,那么如何访问要素类,栅格对象,表等对象呢?使用IMapServerDataAccess接口,该接口主要有两个方法,如下图:第一个方法主要获取表,要素类,栅格数据,但是在地图文档中我们有的数据是和其他数据有关联的的比如join操作,那么通过第二个方法我们不但可以获取源表的数据,还可以获取目的表的数据。2.4 部署SOE当SOE写完之后,我们通过ArcGIS Manager 进行部署
34、,在Manager中找到站点,然后找到扩展,选择添加扩展,如下图:找到我们编译后的SOE文件(.soe)结尾,如下图:部署成功之后会在Manager中看到,如下图:2.5 调试SOESOE的工程实际上是一个类库,对于类库的调试,我们必须要有入口,对于SOE的入口我们知道是ArcGIS Server,如果在10版本以及之前的版本,我们可以写一个控制台程序,然后通过DCOM方式连接,而现在不能使用DCOM方式连接,那么还有没有其他办法?办法肯定是有的,如果写这样的东西不能调试对开发者来说岂不是很痛苦?当启动ArcGIS Server的服务的时候,会在Windows的任务管理器中看到ArcSOC.e
35、xe这样的进程,这些进程对应的就是ArcGIS Server的服务,我们可以采用附加进程的方式对SOE进行调试,如下,我们找到所有的ArcSOC.exe,将这些附加到进程中:在我们的SOE工程中添加断点,如下图:这样当我们通过Rest的方式访问SOE的时候,就会进行调试,我们便可以跟踪,看哪里出现问题。下图是这个SOE运行的结果如下图:2.6 使用SOE由于这个SOE是Rest方式的,所以我们可以在Flex,Silverlight这样的客户端使用,我们只需要构造这个SOE的rest地址,然后通过WebClient对象调用(这个是Silverlight中的,Flex中可能不一样),并获取结果,详
36、细的例子可以参照Esri官网提供的例子:因为在上面的这个例子中,我将几何对象转成json格式的,但是在客户端使用的时候没有将json格式转成几何对象的API,有两种解决办法,我们在客户端获取这个json格式的字符串然后解析,自己构造这个几何对象,第二种方式,我们可以借用FeatureSet.FromJson()方法,这就要求我们在SOE中返回的是一个FeatureSet的描述,我们在代码中稍微修改下即可,如下:private byte pLineOperHandler(NameValueCollection boundVariables, JsonObject operationInput,
37、string outputFormat, string requestProperties, out string responseProperties) responseProperties = "" if (serverObjectHelper.ServerObject is IMapServer) mapServer = (IMapServer3)serverObjectHelper.ServerObject; / IMapServerObjects pMSO = serverObjectHelper.ServerObject as IMapServerObjects
38、; IMapServerDataAccess pMapServerDataAcc = null; IFeatureClass pFeatureClass = null; if (serverObjectHelper.ServerObject is IMapServerDataAccess) pMapServerDataAcc = serverObjectHelper.ServerObject as IMapServerDataAccess; pFeatureClass = pMapServerDataAcc.GetDataSource(mapServer.DefaultMapName, 0)
39、as IFeatureClass; string _pPKName; operationInput.TryGetString("RouteFieldName", out _pPKName); if (_pPKName=null) throw new ArgumentNullException("StationMeasure"); long? _pID; operationInput.TryGetAsLong("RouteID", out _pID); if (_pID = null) throw new ArgumentNullExc
40、eption("RouteID"); double ? _pFrom; operationInput.TryGetAsDouble("Stationfrom", out _pFrom); if (_pFrom = null) throw new ArgumentNullException("Stationfrom"); double? _pTo; operationInput.TryGetAsDouble("Stationto", out _pTo); if (_pTo = null) throw new Argu
41、mentNullException("Stationto"); IPolyline pointColl = FindRoutByMeasure(pFeatureClass, _pPKName.Substring(1, _pPKName.Length - 2), _pID.Value, _pFrom.Value, _pTo.Value); JsonObject featureJson = new JsonObject(); /构造FeatureSet JsonObject pRest = new JsonObject(); pRest.AddString("disp
42、layFieldName","restlt"); pRest.AddString("geometryType", "esriGeometryPolyline"); JsonObject pSpatial = new JsonObject(); /空间参考 pSpatial.AddString("wkid" ,pointColl.SpatialReference.FactoryCode.ToString(); pRest.AddJsonObject("spatialReference",
43、 pSpatial); /属性 JsonObject pAtt = new JsonObject(); pAtt.AddString("ID", "1"); /要素 featureJson.AddJsonObject("attributes", pAtt); featureJson.AddJsonObject("geometry", Conversion.ToJsonObject(pointColl as IGeometry); /要素集合 JsonObject pFea = new JsonObject1; pF
44、ea0 = featureJson; pRest.AddArray("features", pFea); return Encoding.UTF8.GetBytes(pRest.ToJson(); 我们建立一个Silverlight工程,在Silverlight中调用这个SOE,核心代码如下: string SOEurl = "50:6080/arcgis/rest/services/Routes/MapServer/exts/RestLinear/pLineOperation?RouteFieldName=%22ROUTE1
45、%22&RouteID=20000013&Stationfrom=0&Stationto=25&f=pjson" WebClient webClient = new WebClient(); FeatureSet pFeature = new FeatureSet(); webClient.OpenReadCompleted += (s, a) => JsonValue jsonResponse = JsonObject.Load(a.Result); FeatureSet pFeatureSet = FeatureSet.FromJson(js
46、onResponse.ToString(); if (pFeatureSet.Features != null) SimpleLineSymbol symbol = new SimpleLineSymbol(); symbol.Color = new SolidColorBrush(Colors.Red); GraphicsLayer gLayer = new GraphicsLayer(); foreach (Graphic g in pFeatureSet.Features) g.Symbol = symbol; gLayer.Graphics.Add(g); myMap.Layers.A
47、dd(gLayer); ; webClient.OpenReadAsync(new Uri(SOEurl); 运行结果如下图(红色部分为SOE返回的结果):第三章 SOE 在Java下的开发ArcGIS 不仅仅支持在.NET下的开发(因为我习惯NET,所以上面的例子是用C#开发的),对于Java也是支持的,最近在帮同事升级一个用Java写的SOE,借此机会研究了下在Java下如何开发SOE.Esri同样为Java开发者提供了SOE的开发模板,开发者利用这些模板会很快的创建一个SOE的雏形。1233.1 新建SOE模板工程 在eclipse新建项目,找到Server Object Extention(在这里省略了如何安装Java版本的SDK和如何在eclipse中配置ArcGIS的模板,这些不是这篇关注的内容,还不太熟悉的人员,可以查阅相关资料,或者在博客:3.2 填写SOE的名称,显示名称以及描述等信息3.3 选择SOE的类型选择SOE类型(REST或者SOAP,我选择的是REST),并填设置操作资源和
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 项目风险评估中的定量与定性方法试题及答案
- 2025年初期大学英语四六级考试试题
- 沈阳中考生地试题及答案
- 华三java面试题及答案
- 御泥坊java面试题及答案
- 逐步深入的网络题库试题及答案
- 软考网络工程师优势特长试题及答案
- 深入了解信息系统项目管理试题
- 变革2025年西方政治制度试题及答案
- 政治身份与社会结构的互动研究试题及答案
- 理论联系实际谈一谈如何维护政治安全?参考答案1
- 2025届安徽省合肥市A10联盟高三下学期最后一卷历史试题(B卷)
- 2024吉林省农村信用社联合社招聘笔试历年典型考题及考点剖析附带答案详解
- 2024-2025学年度部编版一年级语文下学期期末试卷(含答案)
- DB13(J)-T 8496-2022 城市污水处理厂提标改造技术标准
- 2025至2030中国锂电池粘结剂市场竞争状况及融资并购研究报告
- 聋校语文课程标准解读
- 河南省百师联盟2024-2025学年高二下学期4月联考数学试题(原卷版+解析版)
- 2025-2030中国IDC行业发展趋势与前景展望战略研究报告
- 合伙人商业保密协议书9篇
- 工程保修的管理措施和承诺
评论
0/150
提交评论