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中我们可以发现:

 1 <interceptors>
 2            <interceptor name="alias"class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
 3            <interceptor name="autowiring"class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
 4            <interceptor name="chain"class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
 5            <interceptor name="conversionError"class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
 6            <interceptor name="clearSession"class="org.apache.struts2.interceptor.ClearSessionInterceptor"/>
 7            <interceptor name="createSession"class="org.apache.struts2.interceptor.CreateSessionInterceptor"/>
 8            <interceptor name="debugging"class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor"/>
 9            <interceptor name="externalRef"class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
10            <interceptor name="execAndWait"class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
11            <interceptor name="exception"class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
12            <interceptor name="fileUpload"class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
13            <interceptor name="i18n"class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
14            <interceptor name="logger"class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
15            <interceptor name="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
16            <interceptor name="scopedModelDriven"class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
17            <interceptor name="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
18            <interceptor name="actionMappingParams"class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
19            <interceptor name="prepare"class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
20            <interceptor name="staticParams"class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
21            <interceptor name="scope"class="org.apache.struts2.interceptor.ScopeInterceptor"/>
22            <interceptor name="servletConfig"class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
23            <interceptor name="sessionAutowiring"class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
24            <interceptor name="timer"class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
25            <interceptor name="token"class="org.apache.struts2.interceptor.TokenInterceptor"/>
26            <interceptor name="tokenSession"class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
27            <interceptor name="validation"class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
28            <interceptor name="workflow"class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
29            <interceptor name="store"class="org.apache.struts2.interceptor.MessageStoreInterceptor"/>
30            <interceptor name="checkbox"class="org.apache.struts2.interceptor.CheckboxInterceptor"/>
31            <interceptor name="profiling"class="org.apache.struts2.interceptor.ProfilingActivationInterceptor"/>
32            <interceptor name="roles"class="org.apache.struts2.interceptor.RolesInterceptor"/>
33            <interceptor name="jsonValidation"class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor"/>
34            <interceptorname="annotationWorkflow"class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor"/>

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

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

 1 package ceshi;
 2 import com.opensymphony.xwork2.ActionInvocation;
 3 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 4
 5 publicclassAuthorizationInterceptor extends AbstractInterceptor {
 6
 7     @Override
 8     public Stringintercept(ActionInvocation ai)throws Exception {
 9
10            System.out.println("abc");
11             return ai.invoke();
12
13     }
14
15 }

并且在struts.xml中进行配置

 1 <!DOCTYPEstruts PUBLIC
 2 "-//Apache SoftwareFoundation//DTD Struts Configuration 2.0//EN"
 3 "http://struts.apache.org/dtds/struts-2.0.dtd">
 4
 5
 6 <struts>
 7     <package name="test"extends="struts-default">
 8      <interceptors>
 9       <interceptor name="abc"class ="ceshi.AuthorizationInterceptor"/>
10     </interceptors>
11         <action name="TestLogger"class="vaannila.TestLoggerAction">
12            <interceptor-refname="abc"/>
13            <result name="success">/success.jsp</result>
14            </action>
15     </package>
16 </struts>
  • 摘抄别人对FilterDispatcher工作流程和原理的分析:FilterDispatcher进行初始化并启用核心doFilter
 1 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException ...{
 2         HttpServletRequest request = (HttpServletRequest) req;
 3         HttpServletResponse response = (HttpServletResponse) res;
 4         ServletContext servletContext = filterConfig.getServletContext();
 5         // 在这里处理了HttpServletRequest和HttpServletResponse。
 6         DispatcherUtils du = DispatcherUtils.getInstance();
 7         du.prepare(request, response);//正如这个方法名字一样进行locale、encoding以及特殊request parameters设置
 8         try ...{
 9             request = du.wrapRequest(request, servletContext);//对request进行包装
10         } catch (IOException e) ...{
11             String message = "Could not wrap servlet request with MultipartRequestWrapper!";
12             LOG.error(message, e);
13             throw new ServletException(message, e);
14         }
15                 ActionMapperIF mapper = ActionMapperFactory.getMapper();//得到action的mapper
16         ActionMapping mapping = mapper.getMapping(request);// 得到action 的 mapping
17         if (mapping == null) ...{
18             // there is no action in this request, should we look for a static resource?
19             String resourcePath = RequestUtils.getServletPath(request);
20             if ("".equals(resourcePath) && null != request.getPathInfo()) ...{
21                 resourcePath = request.getPathInfo();
22             }
23             if ("true".equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))
24                     && resourcePath.startsWith("/webwork")) ...{
25                 String name = resourcePath.substring("/webwork".length());
26                 findStaticResource(name, response);
27             } else ...{
28                 // this is a normal request, let it pass through
29                 chain.doFilter(request, response);
30             }
31             // WW did its job here
32             return;
33         }
34         Object o = null;
35         try ...{
36             //setupContainer(request);
37             o = beforeActionInvocation(request, servletContext);
38             //整个框架最最核心的方法,下面分析
39             du.serviceAction(request, response, servletContext, mapping);
40         } finally ...{
41             afterActionInvocation(request, servletContext, o);
42             ActionContext.setContext(null);
43         }
44     }
45     du.serviceAction(request, response, servletContext, mapping);
46     //这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
47
48 public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) ...{
49         HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig());  //实例化Map请求 ,询问ActionMapper是否需要调用某个Action来处理这个(request)请求
50         extraContext.put(SERVLET_DISPATCHER, this);
51         OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
52         if (stack != null) ...{
53             extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack));
54         }
55         try ...{
56             ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
57             //这里actionName是通过两道getActionName解析出来的, FilterDispatcher把请求的处理交给ActionProxy,下面是ServletDispatcher的 TODO:
58             request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
59             proxy.execute();
60             //通过代理模式执行ActionProxy
61             if (stack != null)...{
62                 request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);
63             }
64         } catch (ConfigurationException e) ...{
65             log.error("Could not find action", e);
66             sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
67         } catch (Exception e) ...{
68             log.error("Could not execute action", e);
69             sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
70         }
71 } 
  • 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/

时间: 2024-10-05 04:45:18

Struts2(二):工作原理的相关文章

Struts2(二)工作原理

一.概述 1.struts框架本身分为三个部分:核心控制器FilterDispatcher.业务控制器Action和用户实现的企业业务逻辑组件. 2.struts2工作的基本流程: 客户端初始化一个指向Servlet容器的请求 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter被调用,该过滤器询问ActionMaper这个请求是否需要调用某个Action 如果ActionMapper决定需要调用某个Actio

菜鸟学Struts2——Struts工作原理

在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中需要用户实现的部分只有三个,那就是struts.xml,Action,Template(JSP),如下图: 2.3.31中的org.apache.struts2.dispatcher.ActionContextCleanUp已经被标记为@Deprecated Since Struts 2.1.3,2

struts2的工作原理与文件结构

struts2框架的工作原理: Struts2的文件详解: 1. web.xml 过滤器遇到.action后缀的请求就会拦截处理,当遇到.jsp .html等就会放行. 2. struts.xml <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd&qu

Struts2 的工作原理

Struts2 的工作原理: 1,把Action请求发送给 StrutsPrepareAndExecuteFilter StrutsPrepareAndExecuteFilter.doFilter() --> ExecuteOperations.executeAction() --> Dispatcher.serviceAction() --> 2,StrutsPrepareAndExecuteFilter把请求的处理交给 ActionProxy ActionProxy.execute(

HDSF主要节点讲解(二)工作原理

HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.是根据google发表的论文翻版的.论文为GFS(Google File System)Google 文件系统(中文,英文). HDFS有很多特点: ① 保存多个副本,且提供容错机制,副本丢失或宕机自动恢复.默认存3份. ② 运行在廉价的机器上. ③ 适合大数据的处理.多大?多小?HDFS默认会将文件分割成block,64M为1个block.然后将block按键值对存储在HDFS上,并将键值对的

Struts2学习一----------Struts2的工作原理及HelloWorld简单实现

? 版权声明:本文为博主原创文章,转载请注明出处 Struts2工作原理 一个请求在Struts2框架中的处理步骤: 1.客户端初始化一个指向Servlet容器(例如Tomcat)的请求 2.这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的继承很有帮助,例如SiteMesh Plugin) 3.接着FilterDispatcher被调用,FilterDispatcher询问Action

从Struts2源码学习Struts2的工作原理

今天我和我好基友啊斌通过探讨struts2的源码,总结了一下它的原理,代码是不会骗人的. 总的来说:struts的工作原理有7步: 1 客户端初始化一个指向Servlet容器的请求: 2 这个请求经过一系列的过滤器 在项目部署的时候,由tomcat容器读取项目的web.xml文件,测试的web.xml文件如下: <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5&quo

struts2的工作原理

从图1我们不难看出struts2的工作流程大致分为一下几部分 1.客户端请求一个HttpServletRequest的请求,如在浏览器中输入http://localhost: 8080/bookcode/Reg.action就是提交一个(HttpServletRequest)请求. 2.这个请求经过一系列的过滤器(Filter)如(ActionContextCleanUp.其他过滤器(SiteMesh等). FilterDispatcher).注意:这里是有顺序的,先ActionContext

HDSF主要节点解说(二)工作原理

HDFS(Hadoop Distributed File System )Hadoop分布式文件系统. 是依据google发表的论文翻版的.论文为GFS(Google File System)Google 文件系统(中文.英文). HDFS有非常多特点: ① 保存多个副本,且提供容错机制,副本丢失或宕机自己主动恢复.默认存3份. ② 执行在便宜的机器上. ③ 适合大数据的处理. 多大?多小?HDFS默认会将文件切割成block,64M为1个block.然后将block按键值对存储在HDFS上,并

Struts2的工作原理(工作流程)

Struts2官方站点提供的Struts 2 的整体结构. 一个请求在Struts2框架中的处理大概分为以下几个步骤: 1.客户端提交一个HttpServletRequest请求(action或JSP页面). 2.这个请求被提交到一系列Filter过滤器,如ActionCleanUp和FilterDispatcher等. 3.FilterDispatcher是Struts2控制器的核心,它通常是过滤器链中的最后一个过滤器. 4.请求被发送到FilterDispatcher后,FilterDisp