对于Struts2源代码的分析已经有些时日了,虽然网上有很多解读代码,不过自己还是写一个放上来,供大家参考一下。

解读过程:

直接在action类中打断点(包括构造函数和待执行方法)进行debug调试,查看调用栈即可找到整个执行过程,下面用一张图来表述。

说明一下:

1.下面样例对应Action类为UserAction,在步骤9创建,待调用的方法为addUser

2.因为默认拦截器比较多,下面样例只列了两个拦截器,ExceptionMappingInterceptor和DebuggingInterceptor,限于篇幅,其他的拦截器没有列出;

3.在StrutsSpringObjectFactory到生成UserAction对象之间还有一些类的调用,同样限于篇幅,就省略了。

下面的代码就是StrutsPrepareAndExecuteFilter的doFilter方法,有请求达到时,因为在web.xml配置了StrutsPrepareAndExecuteFilter作为过滤器,所以就会执行到doFilter方法中来,下面的调用过程大致如下:

1.将输入参数转为HttpServletRequest和HttpServletResponse对象

2.如果不符合过滤要求,则直接转由下一个过滤器进行处理

3.设置字符编码和本地化信息

4.创建Action执行上下文对象

5.对request对象进行封装处理

6.通过配置信息查找请求对应的actionMapping对象

7.执行action对象对应的方法,也就是上面流程图所展示的过程

  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. if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
  8. chain.doFilter(request, response);
  9. } else {
  10. prepare.setEncodingAndLocale(request, response);
  11. prepare.createActionContext(request, response);
  12. prepare.assignDispatcherToThread();
  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. }

在调测过程中,特别留意了ParameterInterceptor这个拦截器,没有这个拦截器,页面的参数就无法设置到Action类中去。

看到网上有人说到自定义拦截器的时候,必须要关联defaultStack(<interceptor-ref name="defaultStack"/>),其实这没有清楚,为什么必须这样。

defaulStack中包含很多个拦截器,其实不是所有action都需要这么多拦截器的,说实话我没有尝试过到底哪种类型的操作需要哪些拦截器,如果只是需要完成页面的值设置到action中,则只需要自定义拦截器时关联ParameterInterceptor即可,即:

<interceptor-ref name="params">

                    <param name="excludeParams">^action:.*,^method:.*</param>

</interceptor-ref>

ParameterInterceptor设置值到Action中的具体代码如下:

外部代码调用intercept方法,然后调用到doIntercept方法,将值设置到Action中则是通过下面代码中的setParameters(action, stack, parameters);这一行完成的。

  1. public String intercept(ActionInvocation invocation) throws Exception {
  2. if (applyInterceptor(invocation)) {
  3. return doIntercept(invocation);
  4. }
  5. return invocation.invoke();
  6. }
  1. public String doIntercept(ActionInvocation invocation) throws Exception {
  2. Object action = invocation.getAction();
  3. if (!(action instanceof NoParameters)) {
  4. ActionContext ac = invocation.getInvocationContext();
  5. final Map<String, Object> parameters = retrieveParameters(ac);
  6.  
  7. if (LOG.isDebugEnabled()) {
  8. LOG.debug("Setting params " + getParameterLogMap(parameters));
  9. }
  10.  
  11. if (parameters != null) {
  12. Map<String, Object> contextMap = ac.getContextMap();
  13. try {
  14. ReflectionContextState.setCreatingNullObjects(contextMap, true);
  15. ReflectionContextState.setDenyMethodExecution(contextMap, true);
  16. ReflectionContextState.setReportingConversionErrors(contextMap, true);
  17.  
  18. ValueStack stack = ac.getValueStack();
  19. setParameters(action, stack, parameters);
  20. } finally {
  21. ReflectionContextState.setCreatingNullObjects(contextMap, false);
  22. ReflectionContextState.setDenyMethodExecution(contextMap, false);
  23. ReflectionContextState.setReportingConversionErrors(contextMap, false);
  24. }
  25. }
  26. }
  27. return invocation.invoke();
  28. }




Struts2源代码解读之Action调用的更多相关文章

  1. struts2源代码学习之初始化(一)

    看struts2源代码已有一段时日,从今天開始,就做一个总结吧. 首先,先看看怎么调试struts2源代码吧,主要是下面步骤: 使用Myeclipse创建一个webproject 导入struts2须 ...

  2. struts2源代码分析(个人觉得非常经典)

    读者如果曾经学习过Struts1.x或者有过Struts1.x的开发经验,那么千万不要想当然地以为这一章可以跳过.实际上Struts1.x与Struts2并无我们想象的血缘关系.虽然Struts2的开 ...

  3. Struts2基于注解的Action配置

    使用注解来配置Action的最大好处就是可以实现零配置,但是事务都是有利有弊的,使用方便,维护起来就没那么方便了. 要使用注解方式,我们必须添加一个额外包:struts2-convention-plu ...

  4. Struts2(四):在Action中如何访问Web资源

    1.什么WEB资源? HttpServletRequest,HttpServletRespone,HttpApplication,ServletContext,HttpSession等原生Servle ...

  5. linux内核奇遇记之md源代码解读之四

    linux内核奇遇记之md源代码解读之四 转载请注明出处:http://blog.csdn.net/liumangxiong 运行阵列意味着阵列经历从无到有,建立了作为一个raid应有的属性(如同步重 ...

  6. Apache OFbiz entity engine源代码解读

    简单介绍 近期一直在看Apache OFbiz entity engine的源代码.为了能够更透彻得理解,也由于之前没有看人别人写过分析它的文章,所以决定自己来写一篇. 首先,我提出一个问题,假设你有 ...

  7. Struts2利用注解实现action跳转

    使用注解来配置Action的最大好处就是可以实现零配置,但是事务都是有利有弊的,使用方便,维护起来就没那么方便了. 要使用注解方式,我们必须添加一个额外包:struts2-convention-plu ...

  8. Struts2基础学习(二)—Action

    一.ActionSupport      为了让用户开发的Action类更加规范,Struts2提供了一个Action接口,这个接口定义了Struts2的Action处理类应该实现的规范.下面是标准A ...

  9. Struts2之配置文件中Action的详细配置

    在Struts2之配置一文中,我们知道一个struts配置文件可以分为三部分:常量配置    包含其他配置文件的配置    Action配置  . 这其中 常量配置  和 包含其他配置文件的配置  二 ...

随机推荐

  1. cf442C Artem and Array

    C. Artem and Array time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. 基本NT式驱动代码结构

    #include <ntddk.h> void DriverUnload(IN PDRIVER_OBJECT DriverObject);NTSTATUS MyCreateClose(IN ...

  3. mysql 存储过程 计算报表

    把用例执行情况mysql表汇总起来 proc_write_report 汇总执行用例表中的测试数据 写入report 表,report表包括字段 report_id(自增)execution_flag ...

  4. EBS-PAC成本更新事务处理

     PAC成本更新事务处理 DECLARE   l_itfs_rec mtl_transactions_interface% ROWTYPE; BEGIN   --插入接口表   SELECT mt ...

  5. PCM文件格式简单介绍

    PCM文件格式简单介绍 PCM文件:模拟音频信号经模数转换(A/D变换)直接形成的二进制序列,该文件没有附加的文件头和文件结束标志.Windows的Convert工具能够把PCM音频格式的文件转换成M ...

  6. 破解Veeam过程

    1)运行Veeam_Backup_Setup.exe,但是不要继续下一步: 2)进入到%temp%\IXP000.TMP目录,例如windows xp sp3环境默认为C:\Documents and ...

  7. let关键字

    作用: 与var类似, 用于声明一个变量特点: 只在块作用域内有效 不能重复声明 不会预处理, 不存在提升应用: 循环遍历加监听 //应用实例 <body> <button>测 ...

  8. Oracle - SQL 错误: ORA-00917: 缺失逗号

    ORACLE SQL语句中int型插入数据库时,不要加引号.

  9. weblogic开机启动-超简单

    1.编写weblogic启动脚本,命名为start_weblogic_server.sh,内容如下:  #!/bin/bashnohup /home/weblogic/Oracle/Middlewar ...

  10. 关于C函数的参数个数的问题

    本文引自:http://c.biancheng.net/cpp/html/1592.html 一个函数的参数的数目没有明确的限制,但是参数过多(例如超过8个)显然是一种不可取的编程风格.参数的数目直接 ...