扩展一个 HTTP 请求处理器 |
由 REST 服务发布机制简述 可知,HTTP 请求在达到 REST 应用对象,交给资源实现类处理的时候,整个处理的流程是由 HTTP 请求处理器来管理的,SuperMap iServer 提供了默认的 HTTP 请求处理器实现(DefaultMethodHandler)来管理这个流程。
SuperMap iServer 也提供了对 HTTP 请求处理器的扩展机制,使用户能够自己控制资源实现类的处理 HTTP 请求的流程,扩展 HTTP 请求处理器可以分如下两步:
在 SuperMap iServer 的 REST 实现框架中,提供了 com.supermap.services.rest.AbstractMethodHandler 抽象类用于 HTTP 请求处理器,所有的 HTTP 请求处理器都继承自该类。SuperMap iServer 默认提供的 HTTP 请求处理器有 DefaultMethodHandler。
用户扩展 HTTP 请求处理器,需要继承 AbstractMethodHandler 抽象类,实现其中的抽象方法,或继承 DefaultMethodHandler,改写其中的方法。其中,重要的方法如下表所示:
方法名称 | 含义 |
handleGet(ResourceBase, Request, Response) | 使用目标资源处理 GET 请求。 |
handleHead(ResourceBase, Request, Response) | 使用目标资源处理 HEAD 请求。 |
handlePost(ResourceBase, Request, Response) | 使用目标资源处理 POST 请求。 |
handlePut(ResourceBase, Request, Response) | 使用目标资源处理 PUT 请求。 |
handleDelete(ResourceBase, Request, Response) | 使用目标资源处理 DELETE 请求。 |
handleOptions(ResourceBase, Request, Response) | 使用目标资源处理 OPTIONS 请求。 |
作为示例,这里实现一个简单的 HTTP 请求处理器:MyMethodHandler,实际实现其中的 handleGET 方法,实现以下逻辑:
不再读取 HTTP 请求中,客户端期望的表述类型,对所有的 GET 请求,只返回 XML 格式的表述。
MyMethodHandler 继承于 AbstractMethodHandler 抽象类,其实现如下:
示例代码如下:
package com.supermap.sample.extendREST;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import com.supermap.services.rest.AbstractMethodHandler;
import com.supermap.services.rest.encoders.Encoder;
import com.supermap.services.rest.encoders.XMLEncoder;
import com.supermap.services.rest.resources.ResourceBase;
public class MyMethodHandler extends AbstractMethodHandler {
@Override
public void handleGet(ResourceBase targetResource, Request request, Response response) {
// TODO Auto-generated method stub
Encoder encoder = null;
if (targetResource.isResourceExist()) {
//强制使用 XML 表述生成器。
encoder = new XMLEncoder();
Object content = targetResource.getResourceContent();
if (content != null) {
// 不管请求如何,都返回 XML 格式的资源的表示。
Representation entity = encoder.toRepresentation(MediaType.TEXT_XML, content);
response.setEntity(entity);
response.setStatus(Status.SUCCESS_OK);
} else {
// 资源没有表示。
response.setStatus(Status.SUCCESS_NO_CONTENT);
}
} else {
// 处理资源不存在异常。
response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
}
}
@Override
public void handleHead(ResourceBase arg0, Request arg1, Response arg2) {
// TODO Auto-generated method stub
}
@Override
public void handleOptions(ResourceBase arg0, Request arg1, Response arg2) {
// TODO Auto-generated method stub
}
@Override
public void handlePost(ResourceBase arg0, Request arg1, Response arg2) {
// TODO Auto-generated method stub
}
@Override
public void handlePut(ResourceBase arg0, Request arg1, Response arg2) {
// TODO Auto-generated method stub
}
@Override
public void handleDelete(ResourceBase arg0, Request arg1, Response arg2) {
}
}
至此,一个特殊的 HTTP 请求处理器类就完成了。你可以在%SuperMap iServer_HOME%/samples/code/ExtendREST 下找到该实例程序的源代码。
MyMethodHandler 类编译后,也需要打成 Jar 包放到%SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib 目录下,这里将它打进 extendREST.jar 中。
将自定义的 HTTP 请求处理器配置到 REST 服务的流程跟将自定义的表述生成器配置到 REST 服务的流程类似。也是先注册成为 Bean 组件,然后再配置到单个资源或所有资源。
需要说明的是,配置到 iserver-rest-resources.xml 中的节点变成了 <extensionHttpActionHandlerBeanName/>,配置到所有资源,即配置 iserver-rest-appContext.xml 的<util:map id="restConfig"/>时,<entry/>变成了 key 值为 defaultHttpActionHandler 的<entry/>。
这里在 MyMethodHandler 注册成名为 MyHTTPHandler 的 Bean 组件后,将 MyHTTPHandler 配置到 maps 资源中,maps 资源的资源配置信息位于 %SuperMap iServer_HOME%/lib/iserver-all-{version}.jar/config/rest 下的 mappingResources.xml 中。如下所示:
<resource>
<configID>maps</configID>
<urlTemplate>/maps</urlTemplate>
<resourceType>CatalogList</resourceType>
<implementClass>com.supermap.services.rest.resources.impl.MapsResource</implementClass>
<extensionEncoderBeanNames></extensionEncoderBeanNames>
<extensionDecoderBeanNames></extensionDecoderBeanNames>
<extensionHttpActionHandlerBeanName>MyHTTPHandler</extensionHttpActionHandlerBeanName>
</resource>
至此,一个 HTTP 请求处理器的扩展就完成了,注意,跟表述生成器、参数解析器略有不同的是,一个资源虽然可以有多个可用的表述生成器和参数解析器,却只能有一个 HTTP 请求处理器。
重启服务,最简单地,在 IE 中输入以下 URI,对服务器发送 GET 请求,请求的表述格式为 Json:
http://localhost:8090/iserver/services/components-rest/rest/maps.json
你会发现,返回的是 XML 格式的表述,而不是预期的 Json 格式,因为我们对 maps 资源的 HTTP 请求处理器做了替换,换成了自定义的 MyHTTPHandler,正如前面所讲,MyHTTPHandler 组件对应的类 MyMethodHandler 中,处理 GET 请求时强制生成了 XML 格式的表述。
需要说明的是,本实例仅为了说明扩展 HTTP 请求的过程,采用了一种说明问题的方式(即对 GET 请求强制生成 XML 表述),实际应用中你可以做的事情很多,比如在这里改变 HTTP 请求的处理流程、加入额外的业务处理逻辑等等。