http://www.host01.com/Print.html?30916,1
Structs 控制组件。
·ActionServlet组件:充当Struts框架的中央控制器。
Struts框架采用控制器组件来预处理所有的客户请求,这种集中控制方式可以满足MVC设计模式的两大需求:
·首先,控制器在用户输入数据和模型之间充当媒介 / 翻译者的角色,提供一些通用功能,如安全、登入和其他针对具体用户请求的重要服务,当系统的这些通用功能出现需求变更时,部需要修改整个应用,只需要修改局部的控制器组件即可。
Struts框架采用ActionServlet和RequestProcessor组件进行集中控制,并采用Action组件来处理单项业务。
一 控制器组件的控制机制
Struts的控制器组件主要完成以下任务:
1 Action类
org.apache.struts.action.ActionServlet类是Struts框架的核心控制器组件,所有的用户请求都先有ActionServlet来处理,然后再由ActionServlet把请求转发给其他组件。Struts框架只允许在一个应用中配置一个ActionServlet类,在应用的生命周期中,仅创建ActionServlet类的一个实例,这个ActionServlet实例可以同时响应多个用户请求。
<!--[if !supportLists]-->(a) <!--[endif]-->Struts框架初始化过程
<!--[if !supportLists]-->(b) <!--[endif]-->ActionServlet的process()方法
protected voidprocess (HttpServletRequest request, HttpServletResponse response)
在process()方法中,首先调用org.apache.struts.util.ModuleUtils类的selectModule()方法,这个方法选择负责处理当前请求的子应用模块,然后把与子应用模块相关的ModuleConfig和MessageResources对象存储倒request范围中,这使得框架的其余组件可以方便地从request范围中读取这些对象,从而获取应用配置信息和消息资源。
<!--[if !supportLists]-->(c) <!--[endif]-->扩展ActionServlet类
尽管新版本的Struts框架允许在应用中创建矿展ActionServlet类的子类,但是这在多数情况下没有必要,因为控制器的多数控制功能位于RequestProcessor类中。
如果实际应用确实需要创建自己的ActionServlet类,则可以创建一个ActionServlet的子类,然后在web.xml文件中配置这个客户化ActionServlet类。
如果覆盖了init()方法,应该确保首先调用super.init(),它保证ActionServlet的默认初始化操作被执行。除了覆盖init()方法外,事实上,还可以根据十几需要覆盖ActionServlet的任何其他方法。
2 RequestProcessor类
Struts框架只允许应用中存在一个ActionServlet类,但是可以存在多个客户化的RequestProcessor类,每个子应用模块都可以拥有单独的RequestProcessor类。如果想修改RequestProcessor类的一些默认功能,可以覆盖RequestProcessor基类中的相关方法。
<!--[if !supportLists]-->(a) <!--[endif]-->RequestProcessor类的process()方法
<!--[if !supportLists]-->(b) <!--[endif]-->扩展RequestProcessor类
在Struts配置文件中,<controller>元素的processorClass属性RequestProcessor类。
3 Action类
Action的execute()方法调用模型的业务方法,完成用户请求的业务逻辑,然后根据执行结果把请求转发给其他合适的Web组件。
<!--[if !supportLists]-->(a) <!--[endif]-->Action类缓存
<!--[if !supportLists]-->(b) <!--[endif]-->ActionForward类
采用第二种方式,无需在程序中硬编码来指定转发资源的无力路径,而是在配置文件中配置转发资源,程序中秩序引用转发资源的逻辑名即可,这提高了应用的灵活性和可维护性。
<!--[if !supportLists]-->(c) <!--[endif]-->创建支持多线程的Action类
在Action类中定义的实例变量代表了可以被所有请求线程访问的共享资源。为了避免共享资源的竞争,在必要的情况下,需要采用Java同步机制对访问共享资源的代码块进行同步。
(d)Action类的安全
RequestProcessor类在预处理请求时会调用自身的processRoles()方法,该方法先检查在配置文件中是否未Action配置了安全角色,如果配置了安全角色,就调用HttpServletRequest的isUserInRole()方法,来判断用户是否具备了必要的安全角色。如果不具备,就直接向客户端返回错误。
Struts提供了一些现成的Action类,在Struts应用中直接使用这些Action类可以大大节省开发时间。
1 org.apache.struts.actions.ForwardAction类
在JSP网页中,尽管可以直接通过<jsp:forward>标签把请求转发给其他Web组件,但是Struts框架提倡先把请求转发给控制器,再由控制器来负责请求转发。
·JSP网页之间直接相互转发违背了MVC的分层原则,按照MVC设计思想,控制器负责处理所有请求,然后选择适当的视图组件返回给用户,如果直接让JSP相互调用,控制器就失去了流程控制作用。
ActionServlet把请求转发给ForwardAction,ForwardAction再把请求转发给<action>元素中parameter属性指定的Web组件。总之,在Web组件之间通过ForwardAction类来进行请求转发,可以充分利用Struts控制器的预处理请求功能。此外,也可以通过<action>元素的forward属性来实现请求转发。
2 org.apache.struts.actions.IncludeAction类
3 org.apache.struts.actions.DispatchAction类
在配置DispatchAction类时,需要把parameter属性设置为“method”。设置之后,当用户请求访问DispatchAction时,应该提供method请求参数。
4 org.apache.struts.actions.LookupDispatchAction类
在<action>元素中,设置parameter属性时,需要使它和<html:submit>标签的property属性保持一致。
5 org.apache.struts.actions.SwitchAction类
·page:指定被请求Web组件的URI,只需指定相对于被切换后的子应用模块的相对路径。
创建一个新的令牌,并把它保存在当前session范围内。如果HttpSession对象不存在,就首先创建一个HttpSession对象。
具体的Token处理逻辑由org.apache.struts.util.TokenProcessor类来完成,它的generateToken(request)方法根据用户会话ID和当前系统时间来生成一个唯一的令牌。
四 实用类
在创建Web应用时,有许多检索和处理HTTP请求的操作时重复的。为了提高应用代码的可重用性,减少冗余,Struts框架提供了一组提供这些通用功能的实用类,它们可以被所有的Struts应用共享。
1 RequestUtils类
方法
|
描述
|
absoluteURL(HttpServletRequest request,String utl)
|
创建并返回绝对URL路径,参数path指定相对于上下文(context-relative)的相对路径
|
createActionForm(HttpServletRequest request, ActionMapping mapping, ModuleConfig moduleConfig, ActionServlet servlet)
|
先从request或session范围内查找该ActionForm,如果存在,就直接将它返回,否则先创建它的实例,把它保存在request或session范围内,再把它返回。mapping参数包含了<action>元素的配置信息,例如它的scope属性指定ActionForm的范围
|
populate(Object bean, HttpServletRequest request)
|
把HTTP请求中的参数值组装到指定的JavaBean中,请求的参数名和JavaBean的属性名匹配。当ActionServlet把用户输入的表单数据组装到ActionForm中时,就调用此方法
|
2 TagUtils类
方法
|
描述
|
getInstance()
|
返回一个TagUtils的实例。该方法为静态的,如果要在程序中获得TagUtils的实例,可以调用TagUtils.getInstance()方法
|
getActionMessages(PageContext pageContext, String paramName)
|
调用pageContext.findAttribute(paramName)方法,从page, request, session和application范围内减缩并返回ActionMessages对象,参数paramName指定检索ActionMessages对象的属性key
|
getModuleConfig(PageContext pageContext)
|
返回ModuleConfig对象,如果不存在,就返回null
|
lookup(PageContext pageContext, String name, String scope)
|
返回特定范围内的JavaBean。参数scope指定JavaBean的所在范围,name参数指定JavaBean在特定范围内的名字
|
message(PageContext pageContext, String bundle, String locale, String key)
|
从指定的Resource Bundle中返回一条消息文本,参数locale指定Locale,参数key指定消息key
|
write(PageContext pageContext, String text)
|
向网页上输入特定的文本,参数text用于指定文本内容
|
3 ModuleUtils类
方法
|
描述
|
getInstance()
|
返回一个ModuleUtils的实例。该方法为静态的,如果要在程序中获得ModuleUtils的实例,可以调用ModuleUtils.getInstance()方法。
|
getModuleConfig(javax.servlet.http.HttpervletRequest request)
|
从request范围内检索并返回ModuleConfig对象
|
getModuleConfig(java.lang.String prefix, javax.servlet.ServletContext context)
|
从application范围内检索并返回ModuleConfig对象,参数prefix指定子应用模块名的前缀
|
getModuleName(javax.servlet.http.HttpServletRequest request, javax.servlet.ServletContext context)
|
返回请求访问的子应用模块的名字
|
selectModule(javax.servlet.http.HttpServletRequest request, javax.servlet.ServletContext context)
|
选择请求访问的子应用模块,把和子应用模块相关的ModuleConfig和MessageResources对象存储到request范围中
|
4 Globals类
方法
|
描述
|
ACTION_SERVLET_KEY
|
代表在application范围内存放ActionServlet实例的属性key
|
DATA_SOURCE_KEY
|
代表在application范围内存放默认的DataSource实例的属性key
|
ERROR_KEY
|
代表在request范围内存放ActionErrors实例的属性key
|
LOCALE_KEY
|
代表在session范围内存放Locale实例的属性key
|
MAPPING_KEY
|
代表在request范围内存放ActionMapping实例的属性key
|
MESSAGE_KEY
|
代表在request范围内存放ActionMessages实例的属性key
|
MESSAGES_KEY
|
代表在application范围内存放各个子应用模块的MessageResources实例的属性key的前缀
|
MODULE_KEY
|
代表在application范围内存放各个子应用模块的ModuleConfig实例的属性key的前缀
|
REQUEST_PROCESSOR_KEY
|
代表在application范围内存放各个子应用模块的RequestProcessor实例的属性key的前缀
|