这篇文章对应的并非Struts2的最新版本,但其原理还是相同的。

这是Struts2官方站点提供的Struts 2 的整体结构。

  一个请求在Struts2框架中的处理大概分为以下几个步骤:
客户端提起一个(HttpServletRequest)请求,如上文在浏览器中输入”http://localhost:8080/TestMvc/add.action”就是提起一个(HttpServletRequest)请求。
请求被提交到一系列(主要是三层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher)。注意这里是有顺序的,先ActionContextCleanUp,再其他过滤器(SiteMesh等)、最后到FilterDispatcher。
FilterDispatcher是控制器的核心,就是mvc中c控制层的核心。下面粗略的分析下我理解的FilterDispatcher工作流程和原理:FilterDispatcher进行初始化并启用核心doFilter

其代码如下:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException ...{
       HttpServletRequest request = (HttpServletRequest) req;
       HttpServletResponse response = (HttpServletResponse) res;
       ServletContext servletContext = filterConfig.getServletContext();
       // 在这里处理了HttpServletRequest和HttpServletResponse。
       DispatcherUtils du = DispatcherUtils.getInstance();
       du.prepare(request, response);//正如这个方法名字一样进行locale、encoding以及特殊request parameters设置
       try ...{
           request = du.wrapRequest(request, servletContext);//对request进行包装
       } catch (IOException e) ...{
           String message = "Could not wrap servlet request with MultipartRequestWrapper!";
           LOG.error(message, e);
           throw new ServletException(message, e);
       }
               ActionMapperIF mapper = ActionMapperFactory.getMapper();//得到action的mapper
       ActionMapping mapping = mapper.getMapping(request);// 得到action 的 mapping
       if (mapping == null) ...{
           // there is no action in this request, should we look for a static resource?
           String resourcePath = RequestUtils.getServletPath(request);
           if ("".equals(resourcePath) && null != request.getPathInfo()) ...{
               resourcePath = request.getPathInfo();
           }
           if ("true".equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))
                   && resourcePath.startsWith("/webwork")) ...{
               String name = resourcePath.substring("/webwork".length());
               findStaticResource(name, response);
           } else ...{
               // this is a normal request, let it pass through
               chain.doFilter(request, response);
           }
           // WW did its job here
           return;
       }
       Object o = null;
       try ...{
           //setupContainer(request);
           o = beforeActionInvocation(request, servletContext);
          //整个框架最最核心的方法,下面分析
           du.serviceAction(request, response, servletContext, mapping);
       } finally ...{
           afterActionInvocation(request, servletContext, o);
           ActionContext.setContext(null);
       }
   }
du.serviceAction(request, response, servletContext, mapping);
//这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy

public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) ...{
       HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig());  //实例化Map请求 ,询问ActionMapper是否需要调用某个Action来处理这个(request)请求
       extraContext.put(SERVLET_DISPATCHER, this);  
       OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
       if (stack != null) ...{  
           extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack));
       }  
       try ...{  
           ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
//这里actionName是通过两道getActionName解析出来的, FilterDispatcher把请求的处理交给ActionProxy,下面是ServletDispatcher的 TODO:
           request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
           proxy.execute();  
          //通过代理模式执行ActionProxy
           if (stack != null)...{  
               request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);
           }  
       } catch (ConfigurationException e) ...{  
           log.error("Could not find action", e);  
           sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);  
       } catch (Exception e) ...{  
           log.error("Could not execute action", e);  
           sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
       }  
}

FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类.
如上文的struts.xml配置

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <include file="struts-default.xml"/>
    <package name="struts2" extends="struts-default">
        <action name="add"  
            class="edisundong.AddAction" >
            <result>add.jsp</result>
        </action>    
    </package>
</struts>

如果提交请求的是add.action,那么找到的Action类就是edisundong.AddAction。
ActionProxy创建一个ActionInvocation的实例,同时ActionInvocation通过代理模式调用Action。但在调用之前ActionInvocation会根据配置加载Action相关的所有Interceptor。(Interceptor是struts2另一个核心级的概念)

下面我们来看看ActionInvocation是如何工作的:

ActionInvocation 是Xworks 中Action 调度的核心。而对Interceptor 的调度,也正是由ActionInvocation负责。ActionInvocation 是一个接口, 而DefaultActionInvocation 则是Webwork 对ActionInvocation的默认实现。

Interceptor 的调度流程大致如下:
1. ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。
2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。

Interceptor将很多功能从我们的Action中独立出来,大量减少了我们Action的代码,独立出来的行为具有很好的重用性。XWork、WebWork的许多功能都是有Interceptor实现,可以在配置文件中组装Action用到的Interceptor,它会按照你指定的顺序,在Action执行前后运行。
那么什么是拦截器。
拦截器就是AOP(Aspect-Oriented Programming)的一种实现。(AOP是指用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。)
拦截器的例子这里就不展开了。
struts-default.xml文件摘取的内容:

< interceptor name ="alias" class ="com.opensymphony.xwork2.interceptor.AliasInterceptor" />
< interceptor name ="autowiring" class ="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor" />
< interceptor name ="chain" class ="com.opensymphony.xwork2.interceptor.ChainingInterceptor" />
< interceptor name ="conversionError" class ="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor" />
< interceptor name ="createSession" class ="org.apache.struts2.interceptor.CreateSessionInterceptor" />
< interceptor name ="debugging" class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
< interceptor name ="external-ref" class ="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor" />
< interceptor name ="execAndWait" class ="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor" />
< interceptor name ="exception" class ="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor" />
< interceptor name ="fileUpload" class ="org.apache.struts2.interceptor.FileUploadInterceptor" />
< interceptor name ="i18n" class ="com.opensymphony.xwork2.interceptor.I18nInterceptor" />
< interceptor name ="logger" class ="com.opensymphony.xwork2.interceptor.LoggingInterceptor" />
< interceptor name ="model-driven" class ="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" />
< interceptor name ="scoped-model-driven" class ="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor" />
< interceptor name ="params" class ="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />
< interceptor name ="prepare" class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor" />
< interceptor name ="static-params" class ="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor" />
< interceptor name ="scope" class ="org.apache.struts2.interceptor.ScopeInterceptor" />
< interceptor name ="servlet-config" class ="org.apache.struts2.interceptor.ServletConfigInterceptor" />
< interceptor name ="sessionAutowiring" class ="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor" />
< interceptor name ="timer" class ="com.opensymphony.xwork2.interceptor.TimerInterceptor" />
< interceptor name ="token" class ="org.apache.struts2.interceptor.TokenInterceptor" />
< interceptor name ="token-session" class ="org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />
< interceptor name ="validation" class ="com.opensymphony.xwork2.validator.ValidationInterceptor" />
< interceptor name ="workflow" class ="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor" />
< interceptor name ="store" class ="org.apache.struts2.interceptor.MessageStoreInterceptor" />
< interceptor name ="checkbox" class ="org.apache.struts2.interceptor.CheckboxInterceptor" />
< interceptor name ="profiling" class ="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />

一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。如上文中将结构返回“add.jsp”,但大部分时候都是返回另外一个action,那么流程又得走一遍………

一些默认拦截器的简单说明;有兴趣可以看下源代码,源码就不贴了。
拦截器
名字
说明

Alias Interceptor
alias
在不同请求之间将请求参数在不同名字件转换,请求内容不变

Chaining Interceptor
chain
让前一个Action的属性可以被后一个Action访问,现在和chain类型的result(<result type=”chain”>)结合使用。

Checkbox Interceptor
checkbox
添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。

Cookies Interceptor
cookies
使用配置的name,value来是指cookies

Conversion Error Interceptor
conversionError
将错误从ActionContext中添加到Action的属性字段中。

Create Session Interceptor
createSession
自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。

Debugging Interceptor
debugging
提供不同的调试用的页面来展现内部的数据状况。

Execute and Wait Interceptor
execAndWait
在后台执行Action,同时将用户带到一个中间的等待页面。

Exception Interceptor
exception
将异常定位到一个画面

File Upload Interceptor
fileUpload
提供文件上传功能

I18n Interceptor
i18n
记录用户选择的locale

Logger Interceptor
logger
输出Action的名字

Message Store Interceptor
store
存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。

Model Driven Interceptor
model-driven
如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。

Scoped Model Driven
scoped-model-driven
如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。

Parameters Interceptor
params
将请求中的参数设置到Action中去。

Prepare Interceptor
prepare
如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。

Scope Interceptor
scope
将Action状态存入session和application的简单方法。

Servlet Config Interceptor
servletConfig
提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。

Static Parameters Interceptor
staticParams
从struts.xml文件中将<action>中的<param>中的内容设置到对应的Action中。

Roles Interceptor
roles
确定用户是否具有JAAS指定的Role,否则不予执行。

Timer Interceptor
timer
输出Action执行的时间

Token Interceptor
token
通过Token来避免双击

Token Session Interceptor
tokenSession
和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中

Validation Interceptor
validation
使用action-validation.xml文件中定义的内容校验提交的数据。

Workflow Interceptor
workflow
调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面

Parameter Filter Interceptor
N/A
从参数列表中删除不必要的参数

Profiling Interceptor
profiling
通过参数激活profi

转载于:https://blog.51cto.com/liuzhenyu/1212480

Struts2核心工作原理解析相关推荐

  1. Retrofit2 工作原理解析(一)

    Retrofit2 工作原理解析(一) 概述 Retrofit是square公司开源的一款类型安全的http请求框架,用于Java和Android程序.Retrofit可以说是restful风格的一个 ...

  2. 【深度学习】谷歌大脑EfficientNet的工作原理解析

    [深度学习]谷歌大脑EfficientNet的工作原理解析 文章目录 1 知识点准备1.1 卷积后通道数目是怎么变多的1.2 EfficientNet 2 结构2.1 方式2.2 MBConv卷积块2 ...

  3. 揭开SAP Fiori编程模型规范里注解的神秘面纱 - @OData.publish工作原理解析

    Jerry的前一篇文章 揭开SAP Fiori编程模型规范里注解的神秘面纱 - @ObjectModel.readOnly工作原理解析,给大家分享了@ObjectModel.readOnly这个注解对 ...

  4. Struts2的工作原理及工作流程

    众所周知,Struts2是个非常优秀的开源框架,我们能用Struts2框架进行开发,同时能 快速搭建好一个Struts2框架,但我们是否能把Struts2框架的工作原理用语言表达清楚,你表达的原理不需 ...

  5. 谈谈struts2的工作原理

    2019独角兽企业重金招聘Python工程师标准>>> 一.谈谈struts2的工作原理: 最近学习struts2,其实它就是webwork2.2的升级版,现附上原理图 上图来源于S ...

  6. 2 计算机控制器的组成,组合逻辑控制器组成结构及工作原理解析

    组合逻辑控制器组成结构及工作原理解析 按照控制信号产生的方式不同,控制器分为微程序控制器和组合逻辑控制器两类 微程序控制器是将全部控制信号存贮在控制存储器中. 优点:控制信号的逻辑设计.实现及改动都较 ...

  7. 交换机原理_交换机工作原理解析

    原文连接:http://www.elecfans.com/dianzichangshi/20171204593673.html 交换机原理 数据传输基于OSI七层模型,而交换机就工作于其第二层,即数据 ...

  8. 六轴机械臂控制原理图_六轴工业机器人工作原理解析

    原标题:六轴工业机器人工作原理解析 常见的六轴关节机器人的机械结构如图1所示: 六个伺服电机直接通过谐波减速器.同步带轮等驱动六个关节轴的旋转,注意观察一.二.三.四轴的结构,关节一至关节四的驱动电机 ...

  9. MSN,QQ,IP Messenger,飞鸽传书,的工作原理解析

    MSN,QQ,飞鸽传书,的工作原理解析 http://apps.hi.baidu.com/share/detail/14190263 关键字:MSN,QQ,飞鸽传书,IP Messenger,传文件, ...

最新文章

  1. Anaconda 安装 TensorFlow ImportError:DLL加载失败,错误代码为-1073741795
  2. ZOJ 1048|POJ 1004|HDU1064 Financial Management
  3. 【HTML/CSS】CSS权重、继承及引入方式
  4. oracle move 换用户,Oracle move方法释放delete后的表空间
  5. python 为什么动态语言_Python动态语言
  6. 贷中风控调额方法与策略详解
  7. [bug] VS2013 Brower Link和Aspnetpager引发的问题分析
  8. sas编程技术教程 人大经济论坛sas培训
  9. 计算机怎么格式化硬盘,如何格式化硬盘
  10. 小白能读懂的 《手把手教你学DSP(TMS320X281X)》第六章 CMD文件的编写
  11. 归并算法(详细见解)
  12. 西门子1200 PLC程序 通讯对象:PLC、CNC、机械手、RFID标签读写器、打标机、分布式远程IO模块、MES中控系统、AGV光通讯
  13. TensorFlow深度学习:3.API示范
  14. 万年历、黄历,获取每日的宜忌、五行、冲煞、值神、彭祖百忌、吉神宜趋、今日胎神、凶神宜忌、二十八星宿、建除十二神
  15. jsp2022326税务税收协同办公系统
  16. 计算机网络学习笔记 3.6 局域网
  17. 5大模块带你了解视频后台设计(含推荐策略)
  18. 一文看懂推荐系统:物品冷启05:流量调控
  19. 2021-2027全球与中国连续式网带炉市场现状及未来发展趋势
  20. [附源码]计算机毕业设计Python疫情物资管理系统(程序+源码+LW文档)

热门文章

  1. java异步调用第三方接口_Java调用第三方系统接口获取数据
  2. 使用FindAncestor查找方式绑定且不需要使用datacontext
  3. PHP自动加载上——spl_autoload_register
  4. 2017.5.5-afternoon
  5. jquery实现加载更多效果
  6. Kafka无消息丢失配置
  7. Theano2.1.1-基础知识之准备工作
  8. html5+CSS3实现的炫酷超链接特效
  9. Android 短信模块分析(四) MMS之短信的发送与接收
  10. 【CSON原创】基于HTML5的超级玛丽游戏demo