[原创]java WEB学习笔记70:Struts2 学习之路-- struts2拦截器源码分析,运行流程

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用

内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。

本人互联网技术爱好者,互联网技术发烧友

微博:伊直都在0221

QQ:951226918

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1.运行流程

  

相关的几个 API

  

ActionMapping:Simple class that holds the action mapping information used to invoke a Struts action. The name and namespace are required

ActionMapper:When given an HttpServletRequest, the ActionMapper may return null if no action invocation request matches, or it may return an ActionMapping that describes an action invocation for the framework to try

ActionProxy:ActionProxy is an extra layer between XWork and the action so that different proxies are possible.

ActionInvocation:An ActionInvocation represents the execution state of an Action. It holds the Interceptors and the Action instance. By repeated re-entrant execution of the invoke() method, initially by the ActionProxy, then by the Interceptors, the Interceptors are all executed, and then the Action and the Result.

Struts2 运行流程分析:

  1. 请求发送给 StrutsPrepareAndExecuteFilter

  2. StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 Struts2 请求(即是否返回一个非空的 ActionMapping 对象)

  3. 若 ActionMapper 认为该请求是一个 Struts2 请求,则 StrutsPrepareAndExecuteFilter 把请求的处理交给 ActionProxy

  4. ActionProxy 通过 Configuration Manager 询问框架的配置文件,确定需要调用的 Action 类及 Action 方法

  5. ActionProxy 创建一个 ActionInvocation 的实例,并进行初始化

  6. ActionInvocation 实例在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。

  7. Action 执行完毕,ActionInvocation 负责根据 struts.xml 中的配置找到对应的返回结果。调用结果的 execute 方法,渲染结果。在渲染的过程中可以使用Struts2 框架中的标签。

  8. 执行各个拦截器 invocation.invoke() 之后的代码

  9. 把结果发送到客户端

实际代码:

    StrutsPrepareAndExecuteFilter

  

 1  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
 2
 3         HttpServletRequest request = (HttpServletRequest) req;
 4         HttpServletResponse response = (HttpServletResponse) res;
 5
 6         try {
 7             prepare.setEncodingAndLocale(request, response);
 8             prepare.createActionContext(request, response);
 9             prepare.assignDispatcherToThread();
10             if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
11                 chain.doFilter(request, response);
12             } else {
13                 request = prepare.wrapRequest(request);
14                 ActionMapping mapping = prepare.findActionMapping(request, response, true);
15                 if (mapping == null) {
16                     boolean handled = execute.executeStaticResourceRequest(request, response);
17                     if (!handled) {
18                         chain.doFilter(request, response);
19                     }
20                 } else {
21                     execute.executeAction(request, response, mapping);
22                 }
23             }
24         } finally {
25             prepare.cleanupRequest(request);
26         }
27     }

PrepareOperations

 1  public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response, boolean forceLookup) {
 2         ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
 3         if (mapping == null || forceLookup) {
 4             try {
 5                 mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager());
 6                 if (mapping != null) {
 7                     request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);
 8                 }
 9             } catch (Exception ex) {
10                 dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
11             }
12         }
13
14         return mapping;
15     }

DefaultActionMapper

 1   public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
 2         ActionMapping mapping = new ActionMapping();
 3         String uri = getUri(request);
 4
 5         int indexOfSemicolon = uri.indexOf(";");
 6         uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri;
 7
 8         uri = dropExtension(uri, mapping);
 9         if (uri == null) {
10             return null;
11         }
12
13         parseNameAndNamespace(uri, mapping, configManager);
14         handleSpecialParameters(request, mapping);
15         return parseActionName(mapping);
16     }
1 public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
2         dispatcher.serviceAction(request, response, servletContext, mapping);
3     }

Dispatcher

 1  public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
 2                               ActionMapping mapping) throws ServletException {
 3
 4         Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
 5
 6         // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
 7         ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
 8         boolean nullStack = stack == null;
 9         if (nullStack) {
10             ActionContext ctx = ActionContext.getContext();
11             if (ctx != null) {
12                 stack = ctx.getValueStack();
13             }
14         }
15         if (stack != null) {
16             extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
17         }
18
19         String timerKey = "Handling request from Dispatcher";
20         try {
21             UtilTimerStack.push(timerKey);
22             String namespace = mapping.getNamespace();
23             String name = mapping.getName();
24             String method = mapping.getMethod();
25
26             Configuration config = configurationManager.getConfiguration();
27             ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
28                     namespace, name, method, extraContext, true, false);
29
30             request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
31
32             // if the ActionMapping says to go straight to a result, do it!
33             if (mapping.getResult() != null) {
34                 Result result = mapping.getResult();
35                 result.execute(proxy.getInvocation());
36             } else {
37                 proxy.execute();
38             }
39
40             // If there was a previous value stack then set it back onto the request
41             if (!nullStack) {
42                 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
43             }
44         } catch (ConfigurationException e) {
45             // WW-2874 Only log error if in devMode
46             if (devMode) {
47                 String reqStr = request.getRequestURI();
48                 if (request.getQueryString() != null) {
49                     reqStr = reqStr + "?" + request.getQueryString();
50                 }
51                 LOG.error("Could not find action or result\n" + reqStr, e);
52             } else {
53                 if (LOG.isWarnEnabled()) {
54                     LOG.warn("Could not find action or result", e);
55                 }
56             }
57             sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
58         } catch (Exception e) {
59             if (handleException || devMode) {
60                 sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
61             } else {
62                 throw new ServletException(e);
63             }
64         } finally {
65             UtilTimerStack.pop(timerKey);
66         }
67     }

DefaultActionProxyFactory

 1 public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) {
 2
 3         ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
 4         container.inject(inv);
 5         return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
 6     }
 7
 8
 9 public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
10
11         DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
12         container.inject(proxy);
13         proxy.prepare();
14         return proxy;
15     }

DefaultActionProxy

 1  public String execute() throws Exception {
 2         ActionContext nestedContext = ActionContext.getContext();
 3         ActionContext.setContext(invocation.getInvocationContext());
 4
 5         String retCode = null;
 6
 7         String profileKey = "execute: ";
 8         try {
 9             UtilTimerStack.push(profileKey);
10
11             retCode = invocation.invoke();
12         } finally {
13             if (cleanupContext) {
14                 ActionContext.setContext(nestedContext);
15             }
16             UtilTimerStack.pop(profileKey);
17         }
18
19         return retCode;
20     }

DefaultActionInvocation

 1 public String invoke() throws Exception {
 2         String profileKey = "invoke: ";
 3         try {
 4             UtilTimerStack.push(profileKey);
 5
 6             if (executed) {
 7                 throw new IllegalStateException("Action has already executed");
 8             }
 9
10             if (interceptors.hasNext()) {
11                 final InterceptorMapping interceptor = interceptors.next();
12                 String interceptorMsg = "interceptor: " + interceptor.getName();
13                 UtilTimerStack.push(interceptorMsg);
14                 try {
15                                 resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
16                             }
17                 finally {
18                     UtilTimerStack.pop(interceptorMsg);
19                 }
20             } else {
21                 resultCode = invokeActionOnly();
22             }
23
24             // this is needed because the result will be executed, then control will return to the Interceptor, which will
25             // return above and flow through again
26             if (!executed) {
27                 if (preResultListeners != null) {
28                     for (Object preResultListener : preResultListeners) {
29                         PreResultListener listener = (PreResultListener) preResultListener;
30
31                         String _profileKey = "preResultListener: ";
32                         try {
33                             UtilTimerStack.push(_profileKey);
34                             listener.beforeResult(this, resultCode);
35                         }
36                         finally {
37                             UtilTimerStack.pop(_profileKey);
38                         }
39                     }
40                 }
41
42                 // now execute the result, if we‘re supposed to
43                 if (proxy.getExecuteResult()) {
44                     executeResult();
45                 }
46
47                 executed = true;
48             }
49
50             return resultCode;
51         }
52         finally {
53             UtilTimerStack.pop(profileKey);
54         }
55     }

  

  

时间: 2024-10-18 10:38:55

[原创]java WEB学习笔记70:Struts2 学习之路-- struts2拦截器源码分析,运行流程的相关文章

(转)Bootstrap 之 Metronic 模板的学习之路 - (4)源码分析之脚本部分

https://segmentfault.com/a/1190000006709967 上篇我们将 body 标签主体部分进行了简单总览,下面看看最后的脚本部门. 页面结尾部分(Javascripts 脚本文件) 我们来看看代码最后的代码,摘取如下: <!--[if lt IE 9]> <script src="../assets/global/plugins/respond.min.js"></script> <script src=&quo

关于阅读Struts2部分拦截器源码的记录

Struts2中的拦截器在ActionInvocation对象的invoke()方法中执行. ActionInvocation对象从配置文件中读取Interceptor对象,加入到自己的存取拦截器的容器中. 在invoke()方法中,当容器中还有Interceptor对象时,就执行对应Interceptor的intercept方法;在intercept方法中,除了加入拦截器自己的部分语句,还会调用同一个ActionInvocation对象的invoke方法,然后invoke方法再执行下一个Int

String源码分析之Java中的String为什么是不可变的以及replace方法源码分析

什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变. 区分对象和对象的引用 对于Java初学者, 对于String是不可变对象总是存有疑惑.看下面代码: String s = "ABCabc";

Struts2 源码分析-----拦截器源码解析 --- ParametersInterceptor

ParametersInterceptor拦截器其主要功能是把ActionContext中的请求参数设置到ValueStack中,如果栈顶是当前Action则把请求参数设置到了Action中,如果栈顶是一个model(Action实现了ModelDriven接口)则把参数设置到了model中. 下面是该拦截器的doIntercept方法源码: @Override public String doIntercept(ActionInvocation invocation) throws Excep

Android 学习笔记之 个人认为最简单的查看Android源码方案

相信很多人都会疑惑如何使用Eclipse ADT查看源码? 下面我们将介绍 如何查看Android源码. 本文有如下优点: 1.不用费心去找Android源码地址:一个字烦,网上的东西杂七杂八的... 2.不用担心过程难,这个就三步.. 工具:ADT 第一步:找到你ADT根目录,打开SDK Manager.exe 第二步:勾选你想查看的source for android sdk,下载. 第三步:打开任意一个Android程序使用Ctrl+想要查看的代码,然后跳转到查看源码文件,点击Change

Rplidar学习(四)—— ROS下进行rplidar雷达数据采集源码分析

一.子函数分析 1.发布数据子函数 (1)雷达数据数据类型 Header header # timestamp in the header is the acquisition time of # the first ray in the scan. # # in frame frame_id, angles are measured around # the positive Z axis (counterclockwise, if Z is up) # with zero angle bei

(转)Bootstrap 之 Metronic 模板的学习之路 - (3)源码分析之 body 部分

https://segmentfault.com/a/1190000006697252 body 的组成结构 body 部分包含了 HEADER.CONTAINER.FOOTER,其中 CONTAINER 部分又包含了 SIDEBAR.CONTENT.QUICK SIDEBAR 几个部分.body部分源码折叠后截图如下: Header 页面顶部 Header contains of logo and top menu bar and it used in all pages. 页面顶部(或头部)

java的UDP和TCP详解和北京-赛车平台出租源码分析

1.需求分析北京-赛车平台出租Q1446595067 最近在和硬件做网口的传输协议,一开始告诉我说用TCP的socket进行传输,我说没问题,就写了个socket的发送和接收方法.but过了没一段时间,又告诉我用udp吧,udp传的比较快,就也写了一个udp的.无论是socket还是udp,感觉网上有很多都是写一个监听端口,监听往这个端口发送的数据,然后再写一个发送方法. 2.问题难点本来硬件要是往java端指定端口发,就完全没问题了,但是它是把我发送的数据按照我发的端口号原路返回,就想http

[原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------