java web framework综述
0.简介
本文介绍java web framework的基本工作原理,和一些常用的开源web mvc framework(struts, web work, tapestry, echo, jsf, maverick, spring mvc, turbine, cocoon, barracuda)。
web开发的最重要的基本功是http;java web开发的最重要的基本功是servlet specification。http和servlet specification对于web server和web framework的开发实现来说,是至关重要的协议规范。
应用和剖析开源web framework,既有助于深入掌握http & servlet specification, 也有助于了解一些现代的b/s web框架设计思想,如mvc,事件处理机制,页面组件,ioc,aop等。在这个现代化的大潮中,即使servlet规范本身也不能免俗,不断引入filter、listener等现代框架设计模式。同是sun公司出品的jsf更是如此。
关于mvc模型、项目简介、配置文件、入门示例等基础知识,网上已经有大量的重复资料信息,本文不再赘述。
文中会提到一些相关的开源项目,和一些编程思想,如有需要,可以用相关的关键字在网上搜索,获取基本的背景知识。
本文力图言简意赅,突出重点。着重描述其他资料没有提到、或很少提到的较重要内容,如运行原理、主流用法,相关知识,关键特性等。
1. java web程序工作原理
tomcat的server.xml文件中定义了网络请求路径到主机本地文件路径的映射。比如,<context path="/yourapp" docbase="yourapp_dir/webapp"/>
我们来看一下,一个http request-response cycle的处理过程。
http request url一般分为三段:host, context, path。
如http://yourhost/yourapp/en/index.html这个url,分为host=yourhost, context=yourapp, path=en/index.html三段。其中,context部分由request.getcontext()获得,path部分由request.getservletpath()获得(返回结果是“/en/index.html”)。
yourhost主机上运行的tomcat web server接收到这个url,根据context定义,把yourapp这个网络路径映射为yourapp_dir/webapp,并在此目录下定位en/index.html这个文件,返回到客户端。
如果我们这个url更换为http://yourhost/yourapp/en/index.jsp,这个时候tomcat会试图把yourapp_dir/webapp/en/index.jsp文件编译成servlet,并调用运行这个servlet。
我们再把这个url更换为http://yourhost/yourapp/en/index.do。
注意,戏剧化的事情就发生在这个时候,servlet规范中最重要的类requestdispatcher登场了。requestdispatcher根据web-inf/web.xml配置文件的定义,调用对应的servlet来处理en/index.do这个路径。
假设web.xml里面有这样的定义。
<servlet>
<servlet-name>dispatchservlet</servlet-name>
<servlet-class>yourapp.dispatchservlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatchservlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
那么,requestdispatcher会调用yourapp.dispatchservlet类处理这个路径。
如果web.xml没有定义对应en/index.do这个路径的servlet,那么tomcat返回“您请求的资源不存在”。
requestdispatcher用于web server中,也可以用于应用程序中进行处理转向,资源定位。比如,我们在处理en/index.do的代码中调用,
request.getrequestdispatcher(“cn/index.jsp”).forward(request, response), 就可以转交另外的资源cn/index.jsp来处理。
几乎所有的web framework都需要定义自己的dispatch作用的servlet,并调用requestdispatcher进行转向处理。
阅读web framework源代码,有两条主要线索,(1)根据web.xml找到对应的servlet类;(2)搜索包含“requestdispatcher”词的代码文件。
我们看到,request, response 这两个参数,被requestdispatcher在各种servlet之间传来传去(jsp也是servlet)。所以,request的setattribute()和getattribute()方法是servlet之间传送数据的主要方式。
在mvc结构中,一般的处理流程如下:
处理http request的基本单位一般称为action,是一个比servlet轻量得多的接口定义,通常只有一两个方法,如execute(perform), validate等。
我们知道,url->servlet映射,定义在web.xml配置文件里,但mvc框架通常会有另外一个定义url-> action映射的配置文件。
入口dispatcher servlet根据url -> action的映射关系,把请求转发给action。
action获得输入参数,调用商业逻辑,并把结果数据和view标识给(model & view)返回给dispatcher servlet。
dispatcher servlet根据这个view 标识,定位相应的view template path,把处理转交给view(jsp +taglib, velocity, free marker, xsl等)。
view一般通过request.getattribute()获得结果数据,并显示到客户端。至于是谁把结果数据设置到request.attribute里面,有两种可能:action或dispatcher servlet。
2. struts
http://struts.apache.org/
struts是目前用户群最大、开发厂商支持最多的开源web framework。
struts劳苦功高,为普及mvc框架作出了不可磨灭的贡献。显赫的声望,趋于老化的厚重结构,令struts成为很多现代web framework参照、挑战的目标。
struts应用主要包括3件事情: 配置struts-config.xml文件,实现action类,实现view;还有一些高级扩展用法。下面分别讲述。
1. 配置struts-config.xml文件:
struts支持多级配置文件,具体用法和限制,详见struts文档。这里只讨论struts-config.xml主流配置的内容。:-)
(1) url path到action的映射。
如<action path="/logonsubmit" type="app.logonaction" ... />
struts的入口servlet是actionservlet。
actionservlet需要此信息把url path调用对应的action类处理。
在struts运行期间,一个url path,只存在一个对应的struts action实例。所有的该url path的请求,都经过这同一个struts action实例处理。所以struts action必须线程安全。
想想看,其实这个要求并不过分,action只是一个处理程序,不应该保存跨http请求的状态数据,按理来说,也应该做成线程安全的。
(2) template name到view template path的映射。
<forward name="success" path="/pages/welcome.jsp"/>
action类返回一个template name,actionservlet根据这个template name获得对应的view template path,然后调用
request.getrequestdispatcher(“view template path”),把处理转向路径对应的servlet。在这个例子中,是转向/pages/welcome.jsp编译后的servlet。
我们来看一个一个velocity的例子。
<include name="success" path="/pages/welcome.vm"/>
web.xml的定义如下
<servlet>
<servlet-name>velocity</servlet-name>
<servlet-class>org.apache.velocity.tools.view.servlet.velocityviewservlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>velocity</servlet-name>
<url-pattern>*.vm</url-pattern>
</servlet-mapping>
闽公网安备 35060202000074号