表述生成器扩展 |
作为示例,这里对几何对象空间分析结果(如 geometryBufferResult 资源)的表述格式进行扩展,增加一种伪 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();
}
}
模块配置文件的配制方法,如配置文件说明所述,在【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"即可(如下图所示)。
此处以 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 文件加载在场景中即可。