理解struts流程和actionservlet

对struts的流程和actionservlet的理解如下,若有不对的地方,请指正。
actionservlet是struts的灵魂。
它为到来的请求url映射到相应的actionmapping,创建或找到其实例;
actionservlet调用在actionmapping中声明的action类,创建并生成相应的actionform bean实例。然后把actionform bean传到action类;
actionservlet对action类实例调用适当的perform方法,给它传递actionform bean,actionmapping,request和response对象;
action在其perform方法里将产生处理好的业务逻辑的结果;
actionservlet接受从perform方法返回的actionforward,转发response到由actionforward指定的源(可以是一个jsp或另一个action或另一个servlet)

请问到哪里可以弄到struts的源代码?

整个流程比较容易让人理解,就是actionform bean是做什么用,能讲仔细点吗?

ActionServlet使用ActionForm bean来保存请求的参数,这些bean的属性名称与HTTP请求参数的名称相对应,控制器将请求参数传递到ActionForm bean的实例,然后将这个实例传送到Action类。
典型的ActionFrom bean只有属性的设置与读取方法(getXXX),而没有实现事务逻辑的方法。只有简单的输入检查逻辑,使用的目的是为了存储用户在相关表单中输入的最新数据,以便可以将同一网页进行再生,同时提供一组错误信息,这样就可以让用户修改不正确的输入数据。而真正对数据有效性进行检查的是ACTION类或适当的事务逻辑bean。

最近我会写一些关于STRUTS的文章,希望到时给指教一二。

太好了,能不能请你专门来作一个structs版?

楼上的同志对于ActionForm bean的讲解非常精彩!!!我的项目在refactoring的时候,就遇到了这个问题!现在感觉这种方法实在不错!

再问问,是不是每个form都有单独的ActionForm Bean,那样会不会很浪费,能不能几个form共享同一个Bean,或者利用工厂法,得到自己的FormBean?

可以,比如向导型页面,可以有多个Form,但是只使用一个ActionForm,把scope设置为session。但是需要在reset和validate函数中作一些处理

大家到serverside网站上,有一本struts的书可以预览

Struts controller基本功能是
1. 截获用户的Http请求
2. 把这个请求映射到一个定义好的业务操作上
3. 获取业务操作结果,提供给客户端
4. 决定下一步应该显示哪一个页面

有几个部分共同组成了Struts 的Controller,用户的请求发送到ActionServlet中,ActionServlet调用RequestProssor开始处理用户请求的流程,在这个流程中,会查找ApplicationConfig,得到用户请求对应的Action,调用相应的Action来具体执行用户的请求,最后返回ActionForward,转向相应的流程。
================
org.apache.struts.action.ActionServlet 是Struts Controller中最主要的部分,所有用户请求都会被发送到这里,所有的其它处理也必须从这里经过。ActionServlet是从HttpServlet中继承过来的。
当ActionServlet接收到HTTP request的时候,不管是doGet()或者doPost()方法,都会调用process()方法。

protected void process(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { RequestUtils.selectApplication( request, getServletContext() ); getApplicationConfig(request).getProcessor().process( request, response );}

一般情况下,我们不需要自己实现或者修改ActionServlet类,仅仅使用就可以了。某些情况下,我们可以自己扩展ActionServlet类,从ActionServlet继承,实现自己的MyActionServlet类。覆盖其中的一些方法来达到你的特殊处理的需要。ActionServlet继承自javax.servlet.http.HttpServlet,所以在本质上它和一个普通的servlet没有区别,你完全可以把它当做一个servlet来看待,只是在其中完成的功能不同罢了。
================

RequestProssor具体处理用户的request,作为一个request handler存在。同样,处理request的时候,会执行RequestProcessor类中的process(execute)方法。

process中调用的方法都是可以重载的, 如果有需要,可以实现为自己特定的方法。比如,对于Locale问题,通常都是在系统最一开始加载的时候读取的,如果用户想在任何时刻都可以切换或者选择自己的Locale,我们就可以重载processLocale()方法。然后只需要在配置文件中加入<controller>段就可以了

================
Action类是实现整个体系的核心部分,它在客户请求、界面表示和业务逻辑之间起到一个桥梁的作用。每一个Action都用来处理某一项任务,或者进行一个业务操作。当然了,我们说一项任务不是说Action只实现一个业务操作方法,而是集中实现某一个功能单元。比如登录用的LogonAction、查找用的SearchAction等等。Action是在RequestProcessor中,由processActionPerform方法调用的

非常重要的一点:不要在Action中包含任何业务逻辑操作,而是应该调用一个Model层的JavaBean来实现你的业务逻辑操作。在某些情况下,可能包含少许表现逻辑。这样,就可以充分进行代码重用,比如上例中调用的IStorefrontService接口,这个接口在实现时完全可以不用考虑客户端的事情,所以它可以被其它部分或者其它系统所使用。否则的话,Action会变得非常难于理解,难于维护,代码也不能重用。

struts-example工程的设计就是一个bug,它把业务逻辑封装到了Action类中
===================

在Action的execute方法中,返回一个ActionForward类。ActionForward把配置文件中forward部分的信息包装起来,减少了应用程序和物理资源信息之间的耦合性。通过ActionMapping类,可以在配置文件中查找相应的forward信息。例如,对于一个LoginAction,它的配置信息可能是这样的:

<action input="/security/signin.jsp" name="loginForm" path="/signin" scope="request" type="com.oreilly.struts.storefront.security.LoginAction" validate="true"> <forward name="Success" path="/index.jsp" redirect="true"/> <forward name="Failure" path="/security/signin.jsp" redirect="true"/> </action>
返回的ActionForward就会包含<forward>段中的信息。在ActionMapping类的findForward方法中,首先会根据查找forward的name查找是否有相应的forward段,如果没有,则在配置文件中的<global-forwards>段中进行查找,如果还没有就会抛出一个例外。

=====================

以前,页面上的输入数据都通过HTTP request提交,服务方检索出输入的数据,进行验证,然后将这些数据传递给其它组件进行业务处理。一切基本都需要手工编写代码进行操作,比较麻烦,也使代码变得复杂。
ActionForm[org.apache.struts.action.ActionForm]用来收集用户的输入,并且把这些信息传递给Action对象,然后,在Action对象中,ActionForm中的数据被取出来传递给业务逻辑层进行处理。
ActionForm一方面作为一个缓冲区,临时存储用户输入的数据;另一方面,可以把ActionForm当成是HTTP和Action之间的一个防火墙,它可以验证输入数据的正确性,如果验证不通过,这个request是不会发送给Action进行处理的。
ActionForm可以有两种Scope,request或者session。request就是只能在rquest到response,之后ActionForm就不可见了;session可以保存时间长一点。

==================

在ActionForm的Validate方法中返回的是ActionErrors对象。这个对象可以将错误信息都封装起来,并且自动把它们显示给用户。
在相应JSP页面上添加<html:error/>,可以自动将ActionErrors中的错误信息显示出来。包括,每一个具体的,通过add添加的错误信息,和一个ErrorHeader和一个ErrorFooter,这些都可以通过配置文件指定,并且可以包含HTML语法。

==========================

Struts提供了四种自定义Tag库:
bean:struts-bean taglib包含在访问bean和bean属性时使用的tag,也包含一些消息显示的tag。
html:struts-html taglib包含用来创建struts输入表单的tag,和其它通常用来创建基于HTML用户界面的tag。
logic:struts-logic taglib包含的tag用来管理根据条件生成输出文本,和其它一些用来控制的信息。
template:struts-template taglib包含的tag用来定义模板机制。

谁来调用ActionForm?是control吧,可是谁给ActionForm赋值呢?

在1.1中,过程是:
ActionServlet的process,调用RequestProcessor的process
其中,调用processPopulate函数,这个函数调用RequestUtils的populate方法将Form中的属性按照(名字,值)防止到一个HashMap类型的变量中(properties),然后调用commons中的BeanUtils的populate方法按照名字到定义的ActionForm中去赋值
BeanUtils在1.1中被抽出来,单独存在,在1.02中是作为struts的一部分存在

to cc:
actionServlet根据actionMapping在xml里的配置
而找到相应actionForm,actionForm

典型的struts-config.xml可以定义:全局转发,
ActionMapping类,ActionForm Bean,JDBC数据源,例如
-----------------------------------------
<action-mappings>
<action /*映射所匹配的路径*/
path="/saveRegistration"
/*使用的Action类型*/
type="SaveRegistrationAction"
/*与起关联的表单bean的逻辑名称*/
name="registrationForm"
/*定义为request*/
scope="request"
/*当bean发生了输入检查错误是必须返回的控制*/
input="/registration.jsp"
/*在调用Action对象方法前,ActionServlet将调
用ActionFrom bean的validate()方法进行检查*/
validate="true">
<forward name="failure" path="/registration.jsp"/>
<forward name="cancel" path="/index.jsp"/>
</action>
</action-mappings>
------------------------------------------
<forms-beans>
<form-bean /*相关作用域使用的名称*/
name="registrationForm"
/*使用的类型*/
type="RegistrationForm">
</form-beans>
------------------------------------------
当请求到达ActionServlet,它将寻找相应的Action类的实例。
mapping可以将请求的uri映射到Action类,并且通过name将
Action类与ActionFrom bean相关联
----------------------------------------
ActionForm的值么,当然是在里面用getXXX,setXXX了

Struts controller基本功能是
1. 截获用户的Http请求
2. 把这个请求映射到相应的Action类,如果这是此类收到的第一
个请求,将初始化实例并缓寸。
3. 创建或发现一个ActionForm bean实例(看配置文件是否定
义),然后将请求过程移植到bean.
4. 调用Action实例的perform()方法并将ActioForm bean,
Action Mapping对象,request和response对象传给它。
如:public ActionForword perform(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
5.perform返回一个ActionForword对象,此对象连接到相应的jsp
页面.
banq,本人自知能力还不行,单开论坛还是算了,只能多多捧场了。
不过我现在除了看看java就是struts了,希望大家的讨论能给这里多聚集些人吧。我写了点东东,放在chinajavaunion,不过是入门级的,改天写完一并放在这里,到时给别给我删了啊

哪里哪里 你太谦虚,怎么敢删除你东东,对论坛我认为删除功能是多余的。

Struts我看你解释后,才明白.Pet store也是使用基于Struts一样的原理来处理的。特别是perform方法是关键,比如我写的文章"解剖Petstore用户资料修改流程"http://www.jdon.com:81/jive/thread.jsp?forum=16&thread=273
中就剃刀用户资料修改的CustomerHTMLAction这个servlet就是提供一个perform()方法的具体实现。

建议大家去serverside站点download struts资料,大家多读几遍,将会受益匪浅!