Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Execution action of the DefaultActionInvocation class

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)06/01 Report--

A brief introduction to this chapter

The previous chapter talked about the mechanism of interceptors, which gives us some understanding of interceptors. We also know that before executing the user's action class instance, struts2 will execute the interceptor corresponding to the current action class. As for where to execute the action class instance, the author did not talk about it in detail at all. It's more like a few strokes. Although some of the functions of the Action class have been discussed in the chapter "Struts2 source code analysis-the work of the Action proxy class". It was mentioned that the DefaultActionInvocation class would execute the action class instance. But there is still no specific code to point out the key points. This chapter is about where the code that executes the instance of the action class falls. This is the invokeAction method of the DefaultActionInvocation class.

Execution action of the DefaultActionInvocation class

The invokeActionOnly method in the invoke method of the DefaultActionInvocation class was mentioned in the previous chapter. That's right! When the first half of all interceptors is finished, the invokeActionOnly method is executed. This method is the entry that executes the instance of the action class. The invokeActionOnly method actually calls the invokeAction method of its own class. Just take a look at the code.

DefaultActionInvocation class:

1 public String invokeActionOnly () throws Exception {2 return invokeAction (getAction (), proxy.getConfig ()); 3}

The getAction method in the code is to get an instance of the action class. It is related to the createAction method mentioned in the chapter "Struts2 source code analysis-the work of the Action proxy class". By the time the program executes here, the createAction method has created a new instance of the action class. I don't know. Readers, please take a look at this chapter. Let's take a look at the source of the invokeAction method.

1 protected String invokeAction (Object action, ActionConfig actionConfig) throws Exception {2 String methodName = proxy.getMethod (); / / get the name of the method to execute. 3 4 LOG.debug ("Executing action method = {}", methodName); 56 String timerKey = "invokeAction:" + proxy.getActionName (); 7 try {8 UtilTimerStack.push (timerKey); 9 10 Object methodResult;11 try {12 methodResult = ognlUtil.callMethod (methodName + "()", getStack (). GetContext (), action) / / execute action class instance 13} catch (MethodFailedException e) {14 / / if reason is missing method, try checking UnknownHandlers15 if (e.getReason () instanceof NoSuchMethodException) {16 if (unknownHandlerManager.hasUnknownHandlers ()) {17 try {18 methodResult = unknownHandlerManager.handleUnknownMethod (action, methodName) 19} catch (NoSuchMethodException ignore) {20 / / throw the original one21 throw escape 22} 23} else {24 / / throw the original one25 throw e 26} 27 / / throw the original exception as UnknownHandlers weren't able to handle invocation as well28 if (methodResult = = null) {29 throw e 30} 31} else {32 / / exception isn't related to missing action method, throw it33 throw escape 34} 35} 36 return saveResult (actionConfig, methodResult) 37} catch (NoSuchPropertyException e) {38 throw new IllegalArgumentException ("The" + methodName + "() is not defined in action" + getAction (). GetClass () + ""); 39} catch (MethodFailedException e) {40 / / We try to return the source exception.41 Throwable t = e.getCause () 42 43 if (actionEventListener! = null) {44 String result = actionEventListener.handleException (t, getStack ()); 45 if (result! = null) {46 return result;47} 48} 49 if (t instanceof Exception) {50 throw (Exception) t 51} else {52 throw eTAC 53} 54} finally {55 UtilTimerStack.pop (timerKey); 56} 57}

What this method does is very simple. Is to get the name of the method to be executed by the current instance of the action class. The method corresponding to the instance of the action class is executed according to the OgnlUtil utility class. Obviously, if you want to know a little more, you have to go deep into the source code of the OgnlUtil utility class. Let's have a look.

OgnlUtil class:

1 public Object callMethod (final String name, final Map context, final Object root) throws OgnlException {2 return compileAndExecuteMethod (name, context, new OgnlTask () {3 public Object execute (Object tree) throws OgnlException {4 return Ognl.getValue (tree, context, root); 5} 6}); 7}

OgnlUtil class:

Private Object compileAndExecuteMethod (String expression, Map context, OgnlTask task) throws OgnlException {Object tree; if (enableExpressionCache) {tree = expressions.get (expression); if (tree = = null) {tree = Ognl.parse_Expression (expression); checkSimpleMethod (tree, context);} else {tree = Ognl.parse_Expression (expression) CheckSimpleMethod (tree, context);} final T exec = task.execute (tree); / / if cache is enabled and it's a valid expression, puts it in if (enableExpressionCache) {expressions.putIfAbsent (expression, tree);} return exec;}

When I saw this, I was a little upset. It is mainly known at a glance that we are going to learn some grammar related to ONGL. Readers are asked to add this point themselves. The code Ognl.getValue (tree, context, root) is the embodiment of ONGL syntax. Where tree is the expression of ONGL. Root is the root object. That is, the user action class instance. For context, I really don't know what to explain him. The author understands him as the context of ONGL. It is usually related to the "#" sign in ONGL expressions. To put it simply, Ognl.getValue (tree, context, root) is to execute the action method. And then in-depth is the source code of ognl.jar. Has jumped out of the scope of the struts2 source code.

After executing the above code, you begin to save the corresponding results. The saveResult method is used to process the results. If the result value is of type Result, store it on the member variable explicitResult and return NULL. Otherwise, it is converted to the String type and returned. The code is as follows

1 protected String saveResult (ActionConfig actionConfig, Object methodResult) {2 if (methodResult instanceof Result) {3 this.explicitResult = (Result) methodResult; 4 5 / / Wire the result automatically 6 container.inject (explicitResult); 7 return null; 8} else {9 return (String) methodResult;10} 11}

If I hadn't looked at the source code, I wouldn't have known that the original action class instance was more than just a String type after execution. There is also a class called Result. If there is a hard word, the author of the new channel TOEFL just returns a Result class. Let's look at the following code. I know why the author feels this way.

1 / / now execute the result, if we're supposed to2 if (proxy.getExecuteResult ()) {3 executeResult (); 4}

The above code is in the second half of the invoke method of the DefaultActionInvocation class. If the result returned is a string, you will finally get an instance of the corresponding Result class based on the string. The Result class has many instance classes. Such as ServletDispatcherResult class. When an instance of the Result class is found, it executes its own execute method. We can reflect this in the source code of the executeResult method. Take a look.

DefaultActionInvocation class:

1 private void executeResult () throws Exception {2 result = createResult (); 3 4 String timerKey = "executeResult:" + getResultCode (); 5 try {6 UtilTimerStack.push (timerKey); 7 if (result! = null) {8 result.execute (this) 9} else if (resultCode! = null & &! Action.NONE.equals (resultCode)) {10 throw new ConfigurationException ("No result defined for action" + getAction () .getClass () .getName () 11 + "and result" + getResultCode (), proxy.getConfig ()) 12} else {13 if (LOG.isDebugEnabled ()) {14 LOG.debug ("No result returned for action {} at {}", getAction (). GetClass (). GetName (), proxy.getConfig (). GetLocation ()); 15} 16} 17} finally {18 UtilTimerStack.pop (timerKey); 19} 20}

DefaultActionInvocation class:

1 public Result createResult () throws Exception {2 LOG.trace ("Creating result related to resultCode [{}]", resultCode); 3 4 if (explicitResult! = null) {5 Result ret = explicitResult; 6 explicitResult = null; 7 8 return ret; 9} 10 ActionConfig config = proxy.getConfig (); 11 Map results = config.getResults (); 12 13 ResultConfig resultConfig = null 14 15 try {16 resultConfig = results.get (resultCode); 17} catch (NullPointerException e) {18 LOG.debug ("Got NPE trying to read result configuration for resultCode [{}]", resultCode) 19} 20 21 if (resultConfig = = null) {22 / / If no result is found for the given resultCode, try to get a wildcard'* 'match.23 resultConfig = results.get ("*"); 24} 25 26 if (resultConfig! = null) {27 try {28 return objectFactory.buildResult (resultConfig, invocationContext.getContextMap ()) 29} catch (Exception e) {30 LOG.error ("There was an exception while instantiating the result of type {}", resultConfig.getClassName (), e); 31 throw new XWorkException (e, resultConfig) 32} 33} else if (resultCode! = null & &! Action.NONE.equals (resultCode) & & unknownHandlerManager.hasUnknownHandlers ()) {34 return unknownHandlerManager.handleUnknownResult (invocationContext, proxy.getActionName (), proxy.getConfig (), resultCode); 35} 36 return null;37}

The previous code: describes the executeResult method. The executeResult method is only used to execute an instance of the Result class. That is, the execute method of the Result class is executed.

The latter piece of code: describe the createResult method used in the executeResult method. That is, as mentioned earlier, the author will get an instance of the corresponding Result class based on the returned result string. We can see that if it returns a Result class, it returns directly. If not, the corresponding result element node information is obtained from the configuration information. An instance of the corresponding Result class is generated from the result element node information. Obviously we can see that the ObjectFactory class is working again. In the previous section, the action class instance is also done by him.

At this point, I believe some readers will have a question like the author? What exactly is the Result class? In fact, it is used to process the result of execution on an instance of the action class. To put it simply, it can be understood as dealing with web pages. It turns out, too. The next step is to return the result and display it to the user. We also see a lot of work done by the DefaultActionInvocation class implementation in this process. Including calls to the interceptor. Returns the processing of the Result class. It can't be said that the DefaultActionInvocation class is really important.

The summary of this chapter

This chapter is mainly about the implementation of action by the DefaultActionInvocation class. Let us know how to execute action. The syntax related to ONGL is used. You also know that after the action class instance executes. There will also be corresponding results. Of course, these uses are handed over to the instance of the Result class.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report