第一個(gè)環(huán)節(jié)是FilterDispatcher,過濾、包裝請(qǐng)求,調(diào)用dispatcher的serviceAction方法。主要代碼如下:
可以看到這里面調(diào)用actionMapper找到了當(dāng)前請(qǐng)求對(duì)應(yīng)的actionMapping。然后就是dispatcher.serviceAction這個(gè)方法了。可以想象肯定是找到對(duì)應(yīng)的Action類,執(zhí)行相應(yīng)的action方法。Dispatcher類的serviceAction方法主要代碼如下:
可以看到,其中從configurationManager中找到config,在利用config,通過ActionProxyFactory創(chuàng)建了合適的ActionProxy對(duì)象。后面就是判斷如果當(dāng)前的mapping存在result,那么直接返回result的執(zhí)行結(jié)果,否則執(zhí)行proxy.execute。前者的含義我猜是處理某些不需要Action的請(qǐng)求的時(shí)候用到的。具體要調(diào)用最后的Action中的什么方法也是在這個(gè)時(shí)候確定的(proxy.setMethod(....))。
上面的代碼中,實(shí)際上是使用StrutsActionProxyFactory類的createActionProxy方法來創(chuàng)建ActionProxy的。這個(gè)方法如下:
可以看到創(chuàng)建proxy之后,調(diào)用了proxy的prepare方法,于是看DefaultActionProxy類的prepare方法中有這樣的代碼:
實(shí)際上是創(chuàng)建了這個(gè)proxy中的invocation對(duì)象,這個(gè)對(duì)象很重要,后面是順著這個(gè)對(duì)象的invoke方法去執(zhí)行我們寫的Action中的具體方法的。
回頭再去看上面第二段代碼中,創(chuàng)建proxy之后,調(diào)用了proxy的execute方法,這個(gè)里面寫得很簡單:
就是執(zhí)行了invocation的invoke方法。而這個(gè)invocation是哪里來的,我們也已經(jīng)很清楚了。這個(gè)invocation類實(shí)際上是DefaultActionInvocation類的一個(gè)實(shí)例。其invoke方法如下:
可以看到,其中對(duì)于有沒有interceptor的情況作了分別處理。有interceptor的情況則調(diào)用第一個(gè)interceptor的intercept方法,intercepter的執(zhí)行應(yīng)該是一個(gè)鏈?zhǔn)降模赃@里只是調(diào)用第一個(gè)(這個(gè)事情不確定,沒看interceptor里面的內(nèi)容)。不論如何,最后都會(huì)調(diào)用到invocation的invokeAction方法,這里面基本上就是個(gè)反射,調(diào)用我們寫的action類的相應(yīng)方法了。值得注意的是上面的代碼中,最后判斷了proxy是否需要使用result,如果需要,那么調(diào)用executeResult方法,其中主要內(nèi)容就是調(diào)用相應(yīng)result對(duì)象的execute方法,這里是真?zhèn)€流程的最后一步。
其中:命令模式、代理模式
1
UtilTimerStack.push(timerKey);
2
request = prepareDispatcherAndWrapRequest(request, response);
3
ActionMapping mapping;
4
try {
5
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
6
} catch (Exception ex) {
7
LOG.error("error getting ActionMapping", ex);
8
dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
9
return;
10
}
11
12
if (mapping == null) {
13
// there is no action in this request, should we look for a static resource?
14
String resourcePath = RequestUtils.getServletPath(request);
15
16
if ("".equals(resourcePath) && null != request.getPathInfo()) {
17
resourcePath = request.getPathInfo();
18
}
19
20
if (serveStatic && resourcePath.startsWith("/struts")) {
21
String name = resourcePath.substring("/struts".length());
22
findStaticResource(name, request, response);
23
} else {
24
// this is a normal request, let it pass through
25
chain.doFilter(request, response);
26
}
27
// The framework did its job here
28
return;
29
}
30
31
dispatcher.serviceAction(request, response, servletContext, mapping);

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

可以看到這里面調(diào)用actionMapper找到了當(dāng)前請(qǐng)求對(duì)應(yīng)的actionMapping。然后就是dispatcher.serviceAction這個(gè)方法了。可以想象肯定是找到對(duì)應(yīng)的Action類,執(zhí)行相應(yīng)的action方法。Dispatcher類的serviceAction方法主要代碼如下:
1
UtilTimerStack.push(timerKey);
2
String namespace = mapping.getNamespace();
3
String name = mapping.getName();
4
String method = mapping.getMethod();
5
6
Configuration config = configurationManager.getConfiguration();
7
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
8
namespace, name, extraContext, true, false);
9
proxy.setMethod(method);
10
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
11
12
// if the ActionMapping says to go straight to a result, do it!
13
if (mapping.getResult() != null) {
14
Result result = mapping.getResult();
15
result.execute(proxy.getInvocation());
16
} else {
17
proxy.execute();
18
}
19
20
// If there was a previous value stack then set it back onto the request
21
if (stack != null) {
22
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
23
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

可以看到,其中從configurationManager中找到config,在利用config,通過ActionProxyFactory創(chuàng)建了合適的ActionProxy對(duì)象。后面就是判斷如果當(dāng)前的mapping存在result,那么直接返回result的執(zhí)行結(jié)果,否則執(zhí)行proxy.execute。前者的含義我猜是處理某些不需要Action的請(qǐng)求的時(shí)候用到的。具體要調(diào)用最后的Action中的什么方法也是在這個(gè)時(shí)候確定的(proxy.setMethod(....))。
上面的代碼中,實(shí)際上是使用StrutsActionProxyFactory類的createActionProxy方法來創(chuàng)建ActionProxy的。這個(gè)方法如下:
1
ActionProxy proxy = new StrutsActionProxy(namespace, actionName, extraContext, executeResult, cleanupContext);
2
container.inject(proxy);
3
proxy.prepare();
4
return proxy;

2

3

4

可以看到創(chuàng)建proxy之后,調(diào)用了proxy的prepare方法,于是看DefaultActionProxy類的prepare方法中有這樣的代碼:
1
invocation = new DefaultActionInvocation(objectFactory, unknownHandler, this, extraContext, true, actionEventListener);

實(shí)際上是創(chuàng)建了這個(gè)proxy中的invocation對(duì)象,這個(gè)對(duì)象很重要,后面是順著這個(gè)對(duì)象的invoke方法去執(zhí)行我們寫的Action中的具體方法的。
回頭再去看上面第二段代碼中,創(chuàng)建proxy之后,調(diào)用了proxy的execute方法,這個(gè)里面寫得很簡單:
1
public String execute() throws Exception {
2
ActionContext previous = ActionContext.getContext();
3
ActionContext.setContext(invocation.getInvocationContext());
4
try {
5
return invocation.invoke();
6
} finally {
7
if (cleanupContext)
8
ActionContext.setContext(previous);
9
}
10
}

2

3

4

5

6

7

8

9

10

就是執(zhí)行了invocation的invoke方法。而這個(gè)invocation是哪里來的,我們也已經(jīng)很清楚了。這個(gè)invocation類實(shí)際上是DefaultActionInvocation類的一個(gè)實(shí)例。其invoke方法如下:
1
if (executed) {
2
throw new IllegalStateException("Action has already executed");
3
}
4
5
if (interceptors.hasNext()) {
6
final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
7
UtilTimerStack.profile("interceptor: "+interceptor.getName(),
8
new UtilTimerStack.ProfilingBlock<String>() {
9
public String doProfiling() throws Exception {
10
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
11
return null;
12
}
13
});
14
} else {
15
resultCode = invokeActionOnly();
16
}
17
18
// this is needed because the result will be executed, then control will return to the Interceptor, which will
19
// return above and flow through again
20
if (!executed) {
21
if (preResultListeners != null) {
22
for (Iterator iterator = preResultListeners.iterator();
23
iterator.hasNext();) {
24
PreResultListener listener = (PreResultListener) iterator.next();
25
26
String _profileKey="preResultListener: ";
27
try {
28
UtilTimerStack.push(_profileKey);
29
listener.beforeResult(this, resultCode);
30
}
31
finally {
32
UtilTimerStack.pop(_profileKey);
33
}
34
}
35
}
36
37
// now execute the result, if we're supposed to
38
if (proxy.getExecuteResult()) {
39
executeResult();
40
}
41
42
executed = true;
43
}
44
45
return resultCode;

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

可以看到,其中對(duì)于有沒有interceptor的情況作了分別處理。有interceptor的情況則調(diào)用第一個(gè)interceptor的intercept方法,intercepter的執(zhí)行應(yīng)該是一個(gè)鏈?zhǔn)降模赃@里只是調(diào)用第一個(gè)(這個(gè)事情不確定,沒看interceptor里面的內(nèi)容)。不論如何,最后都會(huì)調(diào)用到invocation的invokeAction方法,這里面基本上就是個(gè)反射,調(diào)用我們寫的action類的相應(yīng)方法了。值得注意的是上面的代碼中,最后判斷了proxy是否需要使用result,如果需要,那么調(diào)用executeResult方法,其中主要內(nèi)容就是調(diào)用相應(yīng)result對(duì)象的execute方法,這里是真?zhèn)€流程的最后一步。
其中:命令模式、代理模式