`

struts2 流程 简单描述

 
阅读更多

1、整体结构

  

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对象。 其在内存中的快照如下:

 2.2 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

Struts2.1.3之后用StrutsPrepareAndExecuteFilter 替换

 

2.3 Dsipatcher:

      struts真正用来转发的类。

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

1 private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();
2   
3 public static Dispatcher getInstance() {
4     return instance.get();
5 }

     用来处理的方法是serviceAction

 

 

1 public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
2                               ActionMapping mapping) throws ServletException

与Action相关的信息如name result path 在ActionMapping中。ActionMapping 的定义

1 public class ActionMapping {
2     private String name;
3     private String namespace;
4     private String method;
5     private String extension;
6     private Map<String, Object> params;
7     private Result result;

2.4 ActionInvocation:如何创建,执行Action。实现类DefaultActionInvocation。包含的对象有

01 protected Object action;
02     protected ActionProxy proxy;
03     protected List<PreResultListener> preResultListeners;
04     protected Map<String, Object> extraContext;
05     protected ActionContext invocationContext;
06     protected Iterator<InterceptorMapping> interceptors;
07     protected ValueStack stack;
08     protected Result result;
09     protected Result explicitResult;
10     protected String resultCode;
11     protected boolean executed = false;
12     protected boolean pushAction = true;
13     protected ObjectFactory objectFactory;
14     protected ActionEventListener actionEventListener;
15     protected ValueStackFactory valueStackFactory;
16     protected Container container;
17     private Configuration configuration;
18     protected UnknownHandlerManager unknownHandlerManager;

 

     核心方法是invoke()

1 interceptor.getInterceptor().intercept(DefaultActionInvocation.this);//调用拦截器
2 invokeActionOnly();//调用Action

    其中invokeActionOnly(Object action, ActionConfig actionConfig)调用Action中对应的方法为:

1 Method method = null;
2             try {
3                 method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);
4             }
5   
6 if (!methodCalled) {
7                 methodResult = method.invoke(action, new Object[0]);//执行该方法
8             }

    创建Action: createAction(Map<String, Object> contextMap)

1 action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
2 //...
3 if (actionEventListener != null) {
4             action = actionEventListener.prepare(action, stack);
5         }

 

  

2.5 ActionProxy:怎么找到Action:存放actionName 和ActionInvocation对象。在ActionInvocation对象的初始化时创建Action:init(ActionProxy proxy)  中调用createAction(contextMap); struts中默认的实现类是StrutsActionProxy

 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)请求。

  1. 请求被提交到一系列(主要是三层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher)。注意这里是有顺序的,先ActionContextCleanUp,再其他过滤器(SiteMesh等)、最后到FilterDispatcher。
  2. FilterDispatcher是控制器的核心,就是mvc中c控制层的核心。下面粗略的分析下我理解的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. public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) ...{ 
    48.         HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig());  //实例化Map请求 ,询问ActionMapper是否需要调用某个Action来处理这个(request)请求
    49.         extraContext.put(SERVLET_DISPATCHER, this); 
    50.         OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY); 
    51.         if (stack != null) ...{ 
    52.             extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack)); 
    53.         } 
    54.         try ...{ 
    55.             ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext); 
    56. //这里actionName是通过两道getActionName解析出来的, FilterDispatcher把请求的处理交给ActionProxy,下面是ServletDispatcher的 TODO: 
    57.             request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack()); 
    58.             proxy.execute(); 
    59.          //通过代理模式执行ActionProxy
    60.             if (stack != null)...{ 
    61.                 request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack); 
    62.             } 
    63.         } catch (ConfigurationException e) ...{ 
    64.             log.error("Could not find action", e); 
    65.             sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e); 
    66.         } catch (Exception e) ...{ 
    67.             log.error("Could not execute action", e); 
    68.             sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e); 
    69.         } 
    FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
  3. ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类.
    如上文的struts.xml配置
    1. <?xml version="1.0" encoding="GBK"?>
    2.  <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
    3.  <struts>
    4.      <include file="struts-default.xml"/>
    5.      <package name="struts2" extends="struts-default">
    6.          <action name="add" 
    7.              class="edisundong.AddAction" >
    8.              <result>add.jsp</result>
    9.          </action>    
    10.      </package>
    11.  </struts>
    如果提交请求的是add.action,那么找到的Action类就是edisundong.AddAction。
  4. 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文件摘取的内容:
    1. < interceptor name ="alias" class ="com.opensymphony.xwork2.interceptor.AliasInterceptor" /> 
    2. < interceptor name ="autowiring" class ="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor" /> 
    3. < interceptor name ="chain" class ="com.opensymphony.xwork2.interceptor.ChainingInterceptor" /> 
    4. < interceptor name ="conversionError" class ="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor" /> 
    5. < interceptor name ="createSession" class ="org.apache.struts2.interceptor.CreateSessionInterceptor" /> 
    6. < interceptor name ="debugging" class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> 
    7. < interceptor name ="external-ref" class ="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor" /> 
    8. < interceptor name ="execAndWait" class ="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor" /> 
    9. < interceptor name ="exception" class ="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor" /> 
    10. < interceptor name ="fileUpload" class ="org.apache.struts2.interceptor.FileUploadInterceptor" /> 
    11. < interceptor name ="i18n" class ="com.opensymphony.xwork2.interceptor.I18nInterceptor" /> 
    12. < interceptor name ="logger" class ="com.opensymphony.xwork2.interceptor.LoggingInterceptor" /> 
    13. < interceptor name ="model-driven" class ="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" /> 
    14. < interceptor name ="scoped-model-driven" class ="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor" /> 
    15. < interceptor name ="params" class ="com.opensymphony.xwork2.interceptor.ParametersInterceptor" /> 
    16. < interceptor name ="prepare" class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor" /> 
    17. < interceptor name ="static-params" class ="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor" /> 
    18. < interceptor name ="scope" class ="org.apache.struts2.interceptor.ScopeInterceptor" /> 
    19. < interceptor name ="servlet-config" class ="org.apache.struts2.interceptor.ServletConfigInterceptor" /> 
    20. < interceptor name ="sessionAutowiring" class ="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor" /> 
    21. < interceptor name ="timer" class ="com.opensymphony.xwork2.interceptor.TimerInterceptor" /> 
    22. < interceptor name ="token" class ="org.apache.struts2.interceptor.TokenInterceptor" /> 
    23. < interceptor name ="token-session" class ="org.apache.struts2.interceptor.TokenSessionStoreInterceptor" /> 
    24. < interceptor name ="validation" class ="com.opensymphony.xwork2.validator.ValidationInterceptor" /> 
    25. < interceptor name ="workflow" class ="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor" /> 
    26. < interceptor name ="store" class ="org.apache.struts2.interceptor.MessageStoreInterceptor" /> 
    27. < interceptor name ="checkbox" class ="org.apache.struts2.interceptor.CheckboxInterceptor" /> 
    28. < 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也不是那么完美无缺

分享到:
评论

相关推荐

    Struts2 创建简单步骤

    下面将详细阐述创建一个简单的Struts2 HelloWorld程序的步骤: ### Step 1. 创建一个简单的Web应用程序 首先,你需要在IDE(如Eclipse、IntelliJ IDEA等)或通过手动方式创建一个新的Java Web项目。这通常包括以下...

    struts2小程序 struts2代码

    在描述中提到花费了3小时搭建,暗示这可能是一个简单的入门示例,用于学习或教学目的。 Struts2框架的核心特性包括: 1. **Action类**:这是处理HTTP请求的核心组件,每个Action对应一个业务逻辑。在`struts2小...

    使用struts1实现简单用户登陆流程

    在"使用Struts1实现简单用户登陆流程"的项目中,我们将深入探讨如何利用Struts1搭建一个基础的用户登录系统。 首先,让我们了解一下Struts1的核心组件: 1. **ActionServlet**:这是Struts1的入口点,负责处理所有...

    struts2写的简单相册管理

    此外,Struts2还有拦截器(Interceptor)机制,允许开发者插入自定义逻辑到Action执行流程中。 2. **JDBC(Java Database Connectivity)**:JDBC是Java访问数据库的标准API,用于与MySQL这样的关系型数据库进行...

    一个超级简单的struts2结构

    "一个超级简单的Struts2结构"是针对初学者设计的,旨在帮助他们快速理解和入门Struts2框架的基本概念和工作流程。 首先,我们需要理解Struts2的核心组件和工作原理。Struts2框架的核心是一个Front Controller(前端...

    配置第一个Struts2的简单登陆程序

    Struts2是一个强大的Java web应用程序框架,用于构建MVC(模型-视图-控制器)架构的应用。...这个简单的例子展示了如何使用Struts2构建Web应用程序的基本流程,但实际应用中还需要考虑更多安全和功能扩展。

    Struts 2实战 Struts 2 in action 的中文版

    Struts 2的工作流程 - 用户发起HTTP请求至服务器。 - 请求被Struts 2的前端控制器FilterDispatcher拦截。 - FilterDispatcher根据配置找到对应的Action实例,并调用其execute方法。 - Action处理完业务逻辑后返回一...

    struts2的一个简单示例项目bookzilla

    通过分析和运行Bookzilla项目,开发者可以了解Struts2的完整工作流程,从用户请求到控制器处理,再到视图展示,同时也可以学习到如何组织业务逻辑和数据访问层。这是一个学习和实践Struts2框架的绝佳案例。

    struts2+JSP

    4. **数据库集成**:在描述中提到的MySQL,Struts2可以通过DAO(Data Access Object)模式与数据库交互,实现数据的增删改查。 结合Struts2和JSP,我们可以创建一个简单的界面应用程序,如用户登录、注册、数据展示...

    struts2项目实例

    接着,描述中的"简单增、删、改、查业务"涉及数据库操作。Struts2与持久层框架(如Hibernate或MyBatis)集成,使得在Action类中可以直接调用DAO(数据访问对象)进行数据库交互。DAO层负责与数据库的通信,提供CRUD...

    struts2 最新版 不用去官网上下载了

    2. **拦截器(Interceptors)**: 拦截器是Struts2的一个重要概念,它们是实现业务逻辑和控制流程之间解耦的关键。开发者可以自定义拦截器,用于登录检查、日志记录、性能监控等多种用途。 3. **插件(Plugins)**: ...

    struts2框架做的学生信息查询系统

    Struts2框架是一种基于Model-View-Controller (MVC)设计模式的Java Web应用程序开发框架。它由Apache软件基金会维护,旨在简化Web应用的开发流程,提供更好的控制和解耦,以及增强可测试性。在"学生信息查询系统"这...

    struts2API文档

    10. **第十章:Struts2与AJAX** - 描述Struts2与Ajax的集成,实现页面的部分刷新。 11. **第十一章:Struts2与Spring集成** - 讨论如何将Struts2与Spring框架结合,实现依赖注入和事务管理。 12. **第十二章:Struts...

    Struts2的执行流程图

    通过以上对比和流程描述,我们可以看出Struts2在设计上更加灵活、可测试和高效,降低了开发复杂性,提升了应用程序的可维护性。而Struts2的执行流程图则有助于开发者直观地理解这个过程,更好地进行应用开发。

    Struts2与JSON

    首先,我们要理解Struts2整合JSON的基本流程。在Struts2中,我们可以通过Action类返回一个JSON结果类型,这样Struts2会自动将Action的属性转化为JSON格式并返回给客户端。客户端通常使用JavaScript库如jQuery来接收...

    jsp+hibernate+struts2简单登录和注册

    3. **Struts2**:Struts2是一个基于MVC(Model-View-Controller)模式的Web应用框架,负责控制应用程序的流程。在这个项目中,Struts2接收用户请求,调用相应的Action(业务逻辑处理类),并将结果返回给视图层...

    Struts2登录界面

    在Web开发中,Struts2帮助开发者处理请求、控制流程、展示视图,使得代码结构清晰,易于维护。本项目"Struts2登录界面"旨在帮助初学者快速理解和实践Struts2框架的基础应用。 首先,让我们了解一下Struts2的核心...

    原创struts2讲义2.pdf

    文件上传是Web应用中常见的一项功能,Struts2提供了简单易用的方式来实现这一需求。 ##### 4.3 高级表单处理技巧 在表单处理方面,Struts2支持多种高级技巧,如自动填充表单字段、动态生成表单元素等。 ##### 4.4...

    Struts2官方例子1(Ant版的)

    总的来说,"Struts2官方例子1(Ant版的)"提供了一个基础的模板,帮助开发者理解和实践Struts2的配置和运行流程。通过这个例子,可以学习到如何配置Struts2框架,编写Action,以及如何利用Ant进行项目的构建和管理。...

    struts2简单版本

    这个“struts2简单版本”可能是一个简化版的示例,展示了如何在实际开发中整合Struts2与Hibernate来实现数据的增删改查操作。 首先,让我们深入理解Struts2的核心概念。Struts2框架提供了一个结构化的控制层,用于...

Global site tag (gtag.js) - Google Analytics