Struts2(二):工作原理
struts可查看源码:https://github.com/apache/struts
在学习struts2之前,我先看了一些比较早版本对struts2的工作原理相关的介绍,顺便抄写过来,用来帮助自己要弄清这个框架的工作原理。
struts2.1.3之前使用的FilterDispatcher,之后的版本使用StrutsPrepareAndExecuteFilter,而我这里还是以Dispatcher为例来记录的。
依据:
Since Struts 2.1.3, use org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter instead or org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter and org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one
To use a custom Dispatcher, the createDispatcher() method could be overriden by the subclass.
Version:$Date$ $Id$See Also:
ActionMapper
ActionContextCleanUp
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter
org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter
下图描述了Struts2的工作原理:

一个请求在Struts2框架中的处理大致分为一下几个步骤:
1、客户端初始化一个纸箱Servlet容器(比如:Tomcat)的请求。
2、这个请求经过一系列的过滤器(Filter)。
备注:这些过滤器中有个叫做ActionContextCleanUp的可选过滤器,它对Struts2和其他框架的集成很有帮助。
3、接着FilterDispatcher被调用,FilterDispatcher询问ActoinMapper来决定这个请求是否需要调用某个Action。FilterDispatcher是控制器的核心,也是MVC的中C控制层的核心。请查看:《摘抄别人对FilterDispatcher工作流程和原理的分析:FilterDispatcher进行初始化并启用核心doFilter》。
4、如果ActionMapper决定要调用某个Action,FilterDispatcher把请求的处理交给ActoinProxy。
5、ActionProxy通过Configuration Manager询问框架配置文件,找到需要调用的Action类,一般是从structs.xml配置中读取。
6、ActionProxy创建一个ActionInvocation的实例。
7、ActoinInvocation实例使用命名模式来调用,在调用Action前后,设计到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据Struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的Jsp或者FreeMarker的模板。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要设计到ActionMapper。
在以上过程中所有的对象(Action,Results,Interceptors等)都是通过ObjectFactory来创建的。
- 下面我们来看看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"/>
<interceptorname="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; publicclassAuthorizationInterceptor 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-refname="abc"/>
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
- 摘抄别人对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作用
Master filter for Struts that handles four distinct responsibilities:
•Executing actions
•Cleaning up the ActionContext (see note)
•Serving static content
•Kicking off XWork's interceptor chain for the request lifecycle
IMPORTANT: this filter must be mapped to all requests. Unless you know exactly what you are doing, always map to this URL pattern: /*
Executing actions
This filter executes actions by consulting the ActionMapper and determining if the requested URL should invoke an action. If the mapper indicates it should, the rest of the filter chain is stopped and the action is invoked. This is important, as it means that filters like the SiteMesh filter must be placed before this filter or they will not be able to decorate the output of actions.
Cleaning up the ActionContext
This filter will also automatically clean up the ActionContext for you, ensuring that no memory leaks take place. However, this can sometimes cause problems integrating with other products like SiteMesh. See ActionContextCleanUp for more information on how to deal with this.
Serving static content
This filter also serves common static content needed when using various parts of Struts, such as JavaScript files, CSS files, etc. It works by looking for requests to /struts/*, and then mapping the value after "/struts/" to common packages in Struts and, optionally, in your class path. By default, the following packages are automatically searched:
•org.apache.struts2.static
•template
This means that you can simply request /struts/xhtml/styles.css and the XHTML UI theme's default stylesheet will be returned. Likewise, many of the AJAX UI components require various JavaScript files, which are found in the org.apache.struts2.static package. If you wish to add additional packages to be searched, you can add a comma separated (space, tab and new line will do as well) list in the filter init parameter named "packages". Be careful, however, to expose any packages that may have sensitive information, such as properties file with database access credentials.
This filter supports the following init-params:
•config - a comma-delimited list of XML configuration files to load.
•actionPackages - a comma-delimited list of Java packages to scan for Actions.
•configProviders - a comma-delimited list of Java classes that implement the ConfigurationProvider interface that should be used for building the Configuration.
•loggerFactory - The class name of the LoggerFactory implementation.
•* - any other parameters are treated as framework constants.
参考:http://blog.csdn.net/laner0515/article/details/27692673/
Struts2(二):工作原理的更多相关文章
- Struts2(二)工作原理
一.概述 1.struts框架本身分为三个部分:核心控制器FilterDispatcher.业务控制器Action和用户实现的企业业务逻辑组件. 2.struts2工作的基本流程: 客户端初始化一个指 ...
- Struts2的工作原理及工作流程
众所周知,Struts2是个非常优秀的开源框架,我们能用Struts2框架进行开发,同时能 快速搭建好一个Struts2框架,但我们是否能把Struts2框架的工作原理用语言表达清楚,你表达的原理不需 ...
- 菜鸟学Struts2——Struts工作原理
在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...
- Struts2的工作原理(图解)详解
Struts2的工作原理 上图来源于Struts2官方站点,是Struts 2 的整体结构. 一个请求在Struts2框架中的处理大概分为以下几个步骤(可查看源码:https://github.com ...
- Struts2 的工作原理
Struts2 的工作原理: 1)client向server发出一个http请求.webserver对请求进行解析,假设在StrutsPrepareAndExecuteFilter的请求映射路径(在w ...
- struts2的工作原理
在学习struts2就必须的了解一下它的工作原理: 首先来看一下这张图 这张工作原理图是官方提供的: 一个请求在Struts2框架中的处理大概分为以下几个步骤 1.客户端初始化一个指向Servlet容 ...
- 第一篇——Struts2的工作原理及HelloWorld简单实现
Struts2工作原理: 一个请求在Struts框架中的处理步骤: 1.客户端初始化一个指向Servlet容器(例如Tomcat)的请求: 2.这个请求经过一系列的过滤器(Filter): 3.接着F ...
- Struts2学习一----------Struts2的工作原理及HelloWorld简单实现
© 版权声明:本文为博主原创文章,转载请注明出处 Struts2工作原理 一个请求在Struts2框架中的处理步骤: 1.客户端初始化一个指向Servlet容器(例如Tomcat)的请求 2.这个请求 ...
- HDSF主要节点解说(二)工作原理
HDFS(Hadoop Distributed File System )Hadoop分布式文件系统. 是依据google发表的论文翻版的.论文为GFS(Google File System)Goog ...
- 分享知识-快乐自己:Struts2框架 工作原理及执行流程图(拦截器的使用)
Struts2 架构图: 1):提交请求 客户端通过 HttpServletRequest 向 Servlet (即Tomcat)提交一个请求. 请求经过一系列的过滤器,例如图中的 ActionCon ...
随机推荐
- NOIp 2014 #2 联合权值 Label:图论 !!!未AC
题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...
- 【BZOJ】2277: [Poi2011]Strongbox
题意 有一个密码箱,\(0\)到\(n-1\)中的某些整数是它的密码.如果\(a\)和\(b\)都是它的密码,那么\((a+b)%n\)也是它的密码(\(a,b\)可以相等).某人试了\(k\)次密码 ...
- InterBase数据库迁移到MySQL(数据导出)
这篇我将记叙我的第二个脚本程序,这篇我使用InterBase数据库提供的“isql”命令来导出我所要的数据,但是由于“isql”命令没有直接导出数据的语句,说以我采用的是导入一个配置文件,在这个文件中 ...
- 华清远见金牌讲师名家大讲堂Android开发篇成功举办
2014年3月5日.12日华清远见金牌讲师名家大讲堂(以下简称名家大讲堂)在线讲座全新升级开讲,至此拉开了新一年名家大讲堂的序幕! 华清远见名家大讲堂作为业内颇具影响力的公益免 费线上课程,自2009 ...
- Mockito学习资料
官网:http://mockito.org/ https://dzone.com/refcardz/mockito
- 高性能分布式内存队列系统beanstalkd(转)
beanstalkd一个高性能.轻量级的分布式内存队列系统,最初设计的目的是想通过后台异步执行耗时的任务来降低高容量Web应用系统的页面访问延迟,支持过有9.5 million用户的Facebook ...
- Windows Phone Foreground Toast
Basically ToastPrompt is an UI component that derives from the Coding4Fun toolkit's abstract PopUp&l ...
- jquery .post .get中文参数乱码解决方法详解
jquery默认的编码为utf-8,做项目时有时处于项目需要用到ajax提交中文参数,乱码问题就很头疼了,折腾了许久终于弄出来了.为了便于传输,我们首先将需要用到的参数用javascript自带的函数 ...
- Java 中的转义字符
注意斜杠方向,为键盘右上角的斜杠 \t 在当前编辑位置插入一个 tab \b 在当前编辑位置插入一个空格 \n 换行(在当前编辑位置插入 a newline) \r 在当前编辑位置插入一个回车 ...
- 对ASM存储管理的一些初步理解记录
ASM:Automatic Storage Management,是ORACEL10G以后为了简化存储管理的复杂性,也是为了摆脱对其他厂商的依赖而推出的.ASM作为目前ORACLE推荐的首选存储方案, ...