读书人

struts2 流程 简略描述

发布时间: 2012-06-29 15:48:46 作者: rapoo

struts2 流程 简单描述

1、整体结构
struts2 流程 简略描述
  

2.几个概念

2.1 actionContext:? is the context in which an Action is executed. Each context is basically a container of objects an action needs for execution like the session, parameters, locale, etc.

??? 保存session,parameters等对象的是一个Map类型叫context对象。 其在内存中的快照如下:struts2 流程 简略描述

?2.2 FilterDispatcher

?Master filter for Struts that handles four distinct responsibilities:

Executing actionsCleaning up the ActionContext (see note)Serving static contentKicking off XWork's interceptor chain for the request lifecycle

Struts2.1.3之后用StrutsPrepareAndExecuteFilter 替换

?

2.3 Dsipatcher:

????? struts真正用来转发的类。

???? 该类是线程安全的。因为它的实例是如下代码生成的???

?2.6 ObjectFactory???

ObjectFactory is responsible for building the core framework objects. Users may register their own implementation of the ObjectFactory to control instantiation of these Objects.

This default implementation uses the buildBean method to create all classes (interceptors, actions, results, etc).

???? buildBean(config.getClassName(), extraContext)这个方法做的事情很简单:用ClassLoader加载classname所对应的class,extraContext这个参数没有用到。

?

2.7 ConfigurationManager - central for XWork Configuration management, including its ConfigurationProvider.

2.8 ConfigurationProvider interface describes the framework's configuration. By default, the framework loads its configurations via an xml document by using the StrutsXmlConfigurationProvider.

?

3、简单步骤

客户端提起一个(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?...{
    1. ????????HttpServletRequest?request?=?(HttpServletRequest)?req;????????HttpServletResponse?response?=?(HttpServletResponse)?res;
    2. ????????ServletContext?servletContext?=?filterConfig.getServletContext();????????//?在这里处理了HttpServletRequest和HttpServletResponse。
    3. ????????DispatcherUtils?du?=?DispatcherUtils.getInstance();????????du.prepare(request,?response);//正如这个方法名字一样进行locale、encoding以及特殊request?parameters设置
    4. ????????try?...{????????????request?=?du.wrapRequest(request,?servletContext);//对request进行包装
    5. ????????}?catch?(IOException?e)?...{????????????String?message?=?"Could?not?wrap?servlet?request?with?MultipartRequestWrapper!";
    6. ????????????LOG.error(message,?e);????????????throw?new?ServletException(message,?e);
    7. ????????}????????????????ActionMapperIF?mapper?=?ActionMapperFactory.getMapper();//得到action的mapper
    8. ????????ActionMapping?mapping?=?mapper.getMapping(request);//?得到action?的?mapping ????????if?(mapping?==?null)?...{
    9. ????????????//?there?is?no?action?in?this?request,?should?we?look?for?a?static?resource? ????????????String?resourcePath?=?RequestUtils.getServletPath(request);
    10. ????????????if?("".equals(resourcePath)?&&?null?!=?request.getPathInfo())?...{????????????????resourcePath?=?request.getPathInfo();
    11. ????????????}????????????if?("true".equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))?
    12. ????????????????????&&?resourcePath.startsWith("/webwork"))?...{????????????????String?name?=?resourcePath.substring("/webwork".length());
    13. ????????????????findStaticResource(name,?response);????????????}?else?...{
    14. ????????????????//?this?is?a?normal?request,?let?it?pass?through ????????????????chain.doFilter(request,?response);
    15. ????????????}????????????//?WW?did?its?job?here
    16. ????????????return;????????}
    17. ????????Object?o?=?null;????????try?...{
    18. ????????????//setupContainer(request); ????????????o?=?beforeActionInvocation(request,?servletContext);
    19. //整个框架最最核心的方法,下面分析 ????????????du.serviceAction(request,?response,?servletContext,?mapping);
    20. ????????}?finally?...{????????????afterActionInvocation(request,?servletContext,?o);
    21. ????????????ActionContext.setContext(null);????????}
    22. ????}du.serviceAction(request,?response,?servletContext,?mapping);
    23. //这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
    24. 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)请求
    25. ????????extraContext.put(SERVLET_DISPATCHER,?this);?????????OgnlValueStack?stack?=?(OgnlValueStack)?request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);?
    26. ????????if?(stack?!=?null)?...{?????????????extraContext.put(ActionContext.VALUE_STACK,new?OgnlValueStack(stack));?
    27. ????????}?????????try?...{?
    28. ????????????ActionProxy?proxy?=?ActionProxyFactory.getFactory().createActionProxy(namespace,?actionName,?extraContext);?//这里actionName是通过两道getActionName解析出来的,?FilterDispatcher把请求的处理交给ActionProxy,下面是ServletDispatcher的?TODO:?
    29. ????????????request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,?proxy.getInvocation().getStack());?????????????proxy.execute();?
    30. ?????????//通过代理模式执行ActionProxy ????????????if?(stack?!=?null)...{?
    31. ????????????????request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);?????????????}?
    32. ????????}?catch?(ConfigurationException?e)?...{?????????????log.error("Could?not?find?action",?e);?
    33. ????????????sendError(request,?response,?HttpServletResponse.SC_NOT_FOUND,?e);?????????}?catch?(Exception?e)?...{?
    34. ????????????log.error("Could?not?execute?action",?e);?????????????sendError(request,?response,?HttpServletResponse.SC_INTERNAL_SERVER_ERROR,?e);?
    35. ????????}?}?
    FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。 ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类.
    如上文的struts.xml配置
      <?xml?version="1.0"?encoding="GBK"?>
    1. ?<!DOCTYPE?struts?PUBLIC?"-//Apache?Software?Foundation//DTD?Struts?Configuration?2.0//EN"?"http://struts.apache.org/dtds/struts-2.0.dtd">?<struts>
    2. ?????<include?file="struts-default.xml"/>?????<package?name="struts2"?extends="struts-default">
    3. ?????????<action?name="add"??????????????class="edisundong.AddAction"?>
    4. ?????????????<result>add.jsp</result>?????????</action>????
    5. ?????</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"?/>?
    1. <?interceptor?name?="autowiring"?class?="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"?/>?<?interceptor?name?="chain"?class?="com.opensymphony.xwork2.interceptor.ChainingInterceptor"?/>?
    2. <?interceptor?name?="conversionError"?class?="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"?/>?<?interceptor?name?="createSession"?class?="org.apache.struts2.interceptor.CreateSessionInterceptor"?/>?
    3. <?interceptor?name?="debugging"?class?="org.apache.struts2.interceptor.debugging.DebuggingInterceptor"?/>?<?interceptor?name?="external-ref"?class?="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"?/>?
    4. <?interceptor?name?="execAndWait"?class?="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"?/>?<?interceptor?name?="exception"?class?="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"?/>?
    5. <?interceptor?name?="fileUpload"?class?="org.apache.struts2.interceptor.FileUploadInterceptor"?/>?<?interceptor?name?="i18n"?class?="com.opensymphony.xwork2.interceptor.I18nInterceptor"?/>?
    6. <?interceptor?name?="logger"?class?="com.opensymphony.xwork2.interceptor.LoggingInterceptor"?/>?<?interceptor?name?="model-driven"?class?="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"?/>?
    7. <?interceptor?name?="scoped-model-driven"?class?="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"?/>?<?interceptor?name?="params"?class?="com.opensymphony.xwork2.interceptor.ParametersInterceptor"?/>?
    8. <?interceptor?name?="prepare"?class?="com.opensymphony.xwork2.interceptor.PrepareInterceptor"?/>?<?interceptor?name?="static-params"?class?="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"?/>?
    9. <?interceptor?name?="scope"?class?="org.apache.struts2.interceptor.ScopeInterceptor"?/>?<?interceptor?name?="servlet-config"?class?="org.apache.struts2.interceptor.ServletConfigInterceptor"?/>?
    10. <?interceptor?name?="sessionAutowiring"?class?="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"?/>?<?interceptor?name?="timer"?class?="com.opensymphony.xwork2.interceptor.TimerInterceptor"?/>?
    11. <?interceptor?name?="token"?class?="org.apache.struts2.interceptor.TokenInterceptor"?/>?<?interceptor?name?="token-session"?class?="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"?/>?
    12. <?interceptor?name?="validation"?class?="com.opensymphony.xwork2.validator.ValidationInterceptor"?/>?<?interceptor?name?="workflow"?class?="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"?/>?
    13. <?interceptor?name?="store"?class?="org.apache.struts2.interceptor.MessageStoreInterceptor"?/>?<?interceptor?name?="checkbox"?class?="org.apache.struts2.interceptor.CheckboxInterceptor"?/>?
    14. <?interceptor?name?="profiling"?class?="org.apache.struts2.interceptor.ProfilingActivationInterceptor"?/>?
    一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。如上文中将结构返回“add.jsp”,但大部分时候都是返回另外一个action,那么流程又得走一遍………

  总结:

  Struts2的工作流就只有这7步,比起Struts1简单了很多(本人能力有限,struts2更多的东西现在还看不明白)。网上有很多很多的关于.net和java的比较之类的文章,可是有几个作者是真正用过java和.net的呢?更多的评论都是人云亦云,想当然的评论java和.net。作为技术人千万不要屁股决定脑袋,关于web的设计模式上.net也不是那么一无是处,java也不是那么完美无缺

读书人网 >软件架构设计

热点推荐