Struts2の実装プロセスのためのフレームワークとソースコードを解析

Struts2の全体的な実装プロセス

コアフィルタ初期
web.xmlの構成フィルタコアStrutsPrepareAndExecuteFilter、負荷のweb.xmlフィルタ構成サーブレットコンテナが起動し、初期化フィルタを実行するための方法、およびオブジェクト(フィルタチュートリアル自身の知識をインスタンス化してください)。
コアは、initメソッドであるディスパッチャ= init.initDispatcher(設定)
に進みます。

public Dispatcher initDispatcher( HostConfig filterConfig ) {
        Dispatcher dispatcher = createDispatcher(filterConfig);
        dispatcher.init();
        return dispatcher;
    }

入射dispatcher.initを();
次のコードブロックを参照してください。

	init_DefaultProperties(); // [1]
    init_TraditionalXmlConfigurations(); // [2]
    init_LegacyStrutsProperties(); // [3]
    init_CustomConfigurationProviders(); // [5]
    init_FilterInitParameters() ; // [6]
    init_AliasStandardObjects() ; // [7]

ここでマークも、Struts2のフレームワークを初期化するために、設定ファイルをロードするStruts2のためにロードされたコンフィギュレーションファイルになります。
1、init_DefaultProperties(); // [
1] ロードORG /アパッチ/ Struts2の/ default.propertiesファイル
のソースコードを見るためにクリック。

private void init_DefaultProperties() {
    configurationManager.addContainerProvider(new DefaultPropertiesProvider());
}

入力する]をクリックして続行します。

public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
    try {
        PropertiesSettings defaultSettings = new PropertiesSettings("org/apache/struts2/default");
        loadSettings(props, defaultSettings);
    } catch (Exception e) {
        throw new ConfigurationException("Could not find or error in org/apache/struts2/default.properties", e);
    }
}

( "ORG / apacheの/ Struts2の/デフォルト")を入力する新しいPropertiesSettingsをクリックして続行します。

public PropertiesSettings(String name) {
    URL settingsUrl = ClassLoaderUtil.getResource(name + ".properties", getClass());
    略......
}

ここでは、へのパスを見つけることは非常に明白されている組織/ apacheの/ Struts2の/ default.propertiesファイルを。
設定ファイルは、実際にビットの定数です。ビューへの無料。

2.init_TraditionalXmlConfigurations()。// [2]
加载
支柱-default.xmlの
支柱-plugin.xmlの
struts.xml

ソースコードを表示します。

private void init_TraditionalXmlConfigurations() {
    String configPaths = initParams.get("config");
    if (configPaths == null) {
        configPaths = DEFAULT_CONFIGURATION_PATHS;
    }
    String[] files = configPaths.split("\\s*[,]\\s*");
    for (String file : files) {
        if (file.endsWith(".xml")) {
            if ("xwork.xml".equals(file)) {
                configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false));
            } else {
                configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
            }
        } else {
            throw new IllegalArgumentException("Invalid configuration file name");
        }
    }
}

どこ:DEFAULT_CONFIGURATION_PATHSは、次のように定義されます

private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";

ここでは、この文がロードされた設定ファイルであることは明らかである:
Strutsの-default.xmlの
Strutsの-plugin.xmlの
struts.xml

  • ストラット-default.xmlの

コアパッケージのStruts2のファイル。

  • ストラット-plugin.xmlの

Struts2のパッケージプラグイン、あなたはStruts2の複数のプラグインをカスタマイズすることができ、各プラグインのjarパッケージがストラット-plugin.xmlの設定ファイルを持っています。

  • struts.xml
    リソースディレクトリに格納されているユーザー定義の構成ファイルに。

3.init_LegacyStrutsProperties(); // [3]
のカスタムファイルはJAR内部struts2.properties定義された一定のカバレッジStruts2のコアの値をカスタマイズするために使用することができるロードstruts2.propertoes。

ソースコードを見るためにクリック

   private void init_LegacyStrutsProperties() {
        configurationManager.addContainerProvider(new PropertiesConfigurationProvider());
    }

入力を続行:

public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
    final DefaultSettings settings = new DefaultSettings();
    loadSettings(props, settings);
}

続行:

    public DefaultSettings() {

        ArrayList<Settings> list = new ArrayList<Settings>();

        // stuts.properties, default.properties
        try {
            list.add(new PropertiesSettings("struts"));
        } catch (Exception e) {
            LOG.warn("DefaultSettings: Could not find or error in struts.properties", e);
        }
略.....
    }

新しいPropertiesSettings(「ストラット」)を入力し、あなたが見ることができます:

URL settingsUrl = ClassLoaderUtil.getResource(name + ".properties", getClass());

リソースディレクトリにstruts2.properties設定ファイルを探しています。
4、init_CustomConfigurationProviders(); // [
5] ユーザ定義の構成は、実質的に詳細に展開していない、アクセス権を持っていません。
5、init_FilterInitParameters(); // [
6] ロードweb.xmlファイル。
これは、ここで注意しなければならない:
web.xmlファイルは、ブート時のサーブレットコンテナにロードされ、そして、そのような荷重は、フレームワークStruts2のStruts2の独自のタグを参照するフィルタの初期化などの他の操作は、web.xmlのファイルの解析を定義しました。
具体的な原理は不明です。
6、init_AliasStandardObjects(); // [
7] のロードBean構成。
以下のコード(自己検査の一部のみの除去):

    private void init_AliasStandardObjects() {
            configurationManager.addContainerProvider(new DefaultBeanSelectionProvider());
        }
点击进入:

    public void register(ContainerBuilder builder, LocatableProperties props) {
        alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);
略...
        /** Checker is used mostly in interceptors, so there be one instance of checker per interceptor with Scope.DEFAULT **/
        alias(ExcludedPatternsChecker.class, StrutsConstants.STRUTS_EXCLUDED_PATTERNS_CHECKER, builder, props, Scope.DEFAULT);
        alias(AcceptedPatternsChecker.class, StrutsConstants.STRUTS_ACCEPTED_PATTERNS_CHECKER, builder, props, Scope.DEFAULT);
    
        switchDevMode(props);
    
        // Convert Struts properties into XWork properties
        convertIfExist(props, StrutsConstants.STRUTS_LOG_MISSING_PROPERTIES, XWorkConstants.LOG_MISSING_PROPERTIES);
        略...   
        LocalizedTextUtil.addDefaultResourceBundle("org/apache/struts2/struts-messages");
        loadCustomResourceBundles(props);
    }

ロード順に、Struts2のフレームワークの構成ファイルを要約すると:

  • コアパッケージのdefault.properties
  • コアパッケージ内のstruts-default.xmlの
  • プラグインパッケージ内のstruts-plugin.xmlの
  • struts.xmlカスタムリソースディレクトリの下に
  • struts.propertiesカスタムリソースディレクトリの下に
  • web.xmlの

第二に、インターセプタ
Struts2のインターセプタは、アクションまたはアクション、またはフィールドの後にアクセスする方法の前の実施形態を傍受し、プラグイン可能なStruts2のインターセプタです、インターセプターは、AOPの実装です。
出典分析:

        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    try {
        if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
            chain.doFilter(request, response);
        } else {
            prepare.setEncodingAndLocale(request, response);
            prepare.createActionContext(request, response);
            prepare.assignDispatcherToThread();
            request = prepare.wrapRequest(request);
            ActionMapping mapping = prepare.findActionMapping(request, response, true);
            if (mapping == null) {
                boolean handled = execute.executeStaticResourceRequest(request, response);
                if (!handled) {
                    chain.doFilter(request, response);
                }
            } else {
                execute.executeAction(request, response, mapping);
            }
        }
    } finally {
        prepare.cleanupRequest(request);
    }
}

execute.executeAction方法を入力します。

public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
        throws ServletException {

    Map<String, Object> extraContext = createContextMap(request, response, mapping);

    // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
    ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    boolean nullStack = stack == null;
    if (nullStack) {
        ActionContext ctx = ActionContext.getContext();
        if (ctx != null) {
            stack = ctx.getValueStack();
        }
    }
    if (stack != null) {
        extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
    }

    String timerKey = "Handling request from Dispatcher";
    try {
        UtilTimerStack.push(timerKey);
        String namespace = mapping.getNamespace();
        String name = mapping.getName();
        String method = mapping.getMethod();

        ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                namespace, name, method, extraContext, true, false);

        request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

        // if the ActionMapping says to go straight to a result, do it!
        if (mapping.getResult() != null) {
            Result result = mapping.getResult();
            result.execute(proxy.getInvocation());
        } else {
            proxy.execute();
        }

        // If there was a previous value stack then set it back onto the request
        if (!nullStack) {
            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
        }
    } catch (ConfigurationException e) {
        logConfigurationException(request, e);
        sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
    } catch (Exception e) {
        if (handleException || devMode) {
            sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
        } else {
            throw new ServletException(e);
        }
    } finally {
        UtilTimerStack.pop(timerKey);
    }
}

ここでは、アクションは、プロキシオブジェクトを作成した見ることができます。内部ビューにプロキシオブジェクトを作成します。

public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {

    DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
    container.inject(proxy);
    proxy.prepare();
    return proxy;
}

方法を準備するために進み、その後のinitメソッドを入力します。

public void init(ActionProxy proxy) {
    this.proxy = proxy;
    Map<String, Object> contextMap = createContextMap();

    // Setting this so that other classes, like object factories, can use the ActionProxy and other
    // contextual information to operate
    ActionContext actionContext = ActionContext.getContext();

    if (actionContext != null) {
        actionContext.setActionInvocation(this);
    }

    createAction(contextMap);

    if (pushAction) {
        stack.push(action);
        contextMap.put("action", action);
    }

    invocationContext = new ActionContext(contextMap);
    invocationContext.setName(proxy.getActionName());

    // get a new List so we don't get problems with the iterator if someone changes the list
    List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
    interceptors = interceptorList.iterator();
}

ここではインターセプタのセットを取得し、イテレータとして返すために、反復子は、ここで迎撃文書、18の合計で定義されたストラット-default.xmlのデフォルトのセットです。

プロキシオブジェクトを生成した後、次のように、メソッドを実行し続けます。

public String execute() throws Exception {
    ActionContext nestedContext = ActionContext.getContext();
    ActionContext.setContext(invocation.getInvocationContext());

    String retCode = null;

    String profileKey = "execute: ";
    try {
        UtilTimerStack.push(profileKey);

        retCode = invocation.invoke();
    } finally {
        if (cleanupContext) {
            ActionContext.setContext(nestedContext);
        }
        UtilTimerStack.pop(profileKey);
    }

    return retCode;
}

次のようにここでインターセプタの実装のコアは、呼び出しメソッドを入力すること、です。

    public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);

            if (executed) {
                throw new IllegalStateException("Action has already executed");
            }

            if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
           }
略.....
    }

インターセプト法は、次のように簡単に、ExceptionMappingInterceptor(18のインターセプタのデフォルトの1)として、ビューにブロッカーを見つけることができ、実際に傍受を実行することです。

public String intercept(ActionInvocation invocation) throws Exception {
    String result;

    try {
        result = invocation.invoke();
    } catch (Exception e) {
        if (isLogEnabled()) {
            handleLogging(e);
        }
        List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
        ExceptionMappingConfig mappingConfig = this.findMappingFromExceptions(exceptionMappings, e);
        if (mappingConfig != null && mappingConfig.getResult()!=null) {
            Map parameterMap = mappingConfig.getParams();
            // create a mutable HashMap since some interceptors will remove parameters, and parameterMap is immutable
            invocation.getInvocationContext().setParameters(new HashMap<String, Object>(parameterMap));
            result = mappingConfig.getResult();
            publishException(invocation, new ExceptionHolder(e));
        } else {
            throw e;
        }
    }

    return result;
}

この方法は、別のメソッドを呼び出しインターセプトするインターセプターの中に発見、前面に戻ります(interceptors.hasNext())判決、18のインターセプタが全て実行されないことを示すデフォルトが、次の要素が存在する場合、反復子、そう再帰的に繰り返します。

ルーチンとスプリングAOPインターセプタは非常に類似している技術は、動的プロキシの使用、特定の処理のための要求です。Struts2のインターセプタはまた、特定のメソッドの実装のためにインターセプトするための手段をカスタマイズし、ターゲットの実行の反射を利用する方法、および動的に変更に実行前と後に、特定の物事を行うか、その機能を強化することができます。

リリース6元記事 ウォンの賞賛0 ビュー125

おすすめ

転載: blog.csdn.net/li210530/article/details/99167943