struts控制器组件

Struts 控制器组件
Struts控制器组件主要包括:
ActionServlet组件:充当Struts框架的中央控制器
RequestProcessor组件:充当每个子应用模块的请求处理器
Action组件:负责处理一项具体的业务。
Struts框架采用ActionServlet和RequestProcessor组件进行集中控制,并采用Action组件来处理单项业务。
Struts的控制器组件主要完成以下任务:
1. 接收用户请求
2. 根据用户请求,调用合适的模型组件来执行相应的业务逻辑。
3. 获取业务逻辑执行结果
4. 根据当前状态以及业务逻辑执行结果,选择合适的视图组件返回给用户。

1. ActionServlet类
org.apache.struts.action.ActionServlet类是Struts框架的核心控制器组件,所有的用户请求都先由 ActionServlet来处理,然后再由ActionServlet把请求转发给其他组件。Struts框架只允许在一个应用中配置一个 ActionServlet类,在应用的生命周期中,仅创建ActionServlet类的一个实例,这个ActionServlet实例可以同时响应多 个用户请求。
ActionServlet的init()方法的时序图

(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配置文件中没有定义<data-sources>元素,就忽略这一流程。
(7)调用initModulePlugins()方法,加载并初始化默认子应用模块的所有插件。
(8)当默认子应用模块被成功初始化后,如果还包括其他子应用模块,将重复流程4-7,分别对其他子应用模块进行初始话。

2.RequestProcessor类
当ActionServlet实例接收到HTTP请求后,在doGet()或doPost()方法中都回调用process()方法来处理请求
以下是ActionServlet的process()方法的源代码:
protected void process(HttpServletRequest request,
        HttpServletResponse response)
        throws IOException, ServletException {
        ModuleUtils.getInstance().selectModule(request, getServletContext());
        ModuleConfig config = getModuleConfig(request);
        RequestProcessor processor = getProcessorForModule(config);
        if (processor == null) {
            processor = getRequestProcessor(config);
        }
        processor.process(request, response);
    }
RequestProcessor类process()方法的部分代码片段
public void process(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
        // Wrap multipart requests with a special wrapper
        request = processMultipart(request);

        // Identify the path component we will use to select a mapping
        String path = processPath(request, response);

        if (path == null) {
            return;
        }

        if (log.isDebugEnabled()) {
            log.debug("Processing a '" + request.getMethod() + "' for path '"
                + path + "'");
        }

        // Select a Locale for the current user if requested
        processLocale(request, response);

        // Set the content type and no-caching headers if requested
        processContent(request, response);
        processNoCache(request, response);

        // General purpose preprocessing hook
        if (!processPreprocess(request, response)) {
            return;
        }

        this.processCachedMessages(request, response);

        // Identify the mapping for this request
        ActionMapping mapping = processMapping(request, response, path);

        if (mapping == null) {
            return;
        }

        // Check for any role required to perform this action
        if (!processRoles(request, response, mapping)) {
            return;
        }

        // Process any ActionForm bean related to this request
        ActionForm form = processActionForm(request, response, mapping);

        processPopulate(request, response, form, mapping);

        // Validate any fields of the ActionForm bean, if applicable
        try {
            if (!processValidate(request, response, form, mapping)) {
                return;
            }
        } catch (InvalidCancelException e) {
            ActionForward forward = processException(request, response, e, form, mapping);
            processForwardConfig(request, response, forward);
            return;
        } catch (IOException e) {
            throw e;
        } catch (ServletException e) {
            throw e;
        }

        // Process a forward or include specified by this mapping
        if (!processForward(request, response, mapping)) {
            return;
        }

        if (!processInclude(request, response, mapping)) {
            return;
        }

        // Create or acquire the Action instance to process this request
        Action action = processActionCreate(request, response, mapping);

        if (action == null) {
            return;
        }

        // Call the Action instance itself
        ActionForward forward =
            processActionPerform(request, response, action, form, mapping);

        // Process the returned ActionForward instance
        processForwardConfig(request, response, forward);
}

processMapping()方法,寻找和用户请求的URI匹配的ActioinMapping.如果不存在这样的ActionMapping,则向用户返回适当的错误消息。

processActionForm()方法,先判断是否为ActionMapping配置了ActionForm,就先从ActionForm 的存在范围内寻找该ActionForm实例;如果不存在,就创建一个实例。接下来把他保存在合适的范围中,保存时使用的属性key为 ActionMapping的name属性。

processPopulate()方法。如果为ActionMapping配置了ActionForm,就先调用ActionForm的reset()方法,再把请求中的表单数据组装到ActionForm中。

processValidate()方法。如果为ActionMapping配置了ActionForm,并且ActionMapping的 validate属性为true,就调用ActionForm的validate()方法。如果validate()方法返回的ActionErrors 对象存储在request范围内,再把如果表单验证失败,就把ActionErrors对象中包含ActionMessage对象,说明表单验证失败,就 把ActionErrors对象存储在request范围内,再把请求转发到ActionMapping的input属性指定的web组件。如果 ActionForm的validate()方法执行表单验证成功,就继续执行下一步请求处理流程。

processForward()方法,判断是否在ActionMapping中配置了forward属性。如果配置了这个属性,就调用RequestDispatcher的forward方法,请求处理流程结束,否则继续下一步。

processInclude()方法,判断是否在ActionMapping中配置了include属性。如果配置了这个属性,就调用RequestDispatcher的include方法,请求处理流程结束,否则继续下一步。

processActionCreate()方法,先判断是否在Action缓存中存在这个Action实例,把它保存在Action缓存中。

processActionPerform()方法,该方法再调用Action实例的execute()方法.execute()方法位于try/catch代码中,以便捕获异常。
protected ActionForward processActionPerform(HttpServletRequest request,
        HttpServletResponse response, Action action, ActionForm form,
        ActionMapping mapping)
        throws IOException, ServletException {
        try {
            return (action.execute(mapping, form, request, response));
        } catch (Exception e) {
            return (processException(request, response, e, form, mapping));
        }
    }

调用processActionForward()方法,把Action的execute()方法返回的ActionForward对象作为参数 传给它。processActionForward()根据ActionForward对象包含的请求转发信息来执行请求转发或重定向。

2.Struts Action类
ForwardAction
IncludeAction
DispatchAction
LookupDispatchAction
SwitchAction

(1) ForwardAction
<action
      attribute="test2Form"
      input="/test/test3.jsp"
      name="test2Form"
      path="/testActionForward"
      scope="request"
  parameter="/test/actionForward.jsp "
      type=" org.apache.struts.actions.ForwardAction " />
<action forward="/test/actionForward.jsp" path="/testActionForward"
/>

(2) IncludeAction
<action   
      path="/testIncludeAction"
      scope="request"
name="test2Form"
input="/test/test4.jsp"
  parameter="/test/includeAction.jsp "
      type=" org.apache.struts.actions.IncludeAction " />
<action
include="/test/includeAction.jsp"
scope="request"
name="test2Form"
input="/test/test4.jsp"
path="/testIncludeAction" />
(3) DispatchAction
<action
      name="test3Form"
      path="/testDispatchForward"
      parameter="method"
      scope="request"
      validate="false"
      type="com.webshop.struts.action.test.TestDispatchAction">
      <forward name="success" path="/test/test5.jsp" />
</action>

<html:link page="/testDispatchForward.do?method=add" >DispatchActiontestadd</html:link>

(4) LookupDispatchAction
protected Map getKeyMethodMap() {
Map map=new HashMap();
map.put("button.test1", "test1");
map.put("button.test2", "test2");
return map;
}
<html:submit property="action" ><bean:message key="button.test1"/></html:submit>
<html:submit property="action" ><bean:message key="button.test2"/></html:submit>
public ActionForward test1(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)
<action
      name="test3Form"
      path="/testLookupDispatchAction"
      parameter="action"
      scope="request"
      validate="false"
      type="com.webshop.struts.action.test.TestLookupDispatchAction">
      <forward name="success" path="/test/success.jsp" />
    </action>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值