作者:MR.
之前的博客经常提到REST API,那么这次就介绍一下iServer REST API。
iServer REST API就是iServer对外提供的REST架构web服务,可以用来做很多很多事情。举个简单的例子,iServer的管理页面以及所有iClient都是在REST API的基础上开发出来的。可以说,REST API=iServer。
以JavaScript为例,可以使用AJAX的方式发送请求、接收iServer响应。
iServer REST API分为services资源和managerRoot资源,前者的代表应用就是各种语言版本的iClient,后者则是iServer管理页面,即http://<server>:<port>/iserver
。
本次介绍通过iServer REST API managerRoot资源创建iServer切图任务及瓦片更新任务(JavaScript,附示例1、iServer在线帮助地址、下载地址)。
###一、准备
由于是managerRoot资源,几乎所有操作都需要身份验证,否则没有权限对iServer系统资源进行管理。managerRoot资源使用token进行身份验证,token有四种模式,如下:
- HTTP Referer:指定使用令牌的客户端地址,即访问 GIS 服务的客户端的页面 URL。此方式可绑定访问服务的 URL,使用其他 URL 访问 GIS 服务时,即使携带了 Token 也会被服务端拒绝。此方式适用于通过 iClient(如 SuperMap iClient for JavaScript)或基于 REST 的其他应用程序来构建 Web Application 的情况。
- 客户端 IP:指定使用 Token 的 IP 地址。此方式绑定了访问 GIS 服务的 IP 地址,使用其他 IP 地址访问 GIS服务时,即使携带了 Token 也会被服务端拒绝。
- 当前请求的 IP:指定当前发送请求的 IP 地址为使用 Token 的 IP 地址。此方式限定了只有申请 Token 的 IP 才可以使用Token。
- NONE:对令牌的使用不做限制。
详见iServer帮助文档,另外,Token是有期限的,并且可以通过REST API来生成,这里不再详述,直接通过iServer管理页面生成Token:
###二、创建MongoDB切图任务
相同地图名重复创建切图任务,MongoDB缓存会记录版本信息,可选创建新版本、追加到已有版本(UGC5.0缓存直接覆盖原切片),地图名相同、地图内容不同(包括原地图数据有改动),则地图的哈希码也不同,MongDB缓存会创建新的切片集(UGC5.0缓存会在地图名文件夹生成新的文件夹名为地图哈希码的文件夹)。
本文示例使用创建新版本方式。
iServer管理页面:
REST API实现:
//host: http://<server>:<port>, token:iServer身份令牌
var commit=getcommit();
var uri=host+"/iserver/manager/tileservice/jobs.rjson?token="+token;
commit.open("post",encodeURI(uri),false,"","");
commit.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
commit.send(toJSON(requestbody));// toJSON:对象转JSON字符串
请求体requestbody
是关键,先来看看iServer帮助文档的说明:
名称 | 类型 | 含义 |
---|---|---|
dataConnectionString | String | 待切图数据的连接信息,支持直接传入服务组件名,如"map-china400"。 |
mapName | String | 待切图的地图名称。 |
tileSize | TileSize | 缓存图片大小,默认为“SIZE_256”。 |
format | OutputFormat | 缓存图片格式,如“PNG”。 |
transparent | boolean | 图片是否透明,默认为 false。 |
scaleDenominators | double[] | 切图比例尺分母集合,如 [“1000000”, “2000000”]。 |
originalPoint | Point2D | 切图索引的起始,计算瓦片行列号的起始坐标点,默认为地图左上角。 |
epsgCode | int | 切图的坐标系,不指定时默认使用原地图的坐标系。 |
cacheBounds | Rectangle2D | 缓存切图范围,如[0,0,180,90],可以不指定,默认为地图全幅范围。 |
storageID | String | 存储配置的 ID。 |
storeConfig | TileSourceInfo | 瓦片存储配置。 |
createNewTileVersion | boolean | 是否新建切片版本。 |
parentTileVersion | String | 待新建切片版本的父版本,null 表示基于最后一个更新版本进行新建版本。 |
tileType | tileType | 切片类型。 |
utfGridParameter | UTFGridJobParameter | 属性切片配置参数。当切片类型为 UTFGrid 时,该参数才生效。 |
vectorParameter | VectorJobParameter | 矢量切片配置参数。当切片类型为 Vector 时,该参数才生效。 |
示例:
var requestbody={};
requestbody.dataConnectionString="map-world";//待切图数据的连接信息,支持直接传入服务组件名
requestbody.mapName="世界地图_Night";//待切图的地图名称
// requestbody.tileSize="SIZE_256";//缓存图片大小,默认为“SIZE_256”。
requestbody.format="JPG_PNG";//缓存图片格式,如“PNG”。
requestbody.convertToPng8=true;//PNG格式尝试转PNG8
requestbody.transparent=true;//图片是否透明,默认为 false。
requestbody.scaleDenominators=[590000000,295000000,147500000,73750000];//切图比例尺分母集合,如 ["1000000", "2000000"]。
// requestbody.originalPoint="";//切图索引的起始,计算瓦片行列号的起始坐标点,默认为地图左上角。
//requestbody.epsgCode=-1;//切图的坐标系,不指定时默认使用原地图的坐标系。
// requestbody.cacheBounds="";//缓存切图范围,如[0,0,180,90],可以不指定,默认为地图全幅范围。
requestbody.storageID="localM1";//存储配置的 ID。
requestbody.storeConfig={
database:"M1",
username:"",
password:"",
type:"MongoDB",
serverAdresses:["192.168.15.25:27017"]
};//瓦片存储配置。可以从REST API获取存储库信息拿到
//requestbody.tileVersionDescription="V1";//表示追加到V1版本
requestbody.createNewTileVersion=true;//是否新建切片版本。
requestbody.parentTileVersion=null;//待新建切片版本的父版本,null 表示基于最后一个更新版本进行新建版本。
requestbody.tileType="Image";//切片类型。
其中很多参数都可以通过REST API获取并设置,使用比较灵活。
iServer响应结构:
字段 | 类型 | 含义 |
---|---|---|
succeed | String | 切图是否成功。 |
newResourceID | String | 创建的切图任务资源的 ID。 |
customResult | TileJob | 创建的切图任务资源的相关信息。 |
newResourceLocation | String | 创建的切图任务资源地址。 |
postResultType | enum | POST 请求的结果类型。"CreateChild"类型指的是创建子资源。 |
注:下文不再给出iServer响应结构,请参考iServer帮助文档或查看网络请求响应。
###三、创建MongoDB切片更新任务
切片更新流程图:
iServer管理页:
REST API实现:
var commit=getcommit();
var uri=host+"/iserver/manager/tilesetupdatejobs.json?token="+token;
//以下示例请求体
//UGC5.0切片更新
// var entryv5='{"sourceTileSourceInfo":{"outputPath":"F:/iServer/iServer810/webapps/iserver/世界地图_Night", "tilesetIdentifier":"F:/iServer/iServer810/webapps/iserver/世界地图_Night/世界地图_Night.sci", "type":"UGCV5"}, "sourceTilesetIdentifier":"F:/iServer/iServer810/webapps/iserver/世界地图_Night/世界地图_Night.sci", "targetTileSourceInfo":{"outputPath":"F:/iServer/iServer810/webapps/iserver/世界地图_Night1", "tilesetIdentifier":"F:/iServer/iServer810/webapps/iserver/世界地图_Night1/世界地图_Night.sci", "type":"UGCV5"}, "targetTilesetIdentifier":"F:/iServer/iServer810/webapps/iserver/世界地图_Night1/世界地图_Night.sci", "scaleDenominators":["124999999.99999999", "64000000", "249999999.99999997"], "bounds":{"left":"-180", "bottom":"-90", "right":"180", "top":"90"}}';
//MongoDB切片更新
// var entrymg='{"sourceTileSourceInfo":{"serverAdresses":["192.168.15.25:27017"], "username":"", "password":"", "database":"M2", "type":"MongoDB"}, "sourceTilesetIdentifier":"-343788577", "targetTileSourceInfo":{"serverAdresses":["192.168.15.25:27017"], "username":"", "password":"", "database":"M1", "type":"MongoDB"}, "targetTilesetIdentifier":"-343788577", "scaleDenominators":["64000000", "125000000", "250000000"], "bounds":{"left":"-180", "bottom":"-90.00000000003598", "right":"180.00000000007202", "top":"90.00000000000001"}}:';
commit.open("post",encodeURI(uri),false,"","");
commit.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
commit.send(toJSON(getstorgeinfo()));//发送请求
其中 getstorgeinfo()
方法通过REST API获取到切片存储库的信息,并对比切片库了的切片集地图哈希码来确认是否同一个地图的切片,然后构造出切片更新需要的请求体。
iServer管理页获取切片库列表及切片库信息:
REST API实现:
function getstorgeinfo()
{//获取存储库信息
var commit = getcommit();
var uri = host + "/iserver/manager/storages.json?token=" + token;
commit.open( "get", encodeURI( uri ), false, "", "" );
commit.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" );
commit.send();
var response = json_parse( commit.responseText, null );//返回切片储存信息
console.log( response, "获取存储库信息" );
var storages = [];
for ( var i in response )
{
storages[i] = {};
storages[i].tilesetinfo = gettilesetinfo( response[i].id );
storages[i].TileSourceInfo = response[i].tileSourceInfo;
}
console.log( storages, "存储库及瓦片集信息" );
//更新切片(视具体情况),这里取第一对哈希码相同的瓦片集进行更新
var entry = {};
for ( var i = 0; i < storages.length; i++ )
{
for ( var j = 0; j < storages[i].tilesetinfo.length; j++ )
{
//比较同一存储库
if ( storages[i].tilesetinfo[j + 1] && storages[i].tilesetinfo[j].mapHashCode == storages[i].tilesetinfo[j + 1].mapHashCode )
{
var sourceTilesetIdentifier = null,//输入切片集唯一标识,选比例尺少的
targetTileSource = null;//目标切片集
if ( storages[i].tilesetinfo[j].scaleDenominators.length > storages[i].tilesetinfo[j + 1].scaleDenominators.length )
{
sourceTilesetIdentifier = storages[i].tilesetinfo[j].TilesetIdentifier;
targetTileSource = storages[i].tilesetinfo[j + 1];
} else
{
sourceTilesetIdentifier = storages[i].tilesetinfo[j + 1].TilesetIdentifier;
targetTileSource = storages[i].tilesetinfo[j];
}
//组装切片更新参数
entry.sourceTileSourceInfo = storages[i].TileSourceInfo;
entry.sourceTilesetIdentifier = sourceTilesetIdentifier;
entry.targetTileSourceInfo = storages[i].TileSourceInfo;
entry.targetTilesetIdentifier = targetTileSource.TilesetIdentifier;
entry.scaleDenominators = targetTileSource.scaleDenominators;
entry.bounds = targetTileSource.bounds;
console.log( entry, "切片更新参数" );
// CreatTilesUpdateJob(entry);//执行创建切片更新任务
return entry;
}
//比较不同存储库
if ( storages[i + 1] && storages[i].tilesetinfo[j].mapHashCode == storages[i + 1].tilesetinfo[j].mapHashCode )
{
var sourceTileSource = null,//输入切片集,选比例尺少的
targetTileSource = null;//目标切片集
if ( storages[i].tilesetinfo[j].scaleDenominators.length > storages[i + 1].tilesetinfo[j].scaleDenominators.length )
{
sourceTileSource = storages[i];
targetTileSource = storages[i + 1];
} else
{
sourceTileSource = storages[i + 1];
targetTileSource = storages[i];
}
//组装切片更新参数
entry.sourceTileSourceInfo = sourceTileSource.TileSourceInfo;
entry.sourceTilesetIdentifier = sourceTileSource.tilesetinfo[j].TilesetIdentifier;
entry.targetTileSourceInfo = targetTileSource.TileSourceInfo;
entry.targetTilesetIdentifier = targetTileSource.tilesetinfo[j].TilesetIdentifier;
entry.scaleDenominators = targetTileSource.tilesetinfo[j].scaleDenominators;
entry.bounds = targetTileSource.tilesetinfo[j].bounds;
console.log( entry, "切片更新参数" );
// CreatTilesUpdateJob(entry);//执行创建切片更新任务
return entry;
}
}
}
}
获取切片库具体信息 gettilesetinfo()
:
function gettilesetinfo( storageid )
{//获取存储瓦片信息
var commit = getcommit();
var uri = host + "/iserver/manager/storages/" + storageid + ".json?token=" + token;
commit.open( "get", encodeURI( uri ), false, "", "" );
commit.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" );
commit.send();
var response = json_parse( commit.responseText, null );//返回切片储存信息
console.log( response, "获取" + storageid + "存储瓦片信息" );
var result = [];
// result[i].TilesetIdentifier="";//瓦片集唯一标识
// result[i].mapName="";//地图名
// result[i].mapHashCode="";//地图哈希码
// result[i].scaleDenominators=[];//比例尺分母
// result[i].bounds={};//全幅范围
for ( var i in response.tilesetInfos )
{
result[i] = {};
result[i].TilesetIdentifier = response.tilesetInfos[i].name;
result[i].mapName = response.tilesetInfos[i].metaData.mapName;
result[i].mapHashCode = response.tilesetInfos[i].metaData.mapStatusHashCode;
result[i].scaleDenominators = response.tilesetInfos[i].metaData.scaleDenominators;
var tpbounds = {};
tpbounds.left = response.tilesetInfos[i].metaData.bounds.left;
tpbounds.bottom = response.tilesetInfos[i].metaData.bounds.bottom;
tpbounds.right = response.tilesetInfos[i].metaData.bounds.right;
tpbounds.top = response.tilesetInfos[i].metaData.bounds.top;
result[i].bounds = tpbounds;
}
if ( !result.length )
{
return false;
}
return result;
}
###四、其他
REST API参数列表可能没有列出所有支持的参数,以及某些REST资源,可以通过浏览器里在iServer管理页面进行操作,抓网络请求来查看请求体,这里推荐 Fiddler工具。
其他方式,比如直接重写JavaScript方法,阻止页面跳转及输出请求体对象等: