扩展一个 HTTP 请求处理器

发送反馈


REST 服务发布机制简述 可知,HTTP 请求在达到 REST 应用对象,交给资源实现类处理的时候,整个处理的流程是由 HTTP 请求处理器来管理的,SuperMap iServer 提供了默认的 HTTP 请求处理器实现(DefaultMethodHandler)来管理这个流程。

SuperMap iServer 也提供了对 HTTP 请求处理器的扩展机制,使用户能够自己控制资源实现类的处理 HTTP 请求的流程,扩展 HTTP 请求处理器可以分如下两步:

  1. 实现一个 HTTP 请求处理器类

  2. 将自定义的 HTTP 请求处理器配置到 REST 服务

1. 实现一个 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 中。

2. 将自定义的 HTTP 请求处理器配置到 REST 服务

将自定义的 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 请求的处理流程、加入额外的业务处理逻辑等等。