资源的基类介绍

SuperMap iServer 为实现资源的扩展专门提供了一些资源基类,他们分别是:

资源基类类型    资源基类名称 资源类型说明 继承该类已实现的资源
所有资源的抽象基类 ResourceBase 所有资源的抽象基类  
简单算法资源 SimpleAlgorithmResultResourceBase 所谓简单算法资源即对该资源传递的参数可以包含在 URI 中;ImageResourceBase 和 MeasureResourceBase 都是其子类。 symbol、clearCache 资源
ImageResourceBase   图片类型的简单算法资源基类,所有跟出图相关的 REST 资源实现都继承自该类。 entireImage、highlightImage、image、overview、tileImage 资源
MeasureResourceBase   量算资源的简单算法资源基类。 area、distance 资源
算法资源  AlgorithmResultSetResource   所谓算法资源即对该资源传递的参数需要通过 POST 方法进行传递。 queryResult 资源
算法结果资源 AlgorithmResultResource 仅支持 GET 操作,通常利用算法资源(AlgorithmResultSetResource)的 POST 操作设置参数后,通过该类获取结果。 queryResults 资源
静态资源 StaticResource   对某种事物的描述,如 layers,map 都是在 StaticResource 类的基础上扩展的一种静态资源。 layers、map、templayers 资源

目录列表资源   

CatalogListResourceBase 顾名思义,对某类事物集合的目录的表达。 maps、root、tempLayersSet、trackingLayers、domainComponents、domainComponent 资源
异步算法资源  AsynchronizedResource 计算比较耗时的一类算法资源。  

这些资源基类分别代表不同类型的资源,这为扩展 REST 资源的开发提供了极大方便,用户可以根据欲扩展的资源的功能去寻找合适的抽象类进行扩展。当预期的资源跟 SuperMap iServer 某个已实现的资源比较类似的话,也可以直接对该资源的实现进行继承,改写一些方法,从而快速地扩展一个新资源。

有关 SuperMap iServer 中, REST 资源抽象类和实现类的情况,请参见 JavaDoc 文档:com.supermap.services.rest.resources 和 com.supermap.services.rest.resources.impl 包。

实例

扩展一个名为 rectangleArea 的资源,实现量算地图上一块矩形区域的面积的功能,并将结果直接返回。该实例代码位于【SuperMap iServer 安装根目录】/samples/code/ExtendREST 中。

第一步:设计资源,包括该资源在 SuperMap iServer 的资源中的位置,资源的请求参数,响应结构等。

a)资源的位置:由于要量算的对象是地图,把 rectangleArea 资源作为地图资源(map 资源)的一个子资源比较合适,设计 URI 为:

http://<server>:<port>/iserver/services/components-rest/rest/maps/{mapName}/rectangleArea[.<format>]

b)设计请求参数为:

名称

类型

含义
rect2D Rectangle2D 地图上欲量算的目标矩形区域。
unit Unit

期望返回结果的单位。

c)设计响应结构为:

字段

类型

说明

area  

double 量算的面积大小的值。
unit  Unit 量算结果的单位。

d)设计使用的基类。

rectangleArea 资源跟简单算法资源比较类似,所以它的实现类 rectangleAreaResource 通过继承 SimpleAlgorithmResultResourceBase 抽象类来实现。SimpleAlgorithmResultResourceBase 类中的抽象方法是必须实现的,如下表所示,详细请参考 JavaDoc 文档。

抽象方法名称

含义
isResourceExist() 判断当前资源是否可用。
checkUrlParamValid(Map) 检查 URI 中的参数是否合法,不合法则抛出异常。
createArithParamClassMappings() 给出算法参数的类型,即请求参数的字段名和类型。
runArithMetic(Map) 利用参数运行算法得到算法结果。

第二步:设计资源的业务逻辑,即量算的功能可以由地图组件(com.supermap.services.components.Map)的一个实现类 com.supermap.services.components.impl.MapImpl(SuperMap iServer 已经提供)来进行,在示例 rectangleAreaResource 类中,地图名和 MapImpl 组件的获取放在了构造函数中进行,地图名从请求对象(URI)中获取,MapImpl 对象从 REST 应用上下文获取。示例代码如下:

package com.supermap.sample.extendREST;

import java.util.HashMap;

import org.restlet.Context;

import org.restlet.Request;

import org.restlet.Response;

import com.supermap.services.components.Map;

import com.supermap.services.components.MapException;

import com.supermap.services.components.commontypes.MeasureParameter;

import com.supermap.services.components.commontypes.MeasureResult;

import com.supermap.services.components.commontypes.Point2D;

import com.supermap.services.components.commontypes.Rectangle2D;

import com.supermap.services.components.commontypes.Unit;

import com.supermap.services.rest.resources.SimpleAlgorithmResultResourceBase;

import com.supermap.services.rest.util.MappingUtil;

public class rectangleAreaResource extends SimpleAlgorithmResultResourceBase{

    private String mapName;

    private MappingUtil mappingUtil;

    public rectangleAreaResource(Context context, Request request, Response response) {

        super(context, request, response);

        mappingUtil = new MappingUtil(this);

        this.mapName = this.mappingUtil.getMapName(this.getRequest());

        this.mapName = this.mapName.trim();

    }

    //判断资源是否存在

    public boolean isResourceExist(){

//      Logger.info("rectangle area resource exist");

        boolean flag = false;

        flag = this.mappingUtil.isMapExist(this.mapName);

        return flag;

    }

  //运行算法得到结果

    protected Object runArithMetic(java.util.Map params){

        Object arithResult=null;

        //如果参数为空,返回 area 字段为 -1

        if(params==null||0==params.size()){

            MeasureResult  result =   new MeasureResult();

            result.area = -1;

            arithResult = result ;

        }else{

                Rectangle2D rect = (Rectangle2D)params.get("rect2D");

            Unit  unit = (Unit)params.get("unit");

            //单位参数可以不传,默认为米。

            if(unit == null){

                unit = Unit.METER;

            }

            //量算参数类,其中存储了单位信息。

            MeasureParameter measureParam = new MeasureParameter();

            measureParam.unit = unit;

            //将 Rectangle2D 转化为 Point2Ds

            Point2D leftBottom=rect.leftBottom;

            Point2D rightTop=rect.rightTop;

            Point2D leftTop=new Point2D(leftBottom.x,rightTop.y);

            Point2D rightBottom=new Point2D(rightTop.x,leftBottom.y);

            Point2D[] point2Ds={leftBottom,leftTop,rightTop,rightBottom};

            //量算结果

            try {

                Map mapComponent = this.mappingUtil.getMapComponent();

                                arithResult = mapComponent.measureArea(mapName, point2Ds, measureParam);

                        } catch (MapException e) {

                                // TODO Auto-generated catch block

                                e.printStackTrace();

                        }

        }

        return arithResult;

    }

    //给出算法参数的类型,即请求参数的结构。

    protected java.util.Map<String, Class> createArithParamClassMappings(){

        java.util.Map<String, Class> paramClassMapping = new HashMap<String, Class>();

        paramClassMapping.put("rect2D", Rectangle2D.class);

        paramClassMapping.put("unit", Unit.class);

        return paramClassMapping;

    }

    //判断 URI 中的参数是否合法,不合法则抛出异常。为了示例的清晰,这里没有判断。

        protected void checkUrlParamValid(java.util.Map arg0) {

                // TODO Auto-generated method stub

          }

}

第三步:编译成 Jar 包。例如 ExtendREST.jar,放到【SuperMap iServer 安装根目录】/webapps/iserver/WEB-INF/lib 目录下。

第四步:添加资源信息到资源配置文件。

需要在【安装根目录】/webapps/iserver/WEB-INF/Resources.xml 中配置扩展资源的资源配置信息,这样,在 SuperMap iServer REST 服务启动的时候,就能自动找到扩展的资源,并发布成 REST 服务。Resouces.xml 文件的结构如下:

<resources>

     ......

     <resource>

            ......

     <resource/>

</resources>

其中,一个 <resource/> 节点表示的就是一个资源的信息,<components/> 节点是发布领域组件时,配置领域组件的地方。

以 rectangleArea 资源为例,<resource/> 节点的结构如下所示:

<resource>

    <configID>rectangleArea</configID>

    <urlTemplate>/maps/{mapName}/rectangleArea</urlTemplate>

    <resourceType>ArithmeticResource</resourceType>

    <implementClass>com.supermap.sample.extendREST.rectangleAreaResource</implementClass>

    <extensionEncoderBeanNames></extensionEncoderBeanNames>

    <extensionDecoderBeanNames></extensionDecoderBeanNames>

    <extensionHttpActionHandlerBeanName></extensionHttpActionHandlerBeanName>

</resource>

其中含义如下:

  • configID:资源的名称。

  • urlTemplate:欲设置的资源 URI 路径(根节点之后的路径)。

  • resourceType:资源的类型,资源的类型有:ArithmeticResource(简单算法资源)、ArithResultResource(算法结果资源)、ArithResultSetResource(算法结果集资源)、CatalogList(目录资源)、DomainArithmeticResource(领域算法资源)、DomainArithResultResource(领域算法结果资源)、StaticResource(静态资源)等,参见 JavaDoc API 文档中 ResourceType 枚举。

  • implementClass:资源的实现类,即该类在 Jar 包(【安装根目录】/webapps/iserver/WEB-INF/lib 目录下,如 ExtendREST.jar)中的路径。

  • extensionEncoderBeanNames:表述生成器组件名称。

  • extensionDecoderBeanNames:参数解析器组件名称。

  • extensionActionHandlerBeanName: HTTP 请求处理器组件名称。

注意:资源配置中,extensionEncoderBeanNames、extensionDecoderBeanNames、extensionActionHandlerBeanName 节点可以没有或为空,这时 SuperMap iServer 会使用默认的值。它们表示该资源对应的扩展表述生成器、扩展参数解码器、扩展 HTTP 请求处理器的实现,在使用这些扩展点的时候会用到,这里暂不深入介绍。

第五步:运行调试。rectangleArea 资源可以实现量算地图上一块矩形区域的面积。启动服务(这里从本机启动),访问 http://localhost:8090/iserver/services/components-rest/rest/maps/世界地图/rectangleArea.xml(这里以 xml 表示格式为例,同时支持其他形式的表述),即访问 World Map 地图下的 rectangleArea 资源。

关于新资源对 HTML 表述的支持的说明

SuperMap iServer REST 服务中所有资源的 HTML 表述都是通过模板表述生成器(com.supermap.services.rest.encoders.TemplateEncoder)按照 FreeMarker 模板文件(*.ftl)指定的格式生成的表述。目前 SuperMap iServer REST 服务提供的所有资源都有各自的 FreeMarker 模板文件用于支持 REST 服务返回 HTML 格式的表述,这些资源的 FreeMarker 模板文件统一存储于【安装根目录】/webapps/iserver/WEB-INF/lib/iserver-all-{version}.jar 中 templates 目录中。用户也可以根据具体需要按照 FreeMarker 的语法为某个/些资源重新定义 FreeMarker 模板文件。 值得注意的是,用户定义的 FreeMarker 模板文件的命名必须与该资源的 ID 一致。

FreeMarker 是基于模板生成文本输出的通用工具。在 SuperMap iServer 的 REST 框架下,资源的 *.ftl 模板文件中的 ${resource.content.*} 表示表述结果的字段,而且文件名必须跟资源的 ID (即资源配置文件中 configID 节点的值)一致。

为了使上节中 rectangleArea 资源能够支持 HTML 表述格式,编写对应的 FreeMarker 模板文件 rectangleArea.ftl 如下,rectangleArea.ftl 需要放在【安装根目录】/webapps/iserver/WEB-INF/lib 目录下的一个 Jar 包中,建议跟资源实现类打在一个 Jar 包 ExtendREST.jar 中,rectangleArea.ftl 在 Jar 包中,必须放在 【Jar 包】/templates 目录下。

<#include "head.ftl">

<h1>rectangleArea 资源</h1>

<br>

<b>资源描述:</b> 面积量算结果资源,用于描述一个面积量算的结果。

<br>

<#if resource.content.area!= -1>

 <p>

 <table width="150px" id="userTable">

<tr valign="left">

<#setting number_format="#0.000000000#">

<td style="width:50px"> <h5>area:</h5></td> <td style="width:50px"> ${resource.content.area}</td>

</tr>

<tr valign="left">

<td style="width:50px"> <h5 >unit:</h5></td> <td style="width:50px">${resource.content.unit}</td>

</tr>

 </table>

 </p>

 <#else>

    <br> <br>

 请设置 rect2D 参数。 没有设置 rect2D 参数,则结果返回-1 表示量算失败。

 </#if>

<p>

<form method="get" >

<table style="border:1px solid #000000;width:800;" >

   <#assign prerect2D>{leftBottom:{x:23,y:34},rightTop:{x:40,y:50}}</#assign>

 

    <tr><td>rect2D</td><td><textarea type="text" style="width:255px;height:50px" name="rect2D" >${prerect2D}</textarea></td></tr>

    <tr><td>unit</td><td>

     <select name="unit">

<option value="METER" selected="selected">METER</option>

<option value="KILOMETER" selected="selected">KILOMETER</option>

<option value="MILE" selected="selected">MILE</option>

<option value="YARD" selected="selected">YARD</option>

<option value="DEGREE" selected="selected">DEGREE</option>

<option value="MILLIMETER" selected="selected">MILLIMETER</option>

<option value="CENTIMETER" selected="selected">CENTIMETER</option>

<option value="INCH" selected="selected">INCH</option>

<option value="DECIMETER" selected="selected">DECIMETER</option>

<option value="SECOND" selected="selected">SECOND</option>

<option value="MINUTE" selected="selected">MINUTE</option>

<option value="RADIAN" selected="selected">RADIAN</option>

 </select>

 </td></tr>

    <tr><td></td><td><input type="submit" value="rect2DareaMeasure"/></td></tr>

</table>

</form>

</p>

<br>

<br>

<hr>

<#include "tail.ftl">