struts1源码学习8,chainBase对request和response的处理

ComposableRequestProcessor的process方法中,最核心的部分实际上是chainBase这个对象来处理的。

在ActionServlet.init执行完之后,这个chainBase对象中包含三个command。当chainBase.excute()时,会分别执行三个command的excute。而这三个command中,又由于有lookUpCommand的存在,导致命令链的跳转,最终执行了个不止3个command。实际上,按照chain-config.xml,这个chainBase会执行process-action,process-view。

先看ChainBase代码

package org.apache.commons.chain.impl;
public class ChainBase implements Chain {
    public ChainBase() {
    }
    public ChainBase(Command command) {
       addCommand(command);
    }
    public ChainBase(Command[] commands) {
        if (commands == null) {
            throw new IllegalArgumentException();
        }
        for (int i = 0; i < commands.length; i++) {
            addCommand(commands[i]);
        }
    }
    public ChainBase(Collection commands) {
        if (commands == null) {
            throw new IllegalArgumentException();
        }
        Iterator elements = commands.iterator();
        while (elements.hasNext()) {
            addCommand((Command) elements.next());
        }
    }
<span style="white-space:pre">	</span>//存放命令链
    protected Command[] commands = new Command[0];

    protected boolean frozen = false;
<span style="white-space:pre">	</span>//添加command到命令链
    public void addCommand(Command command) {

        if (command == null) {
            throw new IllegalArgumentException();
        }
        if (frozen) {
            throw new IllegalStateException();
        }
        Command[] results = new Command[commands.length + 1];
        System.arraycopy(commands, 0, results, 0, commands.length);
        results[commands.length] = command;
        commands = results;

    }

    public boolean execute(Context context) throws Exception {

        // Verify our parameters
        if (context == null) {
            throw new IllegalArgumentException();
        }

        // Freeze the configuration of the command list
        frozen = true;

        // Execute the commands in this list until one returns true
        // or throws an exception
        boolean saveResult = false;
        Exception saveException = null;
        int i = 0;
        int n = commands.length;
        for (i = 0; i < n; i++) {
            try {
<span style="white-space:pre">	</span>//从第一个command开始执行excute,如果返回值是true,则break,否则继续执行
                saveResult = commands[i].execute(context);
                if (saveResult) {
                    break;
                }
            } catch (Exception e) {
<span style="white-space:pre">	</span>//拿到command.excute产生的异常
                saveException = e;
                break;
            }
        }

        // 保证commands[0]到commands[i]都已经执行过excute方法
        if (i >= n) { // Fell off the end of the chain
            i--;
        }
        boolean handled = false;
        boolean result = false;
        for (int j = i; j >= 0; j--) {
<span style="white-space:pre">	</span>//org.apache.commons.chain.Filter(继承自Command)
            if (commands[j] instanceof Filter) {
                try {
<span style="white-space:pre">	</span>//后处理
                    result =
                        ((Filter) commands[j]).postprocess(context,
                                                           saveException);
                    if (result) {
                        handled = true;
                    }
                } catch (Exception e) {
                      // Silently ignore
                }
            }
        }

        // Return the exception or result state from the last execute()
        if ((saveException != null) && !handled) {
            throw saveException;
        } else {
            return (saveResult);
        }

    }

    Command[] getCommands() {

        return (commands);

    }


}

LookUpCommand的代码

package org.apache.commons.chain.generic;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.CatalogFactory;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.chain.Filter;


public class LookupCommand implements Filter {

    // -------------------------------------------------------------- Constructors

    public LookupCommand() {
        this(CatalogFactory.getInstance());
    }
    
    public LookupCommand(CatalogFactory factory) {
        this.catalogFactory = factory;
    }


    // -------------------------------------------------------------- Properties

    private CatalogFactory catalogFactory = null;

    
    public void setCatalogFactory(CatalogFactory catalogFactory) {
        this.catalogFactory = catalogFactory;
    }

    
    public CatalogFactory getCatalogFactory() {

        return this.catalogFactory;
    }


    private String catalogName = null;

    public String getCatalogName() {

        return (this.catalogName);

    }

    public void setCatalogName(String catalogName) {

        this.catalogName = catalogName;

    }

    private String name = null;

    public String getName() {

        return (this.name);
    }

    public void setName(String name) {

        this.name = name;
    }

    private String nameKey = null;

    public String getNameKey() {

        return (this.nameKey);
    }

    public void setNameKey(String nameKey) {

        this.nameKey = nameKey;
    }

    private boolean optional = false;

    public boolean isOptional() {

        return (this.optional);
    }

    public void setOptional(boolean optional) {

        this.optional = optional;
    }

    private boolean ignoreExecuteResult = false;

    public boolean isIgnoreExecuteResult() {
        return ignoreExecuteResult;
    }
    public void setIgnoreExecuteResult(boolean ignoreReturn) {
        this.ignoreExecuteResult = ignoreReturn;
    }

    private boolean ignorePostprocessResult = false;

    public boolean isIgnorePostprocessResult() {
        return ignorePostprocessResult;
    }


    public void setIgnorePostprocessResult(boolean ignorePostprocessResult) {
        this.ignorePostprocessResult = ignorePostprocessResult;
    }
    // ---------------------------------------------------------- Filter Methods


    public boolean execute(Context context) throws Exception {
<span style="white-space:pre">	</span>//getCommand
        Command command = getCommand(context);
        if (command != null) {
<span style="white-space:pre">	</span>//执行command的excute
            boolean result = (command.execute(context));
<span style="white-space:pre">	</span>//表示是否忽略command的执行结果
            if (isIgnoreExecuteResult()) {
                return false;
            }
            return result;
        } else {
            return (false);
        }

    }

    public boolean postprocess(Context context, Exception exception) {

        Command command = getCommand(context);
        if (command != null) {
            if (command instanceof Filter) {
                boolean result = (((Filter) command).postprocess(context, exception));
                if (isIgnorePostprocessResult()) {
                    return false;
                }
                return result;
            }
        }
        return (false);

    }


    // --------------------------------------------------------- Private Methods


    protected Catalog getCatalog(Context context) {
        CatalogFactory lookupFactory = this.catalogFactory;
        if (lookupFactory == null) {
            lookupFactory = CatalogFactory.getInstance();
        }

        String catalogName = getCatalogName();
        Catalog catalog = null;
        if (catalogName == null) {
            // use default catalog
            catalog = lookupFactory.getCatalog();
        } else {
            catalog = lookupFactory.getCatalog(catalogName);
        }
        if (catalog == null) {
            if (catalogName == null) {
                throw new IllegalArgumentException
                    ("Cannot find default catalog");
            } else {
                throw new IllegalArgumentException
                    ("Cannot find catalog '" + catalogName + "'");
            }
        }

        return catalog;
    }

   
    protected Command getCommand(Context context) {
<span style="white-space:pre">	</span>//获取到catalog
        Catalog catalog = getCatalog(context);

        Command command = null;
<span style="white-space:pre">	</span>//获取到commandname,实际上就是lookupcommand标签的name属性
        String name = getCommandName(context);
        if (name != null) {
<span style="white-space:pre">	</span>//根据name找到command
<span style="white-space:pre">	</span>//这里其实是不会找到lookupcommand的,因为catalog在添加command的键值对(name做key,command对象做value)时,只有上一层标签时catalog时才会有;如果上级标签不是catalog,则只可能执行chain.addCommand(command),这种情况下,是没有name做key的
            command = catalog.getCommand(name);
            if ((command == null) && !isOptional()) {
                if (catalogName == null) {
                    throw new IllegalArgumentException
                        ("Cannot find command '" + name
                         + "' in default catalog");
                } else {
                    throw new IllegalArgumentException
                        ("Cannot find command '" + name
                         + "' in catalog '" + catalogName + "'");
                }
            }
            return (command);
        } else {
            throw new IllegalArgumentException("No command name");
        }

    }


    protected String getCommandName(Context context) {

        String name = getName();
        if (name == null) {
            name = (String) context.get(getNameKey());
        }
        return name;

    }

}
从代码可以看出,lookupcommand实际上就是用来跳转命令链的。这样的好处就是使命令链清晰,不必重复配置。


猜你喜欢

转载自blog.csdn.net/wtc860104/article/details/38415061
今日推荐