struts2:Struts

 

Struts1.2.9源码的主要几个实现类。

Struts是最流行的MVC框架之一, 下图是它的流程示意图。

客户端发送一个Request,Servlet负责拦截所有的请求,并决定分发每一个请求。对应的类是ActionServlet,可以说ActionServlet是一个Controller。ActionServlet是怎样分发每一个请求的呢?首先,读取strtuts-config.xml配置文件里的信息,找到每一个Action,Action负责和业务逻辑打交道,也就是Model。最后,通过Servlet来Forward到相应的前端(如html,jsp等)。通常把前端展示部分称为VIEW

       Struts有三个核心的类,分别是ActionServlet,ModuleConfig,RequestProcessor。ActionServlet就是控制器,ModuleConfig封装着Struts应用程序的配置信息,RequestProcessor负责处理每一个HTTP请求。

它们之间的依赖关系如图所示:

ActionServlet在执行init()时,首先从ModuleConfigFactory中得到一个ModuleConfig,并把它传给RequestProcessor。接下来就是doGet()和doPost()方法,对请求进行处理;其实工作都交给了一个process()方法。在这个方法里,如下:

protected void process(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {

        //查找正确的ModuleConfig 对象

        ModuleUtils.getInstance().selectModule(request, getServletContext());
        ModuleConfig config = getModuleConfig(request);

        //得到一个RequestProcessor 对象,并把ModuleConfig 传递给它

        RequestProcessor processor = getProcessorForModule(config);
        if (processor == null) {
           processor = getRequestProcessor(config);
        }

        //调用RequestProcessor 对象的process()方法
        processor.process(request, response);

    }

最后的工作都集中在processor.process(request, response);里完成。

public void process(HttpServletRequest request,
                        HttpServletResponse response)
        throws IOException, ServletException {

         //判断当前请求是不是在上传一个文件;如果是,就调用这个方法       

        request = processMultipart(request);

    //对路径的处理,得到动作路径。例如:htt;//localhost:8080/app/sample.do 那么对应的Action路径是sample

        String path = processPath(request, response);
        if (path == null) {
            return;
        }
       
        if (log.isDebugEnabled()) {
            log.debug("Processing a '" + request.getMethod() +
                      "' for path '" + path + "'");
        }

        // 和国际化有关

        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);

        // 得到ActionMapping       

        ActionMapping mapping = processMapping(request, response, path);
        if (mapping == null) {
            return;
        }

        // 检查权限

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

        // 处理ActionForm

        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;
        }

        // 创建出请求的Action实例。其中,这个方法通过getType()拿到mapping中对应的类名

       //通过类名得到对应的action实例,因为每一个action都和相应的类名建立一个映射关系放在HashMap中
        Action action = processActionCreate(request, response, mapping);
        if (action == null) {
            return;
        }

        // 执行转向信息,查看这个方法,会发现其实还是执行了action.execute()

        ActionForward forward =
                processActionPerform(request, response, action, form, mapping);

        // 最后的跳转任务就交给这个方法来完成了

        processForwardConfig(request, response, forward);

    }

最后,说一下关于ActionConfig类和ForwardConfig类。ActionConfig类里封装了action的信息,它的属性名和action对应的名称一致,比如type,name等,ActionMapping类从这个类继承而来。ForwardConfig类封装了forwar信息,对应配置文件中<forward>标签的内容,ActionForwar类从它继承。

Struts中存在中大量的HashMap,每一个Module通过这些HashMap读取配置信息。如:actionConfigs中存的是action和它的path的键值对;formBeans中存的是formbean和它的name的键值对;forwards中存的是forward和它的name的键值对。这样就能很容易通过get(Key)方法得到相应的Value了。

Tags:  struts2ajax struts标签 struts2标签 struts2

延伸阅读

最新评论

发表评论