2009年3月30日星期一

ArcGIS Server Java ADF 案例教程 7

ADF是怎样开始工作的

ADF现在已经存在于我们的工程中了,接下来的问题就是它是怎么工作的了。换句话说,当我们的开发任务完成以后,把这个ADF项目部署到一个Java Web服务器上,当有浏览器对它发生请求的时候,我们的服务器怎么知道我这是一个JSF应用,进一步还会根据ArcGIS的ADF来生成那些乱七八糟的诸如WebContext之类的对象呢?

我们首先来看一下,当一个用户对服务器发送请求的时候,Java Web服务器怎么判断他要访问的是一个JSF应用。让我们打开“/WebContent/WEB-INF/web.xml”,这个web.xml文件是Java Web工程的部署描述文件,服务器会根据这个文件中的定义来加载Servlet以及其它的内容,在这个文件中我们可以分别找到下面两段定义:

“servlet”元素定义的是Java Web服务器加载的Servlet信息,“servlet-mapping”元素定义的是一个URL模式对应的Servlet,所有符合该URL模式的请求都会被映射到该Servlet上进行处理。在这里首先我们根据FacesServlet 这个类在服务器启动的时候加载了JSF的Servlet:“Faces Servlet”,然后又定义了一个“*.jsf”的URL模式,凡是以“*.jsf”出现的请求都会被映射到“Faces Servlet”进行处理。好了,到这里我们应该可以明白JSF是怎么工作的了。

在此基础上,我们需要进一步了解ADF的运行。还是在刚才的web.xml文件中,从中我们还可以找到以下的这段内容:

“listener”元素会根据相应的监听类配置一个监听。在这里模板工程为我们配置了一个ADFServletContextListener监听器,这个监听器实现了两个接口:ServletContextListener和HttpSessionListener。

ServletContextListener负责监听Web应用(你部署的这个ADF工程)的ServletContext的变化。当我们的Java Web服务器启动的时候,我们的Web应用也会跟着启动,这时,Web应用的ServletContext将会被创建并初始化,因此ADFServletContextListener的contextInitialized(ServletContextEvent event)方法会被调用。在这个方法中,ADF的WebApplication 会被创建并初始化。这个WebApplication相当于我们ADF的女娲娘娘,以下我们会看到一个又一个的ADF对象会从中孕育出来。

WebApplication中包含了由WebSession 组成的一个ArrayList,这个ArrayList中包含了所有的用户的ADF会话WebSession;当然,这个WebSession与整个Web应用的会话HttpSession 并不是独立的,WebSession会作为一个属性存储在HttpSession中。

在这个WebSession中其实也是一片广阔的革命天地。在每个WebSession中都会有一个由WebContext 组成的ArrayList,它存放的是这个会话所用到的所有WebContext对象。还记得WebContext么?在《ADF的逻辑结构》这小节中,WebContext是以一个非常大哥的形象出现的。现在发现,这个大哥其实是WebSession的小弟之一,WebSession则是WebApplication的小弟之一。

下面再说说HttpSessionListener,它负责监听Web应用当前会话的变化。当有一个新的用户向我们的服务器发送请求的时候,应用会为这个用户新建一个会话,这个时候,ADFServletContextListener的sessionCreated(HttpSessionEvent event)方法也会被执行(虽然事实上,在这里ADF并不做任何事情,WebSession并不是在这里创建,这个下面马上就讲);当一个会话结束时,ADFServletContextListener的sessionDestroyed(HttpSessionEvent event)方法会被执行,ADF将会从Web应用的HttpSession中取得WebSession对象,并将之从WebApplication中移除并销毁。

目前为止,只有WebSession的出身不太明白了。还是让我们打开web.xml文件,其中有下面的一段:

这里定义了一个过滤器ADFFilter,每当有用户请求时,请求都会经过ADFFilter过滤,这时,ADFFilter的doFilter(…)方法将会被执行。在这个方法中,ADF会试图获得该请求的HttpSession中保存的WebSession对象,如果这个对象为null,则新建一个WebSession对象并保存(同时保存引用到HttpSession和WebApplication)。

最后,让我们对ADF的工作流程稍作梳理。ADF的工作主要依赖于Web应用的web.xml中配置的ADFServletContextListener监听器和ADFFilter过滤器。当Web应用启动的时候,ADFServletContextListener负责创建WebApplication(老大);当有用户请求的时候,请求会经过ADFFilter过滤并试图获得该请求的WebSession(老大的小弟),如果为null则创建WebSession并保存;在WebSession中包含了该会话使用的所有WebContext(老大的小弟的小弟),有了WebContext,剩下的事情都好办了。

以上是ADF的内部机制,如果理解有困难或者觉得有点麻烦,其实也没必要了解那么清楚,对ADF的几个重要对象的关系有所了解就可以了,下面这个简单的图可能会对你的理解有所帮助。

2009年3月27日星期五

ArcGIS Server Java ADF 案例教程 6

ADF的逻辑结构

尼采说:“我没有肉体,我只有灵魂”,感情这哥们从不吃喝拉撒——咱就不从唯物主义去批判他了,反正咱ADF不一样,它可是有胳膊有腿、有思想有能力的四有框架。上面刚介绍完了ADF的物理组成,根据由表及里、由浅入深的认识论原则,现在我们开始认识一下ADF的逻辑结构。

在ADF的帮助中有一张MVC示意图,其中把视图和控制器合并在了一起,因为ESRI认为ADF的组件不仅仅在视图层,它们还影响到了Web应用流程,有控制器的功能。这种划分我感觉不太清晰,所以这里还是把控制器独立了出来。
图 3 ADF的MVC示意图

如图 3所示是我绘制的MVC示意图。ADF在视图层的表现是一系列的JSF组件;它们是通过控制器层的ADF组件渲染器输出的;最下层的是模型层。在ADF的模型中,WebContext是最为重要的对象,不管是GISResource(各种服务资源)还是其它的WebControl(WebMap、WebToc等等),都是在WebContext中进行管理的。WebContext可以看作在用户会话中存在的管理ADF的一个环境,至于这个WebContext是从何而来,马上在下一小节中会详细叙述。

浏览器中用户所能看到的Map、Toc等,在服务器上都是以WebMap、WebToc等JavaBean对象存在于用户的会话中;同时,这些对象作为WebContext的属性(attribute)被其包含。而Web应用中所用到的GIS服务(如Map Service、Geoprocessing Service等),在ADF中都是作为GISResource(如AGSMapResource、AGSGPResource等)来进行连接使用。这些不同的GISResource各自包含了各种不同的功能(GISFunctionality),这些不同的功能又会各自对应到WebMap、WebToc等对象上去。为什么需要在ADF的WebControl和GISResource之间加上GISFunctionality这一层呢?这主要是ADF为了统一不同服务数据源考虑,比如虽然AGSMapResource和AGSLocalMapResource是两种不同的GISResource,但是它们都可以在Map组件中进行地图浏览,因此ADF定义了AGSMapFunctionality这个功能,AGSMapResource和AGSLocalMapResource都分别实现了这个功能,Map只要调用这个功能就可以实现地图的浏览而不必关心后台的服务到底是什么类型的。

上面这个MVC示意图目前有个大概印象就可以了,因为你还没有真正地使用ADF,都理解了也不太可能;在后续的环节中,经常会过来看看这张图可能会有更加深入的理解,先就认个脸熟吧。

2009年3月26日星期四

ArcGIS Server Java ADF 案例教程 5

ADF的物理组成

现在,ADF对你来说或许就像远处的一个美女,氤氲中你依稀可以看到她的体态轮廓;当然,你同时也迫切希望能更深一步地了解她。现在我们要做的,就是走近她,慢慢揭开她的面纱。

我现在感觉自己有点像一个导演——当然,我可不想是拍《无极》那种烂片的水平——面对一个“她”,目前正在设计一个镜头,目的是怎样可以比较艺术化地表现出她的一切。这里,我决定从她的肉体——ADF的物理组成入手,先带你去一窥它的全貌。

现在,让我们首先新建一个ADF的模板工程,这个模板工程是ESRI使用ADF开发的一个简单的Web应用供你参考,它包含了一些最常用和最基本的GIS功能;当然,它也必不可少会将ADF这个框架包含在这个应用中。

对了,迄今为止我们也没有讲怎么搭建ADF的开发环境,并且新建ADF模板工程来测试我们的开发插件是否安装成功。这些内容在我很久以前的文章中写过,我就不想在这里再重复一遍,分散我们对ADF的注意力了。这些内容,不管是基于Eclipse还是NetBeans,都可以从ADF的帮助文档中找到;你也可以参考我写的文档:《配置ArcGIS Server 9.3 Java开发环境(Eclipse/NetBeans)》——好了,现在我认为你已经配置好了开发环境,并且学会如何新建一个ADF模板工程了。另外,下面的讲解基于的IDE是Eclipse。

让我们打开刚刚新建的ADF模板工程,展开项目的目录结构。我对其中一些重要的部分重点用图 2表示了出来,下面让我们一级一级地展开。
图 2 ADF模板工程的目录结构

在一个ADF的工程中,与开发相关的主要是“/src”目录和“/WebContent”目录。“/src”目录主要存放Java源代码相关内容,这些源代码最终会被编译后放到“/WebContent/WEB-INF/classes”目录中去;“/WebContent”目录主要存放最后需要部署的Web应用的内容。

在“/src”目录中,纯Java的代码一般会放到你自己的命名空间下,比如“/src/com/…”目录;“/src/xsl”是另外一个很重要的目录,其中包含许多xsl文件,ADF通过这些xsl来渲染ADF组件,具体它是怎么工作的我们后续会做更详细的介绍。

现在转到“/WebContent”目录,ADF本身带了一些“css”、“images”、“themes”目录内容来定义默认模板工程的样式;当然,还有一些“*.jsp”页面——事实上,在你自己做应用的时候基本上不需要用到这些页面。在此要详细解释的是“/WebContent/js”和“/WebContent/WEB-INF”两个目录。

“/WebContent/js”目录包含了ADF的JavaScript函数库,主要是ADF在跟服务器做AJAX交互的时候需要用到,当然,你自己定义的JavaScript脚本也可以放到这个目录下;“/WebContent/WEB-INF”目录存放所有不希望被Web访问者访问到的文件和库,包括一些“*.xml”配置文件、“/WebContent/WEB-INF/classes”下的类文件(从“src”编译生成)、“/WebContent/WEB-INF/lib”下的Java库。

在这里我们稍微总结一下ADF的物理组成:ADF的核心主要包括“/WebContent/WEB-INF/lib”目录下的Java库(底层功能、ADF的JSF组件等)、“/WebContent/js”目录下的JavaScript脚本库(支持AJAX)和“/WebContent/WEB-INF/classes/xsl”目录下的XSL样式表语言文件(渲染ADF组件);除此之外,ADF外围还有一些模板页面、CSS文件、图片、主题等可用可不用的附赠品;最后,作为开发框架,ADF还包括帮助文件和例子,虽然这里并没有介绍它们——因为它们并不会被放到工程中去。

2009年3月19日星期四

ArcGIS Server Java ADF 案例教程 4

ADF是什么

说了半天的ADF,突然发现到底ADF是什么还一直没提。突然想到有人在网上恶搞了“卧槽泥马”源自《战国策》,居然还有报纸以此引经据典拽了一把酸文,捧腹之余顿感正本清源的重要。我们的ADF全称是ArcGIS Java Web Application Developer Framework,一般简称Java ADF,在这里我就直接称呼ADF了。从这个名字也可以看到ADF的实质,它是为了开发Web应用而生的一套开发框架,开发人员可以在ADF的基础上相对比较容易地开发出WebGIS应用。相比ArcGIS Server其它的客户端API,用ADF开发的应用功能最强大,对浏览器要求最低。

让我们从帮助文档里的一张图开始,先感性认识一下ADF包含的内容吧。虽然我看过不少描述ADF的图表,但是我认为,这张图,是最简介明了的。
图 1 ADF的组成部分

大概来讲,ADF主要是由一些JSF组件、实现GIS相关功能的Java类库、支持AJAX的JavaScript脚本库和一些帮助文档及例子的集合。

在图 1中,首先你需要把最下面的那些“Data Sources”理解成服务。不管是ArcGIS Server或者是ArcIMS等发布的服务都可以作为ADF的数据源。在这些服务之上,ADF内部通过不同的API(“Common Data Source API”)去使用这些服务,当然,这些API上层会有相应的类库(“Web ADF consolidation classes”)进行支持。在这之上就是与开发者关系最直接的ADF的“Web Controls”(Map、TOC等基本GIS功能)和“Task Framework”(完成比如查询、分析等定制的任务),事实上,我们可以把这两部分看成一个整体——Web组件。这些Web组件包含了JSF组件以及相应的AJAX操作所需的JavaScript脚本库(“Web ADF JavaScript”);它们都会在用户请求的时候被ADF通过一定的规则渲染成对应的DHTML后输出到浏览器。图 1的左上角就是浏览器端,事实上在浏览器中已经基本看不到ADF的影子了,因为用户看到的页面不过是一些HTML和JavaScript脚本的组合,页面会和服务器上的某些ADF对象进行交互,但是这对浏览器来说基本是透明的。

2009年3月18日星期三

ArcGIS Server Java ADF 案例教程 3

JSF的直观印象

如果我是一个项目经理,我当然最喜欢的是又会写代码,又会做美工,顺便最好还能陪我对战几把Warcraft的全能型选手——最好要的薪水也可以少一点。不过,自古文武全才型的选手就比较难得,手下能有一些懂一点美工的程序员或者懂一点代码的美工就已经很不错了。

因此,各种Web开发框架都希望做到的事情是尽量把页面设计和后台逻辑分离开。这里不仅仅涉及到MVC的实现,还在于开发者角色的分离。做美工的希望面向的是一个纯粹的页面设计工作,直接和HTML和CSS打交道会让他们非常舒服和得心应手;而程序员(不管是写页面上的JavaScript还是后台的Java /PHP/.Net…)一般都不喜欢去掺合页面的设计。

JSF一方面有自己的标签库,使得美工可以使用类HTML的标签来设计页面,这样可以实现和程序员角色的分离;另一方面,JSF希望不仅做到这样的分离,而且希望带给程序员在进行Web开发时,来回徜徉于可能远隔千里之外的浏览器和服务器之上的时候,能够有更好的体验。

让我们看一下下面在一个JSF页面中的一段标签:
<h:commandbutton value="确定" actionlistener="#{user.verify}">
在这里出现的“#{…}”中包含的内容是在JSF页面中绑定的服务器端的JavaBean对象,在这里是“user”。“user.verify”是“user”对象的一个监听。我们看一下与其相对应的Java代码吧:
public void verify(ActionEvent e)
{
this.outcome = "login";
}
这样的组合让JSF应用在页面点击那个“commandButton”的时候,服务器会监听到浏览器发来的请求,然后执行相应的代码,在这里让“user”对象的outcome属性值变成“login”。

至于页面怎么向服务器发送请求,服务器怎么监听到请求等等细节,JSF都已经封装了起来,无需你去多考虑和写多余的代码。你只需要派美工做好设计,然后使用JSF相应的标签组织好页面;然后派程序员把后台的功能具体实现了,JSF会帮你把浏览器和服务器联系起来,完成你设计的功能。

嗯,到这里你或许会已经对JSF有一个直观的印象了:MVC、页面绑定服务器端对象。当然,JSF更多的优点和特色还有很多,建议你找一本JSF的教材,内容肯定会很详细,我在这里就不多讲了。不过,关于JSF应用中比较重要的比如配置文件、事件处理、请求的生命周期等内容,我也会在后续的ADF讲解中根据需要做一些详细的解释的。好了,JSF这个幕后英雄就先了解到这里吧,让我们先尽早地接触到ADF再说。

ArcGIS Server Java ADF 案例教程 2

ADF为什么选择JSF

为什么ESRI会选择JSF作为ArcGIS Java ADF的基础框架,想来你也不会很关心,因为这已经是一个既成事实了(说这句话的时候我感觉很对不起我这个小标题)。我以前是用PHP写Web应用的,也没用过Struts、Spring之类的框架,因此也就无从比较JSF与它们的优劣。有句话说的好,生活就像某件事情,如果你不能去反抗,那就闭上眼就享受吧。如果你要使用ArcGIS Java ADF开发,那么你还可以对框架挑三拣四么?好了,既然你无能为力,那么就开始享受它吧。

为了给自己再找点心理上的安慰,证明自己没有吃亏,你可以和我一样无聊地去Google搜一下关于JSF和Struts、Spring的相关页面数量,并把它作为一个框架流行度的大体指标。我在2009.3.16这一天得到的结果是JSF:约15700000,Struts:约14500000——至于Spring,这个名字实在是有太多的含义了,忽略了吧——这时,你发现原来全世界有这么多人和你一样在“享受”着JSF,是不是心里踏实了很多呢?

好了,如果你还没有接触过JSF,那就让我们开始试着去享受JSF吧。

2009年3月16日星期一

ArcGIS Server Java ADF 案例教程 1

前言

如果你开始学ArcGIS Server Java ADF,你会在第一时间发现相关资料的缺乏。手上最靠谱的资料就是自带的Help文件,可是当你虔诚地点开 “Open Java Help”以后一看,章节倒是不少,可是每一篇都是那么出人意料的短小精悍——这可不是因为英文比较精炼的缘故。好吧,吐血之余如果你能通过Google在浩瀚的互联网挖掘一下,你应该会如获至宝地发现前辈高人CJ的Java ADF教程,恭喜你,你基本已经找到中文Java ADF开发资料大约一半的内容了。

相比 .Net ADF的开发资料,你不禁会发出一声感慨:“真是穷的穷死,富的富死啊!”。唉,不用多抱怨这个社会的不公了,想想CJ写那篇教程(2007.8左右)之前的岁月,想想那个时候受苦受难的弟兄们,现在好歹算是解放了吧。

转眼解放也快2年了,Java ADF的资料还是一如既往的少——同时,ArcGIS Server已经从9.2更新到了9.3,CJ的教程是基于9.2的,有一些内容已经和9.3对不上了——这些都成为了我写这篇教程的原因之一。

在我学习Java ADF的时候,非常幸运有一个ADF高手同事在我边上充当我的活字典(在这里我向他表示万分感谢)。由于我有问题马上能够得到解答,还能举一反三,这让我摸索的这个过程变得比较愉快。在我上学的时候就不喜欢看那些可以充当手册的教材,而是比较喜欢听谁来给我把知识像故事一样地娓娓道来——至今我还非常想念当年在实验室的一个师兄,感谢他在带我入门GIS世界时候的循循善诱和耐心教导,顺便也遥祝他在新加坡的学习生活愉快。

希望这篇教程也能给你带来类似的感觉!

ArcGIS Server Java ADF 案例教程 0

开始写一个ArcGIS Server Java ADF 的参考资料,希望可以坚持写完。

——2009.3.16

2009年3月3日星期二

招聘信息

ESRI中国在这段时间可能需要招收一些技术人员,需要精通ArcGIS产品与服务器技术(.Net或J2EE),如果有能力并且有兴趣的话可以和我联系(给我发邮件),或者自己联系:招聘信息