ArcGIS Server Java ADF 案例教程.docx

上传人:b****8 文档编号:9614106 上传时间:2023-02-05 格式:DOCX 页数:14 大小:187.25KB
下载 相关 举报
ArcGIS Server Java ADF 案例教程.docx_第1页
第1页 / 共14页
ArcGIS Server Java ADF 案例教程.docx_第2页
第2页 / 共14页
ArcGIS Server Java ADF 案例教程.docx_第3页
第3页 / 共14页
ArcGIS Server Java ADF 案例教程.docx_第4页
第4页 / 共14页
ArcGIS Server Java ADF 案例教程.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

ArcGIS Server Java ADF 案例教程.docx

《ArcGIS Server Java ADF 案例教程.docx》由会员分享,可在线阅读,更多相关《ArcGIS Server Java ADF 案例教程.docx(14页珍藏版)》请在冰豆网上搜索。

ArcGIS Server Java ADF 案例教程.docx

ArcGISServerJavaADF案例教程

 

第一章有关WebService

在IDE的菜单中,你会看到有个很长的【ArcGISWebServicesProject】,别高兴,这不是给你自定义WebService的,运行完向导你会发现生成的是一个Java桌面程序——有着一如既往丑陋的界面和很不友好的GIS功能。

原来我一直当它是废物,不过前段时间它还真的帮了我大忙。

我们有个测试需要测ArcGISServer对WebService的支持,要求必须抓取到浏览器与服务器交互的可读的SOAP消息;但是你要知道,考虑到效率ArcGISServer内部都是用二进制的SOAP进行交互;要抓到可读的SOAP消息,ArcGIS的WebService包必须被部署到浏览器端——最后,就是靠这个丑陋的“ArcGISWebServicesProject”,做了很多修改封装成了Applet才达到了这个要求。

扯远了,说了这么多其实只为了说明这样一点:

“ArcGISWebServicesProject”是一个使用ArcGIS的WebService类库实现一些GIS功能的Java桌面程序,演示意义大于应用意义。

下面我们首先来讨论一下如何使用SOAPSDK来访问ArcGISServer原生的WebService;然后再谈谈怎么自定义WebService,以便其它业务系统调用或出于其它目的的SOAP访问。

一通过SOAPSDK访问ArcGISWebService

这里我们通过一个简单的功能来演示如何使用SOAPSDK来访问ArcGISServer,调用一个MapService的功能。

不管你是在Java桌面、Applet、ADF还是自定义的servlet中,如果你需要直接使用SOAP和ArcGIS交互,那么下面的这段内容对你可能会有帮助。

这个简单的功能是“计算当前范围内的要素个数“,这个功能是如此的简单以至于我觉得看一下代码就可以明白了:

MapServerBindingStubmapserver=newMapServerBindingStub(url);

SpatialFilterfilter= new SpatialFilter();

filter.setFilterGeometry(mapDescription.getMapArea().getExtent());

filter.setSpatialRel(EsriSpatialRelEnum.esriSpatialRelIntersects);

filter.setGeometryFieldName("SHAPE");

filter.setSubFields("*");

filter.setSearchOrder(EsriSearchOrder.esriSearchOrderSpatial);

filter.setWhereClause("");

filter.setSpatialReferenceFieldName("");

filter.setSpatialRelDescription("");

int count=mapserver.queryFeatureCount(“Layers”,0,(QueryFilter)filter);

JOptionPane.showMessageDialog(this,"Featurecount="+count);

上面涉及到的各个ArcGIS的功能类都在com.esri.arcgisws包下,从命名上就可以看出这是专门为WebService准备的。

代码里用到的url是地图服务的地址,比如“http:

//host:

8399/arcgis/services/name/MapServer“。

在整个环节中你可能会对MapServerBindingStub的queryFeatureCount方法有一点兴趣,其实你打开ArcGIS帮助里的SOAPSDK,找到MapServices下面的QueryFeatureCount方法就可以看到,QueryFeatureCount需要3个参数,分别对应DataFrame名称、图层序号和QueryFilter,正与上面的代码相符。

换句话说,com.esri.arcgisws包里的功能类就是SOAPSDK的Java实现。

可是,不管是ADF还是RESTSDK都提供了比SOAPSDK好用多的调用ArcGISServer功能的方法,所以想来你会和我一样,对上面的这些内容兴趣寥寥——我觉得ESRI对SOAPSDK也是兴趣寥寥,以至于在SOAPSDK的文档里几乎都没有Java的示例代码。

好了,让我们抛开ArcGIS提供的WebService,来看看怎么自定义WebService吧。

我个人觉得自定义的WebService是更加有用的,而且,功能也可以做得更强大。

二 两种方式自定义WebService

在IDE里创建一个WebService工程是很容易的,只要找到【File】-【New】-【WebService】菜单就可以了,点击这个菜单将会弹出下面的对话框:

这里的Webservicetype有两种选择:

一种是Bottomup、另外一种是Topdown。

这两种方式分别对应了自下而上和自上而下两种新建WebService的模式。

如果你已经有了实现的功能类,现在想要把它封装成WebService,那么你应当选择Bottomup模式;如果你首先定义了WebService的描述文件(wsdl),现在想要实现这个wsdl的功能,那么你应当选择Topdown模式。

三 实现WebService的功能

不管通过Bottomup还是Topdown方式,当你把WebService的框架搭起来以后,剩下的工作就是如何去实现WebService的功能了。

下面让我们通过讲解一个网络分析WebService的实现,来了解自定义WebService的运作。

这个网络分析的WebService需要的功能是预先定义好的,其中有比如上下游追溯、连通性分析等等,这里只挑连通性分析这个小功能进行说明。

首先,我们通过给定的wsdl新建了一个WebService工程,然后找到实现类,在这个类中已经根据wsdl自动生成了对应各个功能的方法,这里就连通性分析功能进行讲解,对应的方法是connectivity,下面是这个方法的实现:

public class TestGISAnalysisSoapBindingImpl implements TestGISAnalysisPortType

{

private GeoNetworkAnalysisgeoNetAnalysis;

public TestGISAnalysisSoapBindingImpl()

{

geoNetAnalysis= new GeoNetworkAnalysis();

}

public java.lang.Stringconnectivity(StringsourceDeviceType

StringsourceDeviceID

StringtargetDeviceType

StringtargetDeviceID,

Stringtype) throws java.rmi.RemoteException

{

Stringresult="";

try

{

result=geoNetAnalysis.findPath(Integer.parseInt(sourceDeviceType)

Integer.parseInt(sourceDeviceID)

Integer.parseInt(targetDeviceType)

Integer.parseInt(targetDeviceID)

type);

}

catch (Exceptionex)

{

ex.printStackTrace();

}

return result;

}

}

怎么这么简单?

当然,因为这里对功能做了封装,真正的分析功能在geoNetAnalysis这个对象中,在这个对象中进行的都是直接对AO的操作,我们通过一些代码片段来看一下这个功能的实现:

public class GeoNetworkAnalysis

{

public GeoNetworkAnalysis()

{

try {

EngineInitializer.initializeEngine();

new AoInitialize().initialize(esriLicenseProductCode.esriLicenseProductCodeArcInfo);

ResourceBundlebundle=ResourceBundle.getBundle("geometrynetwork");

traceFlowSolver= new TraceFlowSolver();

INetSolvernetSolver=(INetSolver)traceFlowSolver;

geometricNetwork=openNetwork(bundle.getString("workspacePath"),

bundle.getString("datasetName"),bundle.getString("networkName"));

pNetElements= new INetElementsProxy(geometricNetwork.getNetwork());

netSolver.setSourceNetworkByRef(geometricNetwork.getNetwork());

...

}

catch (Exceptione)

{

e.printStackTrace();

}

}

/**

*连通性分析

*

* @param sourceLyrID

*起点的图层ID

* @param sourceFeatID

*起点的要素ID

* @param targetLyrID

*终点的图层ID

* @param targetFeatID

*终点的要素ID

* @param type

* @return

*/

public StringfindPath(int sourceLyrID

 int sourceFeatID

 int targetLyrID

 int targetFeatID

Stringtype) throws Exception

{

this.putTraceOrigins(getOriginPoints(sourceLyrID

sourceFeatID

targetLyrID

targetFeatID));

IEnumNetEID[]junctionEIDS= new IEnumNetEID[1];

IEnumNetEID[]edgeEIDs= new IEnumNetEID[1];

Object[][]costArray= new Object[1][1];

traceFlowSolver.findPath(esriFlowMethod.esriFMConnected,

esriShortestPathObjFn.esriSPObjFnMinSum

junctionEIDS

edgeEIDs

1

costArray);

...

Setjunctions= this.getSolverResultFeature(junctionEIDS[0]);

Setedges= this.getSolverResultFeature(edgeEIDs[0]);

return FeatureUworkResultToJSON(junctions,edges);

}

}

注意,上面只是代码片段,整个功能的实现代码太长了,和我们要了解的WebService其实又没有什么关系,所以,就看个大概吧。

做完这些,在很多场合都可以调用这个自定义的WebService了,比如上面这个功能我们是在Flex中调用的:

Script>

[CDATA[

privatefunctionanalysisConnectivity():

void

{

opt=wsAnalysis.getOperation("connectivity");

args=newObject();

args.sourceDeviceType=g1.attributes.layerId;

args.sourceDeviceID=g1.attributes.OBJECTID;

args.targetDeviceType=g2.attributes.layerId;

args.targetDeviceID=g2.attributes.OBJECTID;

args.type="connectivity";

opt.arguments=args;

opt.send();

}

]]>

Script>

WebServiceid="wsAnalysis"wsdl="http:

//localhost:

8080/WebServiceProject/wsdl/TestGISAnalysisHttpSoapEndpoint.wsdl"

showBusyCursor="true"

concurrency="last"

result="onWsAnalysisResult(event)"

fault="onWsAnalysisFault(event)"/>

试想一下,是不是不同的业务系统之间交互也可以做了呢?

第一章扩展ArcGISServer

这一章其实和ADF已经没有太大关系了,在ArcGIS的帮助里也是在ArcGISServer开发章节里。

考虑到使用ADF开发的一般对功能要求比较多一点,所以对于怎么扩展ArcGISServer可能比较关心,反正ADF差不多也讲完了,这一章就算是一个结束吧。

从9.3.1开始,ArcGISServer提供了Java开发者更多的可扩展性。

通过扩展ArcGISServer可以使某些自定义的功能更加完善和强大、使你的某些工作可以更加模块化并和ArcGISServer很好地结合在一起。

下面让我们来看看ArcGISServer可以通过什么样的途径进行扩展。

一UtilityObjects

UtilityObjects主要是为了提升ArcGISServer在Local方式连接下某些操作的性能而准备的。

在此之前,让我们首先去了解一些ADF调用服务器端AO对象的过程和特点。

图 29ADF调用服务器端对象的过程

如图29所示,当用户发生请求的时候,ADF首先会和SOM交互(图中1);SOM将根据服务器情况分配一个SO用以处理这个用户的请求,同时返回这个SO的代理(proxy)给ADF(图中2);然后,ADF就会通过这个代理和服务器的SO进行交互(图中3,注意,这是ADF应用和GIS服务器之间的交互,是跨进程的);当请求完成后,ADF释放相应的资源供其它用户使用(图中4)。

跨进程的调用会消耗比较多的系统资源,响应速度较慢;当ADF应用和GIS服务器分开部署的时候,还有相应的网络开销。

因此,当你的ADF应用中有大量细粒度操作,频繁地对服务器端AO对象进行调用的时候,性能会非常低下。

UtilityObjects就是为了解决这个问题而诞生的。

UtilityObjects的原理就是把上述分别属于ADF和GIS服务器两个进程中的操作合并到一起,都放到ArcGISServer中执行,这样可以极大地减小进程间通讯的开销。

在实现上UtilityObjects也并不复杂,你只需要把原来直接在ADF中实现的功能,封装到一个实现了自定义接口的类中,然后在ADF中调用这个自定义的功能类就可以了。

下面让我们看一下这个大体的流程,在ArcGISServer帮助中有这样一个例子:

把计算一个FeatureLayer中所有多边形面积总和的功能封装成一个UtilityObject。

首先,我们需要定义一个接口ICalculateArea,并使用CalcAreaUtil类来实现这个接口,注意,UtilityObject的接口和类都需要使用“@ArcGISExtension”注记来声明:

@ArcGISExtension

public interface ICalculateArea

{

public double calculateArea(IFeatureLayerfeatureLayer)

throws IOException,AutomationException;

}

@ArcGISExtension

public class CalcAreaUtil implements ICalculateArea

{

public double calculateArea(IFeatureLayerfeatureLayer)

{

double totalArea=0;

IFeatureClassfeatureClass=featureLayer.getFeatureClass();

int numFeatures=featureClass.featureCount(null);

IFeatureCursorfeatureCursor=featureLayer.search(null, true);

IFeaturefeature= null;

Polygonpolygon= null;

for (int i=0;i

{

feature=featureCursor.nextFeature();

polygon=(Polygon)feature.getShape();

totalArea+=polygon.getArea();

}

return totalArea;

}

}

有两种方法可以部署这个UtilityObject,当然,作为一个懒人我比较倾向于选择相对简单、绿色的方法:

将上面实现的这个类编译成jar包,再将这个jar包复制到服务器上的%ARCGISHOME%/java/lib/ext目录下。

另外一种复杂一些,而且让我觉得有点脏兮兮的方法,有兴趣的可以到帮助文档中寻觅一下。

好,下面我们就可以使用这个UtilityObject了:

IFeatureLayerfeatureLayer=mapServer.getLayer("",2);

ICalculateAreacalArea=(ICalculateArea)

com.esri.arcgis.server.ServerContext.createObject(CalcAreaUtil.class);

double totalArea=calArea.calculateArea(featureLayer);

在这段代码中我们看到,调用“计算一个FeatureLayer中多边形总面积”的功能全部由一个GIS服务器端的CalcAreaUtil类实现,ADF中只需要使用IServerContext来实例化这个类,再调用它相应的方法即可。

二 使用UtilityObjects提高查询性能【案例】

这是我的同事使用UtilityObjects解决某个用户的一个实际问题。

这个用户通过调用AO进行空间查询,然后在此基础上进行分页,分页的时候遍历该页所有的IFeature,提取属性信息,构造成自己的结果返回——结果,遇到了严重的性能问题,在上万条记录中查询一般两三分钟才可以出结果,这在一个国家级项目中是难以忍受的。

经过添加日志分析,发现AO查询的速度非常快,问题就是出在遍历IFeature这个操作上,是不停地进行跨进程调用产生的。

就在这个时候9.3.1正式发布了,UtilityObjects有如救星般地降临了!

由于在上一小节关于怎么定义UtilityObject已经讲得比较清楚,这里就不在啰嗦怎么封装接口和实现类了。

下面是封装起来的功能代码,主要就是遍历分页要素并提取有用的信息,当然,原先这部分代码是在Web层执行的。

IFeaturefeature=featureCursor.nextFeature();

int featureCount=0;

while (feature!

= null)

{

if (featureCount>=first+pageSize)

{

break;

}

if (featureCount>=first)

{

result.add(ServiceUtil.feature2Einfo(feature));

}

featureCount++;

feature=featureCursor.nextFeature();

}

经过这样的处理,性能有了极大的提升,一个简单的测试可以说明情况:

这里做了一个半径1000公里的空间查询,返回结果总数为30437条。

分页起始记录

分页记录数

优化前(s)

优化后(s)

0

500

179.406

5.203

如果你有细粒度的操作,又遇到了性能问题,现在是不是很心动?

一ServerObjectExtensions

ServerObjectExtensions(以下简称SOE)是ServerObject的扩展,比如MapServer、GPServer等等。

和UtilityObjects不同,SOE只在ServerObject被创建的时候被初始化,它的生命周期和ServerObject是相同的。

相比UtilityObjects,SOE有以下的一些特点:

Ø开发人员不需要手动实例化SOE,SOE是在ServerObject被创建的同时被实例化的

ØArcGISServer的管理程序可以显示SOE的参数配置

ØSOE的运行信息将被记录到ArcGISServer的日志中去

ØSOE的功能可以通过SOAP访问

更直观一点,让我们看一下下面这张截图,这是一个添加了一个自定义SOE的MapService管理界面:

图30添加了SOE的MapService

是不是可以把SOE理解成一个服务的自定义Capability?

似乎ESRI就是这样理解的。

那下面我们就通过自定义一个新的Capability来看看SOE的用法。

二创建一个自定义的ServerObjectExtension【案例】

首先,我们使用IDE插件来帮助我们新建这个SOE,打开菜单的【File】-【New】-【ServerObjectExtension】打开新建窗口,如图31;然后在如图32的属性页中做些自定义的编辑,ArcGIS插件会自动新建一些类和配置文件。

图 31新建SOE窗口

图 32编辑一些SOE的属性

好,现在虽然我们没有添加什么实质的功能代码,但是SOE的框架已经起来了,让我们尝试部署这个SOE到ArcGISSer

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1