服务提供者层的扩展 |
服务提供者层的实现形式如下:
public class SampleProvider implements ProviderContextAware {
...
}
ProviderContextAware 用于获取服务提供者上下文,通过服务提供者上下文,可以获取该服务提供者对应的配置信息。
在 SuperMap iServer 的三层架构中,各层的配置可参考iServer 配置文件说明。
SuperMap iServer 已有的服务提供者类型有地图服务提供者、数据服务提供者、三维服务提供者、空间分析服务提供者、交通网络分析服务提供者。针对这些服务提供者,SuperMap iServer 已经进行了实现,从而提供了 GIS 功能的来源,支撑 SuperMap iServer 提供各种 GIS 功能(参见:服务提供者介绍)。
扩展服务提供者,对已有的服务提供者类型重新实现,可以扩宽 SuperMap iServer 提供 GIS 功能的来源。
表1 扩展服务提供者实现的接口/继承的类
扩展类型 | 继承的类/实现的接口 | 备注 |
地图服务提供者 | com.supermap.services.components.spi.MapProvider | 所有的地图服务提供者都实现该接口。
实现该接口的服务提供者可以被地图服务组件使用。 |
com.supermap.services.components.spi.AbstractRestMapProvider | 封装了访问 REST 地图服务所需的基本功能,所有使用 REST 地图服务的服务提供者都可使用此类扩展。 | |
com.supermap.services.components.spi.RemoteTiledMapProviderBase | RemoteTileProviderBase 是用于聚合第三方地图服务的抽象类,用于构建在线服务提供者,实现了 ProviderContextAware
服务提供者上下文依赖库接口和 MapProvider 地图服务提供者接口。
(参见:RemoteTiledMapProviderBase_扩展) |
|
com.supermap.services.components.spi.LocalTiledMapProviderBase | LocalTileProviderBase 是用于扩展本地地图瓦片服务的抽象类,本地的地图瓦片来源于 ArcGIS 切图所得。
(参见:LocalTiledMapProviderBase_扩展) |
|
其他已有实现类(参见:服务提供者介绍) | ||
数据服务提供者 | com.supermap.services.components.spi.DataProvider | 所有的数据服务提供者都实现该接口。
实现该接口的服务提供者可以被数据服务组件使用。 |
其他已有实现类(参见:服务提供者介绍) | ||
空间分析服务提供者 | com.supermap.services.components.spi.SpatialAnalystProvider | 所有的空间分析服务提供者都实现该接口。
实现该接口的服务提供者可以被空间分析服务组件使用。 |
其他已有实现类(参见:服务提供者介绍) | ||
交通网络分析服务提供者 | com.supermap.services.providers.spi.TransportationAnalystProvider | 所有的交通网络分析服务提供者都实现该接口。
实现该接口的服务提供者可以被交通网络分析服务组件使用。 |
其他已有实现类(参见:服务提供者介绍) | ||
三维服务提供者 | com.supermap.services.components.spi.RealspaceProvider | 所有的三维服务提供者都实现该接口。
实现该接口的服务提供者可以被三维服务组件使用。 |
其他已有实现类(参见:服务提供者介绍) |
在定义新的服务提供者类型,实现特定行业领域的功能时,不受以上接口限制。
在服务提供者实现类中,可以通过 ProviderContextAware 接口获取服务提供者上下文,通过服务提供者上下文,可以获取获取服务提供者配置信息。
用户自定义服务服务配置信息在 iserver-services.xml 中(详见iServer 配置文件说明),配置服务提供者时定制,结构由服务提供者配置类确定。服务提供者配置如下:
<provider class="com.supermap.sample.SampleProvider" name="sampleProvider">
<config class="com.supermap.sample.SampleProviderSetting">
<param1>default</param1>
...
</config>
</provider>
其中,SampleProviderSetting 是 SampleProvider 对应的配置类,param1对应 SampleProviderSetting 类的属性,通过使用服务提供者配置类,可以在 SuperMap iServer 中构建同种类型、不同来源的服务提供者。
在服务提供者实现类中,可以通过 ProviderContextAware 接口获取服务提供者上下文,并通过服务提供者上下文获取服务提供者配置信息,具体方式如下:
public class SampleProvider implements ProviderContextAware{
...
public void setProviderContext(ProviderContext context) {
SampleProviderSetting sampleProviderSetting = context.getConfig(SampleProviderSetting.class);
...
}
}
sampleProviderSetting 对象即对应配置文件中<provider/>下的<config/>配置项。
RemoteTileProviderBase 是用于聚合第三方地图服务的抽象类,用于构建在线服务提供者,实现了 ProviderContextAware 服务提供者上下文依赖库接口和 MapProvider 地图服务提供者接口。
该类的主要出图方法是 getTileImageUrl(TileImageParameter tileImageParameter)。
用户可以继承 RemoteTileProviderBase 抽象类,来聚合第三方地图服务。
需要实现以下方法:
注意:
将编译好的扩展类的 class 文件放到%SuperMap iServer_HOME%\webap\iserver\WEB-INF\classes 目录下(默认情况下没有 classes 目录,需要新建)或是编译好的 jar 包放到%SuperMap iServer_HOME%\webapp\ iserver\WEB-INF\lib\目录下,iServer 就可以使用扩展的服务提供者类,关于如何配置服务提供者,详见 通过 XML 文件配置服务提供者。
该类 cacheEnabled(),可以返回 true 或者 false 来设置是否使用缓存。
为 true 时,使用图片缓存,目前的图片缓存目录即地图服务提供者配置对象 MapProviderSetting.getOutputPath()目录,缓存路径为“\cache\地图名_图片宽度 x 图片高度\比例尺倒数\图片 x 索引\图片 y 索引.图片格式后缀”,同时,该类对访问的第三方地图服务也进行了缓存,缓存路径为“\cache\http\地图名_图片宽度 x 图片高度\比例尺倒数\图片 x 索引\图片 y 索引.图片格式后缀”。
这里扩展一个地图服务提供者。GoogleMapsMapProvider 继承 RemoteTileProviderBase 实现。你可以在%SuperMap iServer_HOME%/samples/code/DSSE/GoogleMapsProviderSample 位置找到该示例的源代码。
GoogleMapsMapProvider 实现类代码如下:
package com.supermap.sample.serviceprovider; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.MapParameter; import com.supermap.services.components.commontypes.OutputFormat; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.PrjCoordSys; import com.supermap.services.components.commontypes.Rectangle; import com.supermap.services.components.commontypes.Rectangle2D; import com.supermap.services.components.commontypes.RectifyType; import com.supermap.services.components.commontypes.Unit; import com.supermap.services.providers.RemoteTileProviderBase; import com.supermap.services.util.TileTool; import com.supermap.services.util.Tool; /** * * 谷歌地图 地图服务提供者 *
* * GoogleMapsMapProvider 提供了聚合第三方的 Google 地图服务的能力,并封装了与 SuperMap iServer 地图相关的 GIS * 功能。 *
* */ public class GoogleMapsMapProvider extends RemoteTileProviderBase { private static final String GOOGLEMAPSADRESSTEMPLATE = "http://mt1.google.cn/vt/hl=zh-CN&x=%d&y=%d&z=%d"; private static final String MAPNAME = "googlemaps"; private static final long EARTH_RADIUS = 6378137; private static final int LEVEL_COUNT = 18; private static final double GOOGLE_DPI = 96.0; private static final double RESOLUTION_PRECISION = 1E-6; private double[] resolutions; /** * * 获取谷歌地图瓦片 URL *
* @param tileParam 图片参数 */ @Override protected String getTileImageUrl(TileImageParameter tileImageParameter) { int z = getLevelByResolution(tileImageParameter.resolution); String googleImageUrl = String.format(GOOGLEMAPSADRESSTEMPLATE, tileImageParameter.x, tileImageParameter.y, z); return googleImageUrl; } @Override protected boolean cacheEnabled() { return false; } @Override protected Point2D getOrigin(String arg0) { return new Point2D(-20037508.3427892, 20037508.3427892); } /** * * * 返回指定地图支持的图片格式数组 *
* @param mapName * @return * @since 7.1.0 */ @Override public OutputFormat[] getSupportImageFormat(String arg0) { return new OutputFormat[0]; } @Override public double[] getSupportResolutions(String arg0) { if (resolutions == null) { /** * 第0级分辨率 = 地球赤道周长/256个像素 */ double resolution = 2 * Math.PI * EARTH_RADIUS / 256.0; resolutions = new double[LEVEL_COUNT]; for (int i = 0; i < LEVEL_COUNT; i++) { resolutions[i] = resolution; resolution /= 2.0; } } return resolutions.clone(); } /** * * 初始化默认地图状态,返回值为一个映射,键为地图名,值为地图参数对象。 *
* * @return 地图状态映射,键为地图名,值为地图参数对象。 */ @Override protected Map<String, MapParameter> initDefaultMapParameter() { String mapName = MAPNAME; MapParameter defaultMapParameter = new MapParameter(); defaultMapParameter.name = mapName; defaultMapParameter.coordUnit = Unit.METER; defaultMapParameter.distanceUnit = Unit.METER; defaultMapParameter.viewer = new Rectangle(0, 0, 256, 256); defaultMapParameter.bounds = new Rectangle2D(-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892); defaultMapParameter.viewBounds = new Rectangle2D(defaultMapParameter.bounds); defaultMapParameter.center = defaultMapParameter.viewBounds.center(); defaultMapParameter.customEntireBoundsEnabled = false; defaultMapParameter.description = ""; defaultMapParameter.prjCoordSys = new PrjCoordSys(); defaultMapParameter.prjCoordSys.coordUnit = Unit.METER; defaultMapParameter.prjCoordSys.distanceUnit = Unit.METER; defaultMapParameter.prjCoordSys.epsgCode = 3857; defaultMapParameter.rectifyType = RectifyType.BYCENTERANDMAPSCALE; defaultMapParameter.visibleScalesEnabled = true; defaultMapParameter.visibleScales = getSupportScales(); defaultMapParameter.scale = defaultMapParameter.visibleScales[0]; defaultMapParameter.layers = new ArrayList<Layer>(); GoogleMapLayer layer = new GoogleMapLayer(); layer.name = defaultMapParameter.name; layer.caption = defaultMapParameter.name; layer.bounds = new Rectangle2D(defaultMapParameter.bounds); layer.description = "Google Maps Layer"; layer.visible = true; defaultMapParameter.layers.add(layer); Map<String, MapParameter> result = new HashMap<String, MapParameter>(); result.put(mapName, defaultMapParameter); return result; } /** * 初始化支持的地图列表 * * @return 地图名列表 */ @Override protected List<String> initSupportedMapNames() { List<String> names = new ArrayList<String>(); names.add(MAPNAME); return names; } private int getLevelByResolution(double resolution) { resolutions = getSupportResolutions(MAPNAME); for (int i = 0; i < resolutions.length; i++) { if (Tool.equal(resolution, resolutions[i], RESOLUTION_PRECISION)) { return i; } } return -1; } private double[] getSupportScales() { double[] resolutions = getSupportResolutions(MAPNAME); double[] scales = new double[LEVEL_COUNT]; for (int i = 0; i < LEVEL_COUNT; i++) { scales[i] = TileTool.resolutionToScale(resolutions[i], GOOGLE_DPI, Unit.METER); } return scales; } /** * * 根据参数向远端发送出图请求 *
*/ @Override protected Map<String, Object> sendRequestByHttpURLConnection(String paramString1, String paramString2, InputStream paramInputStream, Map<String, String> paramMap, int paramInt) { InputStream localInputStream = null; HttpURLConnection localHttpURLConnection = null; OutputStream localOutputStream = null; int i = paramInt; HashMap<String, Object> localHashMap = new HashMap<String, Object>(); try { URL localURL = new URL(paramString1); localHttpURLConnection = (HttpURLConnection) localURL.openConnection(); localHttpURLConnection.setRequestMethod(paramString2); if ((paramString2.equals("POST")) || (paramString2.equals("PUT"))) { localHttpURLConnection.setDoOutput(true); } localHttpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); localHttpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"); localHttpURLConnection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); localHttpURLConnection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch"); localHttpURLConnection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8"); if (paramMap != null) { Iterator<?> localIterator = paramMap.entrySet().iterator(); while (localIterator.hasNext()) { @SuppressWarnings("rawtypes") Map.Entry localEntry = (Map.Entry) localIterator.next(); localHttpURLConnection.setRequestProperty((String) localEntry.getKey(), (String) localEntry.getValue()); } } localHttpURLConnection.setConnectTimeout(40000); localHttpURLConnection.setReadTimeout(20000); if ((paramInputStream != null) && (localHttpURLConnection.getDoOutput())) { localOutputStream = localHttpURLConnection.getOutputStream(); IOUtils.copy(paramInputStream, localOutputStream); localOutputStream.flush(); localOutputStream.close(); paramInputStream.close(); } int responseCode = localHttpURLConnection.getResponseCode(); localHashMap.put("status", Integer.valueOf(responseCode)); if (responseCode < 400) { localInputStream = localHttpURLConnection.getInputStream(); } else { logger.info(message.getMessage("TiledMapProvider.sendRequestByHttpURLConnection.RequestError", new String[] { paramString1, String.valueOf(responseCode) })); } if (localInputStream != null) localHashMap.put("ENTITY", localInputStream); } catch (IOException localIOException) { if (i < 5) { logger.debug(message.getMessage("URL_REQUEST_EXCEPTION", new String[] { paramString1, localIOException.getMessage(), String.valueOf(i) })); return sendRequestByHttpURLConnection(paramString1, paramString2, paramInputStream, ++i); } logger.debug(message.getMessage("URL_REQUEST_FAILED", new String[] { paramString1, String.valueOf(i) })); } return localHashMap; } }
GoogleMapsMapProvider 类中 GoogleMapLayer 表示当前地图使用 Google 图层(扩展其它 provider 时,可以参考 GoogleMapLayer 定义相应的 Layer)。GoogleMapLayer 实现类代码如下:
package com.supermap.sample.serviceprovider; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.LayerType; import com.supermap.services.components.commontypes.Rectangle2D; public class GoogleMapLayer extends Layer { private static final long serialVersionUID = 1L; public GoogleMapLayer() { this.type = LayerType.CUSTOM; } @Override public Layer copy() { GoogleMapLayer googleLayer = new GoogleMapLayer(); googleLayer.name = this.name; googleLayer.type = this.type; googleLayer.bounds = new Rectangle2D(this.bounds); googleLayer.caption = this.caption; googleLayer.visible = this.visible; return googleLayer; } }
配置类直接使用 MapProviderSetting,配置如下:
<provider class="com.supermap.sample.serviceprovider.GoogleMapsMapProvider" name="mapProvider-GoogleMaps">
<config class="com.supermap.services.components.spi.MapProviderSetting">
</config>
</provider>
编译后的 Jar 放到 %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib 目录。
新建一个使用 mapProvider-GoogleMaps 的“地图服务组件”map-google,发布为 rest、WMS 1.1.1 服务:
<component class="com.supermap.services.components.impl.MapImpl" interfaceNames="rest,wms111" name="map-google" providers="mapProvider-GoogleMaps">
<config class="com.supermap.services.components.MapConfig">
</config>
</component>
即可通过根 URI:http://<host>:<port>/iserver/services/map-google/rest 访问地图 REST 功能。通过 http://<host>:<port>/iserver/services/map-google/rest/maps/googlemaps.ijs 访问地图(googlemaps 为地图名,在 GoogleMapsMapProvider 实现类中声明),结果如下:
LocalTileProviderBase 是用于扩展本地地图瓦片服务的抽象类,实现了 ProviderContextAware 服务提供者上下文依赖库接口和 MapProvider 地图服务提供者接口。
该类的主要出图方法是 getTileImage(TiledMapProviderBase.TileImageParameterparamTileImageParameter)。
用户可以继承 LocalTileProviderBase 抽象类,来扩展本地地图服务。
需要实现以下方法:
注意:
配置和部署
将编译好的扩展类的 class 文件放到%SuperMap iServer_HOME%\webap\iserver\WEB-INF\classes 目录下(默认情况下没有 classes 目录,需要新建)或是编译好的 jar 包放到%SuperMap iServer_HOME%\webapp\ iserver\WEB-INF\lib\目录下,iServer 就可以使用扩展的服务提供者类,关于如何配置服务提供者,详见通过 XML 文件配置服务提供者。
关于缓存
该类 cacheEnabled(),可以返回 true 或者 false 来设置是否使用缓存。
为 true 时,使用图片缓存,目前的图片缓存目录即地图服务提供者配置对象 MapProviderSetting.getOutputPath()目录,缓存路径为“\cache\地图名_图片宽度 x 图片高度\比例尺倒数\图片 x 索引\图片 y 索引.图片格式后缀”,同时,该类对访问的第三方地图服务也进行了缓存,缓存路径为“\cache\http\地图名_图片宽度 x 图片高度\比例尺倒数\图片 x 索引\图片 y 索引.图片格式后缀”。
本示例介绍通过继承自 LocalTileProviderBase 的 ArcGISExplodedCacheMapProvider 类来实现将本地的 ArcGIS Server 地图切片发布为 Supermap 地图服务的流程,你可以在%SuperMap iServer_HOME%/samples/code/DSSE/ArcGISExplodedCacheMapProviderSample 位置找到该示例的源代码。
注意:在通过 ArcGIS Server 进行切图的时候,选择的存储格式为”松散”的格式,分块格式选择 PNG8、PNG24、PNG32。
ArcGISExplodedCacheMapProvider 实现类代码如下:
ArcGISExplodedCacheMapProvider.java
package com.supermap.sample.serviceprovider; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import org.apache.commons.lang3.StringUtils; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.MapParameter; import com.supermap.services.components.commontypes.OutputFormat; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.Rectangle; import com.supermap.services.components.commontypes.Rectangle2D; import com.supermap.services.components.commontypes.RectifyType; import com.supermap.services.components.commontypes.Unit; import com.supermap.services.providers.LocalTileProviderBase; import com.supermap.services.util.PrjCoordSysConversionTool; import com.supermap.services.util.TileTool; /** * * ArcGIS 离散缓存 地图服务提供者。 *
* * ArcGISExplodedCacheMapProvider 提供了将本地 ArcGIS 离散缓存发布为地图服务的能力,并封装了与 SuperMap iServer 地图相关的 GIS * 功能。 *
* */ public class ArcGISExplodedCacheMapProvider extends LocalTileProviderBase { private static final String MAPNAME = "arcgismaps"; private double[] scales; private double[] resolutions = null; private Point2D origin; /** * * 获取图片 *
* @param tileParam 图片参数 * @param x * @param y * @param resolution 分辨率 * @return */ @Override protected byte[] getTileImage(TileImageParameter paramTileImageParameter) { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String arcgisMapsAdressTemplate = setting.getCachePath(); arcgisMapsAdressTemplate += "/_alllayers/L%02d/R%08x/C%08x.png"; int z = getLevelByResolution(paramTileImageParameter.resolution); if (z < 0) { return TileTool.getBlankImageByte("",this.tilePixWidth, this.tilePixHeight, paramTileImageParameter.outputOption.transparent); } String arcgisImagePath = String.format(arcgisMapsAdressTemplate, z, paramTileImageParameter.y, paramTileImageParameter.x); if (!new File(arcgisImagePath).exists()) { return TileTool.getBlankImageByte("",this.tilePixWidth, this.tilePixHeight, paramTileImageParameter.outputOption.transparent); } BufferedImage image = null; FileInputStream fs = null; byte[] imagebyte = null; try { fs = new FileInputStream(arcgisImagePath); image = ImageIO.read(fs); imagebyte = TileTool.getBytesFromBufferedImage(image, "PNG"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } return imagebyte; } /** * * 初始化支持的地图列表。 * * * Initialize the supported map list. * @return * * 地图名列表 * * Map name list * */ @Override protected List<String> initSupportedMapNames() { List<String> names = new ArrayList<String>(); names.add(getMapName()); return names; } /** * * 初始化默认地图状态,返回值为一个映射,键为地图名,值为地图参数对象。 * * * Initialize the default map status. Return value is a mapping. The key is the map name and the value is the map parameter object. * * @return 地图状态映射,键为地图名,值为地图参数对象。 * Map status mapping. The key is the map name, and the value is the parameter object.
*/ @Override protected Map<String, MapParameter> initDefaultMapParameter() { String mapName = getMapName(); ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); if (StringUtils.isBlank(setting.getCachePath())) { throw new IllegalArgumentException("cahcePath is null"); } ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); tilePixHeight = arcgisXmlParseTool.getTileRows(); tilePixWidth = arcgisXmlParseTool.getTileCols(); MapParameter defaultMapParameter = new MapParameter(); defaultMapParameter.name = mapName; defaultMapParameter.prjCoordSys = PrjCoordSysConversionTool.getPrjCoordSys(arcgisXmlParseTool.getWkid()); defaultMapParameter.coordUnit = defaultMapParameter.prjCoordSys.coordUnit; defaultMapParameter.distanceUnit = Unit.METER; defaultMapParameter.viewer = new Rectangle(0, 0, arcgisXmlParseTool.getTileCols(), arcgisXmlParseTool.getTileRows()); defaultMapParameter.bounds = arcgisXmlParseTool.getBounds(getConfCDIPath()); defaultMapParameter.center = defaultMapParameter.bounds.center(); double[] resolutionArray = getSupportResolutions(mapName); defaultMapParameter.viewBounds = new Rectangle2D(defaultMapParameter.center.x - arcgisXmlParseTool.getTileCols() * resolutionArray[0] * 0.5, defaultMapParameter.center.y - arcgisXmlParseTool.getTileRows() * resolutionArray[0] * 0.5, defaultMapParameter.center.x + arcgisXmlParseTool.getTileCols() * resolutionArray[0] * 0.5, defaultMapParameter.center.y + arcgisXmlParseTool.getTileRows() * resolutionArray[0] * 0.5); defaultMapParameter.customEntireBoundsEnabled = false; defaultMapParameter.rectifyType = RectifyType.BYCENTERANDMAPSCALE; defaultMapParameter.visibleScalesEnabled = true; defaultMapParameter.visibleScales = getSupportScales(); defaultMapParameter.scale = defaultMapParameter.visibleScales[0]; defaultMapParameter.layers = new ArrayList<Layer>(); ArcGISExplodedCacheMapLayer layer = new ArcGISExplodedCacheMapLayer(); layer.name = defaultMapParameter.name; layer.bounds = new Rectangle2D(defaultMapParameter.bounds); layer.visible = true; defaultMapParameter.layers.add(layer); Map<String, MapParameter> result = new HashMap<String, MapParameter>(); result.put(mapName, defaultMapParameter); return result; } /** * * * 返回指定地图支持的图片格式数组 * * * Return image format array supported by specified map * * @param mapName * @return * @since 7.1.0 */ @Override public OutputFormat[] getSupportImageFormat(String paramString) { return new OutputFormat[0]; } /** * * 获取地图的左上角地理坐标。 * * * Get the geographical coordinates of map top left corner. * * @param 地图名 * * Map name * * @return 地图的左上角地理坐标。 * * The geographical coordinates of map top left corner. * */ @Override protected Point2D getOrigin(String paramString) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (origin == null) { origin = arcgisXmlParseTool.getTileOrigin(); return origin; } return origin; } @Override protected boolean cacheEnabled() { return false; } /** * * 返回当前服务支持的分辨率 。如果支持所有分辨率,则返回空。 * * * Return the resolutions supported by current services. If all resolutions are supported, return null. * * @param mapName * * @return 分辨率数组 * * Resolution array * */ @Override public double[] getSupportResolutions(String paramString) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (resolutions == null) { resolutions = arcgisXmlParseTool.getResolutions(); } return resolutions; } private int getLevelByResolution(double resolution) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); for (int i = 0; i < arcgisXmlParseTool.getResolutions().length; i++) { if (resolution == arcgisXmlParseTool.getResolutions()[i]) { return i; } } return -1; } private double[] getSupportScales() { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (scales == null) { scales = arcgisXmlParseTool.getScales(); } return scales; } private String getConfXMLPath() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String path = setting.getCachePath() + "/conf.xml"; return path; } private String getConfCDIPath() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String path = setting.getCachePath() + "/conf.cdi"; return path; } private String getMapName() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); if (StringUtils.isNotBlank(setting.getMapName())) { return setting.getMapName(); } return MAPNAME; } }
ArcGISExplodedCacheMapProvider 类中 ArcGISExplodedCacheMapLayer 表示当前地图使用 ArcGIS 图层(扩展其它 provider 时,可以参考 ArcGISExplodedCacheMapLayer定义相应的 Layer)。
ArcGISExplodedCacheMapLayer 实现类代码如下:
ArcGISExplodedCacheMapLayer.java
package com.supermap.sample.serviceprovider; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.LayerType; import com.supermap.services.components.commontypes.Rectangle2D; public class ArcGISExplodedCacheMapLayer extends Layer { private static final long serialVersionUID = 1L; public ArcGISExplodedCacheMapLayer() { this.type = LayerType.CUSTOM; } @Override public Layer copy() { ArcGISExplodedCacheMapLayer arcgisLayer = new ArcGISExplodedCacheMapLayer(); arcgisLayer.name = this.name; arcgisLayer.type = this.type; arcgisLayer.bounds = new Rectangle2D(this.bounds); arcgisLayer.caption = this.caption; arcgisLayer.visible = this.visible; return arcgisLayer; } }
ArcGISXMLParseTool 类用于提取 ArcGIS Server 切片目录的 conf.xml 文件和 conf.cdi 文件中的一些节点值。
conf.xml 文件结构如下图:
conf.cdi 文件结构如下图:
ArcGISXMLParseTool 实现类代码如下:
package com.supermap.sample.serviceprovider; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.Rectangle2D; /** * * ArcGIS Server 缓存 conf 文件读取类 提取 conf.xml 和 conf.cdi 相关信息。 *
* * ArcGISXMLParseTool 提供了读取缓存目录下的 conf.xml 文件和 conf.cdi 文件相关信息的功能。 *
* */ public class ArcGISXMLParseTool { private static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); private double[] resolutions; private double[] scales; private int wkid, tileCols, tileRows; private String cachePath; /** * * 带参构造函数 *
* * @param cache 地图缓存目录 */ public ArcGISXMLParseTool(String cachePath) { this.cachePath = cachePath; } /** * * 获取地图比例尺集合 *
* @return 地图比例尺集合 */ public double[] getScales() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList scaleDenominatorList = doc.getElementsByTagName("Scale"); scales = new double[scaleDenominatorList.getLength()]; for (int i = 0; i < scaleDenominatorList.getLength(); i++) { Node scaleDenominatorNode = scaleDenominatorList.item(i); scales[i] = 1 / Double.parseDouble(scaleDenominatorNode.getTextContent()); } } catch (Exception e) { e.printStackTrace(); } if (scales == null) { return new double[0]; } return scales; } /** * * 获取地图分辨率集合 *
* @return 地图分辨率集合 */ public double[] getResolutions() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList resolutionList = doc.getElementsByTagName("Resolution"); resolutions = new double[resolutionList.getLength()]; for (int i = 0; i < resolutionList.getLength(); i++) { Node resolutionNode = resolutionList.item(i); resolutions[i] = Double.parseDouble(resolutionNode.getTextContent()); } } catch (Exception e) { e.printStackTrace(); } if (resolutions == null) { return new double[0]; } return resolutions; } /** * * 获取地图 WKID *
* @return 地图 WKID */ public int getWkid() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList wkidList = doc.getElementsByTagName("WKID"); Node wkidNode = wkidList.item(0); wkid = Integer.parseInt(wkidNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return wkid; } /** * * 获取地图瓦片宽 *
* @return 地图瓦片宽 */ public int getTileCols() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList tileColsList = doc.getElementsByTagName("TileCols"); Node tileColsNode = tileColsList.item(0); tileCols = Integer.parseInt(tileColsNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return tileCols; } /** * * 获取地图瓦片高 *
* @return 地图瓦片高 */ public int getTileRows() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList tileRowsList = doc.getElementsByTagName("TileRows"); Node tileRowsNode = tileRowsList.item(0); tileRows = Integer.parseInt(tileRowsNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return tileRows; } /** * * 获取地图切片原点 * * @return 地图切片原点 */ public Point2D getTileOrigin() { double originX = 0; double originY = 0; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList originXList = doc.getElementsByTagName("X"); NodeList originYList = doc.getElementsByTagName("Y"); originX = Double.parseDouble(originXList.item(0).getTextContent()); originY = Double.parseDouble(originYList.item(0).getTextContent()); } catch (Exception e) { e.printStackTrace(); } return new Point2D(originX, originY); } /** * * 获取地图全图范围 * * @return 地图全图范围 */ public Rectangle2D getBounds(String cdiPath) { double leftBottomX = 0; double leftBottomY = 0; double rightTopX = 0; double rightTopY = 0; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cdiPath); NodeList leftBottomXList = doc.getElementsByTagName("XMin"); NodeList leftBottomYList = doc.getElementsByTagName("YMin"); NodeList rightTopXList = doc.getElementsByTagName("XMax"); NodeList rightTopYList = doc.getElementsByTagName("YMax"); leftBottomX = Double.parseDouble(leftBottomXList.item(0).getTextContent()); leftBottomY = Double.parseDouble(leftBottomYList.item(0).getTextContent()); rightTopX = Double.parseDouble(rightTopXList.item(0).getTextContent()); rightTopY = Double.parseDouble(rightTopYList.item(0).getTextContent()); } catch (Exception e) { e.printStackTrace(); } return new Rectangle2D(leftBottomX, leftBottomY, rightTopX, rightTopY); } }
ArcGISExplodedCacheMapProviderSetting 类,继承自 MapProviderSetting 类,用于扩展地图服务提供者配置,完成一些特定地图参数的设置。其中的 cachePath 表示地图切片路径、mapName 表示地图名。
ArcGISExplodedCacheMapProviderSetting 实现类代码如下:
ArcGISExplodedCacheMapProviderSetting.java
package com.supermap.sample.serviceprovider; import com.supermap.services.components.spi.MapProviderSetting; public class ArcGISExplodedCacheMapProviderSetting extends MapProviderSetting { private static final long serialVersionUID = 1L; private String cachePath; private String mapName; public String getMapName() { return mapName; } public void setMapName(String mapName) { this.mapName = mapName; } public String getCachePath() { return cachePath; } public void setCachePath(String cachePath) { this.cachePath = cachePath; } }
配置类使用扩展自 MapProviderSetting 的 ArcGISExplodedCacheMapProviderSetting 类,其中必须要配置<cachePath>切片路径、并且用户可以选择性配置<mapName>地图名,当用户未配置或配置的地图名为空时,地图名将采用默认值,配置如下:
<provider class="com.supermap.sample.serviceprovider.ArcGISExplodedCacheMapProvider" name="mapProvider-ArcGISExplodedCacheMap">
<config class="com.supermap.sample.serviceprovider.ArcGISExplodedCacheMapProviderSetting">
<cachePath>C:/arcgisserver/arcgiscache/China400/China400</cachePath>
<mapName></mapName>
</config>
</provider>
编译后的 Jar 放到 %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib 目录。
新建一个使用 mapProvider-ArcGISMaps 的“地图服务组件”map-arcgis,发布为 rest、WMS 1.1.1 服务:
<component class="com.supermap.services.components.impl.MapImpl" enabled="true" interfaceNames="wms111,rest" name="map-arcgis" providers="mapProvider-ArcGISExplodedCacheMap">
</component>
即可通过根 URI:http://<host>:<port>/iserver/services/map-arcgis/rest 访问地图 REST 功能。通过 http://<host>:<port>/iserver/services/map-arcgis/rest/maps/arcgismaps.ijs 访问地图(arcgismaps 为地图名,在 ArcGISExplodedCacheMapProvider 实现类中声明),结果如下:
本示例介绍通过继承自 ZXYTilesMapProvider 的 TMSTilesMapProvider 类来实现将本地的 TMS 地图切片发布为 Supermap 地图服务的流程,你可以在%SuperMap iServer_HOME%/samples/code/DSSE/TMSTilesMapProviderSample 位置找到该示例的源代码。
TMSTilesMapProvider 实现类代码如下:
package com.supermap.sample.serviceprovider;
import com.supermap.services.components.commontypes.Point2D;
import com.supermap.services.components.commontypes.Rectangle2D;
public class TMSTilesMapProvider extends ZXYTilesMapProvider {
@Override
protected int getTop(double y, Rectangle2D viewBounds, double tileResolution, int tileImageHeight) {
return this.getTop(viewBounds.getBottom(), y , tileResolution, tileImageHeight);
}
@Override
protected int getBottom(double y, Rectangle2D viewBounds, double tileResolution, int tileImageHeight) {
return this.getBottom(viewBounds.getTop(), y, tileResolution, tileImageHeight);
}
@Override
protected int getTopOrBottomTileIndex(double y, double topOrBottom, double tileHeight, boolean b, int tileImageHeight) {
return this.getTileIndex(topOrBottom, y, tileHeight, b, tileImageHeight);
}
@Override
protected Point2D setTileOrigin(Rectangle2D bounds) {
return new Point2D(bounds.getLeft(), bounds.getBottom());
}
}
package com.supermap.sample.serviceprovider; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import org.apache.commons.lang3.StringUtils; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.MapParameter; import com.supermap.services.components.commontypes.OutputFormat; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.Rectangle; import com.supermap.services.components.commontypes.Rectangle2D; import com.supermap.services.components.commontypes.RectifyType; import com.supermap.services.components.commontypes.Unit; import com.supermap.services.providers.LocalTileProviderBase; import com.supermap.services.util.PrjCoordSysConversionTool; import com.supermap.services.util.TileTool; /** * * ArcGIS 离散缓存 地图服务提供者。 *
* * ArcGISExplodedCacheMapProvider 提供了将本地 ArcGIS 离散缓存发布为地图服务的能力,并封装了与 SuperMap iServer 地图相关的 GIS * 功能。 *
* */ public class ArcGISExplodedCacheMapProvider extends LocalTileProviderBase { private static final String MAPNAME = "arcgismaps"; private double[] scales; private double[] resolutions = null; private Point2D origin; /** * * 获取图片 *
* @param tileParam 图片参数 * @param x * @param y * @param resolution 分辨率 * @return */ @Override protected byte[] getTileImage(TileImageParameter paramTileImageParameter) { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String arcgisMapsAdressTemplate = setting.getCachePath(); arcgisMapsAdressTemplate += "/_alllayers/L%02d/R%08x/C%08x.png"; int z = getLevelByResolution(paramTileImageParameter.resolution); if (z < 0) { return TileTool.getBlankImageByte("",this.tilePixWidth, this.tilePixHeight, paramTileImageParameter.outputOption.transparent); } String arcgisImagePath = String.format(arcgisMapsAdressTemplate, z, paramTileImageParameter.y, paramTileImageParameter.x); if (!new File(arcgisImagePath).exists()) { return TileTool.getBlankImageByte("",this.tilePixWidth, this.tilePixHeight, paramTileImageParameter.outputOption.transparent); } BufferedImage image = null; FileInputStream fs = null; byte[] imagebyte = null; try { fs = new FileInputStream(arcgisImagePath); image = ImageIO.read(fs); imagebyte = TileTool.getBytesFromBufferedImage(image, "PNG"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } return imagebyte; } /** * * 初始化支持的地图列表。 * * * Initialize the supported map list. * @return * * 地图名列表 * * Map name list * */ @Override protected List<String> initSupportedMapNames() { List<String> names = new ArrayList<String>(); names.add(getMapName()); return names; } /** * * 初始化默认地图状态,返回值为一个映射,键为地图名,值为地图参数对象。 * * * Initialize the default map status. Return value is a mapping. The key is the map name and the value is the map parameter object. * * @return 地图状态映射,键为地图名,值为地图参数对象。 * Map status mapping. The key is the map name, and the value is the parameter object.
*/ @Override protected Map<String, MapParameter> initDefaultMapParameter() { String mapName = getMapName(); ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); if (StringUtils.isBlank(setting.getCachePath())) { throw new IllegalArgumentException("cahcePath is null"); } ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); tilePixHeight = arcgisXmlParseTool.getTileRows(); tilePixWidth = arcgisXmlParseTool.getTileCols(); MapParameter defaultMapParameter = new MapParameter(); defaultMapParameter.name = mapName; defaultMapParameter.prjCoordSys = PrjCoordSysConversionTool.getPrjCoordSys(arcgisXmlParseTool.getWkid()); defaultMapParameter.coordUnit = defaultMapParameter.prjCoordSys.coordUnit; defaultMapParameter.distanceUnit = Unit.METER; defaultMapParameter.viewer = new Rectangle(0, 0, arcgisXmlParseTool.getTileCols(), arcgisXmlParseTool.getTileRows()); defaultMapParameter.bounds = arcgisXmlParseTool.getBounds(getConfCDIPath()); defaultMapParameter.center = defaultMapParameter.bounds.center(); double[] resolutionArray = getSupportResolutions(mapName); defaultMapParameter.viewBounds = new Rectangle2D(defaultMapParameter.center.x - arcgisXmlParseTool.getTileCols() * resolutionArray[0] * 0.5, defaultMapParameter.center.y - arcgisXmlParseTool.getTileRows() * resolutionArray[0] * 0.5, defaultMapParameter.center.x + arcgisXmlParseTool.getTileCols() * resolutionArray[0] * 0.5, defaultMapParameter.center.y + arcgisXmlParseTool.getTileRows() * resolutionArray[0] * 0.5); defaultMapParameter.customEntireBoundsEnabled = false; defaultMapParameter.rectifyType = RectifyType.BYCENTERANDMAPSCALE; defaultMapParameter.visibleScalesEnabled = true; defaultMapParameter.visibleScales = getSupportScales(); defaultMapParameter.scale = defaultMapParameter.visibleScales[0]; defaultMapParameter.layers = new ArrayList<Layer>(); ArcGISExplodedCacheMapLayer layer = new ArcGISExplodedCacheMapLayer(); layer.name = defaultMapParameter.name; layer.bounds = new Rectangle2D(defaultMapParameter.bounds); layer.visible = true; defaultMapParameter.layers.add(layer); Map<String, MapParameter> result = new HashMap<String, MapParameter>(); result.put(mapName, defaultMapParameter); return result; } /** * * * 返回指定地图支持的图片格式数组 * * * Return image format array supported by specified map * * @param mapName * @return * @since 7.1.0 */ @Override public OutputFormat[] getSupportImageFormat(String paramString) { return new OutputFormat[0]; } /** * * 获取地图的左上角地理坐标。 * * * Get the geographical coordinates of map top left corner. * * @param 地图名 * * Map name * * @return 地图的左上角地理坐标。 * * The geographical coordinates of map top left corner. * */ @Override protected Point2D getOrigin(String paramString) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (origin == null) { origin = arcgisXmlParseTool.getTileOrigin(); return origin; } return origin; } @Override protected boolean cacheEnabled() { return false; } /** * * 返回当前服务支持的分辨率 。如果支持所有分辨率,则返回空。 * * * Return the resolutions supported by current services. If all resolutions are supported, return null. * * @param mapName * * @return 分辨率数组 * * Resolution array * */ @Override public double[] getSupportResolutions(String paramString) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (resolutions == null) { resolutions = arcgisXmlParseTool.getResolutions(); } return resolutions; } private int getLevelByResolution(double resolution) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); for (int i = 0; i < arcgisXmlParseTool.getResolutions().length; i++) { if (resolution == arcgisXmlParseTool.getResolutions()[i]) { return i; } } return -1; } private double[] getSupportScales() { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (scales == null) { scales = arcgisXmlParseTool.getScales(); } return scales; } private String getConfXMLPath() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String path = setting.getCachePath() + "/conf.xml"; return path; } private String getConfCDIPath() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String path = setting.getCachePath() + "/conf.cdi"; return path; } private String getMapName() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); if (StringUtils.isNotBlank(setting.getMapName())) { return setting.getMapName(); } return MAPNAME; } }
package com.supermap.sample.serviceprovider; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.Rectangle2D; /** * * ArcGIS Server 缓存 conf 文件读取类 提取 conf.xml 和 conf.cdi 相关信息。 *
* * ArcGISXMLParseTool 提供了读取缓存目录下的 conf.xml 文件和 conf.cdi 文件相关信息的功能。 *
* */ public class ArcGISXMLParseTool { private static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); private double[] resolutions; private double[] scales; private int wkid, tileCols, tileRows; private String cachePath; /** * * 带参构造函数 *
* * @param cache 地图缓存目录 */ public ArcGISXMLParseTool(String cachePath) { this.cachePath = cachePath; } /** * * 获取地图比例尺集合 *
* @return 地图比例尺集合 */ public double[] getScales() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList scaleDenominatorList = doc.getElementsByTagName("Scale"); scales = new double[scaleDenominatorList.getLength()]; for (int i = 0; i < scaleDenominatorList.getLength(); i++) { Node scaleDenominatorNode = scaleDenominatorList.item(i); scales[i] = 1 / Double.parseDouble(scaleDenominatorNode.getTextContent()); } } catch (Exception e) { e.printStackTrace(); } if (scales == null) { return new double[0]; } return scales; } /** * * 获取地图分辨率集合 *
* @return 地图分辨率集合 */ public double[] getResolutions() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList resolutionList = doc.getElementsByTagName("Resolution"); resolutions = new double[resolutionList.getLength()]; for (int i = 0; i < resolutionList.getLength(); i++) { Node resolutionNode = resolutionList.item(i); resolutions[i] = Double.parseDouble(resolutionNode.getTextContent()); } } catch (Exception e) { e.printStackTrace(); } if (resolutions == null) { return new double[0]; } return resolutions; } /** * * 获取地图 WKID *
* @return 地图 WKID */ public int getWkid() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList wkidList = doc.getElementsByTagName("WKID"); Node wkidNode = wkidList.item(0); wkid = Integer.parseInt(wkidNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return wkid; } /** * * 获取地图瓦片宽 *
* @return 地图瓦片宽 */ public int getTileCols() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList tileColsList = doc.getElementsByTagName("TileCols"); Node tileColsNode = tileColsList.item(0); tileCols = Integer.parseInt(tileColsNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return tileCols; } /** * * 获取地图瓦片高 *
* @return 地图瓦片高 */ public int getTileRows() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList tileRowsList = doc.getElementsByTagName("TileRows"); Node tileRowsNode = tileRowsList.item(0); tileRows = Integer.parseInt(tileRowsNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return tileRows; } /** * * 获取地图切片原点 * * @return 地图切片原点 */ public Point2D getTileOrigin() { double originX = 0; double originY = 0; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList originXList = doc.getElementsByTagName("X"); NodeList originYList = doc.getElementsByTagName("Y"); originX = Double.parseDouble(originXList.item(0).getTextContent()); originY = Double.parseDouble(originYList.item(0).getTextContent()); } catch (Exception e) { e.printStackTrace(); } return new Point2D(originX, originY); } /** * * 获取地图全图范围 * * @return 地图全图范围 */ public Rectangle2D getBounds(String cdiPath) { double leftBottomX = 0; double leftBottomY = 0; double rightTopX = 0; double rightTopY = 0; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cdiPath); NodeList leftBottomXList = doc.getElementsByTagName("XMin"); NodeList leftBottomYList = doc.getElementsByTagName("YMin"); NodeList rightTopXList = doc.getElementsByTagName("XMax"); NodeList rightTopYList = doc.getElementsByTagName("YMax"); leftBottomX = Double.parseDouble(leftBottomXList.item(0).getTextContent()); leftBottomY = Double.parseDouble(leftBottomYList.item(0).getTextContent()); rightTopX = Double.parseDouble(rightTopXList.item(0).getTextContent()); rightTopY = Double.parseDouble(rightTopYList.item(0).getTextContent()); } catch (Exception e) { e.printStackTrace(); } return new Rectangle2D(leftBottomX, leftBottomY, rightTopX, rightTopY); } }
TMSTilesMapProviderSetting 类,继承自 ZXYTilesMapProviderSetting 类,用于扩展地图服务提供者配置,完成一些特定地图参数的设置。TMSTilesMapProviderSetting 实现类代码如下:
package com.supermap.sample.serviceprovider;
public class TMSTilesMapProviderSetting extends ZXYTilesMapProviderSetting{
private static final long serialVersionUID = 1L;
}
package com.supermap.sample.serviceprovider; import com.supermap.services.components.spi.MapProviderSetting; public class ArcGISExplodedCacheMapProviderSetting extends MapProviderSetting { private static final long serialVersionUID = 1L; private String cachePath; private String mapName; public String getMapName() { return mapName; } public void setMapName(String mapName) { this.mapName = mapName; } public String getCachePath() { return cachePath; } public void setCachePath(String cachePath) { this.cachePath = cachePath; } }
将编译好的扩展类的 class 文件放到 %SuperMap iServer_Home%\webap\iserver\WEB-INF\classes 目录下(默认情况下没有classes目录,需要新建),或将编译后的 Jar 放到 %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib 目录下。
在 iserver-services.xml(位于%SuperMap iServer Java_HOME%/webapps/iserver/WEB-INF)配置服务提供者,配置如下:
<provider class="com.supermap.sample.serviceprovider.TMSTilesMapProvider" enabled="true" name="TMSTiles-test">
<config class="com.supermap.sample.serviceprovider.TMSTilesMapProviderSetting">
<filePath>D:/sample/TMSTile_file</filePath>
</config>
</provider>
其中<filePath>为必须参数,表示 TMS 瓦片路径,路径需要写到 TMS 瓦片地图名的上一级。如,示例中TMS 瓦片存储路径为 D:/sample/TMSTile_file/<MapName>/<Z>/<X>/<Y> ,则 filePath 应为 D:/sample/TMSTile_file。
在 iserver-services.xml 中配置地图服务组件 TMSTiles-test,发布为rest服务:
<component class="com.supermap.services.components.impl.MapImpl" enabled="true" interfaceNames="rest" name="map-TMSTiles-test" providers="TMSTiles-test">
</component>
即可通过根 URI:http://<host>:<port>/iserver/services/map-TMSTiles-test/rest 访问地图 REST 功能。通过 http://<host>:<port>/iserver/services/map-TMSTiles-test/rest/maps/test.leaflet 访问地图。