SuperMap iServer 中提供的 Encoder 有:模板表述生成器(主要用于生成 HTML 格式的表述)、 Json 表述生成器、RJson(格式化的 Json) 表述生成器、XML 表述生成器、图片表述生成器(支持 BMP、GIF、JPEG、JPG、PNG 等图片格式)等。资源根据客户端请求中指定的媒体类型(期望的表述格式),选择合适的 Encoder 将结果(内容)进行处理,返回给客户端。
SuperMap iServer 提供了 Encoder 的扩展机制。当将资源发布成一种新的表述格式,而这种表述格式 SuperMap iServer 中现有的 Encoder 并不能提供,这时可以对 Encoder 进行扩展,从而可以用新的表述格式将资源发布出来。
表述生成器基类介绍
在 SuperMap iServer 的 REST 实现框架中,提供了 com.supermap.services.rest.encoders.Encoder 抽象类用于表述生成器,所有的表述生成器都继承自该类。例如,在 SuperMap iServer 中已提供的 ImageEncoder, JsonEncoder, SceneEncoder, StreamEncoder, TemplateEncoder, XMLEncoder 等。
用户对表述生成器进行扩展,既可以继承 Encoder 抽象类,对其中的抽象方法进行实现,也可以继承现有的表述生成器类,改写其中的方法。其中,重要的方法如下表所示:
方法名称 | 含义 |
createSupportedMediaTypes() | 创建本表述生成器支持的表述格式的列表。即能将 Java 对象转换成什么媒体类型的表述。 |
toRepresentation(MediaType, Object) | 将 Java 对象转换成指定媒体类型的表述。 |
继承 Encoder 抽象类(或其子类),实现(或重写)上表中的两个方法,就可以实现一个自定义的表述生成器。
实例
扩展一个表述生成器,仅为说明问题,该扩展实现了一个跟 JsonEncoder 基本一样的表述生成器 MyEncoder,只是支持的媒体类型改为“application/cjson”这种自定义的媒体类型,cjson 格式的表述内容跟 json 格式完全一致,只是 HTTP 响应中的媒体类型不同(由 application/json 变为 application/cjson)。具体应用时,可以根据需求定义具体的实现。该实例代码位于【SuperMap iServer 安装根目录】/samples/code/ExtendREST 中。
第一步,设计并实现代码。MyEncoder 的示例代码如下:
package com.supermap.sample.extendREST;
import java.util.ArrayList;
import java.util.List;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import com.supermap.services.rest.encoders.JsonEncoder;
public class MyEncoder extends JsonEncoder{
public Representation toRepresentation(MediaType mediaType, Object resourceObj) {
//得到表述内容,内容跟 JSON 表述生成器转换得到的内容一致。
Representation rep = super.toRepresentation(mediaType, resourceObj);
if(rep != null){
//设置 HTTP 响应中的媒体类型为 application/cjson。
rep.setMediaType(new MediaType("application/cjson"));
}
return rep ;
}
protected List<MediaType> createSupportedMediaTypes() {
List<MediaType> supportedMediaTypes = new ArrayList<MediaType>(); // NOPMD
//MyEncoder 表述生成器支持的媒体类型为 application/cjson
supportedMediaTypes.add(new MediaType("application/cjson"));
return supportedMediaTypes;
}
}
第二步,编译 MyEncoder 类成 Jar 包,并将 Jar 包放到【安装根目录】/webapps/iserver/WEB-INF/lib 目录下,这里将它打进 extendREST.jar 中。
第三步,将自定义的表述生成器配置到 REST 服务。
配置自定义的表述生成器到 REST 服务,首先要将实现类注册成一个组件,然后将组件配置到资源中。既可以配置到单个资源,为单个资源所有,也可以配置到所有资源,成为所有资源都支持的表述生成器。流程如下所示:
注册 MyEncoder 类为 Bean 组件,需要在 REST 应用配置文件中添加一个<bean/>节点,REST 应用配置文件 AppContext.xml 位于【安装根目录】/webapps/iserver/WEB-INF 目录下。如下所示,将 MyEncoder 类注册成了 MyEncoder Bean 组件(class 的路径为 MyEncoder 类在 Jar 包中的路径):
<bean id="MyEncoder" class="com.supermap.sample.extendREST.MyEncoder"></bean>
-
配置到单个资源
配置到单个资源需要在资源配置文件 Resources.xml 中进行。每一个资源配置项(<resource/>)都可以有一个 <extensionEncoderBeanNames/> 子节点,表示扩展的资源表述生成器有哪些。它的取值为已注册过的 Bean 组件的 ID,如果有多个 Bean 组件,则 ID 之间用“,”隔开。这样,该资源配置项对应的资源就拥有了额外的表述生成器。如将 MyEncoder 组件配置到 rectangleArea 资源如下:
<resource>
<configID>rectangleArea</configID>
<urlTemplate>/maps/{mapName}/rectangleArea</urlTemplate>
<resourceType>ArithmeticResource</resourceType>
<implementClass>com.supermap.sample.extendREST.rectangleAreaResource</implementClass>
<extensionEncoderBeanNames>MyEncoder</extensionEncoderBeanNames>
<extensionDecoderBeanNames></extensionDecoderBeanNames>
<extensionHttpActionHandlerBeanName></extensionHttpActionHandlerBeanName>
</resource>
这样,rectangleArea 资源就多了一种可用的表述生成器——MyEncoder,从而可以支持 application/cjson 这种表述格式。
需要说明的是,在 SuperMap iServer REST 服务中,服务器根据请求 URI 的后缀来选择表述生成器,从而返回不同类型的表述。默认地,服务器会根据值为“application/后缀名”的媒体类型去选择表述生成器,例如当 URI 后缀为 cjson 时,服务器就会去选择支持“application/cjson”这种媒体类型的表述生成器,在这里,就找到了 MyEncoder,由 MyEncoder 对结果进行处理,并返回客户端,响应的媒体类型即为“application/cjson”。当然,如果你不想使用这种 URI 后缀跟媒体类型的对应关系,也可以在 REST 应用配置文件(AppContext.xml)中修改,例如显式地声明 cjson 跟 application/cjson 的对应关系,可以在 AppContext.xml 中修改如下:
<beans>
......
<!-- 表述类型与 url 后缀的映射关系。 -->
<util:map id="MediaTypeMappingInfoBean">
......
<entry key="cjson" value="application/cjson" />
</util:map>
</beans>
重启服务后,在 IE 中输入以下 URI,模拟 GET 请求,获取资源 cjson 的表述格式:
http://localhost:8090/iserver/services/components-rest/rest/maps/世界地图/rectangleArea.cjson?rect2D={leftBottom:{x:23,y:34},rightTop:{x:40,y:50}}&unit=METER
由于 application/cjson 这种媒体类型是这里自定义的一种媒体类型,IE 不能解析 ,所以提示保存文件,如下所示:
用文本编辑器打开保存之后的文件,里面存放了量算的结果。(正如前面示例说明中所讲,仅做示例,内容跟 json 格式的表述一样)。
-
配置到所有资源
配置到所有资源需要在 REST 应用配置文件 AppContext.xml 中进行。即增加一个默认表述生成器。默认表述生成器在 AppContext.xml 中由 key="systemEncoders"的<entry/>节点表示。将 MyEncoder 组件在 AppContext.xml 中注册到所有资源,如下所示:
<beans>
......
<util:map id="restConfig">
<entry key="systemEncoders" value="xmlEncoder,jsonEncoder,pjsonEncoder,templateEncoder,MyEncoder" />
</util:map>
......
</beans>
这样,所有的资源都可以使用 MyEncoder 表述生成器,效果跟 rectangleArea 资源的 cjson 格式表述类似。
需要说明的是,MyEncoder 这个表述生成器比较简单,没有实际意义,仅仅是作为例子说明扩展表述生成器的过程。
注:Resources.xml、AppContext.xml 位于%SuperMap iServer_HOME%/webapps/iserver/WEB-INF 目录下。