struts2 구현 프로세스 프레임 워크 및 소스 코드를 구문 분석

struts2 전체 구현 프로세스

핵심 필터 초기화
web.xml을 구성 필터 코어 StrutsPrepareAndExecuteFilter,로드 web.xml에 필터 구성 서블릿 컨테이너 출시, 초기화 필터를 수행하기위한 방법 및 객체 (필터 튜토리얼 자신의 지식을 인스턴스화하십시오 ).
코어는 초기화 방법이다 운영자 = 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] 부하 조직 / 아파치 / 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);
    }
}

( "조직 / 아파치 / struts2 / 기본")를 입력 할 수있는 새로운 PropertiesSettings을 클릭하여 계속 :

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

여기에는 경로 찾기 위해 매우 분명했습니다 조직 / 아파치 / 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";

다음은이 문장은로드 된 구성 파일입니다 분명하다 :
스트럿츠-default.xml에
스트럿츠 - 더 plugin.xml에
struts.xml

  • 스트럿-default.xml에

핵심 패키지에 대한 Struts2 파일.

  • 스트럿-plugin.xml에

Struts2 플러그 - 인 패키지, 당신은 struts2 여러 플러그인을 사용자 정의 할 수 있습니다, 각 플러그인 항아리 패키지는 스트럿-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] .로드 콩 구성
다음 코드 (자체 검사 부분만을 제거)

    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
  • 핵심 패키지에 스트럿-default.xml에
  • 플러그인 패키지 스트럿-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;
}

방법을 준비하고 초기화 방법을 입력 진행 :

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

다음 여기 인터셉터 구현의 코어는 메서드 Invoke 입력한다 :

    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 인터셉터의 기본 중 하나)로 쉽게,보기에 차단기를 찾을 수 있습니다, 실제로 차단을 수행하는 것입니다 :

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 인터셉터는 실행 대상의 반사를 이용하여 소정의 방법, 방법의 구현을 차단하는 수단을 정의 할 수 있고, 이전에 동적으로 변화 실행 후 특정 작업을 수행하거나 그 기능을 향상시키기 위해.

출시 여섯 개 원래 기사 · 원의 칭찬 0 · 조회수 125

추천

출처blog.csdn.net/li210530/article/details/99167943