话说现在做GIS项目用SuperMap iServer的逐渐增多,而SuperMap iServer具备“服务聚合”的能力,这对于我们的实际应用带来了新的价值,所以有必要研究研究。其实用过ArcGIS Server的朋友或许对于数据/服务熔合有些印象,就是将不同来源的数据/服务mashup在一起来显示,不过现在由于一些大型系统的建设来说,通常是两级/三级部署应用,如图。
那么在这样的部署下,上级系统需要发布全局性信息,并且能够保持与下级系统之间的信息共享与交互;下级系统则维护自身的数据和系统,并且开展本地有特色的系统应用。
说到数据共享和互操作,就引到本文的话题了,也就是利用服务接口实现数据共享,功能共享。
文中中记录了作者采用SuperMap iServer Java SDK尝试数据与功能聚合的一些内容,供大家参考。
1、数据共享
通常我们考虑的是用OGC服务来做,而且现在GIS的客户端都提供了这种能力,也就是在客户端实现数据mashup,这不是本文的重点,不过贴一段我用SuperMap iServer Java JS接口中的TiledMapLayer做的数据共享,至于原因,主要是因为这样共享的数据是已经经过配置的地图,相对WMS SLD来说容易上手些。
SuperMap.TiledMapLayer
1
var
mapControl;
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代码是开源的,那么我就改点代码)。
首先看看调用查询功能,这个功能主要是为了实现在两地地图服务聚合后,本系统查询聚合地图源数据的内容。为什么搞的这么麻烦呢?因为本系统的数据服务中没有你想查询的数据内容,只能向聚合过来的源系统发送查询请求来实现,请看代码:
聚合后SQL查询聚合数据
1
function
sqlqueryTiledMapLayer(){
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服务地址,可是我们要查询的数据是来自于聚合服务的系统,因此这里写点代码,让请求能够发向上面代码中设置的地址去:
SuperMap.Map.js
1
_queryBase:
function
(methodName, paramNames, paramValues, onComplete, onError, userContext){
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,查询的请求发送到了该发送的地址了。
下面看看编辑功能,思路上和查询的实现过程差不多,直接看代码:
聚合后编辑聚合数据
1
function
addEntityTiledMapLayer(){
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 ,这里以增加地物为例
代码
SuperMap.UI.AddEntityAction
=
function
(layerName, layerType, needHighlight, onComplete, onError, customParam){
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);
......
......
};
SuperMap.Map.js
_editBase:
function
(mapName, methodName, paramNames, paramValues, onComplete, onError, userContext){
......
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做的一些服务聚合,功能共享的工作,供参考。