struts的具體執行過程

下面以用戶登錄爲例:部分需要參考的配置文件如下:

<form-beans >
    <form-bean name="loginForm" type="com.hundsun.struts.form.LoginForm" />

</form-beans>

  <action-mappings >
    <action
      attribute="loginForm"
      input="/login.jsp"
      name="loginForm"
      path="/login"
      scope="request"
      validate="true"
      type="com.hundsun.struts.action.LoginAction" />

  </action-mappings>

  struts有一箇中央控制器ActionServlet,負責處理用戶的url請求,ActionServlet在web.xml文件中配置,它繼承了HttpServlet,其實就是一個普通的servlet。ActionServlet中有兩個方法,如下:

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

        process(request, response);

    }

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

        process(request, response);

    }

ActionServlet會自動調用doGet()或doPost()方法。從中可以看出doGet(),doPost()直接調用了process(request, response)方法:

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

    }

process方法繼續調用RequestProcessor 的process(request, response)方法,process的部分源代碼如下:

   public void process(HttpServletRequest request,
                        HttpServletResponse response){

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

        ActionForm form = processActionForm(request, response, mapping);
        processPopulate(request, response, form, mapping);  
   
        if (!processForward(request, response, mapping)) {
            return;
        }

        Action action = processActionCreate(request, response, mapping);
        if (action == null) {
            return;
        }

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

    }

processMultipart(request);主要是用來處理file域,其實就是重寫request得到屬性的方法。

String path = processPath(request, response);截取用戶提交的url地址,該方法主要的兩句代碼如下:

     int slash = path.lastIndexOf("/");
        int period = path.lastIndexOf(".");

此時的path="/login";接着我們來看

ActionMapping mapping = processMapping(request, response, path);主要源代碼如下:

 protected ActionMapping processMapping(HttpServletRequest request,
                                           HttpServletResponse response,
                                           String path)
        throws IOException {

        ActionMapping mapping = (ActionMapping)
            moduleConfig.findActionConfig(path);

        ActionConfig configs[] = moduleConfig.findActionConfigs();
        for (int i = 0; i < configs.length; i++) {
            if (configs[i].getUnknown()) {
                mapping = (ActionMapping) configs[i];
                request.setAttribute(Globals.MAPPING_KEY, mapping);
                return (mapping);
            }
        }

    }
我們先看ActionMapping mapping = (ActionMapping)moduleConfig.findActionConfig(path)方法。

moduleConfig類是個接口,他的實現類是moduleConfigImpl

   public ActionConfig findActionConfig(String path) {

        ActionConfig config = (ActionConfig) actionConfigs.get(path);
        return config;

    }

actionConfigs是個hashmap通過key=path="/login"獲取,actionConfigs的這個值是在struts初始化的時候放進去的。

ok,現在ActionMapping已經得到,一個ActionMapping就是對應一個<action/>標籤,它的key爲 <action/>標籤中的path的值,這裏爲"/login",其餘的<action/>標籤中的屬性值就是value。

 下面看:ActionForm form = processActionForm(request, response, mapping);

   protected ActionForm processActionForm(HttpServletRequest request,
                                           HttpServletResponse response,
                                           ActionMapping mapping) {

       
        ActionForm instance = RequestUtils.createActionForm
            (request, mapping, moduleConfig, servlet);
        if (instance == null) {
            return (null);
        }

        if ("request".equals(mapping.getScope())) {
            request.setAttribute(mapping.getAttribute(), instance);
        } else {
            HttpSession session = request.getSession();
            session.setAttribute(mapping.getAttribute(), instance);
        }
        return (instance);

    }

先看ActionForm instance = RequestUtils.createActionForm(request, mapping, moduleConfig, servlet);

    public static ActionForm createActionForm(
            HttpServletRequest request,
            ActionMapping mapping,
            ModuleConfig moduleConfig,
            ActionServlet servlet) {

        // Is there a form bean associated with this mapping?
        String attribute = mapping.getAttribute();
        if (attribute == null) {
            return (null);
        }
        String name = mapping.getName();
        FormBeanConfig config = moduleConfig.findFormBeanConfig(name);

        ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());

        return createActionForm(config, servlet);
    }

String attribute = mapping.getAttribute();是來找attribute="loginForm"如果沒有就直接返回,因爲formbean我們不一定要創建。

這句String name = mapping.getName();是得到form的名字 name="loginForm"

接着是FormBeanConfig config = moduleConfig.findFormBeanConfig(name);

    public FormBeanConfig findFormBeanConfig(String name) {

        return ((FormBeanConfig) formBeans.get(name));

    }

formBeans也是個hashmap,裏面存放的就是一個個<form-bean/>標籤這裏例子中的key="loginForm"

現在我們得到了一個FormBeanConfig。接着:

       ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());

   private static ActionForm lookupActionForm(HttpServletRequest request, String attribute, String scope)
    {
     
        ActionForm instance = null;
        HttpSession session = null;
        if ("request".equals(scope)) {
            instance = (ActionForm) request.getAttribute(attribute);
        } else {
            session = request.getSession();
            instance = (ActionForm) session.getAttribute(attribute);
        }

        return (instance);
    }

先在request和session找下是否存在這個FormBean,如果有就直接返回。如果instance爲空,就繼續創建createActionForm(config, servlet);

    public static ActionForm createActionForm(FormBeanConfig config, ActionServlet servlet)
    {
        ActionForm instance = null;

            instance = config.createActionForm(servlet);
           
        return (instance);

    }

    public ActionForm createActionForm(ActionServlet servlet)
        throws IllegalAccessException, InstantiationException {

        Object obj = null;

        // Create a new form bean instance
        if (getDynamic()) {
            obj = getDynaActionFormClass().newInstance();
        } else {
            obj = formBeanClass().newInstance();
        }

        ActionForm form = null;
        if (obj instanceof ActionForm) {
            form = (ActionForm)obj;
        } else  {
            form = new BeanValidatorForm(obj);
        }

        return form;

    }

通過動態代理得到一個formBean。

好了,現在我們看  Action action = processActionCreate(request, response, mapping);

 protected Action processActionCreate(HttpServletRequest request,
                                         HttpServletResponse response,
                                         ActionMapping mapping)
        throws IOException {

        String className = mapping.getType();
        Action instance = null;
        synchronized (actions) {
            instance = (Action) actions.get(className);
            if (instance != null) {
                return (instance);
            }
                instance = (Action) RequestUtils.applicationInstance(className);
      
            instance.setServlet(this.servlet);
            actions.put(className, instance);
        }

        return (instance);

    }

String className = mapping.getType();得到的就是action的完整路徑名,這裏爲com.hundsun.struts.action.LoginAction

synchronized (actions) actions是個hashmap,loginAction存在就返回,這裏進行了同步,也就是說只會創建一個loginAction實例。接下看下面的代碼,如果不存在就調用instance = (Action) RequestUtils.applicationInstance(className)

  public static Object applicationInstance(String className)
            throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        return (applicationClass(className).newInstance());

    }

返回一個loginAction實例。

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

    protected ActionForward
        processActionPerform(HttpServletRequest request,
                             HttpServletResponse response,
                             Action action,
                             ActionForm form,
                             ActionMapping mapping)
        throws IOException, ServletException {

            return (action.execute(mapping, form, request, response)); 

}

這裏直接調用了action類的execute方法,返回一個ActionForward,ActionForward類裏存放着對應<action/>標籤下的所有的forward信息。最後執行processForwardConfig(request, response, forward);

    protected void processForwardConfig(HttpServletRequest request,
                                        HttpServletResponse response,
                                        ForwardConfig forward)
        throws IOException, ServletException {

        if (forward == null) {
            return;
        }

        String forwardPath = forward.getPath();
        String uri = null;
        if (forwardPath.startsWith("/")) {
            uri = RequestUtils.forwardURL(request, forward, null); 
        } else {
            uri = forwardPath;
        }
        
        if (forward.getRedirect()) {
            if (uri.startsWith("/")) {
                uri = request.getContextPath() + uri;
            }
            response.sendRedirect(response.encodeRedirectURL(uri));
            
        } else {
            doForward(uri, request, response);
        }

    }

。。。。。

分兩種情況進行轉發,一種是: response.sendRedirect(response.encodeRedirectURL(uri));

另二種是:doForward(uri, request, response);該方法裏主要的兩句代碼是:
      RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);

     rd.forward(request, response);

OVER!

 

 

轉自http://lovedance.blogbus.com/logs/36997014.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章