话说现在做GIS项目用SuperMap iServer的逐渐增多,而SuperMap iServer具备“服务聚合”的能力,这对于我们的实际应用带来了新的价值,所以有必要研究研究。其实用过ArcGIS Server的朋友或许对于数据/服务熔合有些印象,就是将不同来源的数据/服务mashup在一起来显示,不过现在由于一些大型系统的建设来说,通常是两级/三级部署应用,如图。
那么在这样的部署下,上级系统需要发布全局性信息,并且能够保持与下级系统之间的信息共享与交互;下级系统则维护自身的数据和系统,并且开展本地有特色的系统应用。
说到数据共享和互操作,就引到本文的话题了,也就是利用服务接口实现数据共享,功能共享。
文中中记录了作者采用SuperMap iServer Java SDK尝试数据与功能聚合的一些内容,供大家参考。
1、数据共享
通常我们考虑的是用OGC服务来做,而且现在GIS的客户端都提供了这种能力,也就是在客户端实现数据mashup,这不是本文的重点,不过贴一段我用SuperMap iServer Java JS接口中的TiledMapLayer做的数据共享,至于原因,主要是因为这样共享的数据是已经经过配置的地图,相对WMS SLD来说容易上手些。
2 var params = new Object();
3 function onPageLoad(){
4 SuperMap.Resource.ins = new SuperMap.Resource();
5 SuperMap.Resource.ins.setLanguage("Chinese");
6 var contextPath = "http://localhost:7080/test/";
7 SuperMap.Committer.handler = contextPath + "commonhandler";
8
9 params.contextPath = contextPath;
10 params.mapHandler = params.contextPath + "maphandler";
11
12 params.mapName = "World";
13 params.mapServicesAddress = "localhost";
14 params.mapServicesPort = 8600;
15 params.imageFormat = "png";
16 params.buffer=1;
17
18 mapControl = new SuperMap.UI.MapControl(document.getElementById("mapcontrol1Div"));
19 mapControl.set_params(params);
20
21 mapControl.initialize();
22 }
23 function addTiledMapLayer(){
24 var tiledMapLayerParam = new Object();
25 tiledMapLayerParam.mapHandler = "http://192.168.44.125:7080/demo/maphandler";
26 tiledMapLayerParam.mapName = "World";
27 var map = mapControl.getMap();
28 var tiledMapLayer = new SuperMap.TiledMapLayer(null, tiledMapLayerParam, map);
29 tiledMapLayer.set_id("tiledMapLayer");
30 tiledMapLayer.opacity = 50;
31 map.addLayer(tiledMapLayer);
32 mapControl.refreshMapControl();
33 }
34 function removeTiledMapLayer(layerName){
35 var map = mapControl.getMap();
36 if(layerName && layerName.trim()!=""){
37 var layerID = layerName ;
38 var containerID = mapControl.get_mapDiv().id + "_" + layerID +"_Div";
39 if(mapControl.get_mapDiv()){
40 var layerContainer = document.getElementById(containerID);
41 if(layerContainer){
42 mapControl.get_mapDiv().removeChild(layerContainer);
43 }
44 }
45 if(map.get_imageLayers()){
46 var length = map.get_imageLayers().length;
47 for(var i = length - 1 ; i >= 0 ; i-- ) {
48 var layer = map.get_imageLayers()[i];
49 if(layer.get_id() && layer.get_id() == layerID){
50 map.get_imageLayers().splice(i,1);
51 }
52 }
53 }
54 }
55 };
2、功能共享
现在做功能层面的共享,可以考虑用XML WebService来做,不过如果是多级部署都采用一个GIS平台,又希望GIS系统之间实现功能共享的话,建议使用其提供的原生服务来实现功能共享,因为这样的效率会高很多。
用SuperMap iServer Java的SDK来实现各地GIS系统之间的功能,还需要改点SDK的源代码(其js SDK代码是开源的,那么我就改点代码)。
首先看看调用查询功能,这个功能主要是为了实现在两地地图服务聚合后,本系统查询聚合地图源数据的内容。为什么搞的这么麻烦呢?因为本系统的数据服务中没有你想查询的数据内容,只能向聚合过来的源系统发送查询请求来实现,请看代码:
2 var queryParam = new SuperMap.QueryParam();
3 queryParam.expectCount = 100;
4 layerParam = new SuperMap.QueryLayerParam();
5 layerParam.name = "World@world";
6 layerParam.sqlParam = new SuperMap.SqlParam();
7 layerParam.sqlParam.whereClause = "";
8 queryParam.queryLayerParams = new Array();
9 queryParam.queryLayerParams.push(layerParam);
10 //queryParam.customParams用来传递一些聚合服务的源Url和地图名称,从而帮助Ajax请求向源系统发送
11 queryParam.customParams = new Array();
12 queryParam.customParams.push("TiledMapLayer");
13 queryParam.customParams.push("World");
14 queryParam.customParams.push("http://192.168.44.125:7080/demo/commonhandler");
15 var needHighlight = true;
16 var map = mapControl.getMap();
17 map.queryBySql(queryParam, needHighlight, onQueryComplete, onError);
18 }
19 function onQueryComplete(resultSets){
20 alert(resultSets.totalCount);
21 }
22 function onError(msg){
23 alert(msg);
24 }
有了这些还不够,上面的代码只是系统功能,下面还需要改改SuperMap.Map.js中_queryBase内容,因为_queryBase是直接用于向后台提交请求的接口,而源代码中_queryBase提交请求的地址都是本地系统的iServer服务地址,可是我们要查询的数据是来自于聚合服务的系统,因此这里写点代码,让请求能够发向上面代码中设置的地址去:
2 ......
3 ......
4 onCompleteArray.push(onQueryComplete);
5 ///////////////////////////////////////////////////////////////////
6 ///////////////////////////////////////////////////////////////////
7 var tiledMapName;
8 var tiledUrl;
9 if(paramValues[0].customParams != null && paramValues[0].customParams.length > 0){
10 var customParams = paramValues[0].customParams;
11 if(customParams[0] == "TiledMapLayer"){
12 tiledMapName = customParams[1];
13 tiledUrl = customParams[2];
14 SuperMap.Committer.commitAjax(tiledMapName, tiledUrl, methodName, paramNames, paramValues, false, onCompleteArray, onError, userContext);
15 }else{
16 SuperMap.Committer.commitAjax(this._params.mapName, this.queryUrl, methodName, paramNames, paramValues, false, onCompleteArray, onError, userContext);
17 }
18 }
19 ///////////////////////////////////////////////////////////////////
20 ///////////////////////////////////////////////////////////////////
ok,查询的请求发送到了该发送的地址了。
下面看看编辑功能,思路上和查询的实现过程差不多,直接看代码:
2 var layername = "World@world";
3 var layertype = 5;
4 var needHighlight = true;
5 var customParam = new Array();
6 customParam.push("TiledMapLayer");
7 customParam.push("World");
8 customParam.push("http://192.168.44.125:7080/demo/commonhandler");
9 var addEntityAction = new SuperMap.UI.AddEntityAction(layername, layertype, needHighlight, onAddEntityComplete, onError, customParam);
10 mapControl.set_action(addEntityAction);
11 }
12 function onAddEntityComplete(editResult){
13 if(editResult.succeed) alert("succeed");
14 else alert("failed");
15 }
然后修改两个文件,其中一个是SuperMap.UI.Action.js,另一个还是SuperMap.Map.js ,这里以增加地物为例
this._customParam = customParam;
......
......
SuperMap.UI.AddEntityAction.prototype={
......
......
_onAddEntityComplete:function(editResult){
......
......
onClick:function(e){
......
......
this._mapControl.getMap().addEntity(this._layerName, entity, this._needHighlight, onAddEntityCompleteDelegate, this._onError, this._customParam);
......
......
onDblClick:function(e){
......
......
this._mapControl.getMap().addEntity(this._layerName, entity, this._needHighlight, onAddEntityCompleteDelegate, this._onError, this._customParam);
......
......
this._mapControl.getMap()._t = new Date().getTime();
this._mapControl.getMap().addEntity(this._layerName, entity, this._needHighlight, onAddEntityCompleteDelegate, this._onError, this._customParam);
......
......
};
......
var lockID = new Date().getTime().toString() + Math.floor(Math.random( )*1000000000);
paramNames.push("lockID");
paramValues.push(lockID);
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
var tiledMapName;
var tiledUrl;
if(paramValues[3] != null && paramValues[3].length > 0){
var customParam = paramValues[3];
if(customParam[0] == "TiledMapLayer"){
tiledMapName = customParam[1];
tiledUrl = customParam[2];
SuperMap.Committer.commitAjax(tiledMapName, tiledUrl, methodName, paramNames, paramValues, false, onCompleteArray, onError, userContext);
}else{
SuperMap.Committer.commitAjax(mapName, this.queryUrl, methodName, paramNames, paramValues, false, onCompleteArray, onError, userContext);
}
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
ok,这样编辑功能也完成了。
3、其他说明
(1)功能聚合可以做到查询系列、编辑系统和专题图系列,这里没有列出专题图,因为我也没有考虑好究竟怎样实现比较理想;
(2)关于功能共享(数据互操作)的安全性,这是系统建设必须要考虑的,上面实现的代码没有包含权限管理的内容,建议采用SuperMap提供的扩展Map机制,使用Session来进行权限管理。
(3)文中的代码没有详细的注释,也没有仔细整理过,是直接贴上来的,可能存在漏洞,请谅解。
以上就是利用SuperMap iServer Java 2.0 JS SDK做的一些服务聚合,功能共享的工作,供参考。