Struts2核心工作原理解析

Struts2工作原理及代码 【代码】Struts2工作原理及代码。 阅读详情

这篇文章对应的并非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

struts2工作原理 struts2工作原理、请求响应流程。。。。。。。。。。。。。。。 立即下载

相关推荐

spring+hibernate+struct2框架整合

完美整合ssh,并附上数据库增删查改的操作.适合初学者学习

Struts2工作原理详解

Struts2的工作原理图如下所示: Struts2工作原理详解: 1、Struts2框架会将得到的用户请求封装成为一个HttpServletRequest请求对象。 2、这个请求会经过一系列的过滤器,如果Struts2与其他的框架进行了集成,首先会经过ActionContextCleanUp过滤器,然后再经过其他的一些过滤器,最后经过核心过滤器FilterDispatcher或Stru...

我是猿小白的博客 4087

struts2重要知识点原理

struts hibernate 安装及配置详解

【框架学习】Struts2(一)工作原理

众所周知Struts2是MVC模式在web开发中经典的框架之一,学习web开发,这也是一个必经过之路吧,实在不行也得瞅瞅,万一哪天用到了。技术优势: Struts2有两方面的技术优势,一是所有的Struts2应用程序都是基于client/server HTTP交换协议,The Java Servlet API揭示了Java Servlet只是Java API的一个很小子集,这样我们可以在业务逻辑

小鼠标的博客 1541

机场数据治理系列介绍(1):机场行业数据中台中的数据管理顶层设计方案

民航机场行业的数据中台中,有关数据管理顶层设计方案需要结合机场行业的业务特点和技术需求进行具体的设计,今日我们简要考量设计提供一个参考方案:

机场信息系统研究员的专栏 1604

强化学习-马尔可夫模型

前文提到了强化学习源自马尔可夫决策过程,本文从马尔可夫概念入手,讲解和马尔可夫有关的模型和概念。在马尔科夫决策过程中,我们有一个智能体,它在一个马尔科夫过程中进行决策,每次决策都会导致状态的转移和获得即时奖励。智能体的目标是通过选择动作来最大化未来奖励的期望值。通常马尔科夫决策过程是个五元组:SAPRγSAPRγS 表示状态集合,代表智能体可能处于的所有状态。A 表示动作集合,代表智能体可以采取的所有动作。

君子之学必日新,日新者日进也。不日新者必日退,未有不进而不退者 8060

struts2原理及基本应用

struts2工作原理 1、tomcat启动,会先去读取web.xml文件;然后会去初始化struts2核心过滤器StrutsPreparedAndExecuteFilter,在该过滤器中第一次会调用过滤器中的init方法进行初始化,而初始化方法中就有一个对象,Dispatcher对象,该对象会去读取并解析struts2.xml,struts-default.xml等文件。 2、客户端向服务器发送...

hyly_zhard的博客 752

SAP开发顾问简历模板范文(精选篇)

SAP开发顾问简历该怎么写呢?

Huanzhucv的博客 1568

Struts2工作原理(图解)—六大核心组件关系

写在前面:Struts2主要包含前端控制器FC、Action、ValueStack容器、Result、Interceptor拦截器、Tags标签6个核心组件,本文主要介绍这几个组件的合作关系,由此构成Struts2的工作流程,以便更好地理解和使用Struts2。 背景知识 1、Struts2基础标签     1)用于输出的标签         --*    value的值实际上是OGNL表

厚积而薄发,谋定而后动 1万+

Numpy快速入门(np)!看这一篇就够了

Numpy快速入门(np)!看这一篇就够了

weixin_74009895的博客 2678

手把手教你学Simulink——基于重复控制(RC)的并网逆变器场景实例:基于RC的单相并网逆变器仿真

本次教程深入剖析了重复控制(RC)在单相并网逆变器中的应用,解决了周期性谐波抑制这一核心难题。核心收获RC是谐波抑制的“核武器”:它利用内模原理,对所有周期性谐波提供无限大增益,实现理论上无静差的跟踪和抑制。PI+RC是黄金组合:PI提供快速响应,RC提供稳态精度,二者结合,兼顾了动态与稳态性能。结构简单,效果卓越:相比多个PR控制器,RC仅需一个模块,即可抑制所有谐波,设计简洁。电能质量的终极追求,是波形的纯净。重复控制,如同一位不知疲倦的校对员它记住每一次错误(上一周期的误差),

MHD0815的博客 189
上一篇: 游标的概念和作用
下一篇: hibernate隔离级别
andyLiuJava
博客等级 码龄14年 0粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值