GeoServer学习手记(十):一个完整的WMS请求响应过程
粟卫民http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期:2009-12-23
保留所有版权。如需转载,请联系作者,并在醒目位置注明出处
前面对Servlet及HTTP派发过程进行了介绍:
GeoServer学习手记(四):Servlet及HTTP派发过程之一:
http://blog.csdn.net/suen/archive/2009/11/02/4759332.aspx
GeoServer学习手记(五):Servlet及HTTP派发过程之二:
http://blog.csdn.net/suen/archive/2009/11/02/4759398.aspx
GeoServer学习手记(六):Servlet及HTTP派发过程之三:
http://blog.csdn.net/suen/archive/2009/11/02/4759410.aspx
GeoServer学习手记(七):Servlet及HTTP派发过程之四:
http://blog.csdn.net/suen/archive/2009/11/11/4799572.aspx
GeoServer学习手记(八):Servlet及HTTP派发过程之五:
http://blog.csdn.net/suen/archive/2009/11/11/4799587.aspx
也分析了WMS工程的包:
http://blog.csdn.net/suen/archive/2009/11/13/4808860.aspx
接下来以一个完整的WMS访问过程来分析WMS工程中代码执行的过程。
WMS的请求一般使用HTTP Get的形式直接从地址栏输入或者通过JS代码发送到服务器端。请求的格式如下所示:
http://localhost:8080/geoserver /wms?bbox=-74.01199448397661,40.70732689845813,-74.00841053684495,40.71216558957052&styles=&Format=application/openlayers&request=GetMap&version=1.1.1&layers=tiger:poi&width=457&height=550&srs=EPSG:4326,该请求中wms是要请求的服务,version=1.1.1是请求的wms版本,GetMap是请求的服务方法,tiger:poi是要访问的地理数据。
GeoServer的MVC架构是建立在Spring的Web MVC的基础之上的。Spring Web MVC的核心控制类是org.springframework.web.servlet.DispatcherServlet。HTTP请求一般都先发送给这个Servlet,做一些HTTP请求的通用处理(比如文件上载)后,通过合适的派发机制转发给不同的Spring容器中的Bean,也就是不同业务逻辑、服务处理的控制器(Logic Control),由这些控制器结合不同模型(Model),如空间数据模型、属性数据模型、地图样式模型等,进行处理,形成结果模型,并经 DispatcherServlet返回客户端。
org.springframework.web.servlet.DispatcherServlet相关配置位于GeoServer的Web工程的配置文件web.xml中。
1、Servlet声明
2、URL Mapping
这说明,对于/wms/*、/wcs/*、/wfs/*、/ows/*等地址的请求,都会调用org.springframework.web.servlet.DispatcherServlet对象来响应。
在Spring框架下,org.springframework.web.servlet.DispatcherServlet基于每个工程的applicationContext.xml的配置,将请求转发给专门的对象处理。其中,根据wms工程的配置,wms除putstyles路径下的请求,都由dispatcher处理。
<bean id="wmsURLMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"/>
<property name="mappings">
<props>
<prop key="/wms">dispatcherprop>
<prop key="/wms/putstyles">putStylesWrapperprop>
<prop key="/wms/*">dispatcherprop>
props>
property>
bean>
关于dispatcher对象的配置在main工程的applicationContext.xml,处理对象的类是org.geoserver.ows.Dispatcher。
<bean id="dispatcher" class="org.geoserver.ows.Dispatcher">
<property name="securityInterceptor">
<ref bean="operationSecurityInterceptor"/>
property>
bean>
org.geoserver.ows.Dispatcher继承自spring框架的AbstractController类。它对于HTTP请求的处理是在handleRequestInternal(HttpServletRequest httpRequest, HttpServletResponse httpResponse)中处理。此函数再调用本身的execute(Request req, Operation opDescriptor),先分析出请求的服务(Service)、版本(Version)、操作(Operation),然后根据配置信息与GeoServerExtensions匹配找到服务处理的Bean,wms的配置信息如下所示。
<bean id="wmsService2" class="org.geoserver.wms.DefaultWebMapService">
<constructor-arg ref="wms"/>
bean>
<alias name="wmsService2" alias="webMapService"/>
<bean id="wmsServiceDescriptor" class="org.geoserver.platform.Service">
<constructor-arg index="0" value="wms"/>
<constructor-arg index="1" ref="wmsService2"/>
<constructor-arg index="2" value="1.1.1"/>
bean>
此配置信息说明对于服务ID为wms的操作,由org.geoserver.wms.DefaultWebMapService来使用与操作同名的函数来处理。
这样,对于下面的请求:
http://localhost:8080/geoserver /wms?bbox=-74.01199448397661,40.70732689845813,-74.00841053684495,40.71216558957052&styles=&Format=application/openlayers&request=GetMap&version=1.1.1&layers=tiger:poi&width=457&height=550&srs=EPSG:4326
将由org.geoserver.wms.DefaultWebMapService的getMap函数来处理。
此函数先根据配置信息得到wmsGetMap对象,所属类是org.vfny.geoserver.wms.servlets.GetMap。
<bean id="wmsGetMap"
class="org.vfny.geoserver.wms.servlets.GetMap"
parent="wmsService">
bean>
然后执行此对象的getResponse()方法。然后创建一个GetMapResponse对象。
写输出是通过执行org.geoserver.ows.Dispatcher的void response(Object result, Request req, Operation opDescriptor)函数。此函数先循环搜索和排序响应类集合responses(List responses = GeoServerExtensions.extensions(Response.class);),确定响应类response (Response response = (Response) responses.get(0);),再根据输出策略outputStrategy(ServiceStrategy outputStrategy = findOutputStrategy(req.httpResponse);)进行输出。
具体执行在set the mime type时(req.httpResponse.setContentType(response.getMimeType(result, opDescriptor));)调用ResponseAdapter的getMimeType(Object value, Operation operation)函数,此函数再调用delegate.execute(request)来执行(delegate即第四步创建的GetMapResponse对象)。最终的执行在GetMapResponse对象的execute(Request req)函数。