`
Mojarra
  • 浏览: 128775 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

白话MVC(二)Struts2中Model的处理基础-ActionContext

阅读更多

白话MVC(一)                                                                                                                    白话MVC(三)

 

在第一篇中,花了主要篇幅探讨了MVC框架中对于编写Model层的约定,约定的目的是为了在Action类中进行自动装配,那么,struts2是如何自动装配Model Bean呢?在阅读struts2的源代码之前,不烦先做几个假设,带着这几个假设去看代码,效率高很多。

  1. 当Action类的实例被创建的时候,该实例中的Model Bean也一起被装配
  2. 当Action类的 实例 execute方法被执行之前, 实例中的Model Bean被装配
  3. 当ActionProxy类的 实例 execute方法执行时,被代理的Action实例中的Model Bean被装配

至于struts2是不是采用上述三种假设中的一个,符合不符合假设并不重要,重要的是找到了正确的结果。本文探讨的源码基于struts 2.3.4这个最新的发行版本。在探讨的过程中,仍然聚焦在Model层的处理,不详细描述每个细节(其实,以我对struts2框架的了解水平,显然是不可能的 )。

 

struts 2.3.4以StrutsPrepareAndExecuteFilter作为整个框架处理Request的接入点,从名字可以看出来,它是一个Filter(它真是一个Filter),在init方法中,读取了struts的配置文件,并且创建了Dispatcher、PrepareOperations和ExecuteOperations这三个重要的对象,其中Dispatcher是派发request给代理的工具类,很多实际的功能由这个类完成。

public void init(FilterConfig filterConfig) throws ServletException {
        InitOperations init = new InitOperations();
        try {
        	// FilterHostConfig其实是FilterConfig类的Wrapper,具有功能性的方法都是通过调用FilterConfig的相应方法实现的,主要的关注方法是
        	//getServletContext()和getInitParameter()
            FilterHostConfig config = new FilterHostConfig(filterConfig); 
            init.initLogging(config);
            Dispatcher dispatcher = init.initDispatcher(config); 
            //通过调用此方法,载入struts2框架需要用到配置文件,并创建Dispatcher对象,
            //Dispatcher是struts2框架中调度的最上层工具类
            init.initStaticContentLoader(config, dispatcher);

            //创建prepare和execute这两个顶层对象
            prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
            execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
            
            //被排除执行的action配置
			this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

            postInit(dispatcher, filterConfig);
        } finally {
            init.cleanup();
        }
    }
 

如果深入的说这个init方法,非要结合strut的配置文件和xwork具有迷你型的DI功能的容器来讨论,上面的只是惊鸿一瞥的把这个复杂载入配置文件的过程带过。

介绍完init方法,再来看一下doFilter方法,这个方法只有20几行代码,这20几行代码就把一个Action对象给执行了(执行前的N个步骤省略....),简洁至极。回到这里所关心的问题,什么时候Action的Model Bean被装配了,仔细的看看这20几行代码,实在是很高深,根本看不出跟装配Model Bean有什么直接关系。猜猜吧,执行装配工作的地方可能存在与这第3、8、16这三行代码之中。

try {
            prepare.setEncodingAndLocale(request, response); //设置字符集编码和本地化
            prepare.createActionContext(request, response);    //创建ActionContext
            prepare.assignDispatcherToThread();
			if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) { //如果excludes的,直接交给WEB容器处理
				chain.doFilter(request, response);
			} else {
				request = prepare.wrapRequest(request); //包装HttpServletRequest类,根据content-type来决定是MultiPartRequestWrapper类,还是StrutsRequestWrapper,
				ActionMapping mapping = prepare.findActionMapping(request, response, true); //根据request和配置文件,找到一个对应的Action类的ActionMapping对象
				if (mapping == null) {
					boolean handled = execute.executeStaticResourceRequest(request, response);
					if (!handled) {
						chain.doFilter(request, response); //只执行静态资源请求后,仍然交给WEB容器
					}
				} else {
					execute.executeAction(request, response, mapping);  //执行action
				}
			}
        } finally {
            prepare.cleanupRequest(request); //清除在执行Action过程之前向request写入的内容,设置actionContext, invocationContext为null,如果是multipart/form-data请求,清除生产的临时文件。
        }

  先看第3行,创建ActionContext对象。所谓ActionContext代表了框架处理Action时的上下文,包含了很多数据,主要包括action名,默认的值栈,具有抽象意义的SessionMap,ParameterMap,ApplicationMap, Local,ActionInvocation,Container。ActionContext实例被包装在ThreadLocal对象内,是线程安全的,很多框架也采用ThreadLocal解决多线程并发问题。


下面关键的代码显示,struts框架内,先通过x-work容器创建初始的OnglValueStack对象,此时,OnglValueStack对象是不包含任何和Model层所用的数据,prepare.createActionContext通过调用Dispatcher.createContextMap(...)方法创建的上面列出的map大对象,并且把这些map对象再放到extraContext这个“大”Map对象中去,注意,放的过程中,用到了strut框架里默认的值栈名(key),这些名字取数据的时候会再次用到。

Dispatcher.createContextMap(...)方法其实是struts2框架中Model层预处理的核心部分,有兴趣的读者可以推敲推敲其中的代码。

ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
ctx = new ActionContext(stack.getContext());
 
Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);

 是不是struts框架非常偏爱Map这个类?这是框架使用了Ongl处理request参数的情形下合理选择。

 

通过阅读这些代码,我们发现,这个时候Action实例还没有被创建,因此不可能会出现装配的Model Bean的情形。但是,这个时候ActionContext已经具备了和Reqeust脱离的条件,也即在框架下一层的处理中,对于数据上的需要,操作的重点对象不再是Request对象,而是ActionContext对象。

 

[本文系作者原创,如若转载,请注明出处,新浪微博:@仪山湖]

分享到:
评论

相关推荐

    struts2-junit-plugin-2.1.8.jar

    可解决java.lang.NoSuchMethodError: com.opensymphony.xwork2.ActionContext.get(Ljava/lang/Object;)Ljava/lang/Object; java.lang.ClassNotFoundException: com.opensymphony.xwork2.util.TextUtils struts2.1.8...

    ActionContext介绍(在Struts2中)

    在Web应用程序开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话 (Session)的一些信息, 甚至需要直接对JavaServlet Http的请求(HttpServletRequest),响应...

    struts2中的ActionContext与ognl

    NULL 博文链接:https://lijiejava.iteye.com/blog/628636

    基于struts2注册登录ActionContext.zip

    struts2大量使用拦截器来处理请求,从而允许与业务逻辑控制器 与 servlet-api分离,避免了侵入性(所谓侵入性就是指的这个架构设计出来的部件对系统的影响范围,标签库几乎可以完全替代JSTL的标签库,并且 struts2.x...

    struts2流程与流程图

    一个请求在Struts 2框架中的处理大概分为以下几个步骤。  客户端提交一个(HttpServletRequest)请求,如上文在浏览器中输入 http://localhost: 8080/bookcode/ch2/Reg.action就是提交一个(HttpServletRequest)...

    Struts2中Servlet的配置

    2、使用struts2提供的ActionContext类直接获取Servlet API。 在同一个项目中,如果既用到servlet又用了struts框架,运行项目时可能无法正常使用servlet,解决办法如下: 该类是定义了一个过滤器,当既用到struts2...

    struts2OGNL表达式ActionContext及valuesStack.pdf

    struts2OGNL表达式ActionContext及valuesStack.pdf

    struts2_OGNL表达式ActionContext及valuesStack

    struts2 OGNL,struts2 表达式语言,Struts2 中OGNL表达式的用法,Struts2 #,表达式语言的好处,Struts2 $,struts2 井号,星号,百分号

    Struts2 in action中文版

    1.3.2 Struts 2概览:MVC模式 10 1.3.3 Struts 2的工作原理 12 1.4 小结 14 第2章 初识Struts 2 16 2.1 声明性架构 16 2.1.1 两种配置 16 2.1.2 声明架构的两种方式 17 2.1.3 智能默认值 20 2.2 简单的HelloWorld...

    Struts2整合SiteMesh技巧

    注意ActionContextCleanUp过滤器必须在FilterDispatcher之前配置,ActionContextCleanUp的主要功能是通知FilterDispatcher执行完毕不要清除ActionContext,以便sitemesh装饰器可以访问Struts值堆栈。 配置装饰器 ...

    Struts2 学习笔记

    二、 搭建Struts2的运行环境: 5 三、 Namespace 6 四、 标签 6 五、 Action 6 六、 路径问题的说明 8 七、 Action的动态调用方法 8 八、 Action通配符(wildcard)的配置 9 九、 Action的属性接收参数 10 1、 在...

    Struts2帮助```````

    二、 搭建Struts2的运行环境: 5 三、 Namespace 6 四、 标签 6 五、 Action 6 六、 路径问题的说明 8 七、 Action的动态调用方法 8 八、 Action通配符(wildcard)的配置 9 九、 Action的属性接收参数 10 1、 在...

    struts2文件上传,与struts2-xml校验

    struts2文件上传,与xml校验 struts2文件校验可通过xml配对action的名称去校验属性的值。例如UploadAction.java中有一个book的属性。那么我可以定义一个UploadAction-validation.xml去校验这个book属性的内容。 xml的...

    Struts2通过使用ActionContext类获取request和response对象

    NULL 博文链接:https://zhouhaitao.iteye.com/blog/1126042

    struts2 标签库 帮助文档

    Struts 2 标签库(文档手册) Tags-API-CLSW-JSP &lt;%@ taglib prefix="s" uri="/struts-tags" %&gt; 就能使用struts2.0的标签库 下面就介绍每个标签的具体应用实例说明:按字母排列 A: 1. 2. &lt;s:a href=""&gt;&lt;/s:a&gt;-...

    ActionContext在struts2.0中的详细应用

    ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文可以看作是一个容器(其实我们这里的容器就是一个Map而已),它存放放的是Action在执行时需要用到的对象

    Struts2 s2-061 Poc分析1

    简介分析性。2. 已实例类的法调 (OgnlContext 中的对象),不允许调静态法idea 中可以通过 ActionContext.actionContex

    struts_2.3.12GA_API文档(chm版本)

    接口 ValidationAware 中的 setActionMessages 参数: messages - Collection of String messages (not errors). -------------------------------------------------------------------------------- ...

    Struts2 ActionContext 中的数据详解

    主要介绍了Struts2 ActionContext 中的数据详解,需要的朋友可以参考下

    struts2验证码完整实例

    (参照别人的代码) 部署: 1、将整个源码引入到MyEclipse当中. 2、部署到Tomcat下面,启动服务器,直接 敲...2、当你登录时候,提交的输入框中的验证码和session中存放的验证码比较,如果一样,则通过,不一样,则失败

Global site tag (gtag.js) - Google Analytics