Structs ActionProxy deep reading

Source: Internet
Author: User

Structs ActionProxy deep reading

Actionproxyis a proxy class of the actionaction. It also means that the call of the actionaction is passed through the actionproxyactually. The actual call of the actionproxy.exe cute () method calls the ActionInvocation. invoke () method. In the final analysis, the DefaultActionInvocation. invokeAction () method is called.
DefaultActionInvocation ()-> init ()-> createAction ().
Finally, call ActionProxy. exute () --> ActionInvocation. invoke () --> Intercepter. intercept () --> ActionInvocation. invokeActionOnly () --> invokeAction ()
The steps here are to first create ActionInvocation and ActionProxy by ActionProxyFactory.

Java code
  1. Public ActionProxy createActionProxy (String namespace, String actionName, String methodName, Map ExtraContext, boolean executeResult, boolean cleanupContext ){
  2. ActionInvocation inv = new DefaultActionInvocation (extraContext, true );
  3. Container. inject (inv );
  4. Return createActionProxy (inv, namespace, actionName, methodName, executeResult, cleanupContext );
  5. }

    The following describes the init method of defaactionactioninvocation.

    Java code
    1. Public void init (ActionProxy proxy ){
    2. This. proxy = proxy;
    3. Map ContextMap = createContextMap ();
    4. // Setting this so that other classes, like object factories, can use the ActionProxy and other
    5. // Contextual information to operate
    6. ActionContext actionContext = ActionContext. getContext ();
    7. If (actionContext! = Null ){
    8. ActionContext. setActionInvocation (this );
    9. }
    10. // Create an Action. Each Request in struts2 creates a new Action.
    11. CreateAction (contextMap );
    12. If (pushAction ){
    13. Stack. push (action );
    14. ContextMap. put ("action", action );
    15. }
    16. InvocationContext = new ActionContext (contextMap );
    17. InvocationContext. setName (proxy. getActionName ());
    18. // Get a new List so we don't get problems with the iterator if someone changes the list
    19. List InterceptorList = new ArrayList (Proxy. getConfig (). getInterceptors ());
    20. Interceptors = interceptorList. iterator ();
    21. }
    22. Protected void createAction (Map ContextMap ){
    23. // Load action
    24. String timerKey = "actionCreate:" + proxy. getActionName ();
    25. Try {
    26. UtilTimerStack. push (timerKey );
    27. // The default value is SpringObjectFactory: struts. objectFactory = spring. This attribute is very clever. You can override this attribute in struts. properties.
    28. // In BeanSelectionProvider, set the implementation class for ObjectFactory through the configuration file.
    29. // Here, Spring is used as an example. Here, the buildBean method of SpringObjectFactory is adjusted. You can use the getBean () method of ApplicationContext to obtain Spring Bean.
    30. Action = objectFactory. buildAction (proxy. getActionName (), proxy. getNamespace (), proxy. getConfig (), contextMap );
    31. } Catch (InstantiationException e ){
    32. Throw new XWorkException ("Unable to intantiate Action! ", E, proxy. getConfig ());
    33. } Catch (IllegalAccessException e ){
    34. Throw new XWorkException ("Illegal access to constructor, is it public? ", E, proxy. getConfig ());
    35. } Catch (Exception e ){
    36. ...
    37. } Finally {
    38. UtilTimerStack. pop (timerKey );
    39. }
    40. If (actionEventListener! = Null ){
    41. Action = actionEventListener. prepare (action, stack );
    42. }
    43. }
    44. // SpringObjectFactory
    45. Public Object buildBean (String beanName, Map ExtraContext, boolean injectInternal) throws Exception {
    46. Object o = null;
    47. Try {
    48. // SpringObjectFactory will automatically inject ClassPathXmlApplicationContext through context-param: contextConfigLocation in web. xml
    49. O = appContext. getBean (beanName );
    50. } Catch (NoSuchBeanDefinitionException e ){
    51. Class beanClazz = getClassInstance (beanName );
    52. O = buildBean (beanClazz, extraContext );
    53. }
    54. If (injectInternal ){
    55. InjectInternalBeans (o );
    56. }
    57. Return o;
    58. }

      Java code
      1. // Next let's take a look at the invoke method of DefaultActionInvocation.
      2. Public String invoke () throws Exception {
      3. String profileKey = "invoke :";
      4. Try {
      5. UtilTimerStack. push (profileKey );
      6. If (executed ){
      7. Throw new IllegalStateException ("Action has already executed ");
      8. }
      9. // Recursively execute interceptor
      10. If (interceptors. hasNext ()){
      11. // Interceptors are InterceptorMapping, which is actually an Interceptor chain like FilterChain.
      12. // Call Invocation. invoke () to implement recursive callback Loop
      13. Final InterceptorMapping interceptor = (InterceptorMapping) interceptors. next ();
      14. String interceptorMsg = "interceptor:" + interceptor. getName ();
      15. UtilTimerStack. push (interceptorMsg );
      16. Try {
      17. // Return invocation. invoke () in each Interceptor Method ()
      18. ResultCode = interceptor. getInterceptor (). intercept (defaactionactioninvocation. this );
      19. }
      20. Finally {
      21. UtilTimerStack. pop (interceptorMsg );
      22. }
      23. } Else {
      24. // When all interceptors are completed and finally the Action is executed, invokeActionOnly calls the invokeAction () method
      25. ResultCode = invokeActionOnly ();
      26. }
      27. // This is needed because the result will be executed, then control will return to the Interceptor, which will
      28. // Return abve and flow through again
      29. // Call preResultListeners before the Result is returned.
      30. // Execute only once through executed Control
      31. If (! Executed ){
      32. If (preResultListeners! = Null ){
      33. For (Object preResultListener: preResultListeners ){
      34. PreResultListener listener = (PreResultListener) preResultListener;
      35. String _ profileKey = "preResultListener :";
      36. Try {
      37. UtilTimerStack. push (_ profileKey );
      38. Listener. beforeResult (this, resultCode );
      39. }
      40. Finally {
      41. UtilTimerStack. pop (_ profileKey );
      42. }
      43. }
      44. }
      45. // Now execute the result, if we're re supposed
      46. // Execute Result
      47. If (proxy. getExecuteResult ()){
      48. ExecuteResult ();
      49. }
      50. Executed = true;
      51. }
      52. Return resultCode;
      53. }
      54. Finally {
      55. UtilTimerStack. pop (profileKey );
      56. }
      57. }
      58. // InvokeAction
      59. Protected String invokeAction (Object action, ActionConfig actionConfig) throws Exception {
      60. String methodName = proxy. getMethod ();
      61. String timerKey = "invokeAction:" + proxy. getActionName ();
      62. Try {
      63. UtilTimerStack. push (timerKey );
      64. Boolean methodCalled = false;
      65. Object methodResult = null;
      66. Method method = null;
      67. Try {
      68. // Obtain the method to be executed using the java reflection mechanism
      69. Method = getAction (). getClass (). getMethod (methodName, new Class [0]);
      70. } Catch (NoSuchMethodException e ){
      71. // Hmm -- OK, try doXxx instead
      72. // If no corresponding method exists, use do + Xxxx to obtain the method again.
      73. Try {
      74. String altMethodName = "do" + methodName. substring (0, 1). toUpperCase () + methodName. substring (1 );
      75. Method = getAction (). getClass (). getMethod (altMethodName, new Class [0]);
      76. } Catch (NoSuchMethodException e1 ){
      77. // Well, give the unknown handler a shot
      78. If (unknownHandlerManager. hasUnknownHandlers ()){
      79. Try {
      80. MethodResult = unknownHandlerManager. handleUnknownMethod (action, methodName );
      81. MethodCalled = true;
      82. } Catch (NoSuchMethodException e2 ){
      83. // Throw the original one
      84. Throw e;
      85. }
      86. } Else {
      87. Throw e;
      88. }
      89. }
      90. }
      91. // Execute Method
      92. If (! MethodCalled ){
      93. MethodResult = method. invoke (action, new Object [0]);
      94. }
      95. // From this we can see that the Action method can return a String to match the Result, or directly return the Result class.
      96. If (methodResult instanceof Result ){
      97. This. explicitResult = (Result) methodResult;
      98. // Wire the result automatically
      99. Container. inject (explicitResult );
      100. Return null;
      101. } Else {
      102. Return (String) methodResult;
      103. }
      104. } Catch (NoSuchMethodException e ){
      105. Throw new IllegalArgumentException ("The" + methodName + "() is not defined in action" + getAction (). getClass () + "");
      106. } Catch (InvocationTargetException e ){
      107. // We try to return the source exception.
      108. Throwable t = e. getTargetException ();
      109. If (actionEventListener! = Null ){
      110. String result = actionEventListener. handleException (t, getStack ());
      111. If (result! = Null ){
      112. Return result;
      113. }
      114. }
      115. If (t instanceof Exception ){
      116. Throw (Exception) t;
      117. } Else {
      118. Throw e;
      119. }
      120. } Finally {
      121. UtilTimerStack. pop (timerKey );
      122. }
      123. }

        After the action is executed, view is returned Based on ResultConfig, that is, the executeResult method is called in the invoke method.

        Java code
        1. Private void executeResult () throws Exception {
        2. // Create Result Based on ResultConfig
        3. Result = createResult ();
        4. String timerKey = "executeResult:" + getResultCode ();
        5. Try {
        6. UtilTimerStack. push (timerKey );
        7. If (result! = Null ){
        8. // Start executing Result,
        9. // You can refer to the implementation of Result, for example, using more ServletDispatcherResult, ServletActionRedirectResult, ServletRedirectResult
        10. Result.exe cute (this );
        11. } Else if (resultCode! = Null &&! Action. NONE. equals (resultCode )){
        12. Throw new ConfigurationException ("No result defined for action" + getAction (). getClass (). getName ()
        13. + "And result" + getResultCode (), proxy. getConfig ());
        14. } Else {
        15. If (LOG. isDebugEnabled ()){
        16. LOG. debug ("No result returned for action" + getAction (). getClass (). getName () + "at" + proxy. getConfig (). getLocation ());
        17. }
        18. }
        19. } Finally {
        20. UtilTimerStack. pop (timerKey );
        21. }
        22. }
        23. Public Result createResult () throws Exception {
        24. // If the Result type returned directly in the Action, the invokeAction () is saved in the explicitResult
        25. If (explicitResult! = Null ){
        26. Result ret = explicitResult;
        27. ExplicitResult = null;
        28. Return ret;
        29. }
        30. // If the String is returned, the current Action's Results list is obtained from config.
        31. ActionConfig config = proxy. getConfig ();
        32. Map Results = config. getResults ();
        33. ResultConfig resultConfig = null;
        34. Synchronized (config ){
        35. Try {
        36. // Match resultConfig with the returned String
        37. ResultConfig = results. get (resultCode );
        38. } Catch (NullPointerException e ){
        39. // Swallow
        40. }
        41. If (resultConfig = null ){
        42. // If no result is found for the given resultCode, try to get a wildcard '*' match.
        43. // If ResultConfig of the corresponding name cannot be found, use the Result with name *
        44. // You can use * to assign all results.
        45. ResultConfig = results. get ("*");
        46. }
        47. }
        48. If (resultConfig! = Null ){
        49. Try {
        50. // Create Result
        51. Return objectFactory. buildResult (resultConfig, invocationContext. getContextMap ());
        52. } Catch (Exception e ){
        53. LOG. error ("There was an exception while instantiating the result of type" + resultConfig. getClassName (), e );
        54. Throw new XWorkException (e, resultConfig );
        55. }
        56. } Else if (resultCode! = Null &&! Action. NONE. equals (resultCode) & unknownHandlerManager. hasUnknownHandlers ()){
        57. Return unknownHandlerManager. handleUnknownResult (invocationContext, proxy. getActionName (), proxy. getConfig (), resultCode );
        58. }
        59. Return null;
        60. }
        61. Public Result buildResult (ResultConfig resultConfig, Map ExtraContext) throws Exception {
        62. String resultClassName = resultConfig. getClassName ();
        63. Result result = null;
        64. If (resultClassName! = Null ){
        65. // BuildBean will use the reflection mechanism Class. newInstance to create bean
        66. Result = (Result) buildBean (resultClassName, extraContext );
        67. Map Params = resultConfig. getParams ();
        68. If (params! = Null ){
        69. For (Map. Entry ParamEntry: params. entrySet ()){
        70. Try {
        71. // For reflectionProvider, see OgnlReflectionProvider;
        72. // ResultConfig. getParams () is the parameter configured in the result configuration file.
        73. // The setProperties method calls the setValue method of the Ognl class.
        74. // Set the param name value to the result of the root object.
        75. ReflectionProvider. setProperty (paramEntry. getKey (), paramEntry. getValue (), result, extraContext, true );
        76. } Catch (ReflectionException ex ){
        77. If (LOG. isErrorEnabled ())
        78. LOG. error ("Unable to set parameter [#0] in result of type [#1]", ex,
        79. ParamEntry. getKey (), resultConfig. getClassName ());
        80. If (result instanceof ReflectionExceptionHandler ){
        81. (ReflectionExceptionHandler) result). handle (ex );
        82. }
        83. }
        84. }
        85. }
        86. }
        87. Return result;
        88. }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.