Chinaunix首页 | 论坛 | 博客
  • 博客访问: 456315
  • 博文数量: 750
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4970
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-09 12:36
文章分类

全部博文(750)

文章存档

2011年(1)

2008年(749)

我的朋友
最近访客

分类:

2008-09-09 15:19:45


  Struts控制器组件负责接受用户请求、更新模型,以及选择合适的视图组件返回给用户。控制器组件有助于将模型层和视图层分离,有了这种分离,就可以在同一个模型的基础上得心应手地开发多种类型的视图。Struts控制器组建主要包括:
  
  ·ActionServlet组件:充当Struts框架的中央控制器。
  
  ·RequestProcessor组件:充当每个子应用模块的请求处理器。
  
  ·Action组件:负责处理一项具体的业务。
  
  Struts框架采用控制器组件来预处理所有的客户请求,这种集中控制方式可以满足MVC设计模式的两大需求:
  
  ·首先,控制器在用户输入数据和模型之间充当媒介 / 翻译者的角色,提供一些通用功能,如、登入和其他针对具体用户请求的重要服务,当系统的这些通用功能出现需求变更时,部需要修改整个应用,只需要修改局部的控制器组件即可。
  
  ·其次,由于所有的请求都经过控制器过滤,因此可以降低视图组件之间,以及视图组件和模型组件之间的相互依赖关系,提高每个组件的相对独立性。由控制器组件来决定把合适的视图组件返回给用用户,这可以减少视图组件之间直接的,错综复杂的连接关系,使应用更加灵活,便于维护。
  
  Struts框架采用ActionServlet和RequestProcessor组件进行集中控制,并采用Action组件来处理单项业务。
  
  一 控制器组件的控制机制
  
  Struts的控制器组件主要完成以下任务:
  
  ·接受用户请求
  
  ·根据用户请求,调用合适的模型组件来执行相应的业务逻辑。
  
  ·获取业务逻辑执行结果。
  
  ·根据当前状态以及业务逻辑执行结果,选择合适的视图组件返回给用户。
  
  1 Action类
  
  org.apache.struts.action.ActionServlet类是Struts框架的核心控制器组件,所有的用户请求都先有ActionServlet来处理,然后再由ActionServlet把请求转发给其他组件。Struts框架只允许在一个应用中配置一个ActionServlet类,在应用的生命周期中,仅创建ActionServlet类的一个实例,这个ActionServlet实例可以同时响应多个用户请求。
  
  (a)  Struts框架初始化过程
  
  (1)  调用initInternal()方法,初始化Struts框架内在的消息资源,如与系统日志相关的同志、警告和错误消息。
  
  (2)  调用initOther()方法,从web.xml文件中加载ActionServlet的初始化参数,如config参数。
  
  (3)  调用initServlet()方法,从web.xml文件中加载ActionServlet的URL映射信息。此外还会注册web.xml和Struts配置文件所使用的DTD文件,这些DTD文件用来验证web.xml和Struts配置文件的语法。
  
  (4)  调用initModuleConfig()方法,加载并解析子应用模块的Struts配置文件;创建ModuleConfig对象,把它在ServletContext中。
  
  (5)  调用initModuleMessageResources()方法,加载并初始化默认子应用模块的消息资源:创建MessageResources对象,把它在ServletContext中。
  
  (6)  调用initModuleDataSources()方法,加载并初始化默认子应用模块的数据源。如果在Struts配置文件中没有定义元素,就忽略这一流程。
  
  (7)  调用InitModulePlugins()方法,加载并初始化默认子应用模块的所有插件。
  
  (8)  当默认子应用模块被成功地初始化后,如果还包括其他子应用模块,将重复流程(4)~(7),分别对其他子应用模块进行初始化。
  
  (b)  ActionServlet的process()方法
  
  当ActionServlet实例接受到HTTP请求之后,在doGet()或doPost()方法都会调用process()方法来处理请求。一下是ActionServlet的process()方法的源代码:
  
  protected void process (HttpServletRequest request, HttpServletResponse response)
  
  throw IOException, ServletException {
  
  ModuleUtils.getInstance().selectModule(request, getServletContext());
  
  getRequestProcessor(getModuleConfig(request)).process(request, response);
  
  }
  
  在process()方法中,首先调用org.apache.struts.util.ModuleUtils类的selectModule()方法,这个方法选择负责处理当前请求的子应用模块,然后把与子应用模块相关的ModuleConfig和MessageResources对象存储倒request范围中,这使得框架的其余组件可以方便地从request范围中读取这些对象,从而获取应用配置信息和消息资源。
  
  process()方法的第二步操作为获得RequestProcessor类的实例,然后调用RequestProcessor类的process()方法,来完成十几的预处理请求操作。
  
  (c)  扩展ActionServlet类
  
  在Sturts 1.1 之前的版本中,ActionServlet类本身包含了很多处理请求的代码。从Struts 1.1 开始,多数功能被移到 org.apache.struts.action.RequestProcessor 类中,以便减轻ActionServlet类的控制负担。
  
  尽管新版本的Struts框架允许在应用中创建矿展ActionServlet类的子类,但是这在多数情况下没有必要,因为控制器的多数控制功能位于RequestProcessor类中。
  
  如果实际应用确实需要创建自己的ActionServlet类,则可以创建一个ActionServlet的子类,然后在web.xml文件中配置这个客户化ActionServlet类。
  
  如果覆盖了init()方法,应该确保首先调用super.init(),它保证ActionServlet的默认初始化操作被执行。除了覆盖init()方法外,事实上,还可以根据十几需要覆盖ActionServlet的任何其他方法。
  
  2 RequestProcessor类
  
  对于多应用模块的Struts应用,每个子应用模块都有各自的RequestProcessor实例。在ActionServlet的process()方法中,一旦选择了正确的子应用模块,就会调用子应用模块的RequestProcessor实例的process()方法来处理请求。在ActionServlet调用这个方法时,会把当前的request和response对象传给它。
  
  Struts框架只允许应用中存在一个ActionServlet类,但是可以存在多个客户化的RequestProcessor类,每个子应用模块都可以拥有单独的RequestProcessor类。如果想修改RequestProcessor类的一些默认功能,可以覆盖RequestProcessor基类中的相关方法。
  
  (a)  RequestProcessor类的process()方法
  
  RequestProcessor类的process()方法负责实际的预处理请求操作。
  
  RequestProcessor类的process()方法一次执行一下流程:
  
  (1) 调用processMultipart()方法。如果HTTP请求方式为POST,并且请求的contentType属性以“multipart/form-data”开头,标准的HttpServletRequest对象将被重新包装,以方便处理“multipart”类型的HTTP请求。如果请求方式为GET,或者contentType属性不是“multipart”,就直接返回原始的HttpServletRequest对象。
  
  (2) 调用processPath()方法,获得请求URI的路径,这一信息可用于选择合适的Struts Action组件。
  
  (3) 调用processLocale()方法,当ControllerConfig对象的locale属性为true,将读取用户请求中包含的Locale信息,然后把Locale实例保存在session范围内。
  
  (4) 调用processContent()方法,读取ControllerConfig对象的contentType属性,然后调用response.setContentType(contentType)方法,设置响应结果的文档类型和字符编码。
  
  (5) 调用processNoCache()方法,读取ControllerConfig对象的nocache属性,如果nocache属性为true,在响应结果中将加入特定的头参数:Pragma、Cache-Control和Expires,防止页面被存储在客户浏览器的缓存中。
  
  (6) 调用processPreprocess()方法。该方法不执行任何操作,直接返回true。子类可以覆盖这个方法,执行客户化的预处理请求操作。
  
  (7) 调用processMapping()方法,寻找和用户请求的URI匹配的ActionMapping。如果不存在这样的ActionMapping,则向用户返回恰当的错误消息。
  
  (8) 调用processRoles()方法,先判断是否为Action配置了角色,如果配置了安全角色,就调用isUserRole()方法判断当前用户是否具备必需的角色;如果不具备,就结束请求处理流程,向用户返回恰当的错误消息。
  
  (9) 调用processActionForm()方法,先判断是否为ActionMapping配置了ActionForm,如果配置了ActionForm,就先从ActionForm的存在范围内寻找该ActionForm实例;如果不存在,就创建一个实例。接下来把它保存在合适的范围中,保存时使用的属性key为ActionMapping的name属性。
  
  (10) 调用processActionForm()方法。如果为ActionMapping配置了ActionForm,就先调用ActionForm的reset()方法,再把请求中的表单数据组装到ActionForm中。
  
  (11) 调用processValidate()方法,如果为ActionMapping配置了ActionForm,并且ActionMapping的validate属性为true,就调用ActionForm的validate()方法。如果validate()方法返回的ActionErrors对象中包
【责编:admin】

--------------------next---------------------

阅读(238) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~