表述生成器扩展

发送反馈


作为示例,这里对几何对象空间分析结果(如 geometryBufferResult 资源)的表述格式进行扩展,增加一种伪 KML 格式,即根据分析结果中的面生成一个简单的 KML 面。

实现新的表述生成器伪 KML

第一步,确定该 KML 表述的媒体类型为“application/mykml”,在 iServer 中,默认地,当 GET 请求的 URI 后缀为“.kml”时,iServer 服务器会返回媒体类型为“application/mykml”的 HTTP 响应(关于 URI 后缀和媒体类型的对应关系,可以显式配置,参见:URI 后缀与媒体类型对应关系);

第二步,基于 javax.ws.rs.ext.MessageBodyWriter,使用@Provider 标注来注册使用自定义的 MessageBodyProvider,即 FakeKMLEncoder,并使用@Produces 将媒体类型指定为"application/mykml";

第三步,自定义 KML 文件,为一个面对象,实现将一个 Geometry 表示的面转化为一个 KML 表示的面;

第四步,判断返回结果是否支持解析为"application/mykml"媒体类型,如果支持则返回媒体类型为“application/mykml”的响应结果,即返回一个 kml 文件。

以上过程实现代码如下,代码文件可在%SuperMap iServer_HOME%\samples\code\ExtendExist_JSR\FakeKMLEncoder.java 获取。

package com.supermap.sample.extend;

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.Writer;

import java.lang.annotation.Annotation;

import java.lang.reflect.Type;

import javax.ws.rs.Produces;

import javax.ws.rs.WebApplicationException;

import javax.ws.rs.core.MediaType;

import javax.ws.rs.core.MultivaluedMap;

import javax.ws.rs.ext.MessageBodyWriter;

import javax.ws.rs.ext.Provider;

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

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

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

@Provider

@Produces("application/mykml")

public class FakeKMLEncoder implements MessageBodyWriter {

        // 确定要写入的对象序列化之后的长度,-1表示未知

        public long getSize(Object object, Class type, Type genericType,

                        Annotation[] annotations, MediaType mediaType) {

                return -1;

        }

        /**

         * <p>

         * 是否支持 解析 application/kml 媒体类型

         * </p>

         */

        public boolean isWriteable(Class type, Type genericType,

                        Annotation[] annotations, MediaType mediaType) {

                if (mediaType.equals(new MediaType("application", "mykml"))) {

                        return true;

                }

                return false;

        }

        public void writeTo(Object resourceObj, Class type, Type genericType,

                        Annotation[] annotations, MediaType mediaType,

                        MultivaluedMap httpHeaders, OutputStream entityStream)

                        throws IOException, WebApplicationException {

                String result;

                // KML 名称(<name/>标签)

                String resultName = "result.kml";

                if (resourceObj instanceof Geometry) {

                        Geometry geometry = (Geometry) resourceObj;

                        result = this.createKMLRegion(resultName, geometry);

                } else if (resourceObj instanceof GeometrySpatialAnalystResult) {

                        Geometry geometry = ((GeometrySpatialAnalystResult) resourceObj).resultGeometry;

                        result = this.createKMLRegion(resultName, geometry);

                } else {

                        result = "响应结果不是一个合法的 Geometry 对象";

                }

                // 将 KML 文件写入 entityStream,作为 KML 表述的消息体。

                Writer writer = new BufferedWriter(new OutputStreamWriter(entityStream,

                                "utf-8"));

                writer.write(result.toString(), 0, result.length());

                writer.close();

        }

        // 将一个表示面的 Geometry 转化为一个 KML 表示的面

        private String createKMLRegion(String filename, Geometry geometry) {

                Point2D[] points = geometry.points;

                // 转换成 KML 中的点串(<coordinates/>标签内容)

                String coordinates = "";

                for (Point2D point : points) {

                        coordinates += point.x + "," + point.y + "," + "0 \n";

                }

                // 自定义的 KML 文件,为一个面对象

                StringBuffer sb = new StringBuffer();

                sb.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");

                sb.append("<Placemark>\n");

                sb.append("<name>" + filename + "</name>\n");

                sb.append("<Polygon>\n<outerBoundaryIs>\n<LinearRing>\n<coordinates>\n");

                sb.append(coordinates);

                sb.append("</coordinates>\n</LinearRing>\n</outerBoundaryIs>\n</Polygon>\n");

                sb.append("</Placemark>\n");

                sb.append("</kml>");

                return sb.toString();

        }

}

伪 KML 表述的配置

模块配置文件的配制方法,如配置文件说明所述,在【Jar 包】\META-INF\extensions\services\spatialAnalystRest 中添加如下内容:

encoders=com.supermap.sample.extend.FakeKMLEncoder

resourceFiles=MyBufferAnalystRest.xml

将以上代码所在的工程文件 ExtendExist_JSR 导出为 JAR 包(参见:extendexist_jsr.jar),并放在%SuperMap iServer_HOME%\webapps\iserver\WEB-INF\lib 下,即可完成配置。

示范代码请参见:%SuperMap iServer_HOME%\samples\code\ExtendExist_JSR,可在 Eclipse 中作为 Java 工程直接导入使用。需要注意的是,Jar 包中需要有目录条目,在 Eclipe 中导出 Jar 包时,勾选"Add directory entries"即可(如下图所示)。

伪 KML 表述的使用

此处以 Geometry 空间分析中的 buffer 分析结果为例介绍伪 KML 表述的使用方法。启动 SuperMap iServer 服务,访问 http://supermapiserver:8090/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst/geometry/buffer 资源,将左右缓冲区距离改为1,其他各项采用默认设置,执行 POST 请求,得到分析结果为:http://supermapiserver:8090/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst/geometry/buffer/1.mykml

保存1.mykml 文件到本地,修改后缀后,在三维场景中的效果如下图所示:

注:可使用 SuperMap iDesktop 中加载 KML,打开已有三维场景或新建三维场景,在三维场景的图层管理器中,点击普通图层,右键选择添加 KML 图层,把上述 KML 文件加载在场景中即可。