服务接口的实现形式如下:
@Interface(componentTypes = { com.supermap.services.components.Map.class }, optional = false, multiple = false)
@Protocol(names={"BingMaps"})
public class BingMapsServlet extends HttpServlet implements InterfaceContextAware {
...
}
其中:
- 服务接口实现类需要是一个 Servlet,通过继承 HttpServlet 实现。InterfaceContextAware 是服务接口上下文接口,用于获取服务组件、服务接口配置信息。
- @Interface 注记标识了该服务接口的一些配置信息,componentTypes 标识了当前服务接口使用的服务组件,从 SuperMap iServer 7C(2015) SP2开始,该属性值由支持普通 Java 类变更为必须使用接口
- @Protocol 注记标识了该服务接口的一些元信息,names 指该服务接口类可提供的服务类型,用于在集群时提供服务接口信息(SuperMap iServer 支持对扩展的服务进行集群,参见:搭建领域空间服务集群),在使用集群时必选
服务接口上下文
在服务接口实现类中,可以通过 InterfaceContextAware 接口获取服务接口上下文,通过服务接口上下文,可以获取获取服务接口配置信息,从而获取服务组件。
获取服务接口配置
服务接口配置信息在 iserver-services-interfaces.xml 中(详见服务配置文件结构),配置服务接口时定制,结构由服务接口配置类确定。服务接口配置如下:
<interface class="com.supermap.sample.SampleServlet" name="sampleinterface">
<config class="com.supermap.sample.SampleServletSetting">
<param1>default</param1>
...
</config>
</interface>
其中,SampleServletSetting 是 SampleServlet 对应的配置类,param1对应 SampleServletSetting 类的属性。
在服务接口实现类中,可以通过 InterfaceContextAware 接口获取服务接口上下文,通过服务接口上下文,可以获取获取服务接口配置信息(即以上配置),具体方式如下:
@Interface(componentTypes = { com.supermap.services.components.Map.class }, optional = false, multiple = false)
@Protocol(names={"SampleInterface"})
public class SampleServlet extends HttpServlet implements InterfaceContextAware {
...
public void setInterfaceContext(InterfaceContext context) {
//从服务接口上下文中获取服务接口配置
SampleInterfaceConfig sampleConfig = context.getConfig(SampleInterfaceConfig.class);
}
}
SampleInterfaceConfig 对象即对应接口配置中的<config class="com.supermap.sample.SampleServletSetting"/> 配置项。
如果服务接口无需额外配置,则可以不定义服务接口配置类。
获取服务组件
SuperMap iServer 中,服务组件通过相匹配的服务接口发布为 Web 服务,在服务接口实现类中,可通过服务接口上下文获取服务组件,从而获取相应的 GIS 功能。获取方式如下:
@Interface(componentTypes = { com.supermap.services.components.Map.class }, optional = false, multiple = false)
@Protocol(names={"SampleInterface"})
public class SampleServlet extends HttpServlet implements InterfaceContextAware {
...
public void setInterfaceContext(InterfaceContext context) {
//从服务接口上下文中获取服务组件(这里是地图服务组件)
List components = context.getComponents(Map.class);
...
}
}
服务接口扩展示例
服务接口决定了 GIS 功能提供的形式,扩展服务接口,可以丰富 GIS 功能的提供形势,以适应更多客户端需求。
这里实现一个 BingMaps 出图接口,提供跟 BingMaps REST 服务静态出图类似的 REST 接口。你可以在 %SuperMap iServer_HOME%/samples/DSSE/BingMapsInterfaceSample 位置找到该示例的源代码。
按照 BingMaps 的 REST 接口,访问如下 URI 可获取一张地图:
http://dev.virtualearth.net/REST/v1/Imagery/Map/ Road?mapArea=30.0,100.0,50.0,120.0&mapSize=512,512&key=BingMapsKey
其中,“Road”是 BingMap 提供的地图名称,mapArea 是出图的地理区域(南纬,西经,北纬,东经),mapSize 是出图大小(宽,高), BingMapsKey 是 BingMaps 的授权密匙,参见获取 BingMaps Key(http://msdn.microsoft.com/en-us/library/ff428642.aspx)。
实际上,BingMap 的 REST 接口有更多的参数,作为示例,这里“BingMaps 出图接口”只模拟实现地图名称、地理区域、出图大小3个参数。
BingMapServlet 实现类代码如下,实现了处理 URI,调用 Map 组件响应正确图片的功能:
package com.supermap.sample.serviceinterface;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.supermap.services.Interface;
import com.supermap.services.InterfaceContext;
import com.supermap.services.InterfaceContextAware;
import com.supermap.services.components.Map;
import com.supermap.services.components.MapException;
import com.supermap.services.components.commontypes.ImageOutputOption;
import com.supermap.services.components.commontypes.MapImage;
import com.supermap.services.components.commontypes.MapParameter;
import com.supermap.services.components.commontypes.OutputFormat;
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.ReturnType;
import com.supermap.services.interfaces.Protocol;
import com.supermap.services.util.Tool;
/**
* <p>
* BingMaps REST 地图服务 URI:http://dev.virtualearth.net/REST/v1/Imagery/Map/ imagerySet?mapArea=mapArea&mapSize=mapSize&key=BingMapsKey
* imagerySet:地图名称
* mapArea:南纬,西经,北纬,东经
* mapSize:图片宽度,图片高度
* BingMapsKey:BingMaps 访问密匙
*
* http://dev.virtualearth.net/REST/v1/Imagery/Map/ Road?mapArea=30.0,100.0,50.0,120.0&mapSize=512,512&key=BingMapsKey
* http://localhost:8090/iserver/services/map-world/bingmaps/世界地图?mapArea=30.0,100.0,50.0,120.0&mapSize=512,512
* </p>
*/
@Interface(componentTypes = { com.supermap.services.components.Map.class }, optional = false, multiple = false)
@Protocol(names={"BingMaps"})
public class BingMapsServlet extends HttpServlet implements InterfaceContextAware {
private Map mapImpl;
public BingMapsServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取服务的根路径,在 iServer 中,根路径为:/iserver/services/<servicecomponent>/<serviceinterface>
String rootPath = request.getContextPath() + request.getServletPath();
String requestURI = request.getRequestURL().toString();
java.util.Map<String, String> paramMap = request.getParameterMap();
int rootPathIndex = requestURI.indexOf(rootPath);
String remainPart = requestURI.substring(rootPathIndex + rootPath.length() + 1);
//地图名称
String mapName = (remainPart.indexOf('/') == -1 ? remainPart : remainPart.substring(0, remainPart.indexOf('/')));
mapName = URLDecoder.decode(mapName,"utf-8");
//地理范围和图片大小
String mapArea = (String) request.getParameter("mapArea");
String mapSize = (String) request.getParameter("mapSize");
String[] mapAreaStrs = mapArea.split(",");
String[] mapSizeStrs = mapSize.split(",");
if(mapAreaStrs.length < 4||mapSizeStrs.length < 2){
return;
}
Rectangle2D viewBounds = new Rectangle2D(Double.valueOf(mapAreaStrs[1]),Double.valueOf(mapAreaStrs[0]),
Double.valueOf(mapAreaStrs[3]),Double.valueOf(mapAreaStrs[2]));
Rectangle viewer = new Rectangle(0, 0, Integer.valueOf(mapSizeStrs[0]), Integer.valueOf(mapSizeStrs[1]));
try {
MapParameter mapParameter = this.mapImpl.getDefaultMapParameter(mapName);
mapParameter.viewBounds = viewBounds;
mapParameter.viewer = viewer;
mapParameter.name = mapName;
mapParameter.rectifyType = RectifyType.BYVIEWBOUNDS;
//返回图片流
mapParameter.returnType=ReturnType.BINARY;
ImageOutputOption outputOption = new ImageOutputOption();
//图片格式为 PNG
outputOption.format = OutputFormat.PNG;
MapImage mapImage=null;
if (mapImpl != null) {
mapImage = mapImpl.getMapImage(mapParameter, outputOption);
}
if(mapImage.imageData!=null){
//获取 mapImage 中的图片流,写入 HTTP 响应
response.getOutputStream().write(mapImage.imageData);
}
} catch (MapException e) {
e.printStackTrace();
}
}
public void setInterfaceContext(InterfaceContext context) {
//从服务接口上下文中获取服务接口配置,这里没有配置
//InterfaceConfig interfaceConfig = context.getConfig(InterfaceConfig.class);
//从服务接口上下文中获取服务组件(这里是地图服务组件)
List<Map> components = context.getComponents(Map.class);
if (components != null) {
for (Object component : components) {
if (component instanceof Map) {
this.mapImpl = (Map) component;
break;
}
}
}
}
}
编译后,将 Jar 包放到 %SuperMap iServer_HOME%\webapps\iserver\WEB-INF\lib 目录下。
在服务接口配置文件中(参见:服务配置文件结构)中添加 BingMapsREST 服务接口,即添加< interface />节点如下:
<interface class="com.supermap.sample.serviceinterface.BingMapsServlet" name="bingmapsrest">
</interface>
修改 map-world 地图服务组件的配置,添加 bingmapsrest 到 map-world 绑定的服务接口,如下:
<component class="com.supermap.services.components.impl.MapImpl" interfaceNames="rest,wms111,wms130,wmts100,bingmapsrest"
name="map-world" providers="ugcMapProvider-World">
<config class="com.supermap.services.components.MapConfig">
</config>
</component>
对 URI:http://localhost:8090/iserver/services/map-world/bingmaps/世界地图?mapArea=10.0,100.0,50.0,180.0&mapSize=512,512执行 GET 请求,获取 png 格式的地图图片如下:
