转自:

  http://www.cnblogs.com/xiadongqing/p/5240615.html

在学习struts2之前,首先我们要明白使用struts2的目的是什么?它能给我们带来什么样的好处?

设计目标

Struts设计的第一目标就是使MVC模式应用于web程序设计。在这儿MVC模式的好处就不在提了。

技术优势

Struts2有两方面的技术优势,一是所有的Struts2应用程序都是基于client/server HTTP交换协议,The Java Servlet API揭示了Java Servlet只是Java API的一个很小子集,这样我们可以在业务逻辑部分使用功能强大的Java语言进行程序设计。

二是提供了对MVC的一个清晰的实现,这一实现包含了很多参与对所以请求进行处理的关键组件,如:拦截器、OGNL表达式语言、堆栈。

因为struts2有这样目标,并且有这样的优势,所以,这是我们学习struts2的理由,下面,我们在深入剖析一下struts的工作原理。

工作原理

Suruts2的工作原理可以用下面这张图来描述,下面我们分步骤介绍一下每一步的核心内容

一个请求在Struts2框架中的处理大概分为以下几个步骤

   1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求

    2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 

    3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action 

        FilterDispatcher是控制器的核心,就是mvc中c控制层的核心。下面粗略的分析下我理解的FilterDispatcher工作流程和原理:FilterDispatcher进行初始化并启用核心doFilter

    4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 

    5、ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类 ,这里,我们一般是从struts.xml配置中读取。

    6、ActionProxy创建一个ActionInvocation的实例。

    7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。 

    8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是, 也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。

    在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

 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);
}
}

 

 

下面我们来看看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执行前后运行。

这里,我们简单的介绍一下Interceptor

在struts2中自带了很多拦截器,在struts2-core-2.1.6.jar这个包下的struts-default.xml中我们可以发现:

 <interceptors>
<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="clearSession"class="org.apache.struts2.interceptor.ClearSessionInterceptor"/>
<interceptor name="createSession"class="org.apache.struts2.interceptor.CreateSessionInterceptor"/>
<interceptor name="debugging"class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor"/>
<interceptor name="externalRef"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="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven"class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="actionMappingParams"class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
<interceptor name="prepare"class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams"class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope"class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig"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="tokenSession"class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation"class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<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"/>
<interceptor name="roles"class="org.apache.struts2.interceptor.RolesInterceptor"/>
<interceptor name="jsonValidation"class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor"/>
<interceptornameinterceptorname="annotationWorkflow"class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor"/>

对于sturts2自带的拦截器,使用起来就相对比较方便了,我们只需要在struts.xml的action标签中加入<interceptor-ref name=" logger " />并且struts.xml扩展struts-default,就可以使用,

如果是要自定义拦截器,首先需要写一个拦截器的类:

 package ceshi;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class AuthorizationInterceptor extends AbstractInterceptor { @Override
public Stringintercept(ActionInvocation ai)throws Exception { System.out.println("abc");
return ai.invoke(); } }

并且在struts.xml中进行配置

 <!DOCTYPEstruts PUBLIC
"-//Apache SoftwareFoundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"> <struts>
<package name="test"extends="struts-default">
<interceptors>
<interceptor name="abc"class ="ceshi.AuthorizationInterceptor"/>
</interceptors>
<action name="TestLogger"class="vaannila.TestLoggerAction">
<interceptor-refnameinterceptor-refname="abc"/>
<result name="success">/success.jsp</result>
</action>
</package>
</struts>

在上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。

Struts2和struts1的比较

struts2相对于struts1来说简单了很多,并且功能强大了很多,我们可以从几个方面来看:

从体系结构来看:struts2大量使用拦截器来出来请求,从而允许与业务逻辑控制器 与 servlet-api分离,避免了侵入性;而struts1.x在action中明显的侵入了servlet-api.

从线程安全分析:struts2.x是线程安全的,每一个对象产生一个实例,避免了线程安全问题;而struts1.x在action中属于单线程。

性能方面:struts2.x测试可以脱离web容器,而struts1.x依赖servlet-api,测试需要依赖web容器。

请求参数封装对比:struts2.x使用ModelDriven模式,这样我们 直接 封装model对象,无需要继承任何struts2的基类,避免了侵入性。

标签的优势:标签库几乎可以完全替代JSTL的标签库,并且 struts2.x支持强大的ognl表达式。

当然,struts2和struts1相比,在 文件上传,数据校验 等方面也 方便了好多。在这就不详谈了。

    一个比较优秀的框架可以帮着我们更高效,稳定的开发合格的产品,不过我们也不要依赖框架,我们只要理解了思想,设计模式,我们可以自己扩展功能,不然 就要 永远让别人牵着走了!

Struts2 的核心、执行原理的更多相关文章

  1. struts2的核心和工作原理

    struts2的核心和工作原理 设计目标 Struts设计的第一目标就是使MVC模式应用于web程序设计.技术优势 Struts2有两方面的技术优势,一是所有的Struts2应用程序都是基于clien ...

  2. Struts2进阶(一)运行原理及搭建步骤

    Struts2进阶(一)运行原理 Struts2框架 Struts2框架搭建步骤 致力于web服务,不可避免的涉及到编程实现部分功能.考虑使用到SSH框架中的Struts2.本篇文章只为深入理解Str ...

  3. DEDECMS数据库执行原理、CMS代码层SQL注入防御思路

    我们在上一篇文章中学习了DEDECMS的模板标签.模板解析原理,以及通过对模板核心类的Hook Patch来对模板的解析流量的攻击模式检测,达到修复模板类代码执行漏洞的目的 http://www.cn ...

  4. Servlet、Struts2、SpringMVC执行流程

    Servlet 有以下四个阶段: 1.加载和实例化 Servlet容器负责加载和实例化Servlet. 当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Ser ...

  5. 为什么struts2 ajax 方法执行两次

    struts2中使用json插件执行ajax处理时,如果方法名是get方法的时候,方法会莫名其妙的执行两次. 原因: struts2 中JSON的原理是在ACTION中的get方法都会序列化,所以前面 ...

  6. erlang虚拟机代码执行原理

     转载:http://blog.csdn.NET/mycwq/article/details/45653897 erlang是开源的,很多人都研究过源代码.但是,从erlang代码到c代码,这是个不小 ...

  7. 深度剖析Spark分布式执行原理

    让代码分布式运行是所有分布式计算框架需要解决的最基本的问题. Spark是大数据领域中相当火热的计算框架,在大数据分析领域有一统江湖的趋势,网上对于Spark源码分析的文章有很多,但是介绍Spark如 ...

  8. Spring MVC执行原理

    spring的MVC执行原理 1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求 进行真正的处理工作. 2.DispatcherSer ...

  9. spring的MVC执行原理

    spring的MVC执行原理 1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求 进行真正的处理工作. 2.DispatcherSer ...

  10. (4.1)Spring MVC执行原理和基于Java的配置过程

    一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...

随机推荐

  1. softmax与logistic关系

    Softmax回归模型,该模型是logistic回归模型在多分类问题上的推广,在多分类问题中,类标签  可以取两个以上的值. Softmax回归模型对于诸如MNIST手写数字分类等问题是很有用的,该问 ...

  2. IIS项目发布完整流程

    第一步: 发布项目 使在IIS上发布是防止源码泄露 第二步: 打开IIS(如果没有就自己安装一个)打开IIS步骤 控制面板>系统安全>管理工具>IIS管理器 填写网站的名称和之前发布 ...

  3. python函数参数总结

    python中函数参数有:默认参数.关键字参数.非关键字可变长参数(元组).关键字可变长参数(字典) 默认参数:在函数声明时,指定形参的默认值,调用时可不传入改参数(使用默认值)def foo(x): ...

  4. 数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群)

    数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群) 因为不会做目录所以请善用ctrl+F 本来想的是笔记之类的,写着写着就变成了资源整理 一些有的 ...

  5. test20181029 思考熊的马拉松

    题意 思考熊的马拉松 问题描述 今年,n只思考熊参加了校园马拉松比赛.马拉松的赛道是环形的,每圈的长度是A,完成比赛需要跑L圈. 比赛中,甲领先乙很长距离,绕过一圈或多圈后从后面追上了乙的现象叫做&q ...

  6. What is DB time in AWR?

    AWR中有 DB time这个术语,那么什么是DB time呢? Oracle10gR2 官方文档 给出了详细解释(Oracle10gPerformance Tuning Guide 5.1.1.2 ...

  7. MEF学习总结(2)---Primitive层

    Primitive层是属于依赖注入的通用模型,主要有如下核心类型: 1. ComposablePart是核心类,他表示组件容器中的每一个组件,是对真正组件实例的包装.ExportDefinition属 ...

  8. centos7下安装docker 17.x

    docker的17.X版本与以前的docker安装有些不同,参考了下这篇文章http://www.itmuch.com/docker/docker-2/,以下是我的docker 17.X版本安装过程, ...

  9. Asp.net中的web.config配置文件(转)

    最近开始学习.NET的开发,首先碰到的就是web.config的配置问题,把网上大虾的资料转发记录一下,以备不时之需. 原贴路径如下:http://blog.csdn.net/hbqhdlc/arti ...

  10. 从C++Primer某习题出发,谈谈C语言标准I/O的缓存问题

    刚看完信号那章,觉得处理信号时的sigsetjmp/siglongjmp似乎跟异常的跳出很像,于是想去复习C++异常,然后发现了对I/O没有充分理解的问题. 题目是C++ Primer 5.6.3节的 ...