valuestack,stackContext,ActionContext.之间的关系



三者之间的关系如下图所示:

relation


ActionContext 


一次Action调用都会创建一个ActionContext 
调用:ActionContext context = ActionContext.getContext() 




ValueStack 


由OGNL框架实现 
可以把它简单的看作一个List 
 

Stack Object:放入stack中的对象,一般是action。 
Stack Context(map):stack上下文,它包含一些列对象,包括request/session/attr/application map等。 
EL:存取对象的任意属性,调用对象的方法,遍历整个对象结构图。 



ActionContext是Action上下文
可以得到request session application
ValueStack是值栈 存放表单中的值
Stack Context 栈上下文 也是用来存值的



个人感觉吧,action context 是在action中通过actionSupport类来获取到,主要作用是获取request之类的对象

然后valuestack和stack context都是为了使用OGNL,其中value stack 是stack context的根对象,所以我们在JSP页面中访问value stack的内容时,是不用加#,而如果是访问stack context的其他对象则要加上#。



[首页]
[新闻]
[文章]


[登录]  [注册]




布布扣,bubuko.com 


 
首页
Web开发
Windows开发
编程语言
数据库技术
移动平台
系统服务
微信
设计
布布扣
其他
数据分析
 



首页 > 其他 > 详细



 

 

ActionContext详解

时间:2014-09-09 17:40:39      阅读:1843      评论:0      收藏:0      [点我收藏+]


标签:class   style   代码   java   html   使用   数据   com   方法  

ActionContext
    ActionContext是Action的上下文,Struts2自动在其中保存了一些在Action执行过程中所需的对象,比如session, parameters, locale等。Struts2会根据每个执行HTTP请求的线程来创建对应的ActionContext,即一个线程有一个唯一的ActionContext。因此,使用者可以使用静态方法ActionContext.getContext()来获取当前线程的ActionContext,也正是由于这个原因,使用者不用去操心让Action是线程安全的。

    无论如何,ActionContext都是用来存放数据的。Struts2本身会在其中放入不少数据,而使用者也可以放入自己想要的数据。ActionContext本身的数据结构是映射结构,即一个Map,用key来映射value。所以使用者完全可以像使用Map一样来使用它,或者直接使用Action.getContextMap()方法来对Map进行操作。

    Struts2本身在其中放入的数据有ActionInvocation、application(即ServletContext)、conversionErrors、Locale、action的name、request的参数、HTTP的Session以及值栈等。完整的列表请参考它的Javadoc(本文附录有对它包含内容的讨论)。

    由于ActionContext的线程唯一和静态方法就能获得的特性,使得在非Action类中可以直接获得它,而不需要等待Action传入或注入。需要注意的是,它仅在由于request而创建的线程中有效(因为request时才创建对应的ActionContext),而在服务器启动的线程中(比如fliter的init方法)无效。由于在非Action类中访问其的方便性,ActionContext也可以用来在非Action类中向JSP传递数据(因为JSP也能很方便的访问它)。

   ValueStack与ActionContext的联系和区别:
相同点:它们都是在一次HTTP请求的范围内使用的,即它们的生命周期都是一次请求。
不同点:值栈是栈的结构,ActionContext是映射(Map)的结构。
联系:ValueStack.getContext()方法得到的Map其实就是ActionContext的Map。查看Struts2的源代码可知(Struts2.3.1.2的org.apache.struts2.dispatcher.ng.PrepareOperations的第79行,createActionContext方法),在创建ActionContext时,就是把ValueStack.getContext()作为ActionContext的构造函数的参数。所以,ValueStack和ActionContext本质上可以互相获得。
注意:在一些文档中,会出现把对象存入“stack‘s context”的字样,其实就是把值存入了ActionContext。所以在阅读这些文档时,要看清楚,到底是放入了栈结构(即值栈),还是映射结构(值栈的context,即ActionContext)。
    如何获得ActionContext:
在自定义的拦截器中:使用ActionInvocation.getInvocationContext()或者使用ActionContext.getContext()。
在Action类中:让拦截器注入或者使用ActionContext.getContext()。
在非Action类中:让Action类传递参数、使用注入机制注入或者使用ActionContext.getContext()。注意:只有运行在request线程中的代码才能调用ActionContext.getContext(),否则返回的是null。
在JSP中:一般不需要获得ActionContext本身。
    如何向ActionContext中存入值:
在拦截器、Action类、非Action类等Java类中:使用ActionContext.put(Object key, Object value)方法。
在JSP中:标签<s:set value="..."/>默认将值存入ActionContext中(当然,<s:set>标签还可以把值存到其他地方)。另外,许多标签都有var属性(以前用的是id属性,现在id属性已被弃用),这个属性能向ActionContext存入值,key为var属性的值,value为标签的value属性的值。(有些文档写的是向ValueStack的context存入值,其实是一样的)
    如何从ActionContext中读取值:
在拦截器、Action类、非Action类等Java类中:使用ActionContext.get(Object key)方法。
在JSP中:使用#开头的Ognl表达式,比如<s:property value="#name"/>会调用ActionContext.get("name")方法。注意:如果某标签的属性默认不作为Ognl表达式解析,则需要使用%{}把表达式括起来,于是就会出现类似“%{#name}的表达式”。(“#”的更多用途参见这里)
    总之,在JSP中使用ActionContext一方面是由于它是映射结构,另一方面是能读取Action的一些配置。当你需要为许多Action提供通用的值的话,可以让每个Action都提供getXXX()方法,但更好的方法是在拦截器或JSP模板中把这些通用的值存放到ActionContext中(因为拦截器或JSP模板往往通用于多个Action)。
 
    一些例子:
Java代码 
// 本类将演示拦截器中对ActionContext的操作  
publicclass MyInterceptor extends AbstractInterceptor {  
 
    public String intercept(ActionInvocation invocation) throws Exception {  
        // 获得ActionContext  
        ActionContext actionContext = invocation.getInvocationContext();  
        // 存入值  
        Person person = new Person();  
        actionContext.put("person", person);  
        // 获取值  
        Object value = actionContext.get("person");  
        // 获取HttpServletRequest  
        HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);  
        // 获取request的Map,即HttpServletRequest.getAttribute(...)和HttpServletRequest.setAttribute(...)所操作的值 
        Map requestMap = (Map) actionContext.get("request");  
        // 其他代码  
        // ......  
        return invocation.invoke();  
    }  

Java代码 
// 本类将演示在Action中对ActionContext进行操作  
publicclass MyAction extends ActionSupport {  
 
    @Override 
    public String execute() throws Exception {  
        // 获得值栈  
        ActionContext actionContext = ActionContext.getContext();  
        // 存入值  
        Person person = new Person();// 这是之前例子中定义的类 
        actionContext.put("person", person);  
        // 获取值  
        Object object = actionContext.get("person");  
        // 其他代码  
        // ......  
        return SUCCESS;  
    }  

Html代码 
<!DOCTYPE html> 
<html> 
    <head> 
        <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"> 
        <title>JSP Page</title> 
    </head> 
    <body> 
        <!-- 本JSP将演示在JSP中对ActionContext的使用 --> 
        <!-- 本JSP为MyAction对应的JSP --> 
 
        <!-- 由于Action中已经向ActionContext存入了key为"person"的值,所以可以使用“#person”来获取它,如下  --> 
        <s:propertyvalue="#person"/> 
        <!-- 获得person的name属性,如下  --> 
        <s:propertyvalue="#person.name"/> 
        <!-- 获得Struts2在ActionContext中存入的值,比如request的Map,如下  --> 
        <s:propertyvalue="#request"/> 
        <!-- 获得Struts2在ActionContext中存入的值,比如session的Map,如下  --> 
        <s:propertyvalue="#session"/> 
        <!-- 获得Struts2在ActionContext中存入的值,request请求传递的GET参数或POST参数的Map,如下  --> 
        <s:propertyvalue="#parameters"/> 
          
        <!-- 以下演示在JSP中把值存入ActionContext中  --> 
        <!-- 存入一个字符串"myName",key为"myKey",如下 --> 
        <s:setvalue="%{‘myName‘}"var="myKey"/> 
        <!-- 使用s:bean标签来创建一个对象,并把它存入ActionContext中,key为myObject,如下  --> 
        <s:beanname="com.example.Person"var="myObject"/> 
        <!-- 之后就可以用“#”来读取它们,如下  --> 
        <s:propertyvalue="#myKey"/> 
        <s:propertyvalue="#myObject"/> 
    </body> 
</html> 

3. HttpServletRequest类或request的Map
    Struts2中提供了两种对request的操作:一种是Web服务器提供的HttpServletRequest类,这和传统Java Web项目中的操作request的方式相同;另一种是一个“request的Map”,即封装了HttpServletRequest的attributes的映射类,操作该Map相当于操作HttpServletRequest的attributes。之所以提供了Map的操作方式,一是方便操作,二是能方便使用Ognl在JSP标签中读取request。无论如何,这两个request是互通的。至于request的生命周期等概念,与其他的Java Web项目没有区别,本文不再详述。

    使用HttpServletRequest类还是request的Map
虽然两者是互通的,但就读取request的attributes而言,使用request的Map要方便许多,并且不会暴露不必要的接口。当然,HttpServletRequest有一些request的Map没有的方法,使用这些方法时当然还是要用前者。
    使用request的Map还是ActionContext:
两者都是Map,两者的生命周期都是一个请求。
传统的Java Web项目中,往往是通过request的attributes来向JSP传递值的:先在Servlet里setAttribute(),然后在JSP里getAttribute()。当然在Struts2的项目中,你仍然可以使用这个方法,然而抛弃了Struts2提供的传递功能是得不偿失的。虽然笔者没有找到官方文档说一定要用ActionContext替换request的Map,也没有发现程序中有能获得ActionContext却获得不了request的Map的地方,但在Struts2框架下,操作ActionContext要比操作request的Map更加方便。因此,笔者建议:尽量使用ActionContext而不是request的Map来传递值。
request的Map有时候会包含其他框架设置的值,比如Spring框架。获取这些值的时候就需要用request的Map了,因为ActionContext里没有。
通过ActionContext可以获得HttpServletRequest类:“HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);”。
通过ActionContext也可以获得request的Map:“Map requestMap = (Map) actionContext.get("request");”。因此,在JSP标签中,使用表达式“#request”就可以获得request的Map的数据。
    如何获得HttpServletRequest:
如果已经有ActionContext,则使用“actionContext.get(StrutsStatics.HTTP_REQUEST)”来获得HttpServletRequest。
在自定义的拦截器中,先获得ActionContext,再通过ActionContext来获得。
在Action中,先获得ActionContext,再通过ActionContext来获得。或者让Action实现ServletRequestAware接口,并使用ServletConfigInterceptor拦截器,这样这个拦截器就会注入HttpServletRequest。
在JSP中,一般不需要获得HttpServletRequest。
    如何获得request的Map:
如果已经有ActionContext,则使用“actionContext.get("request")”来获得。
在自定义的拦截器中,先获得 ActionContext,再通过ActionContext来获得。
在Action中,先获得ActionContext,再通过ActionContext来获得。或者让Action实现RequestAware接口,并使用ServletConfigInterceptor拦截器,这样这个拦截器就会注入Map request。
在JSP中,用“#request”来获得request的Map,用“#request.key”或者“#request[‘key‘]”来读取Map中的值。
    总之,request仍然符合Java Web网站的一般规律。不过笔者建议使用者应尽量避免用request传值。

    一些例子:

Java代码 
// 本类将演示拦截器中对HttpServletRequest和request的Map的操作  
publicclass MyInterceptor extends AbstractInterceptor {  
 
    public String intercept(ActionInvocation invocation) throws Exception {  
        // 获得ActionContext  
        ActionContext actionContext = invocation.getInvocationContext();  
        // 获得HttpServletRequest  
        HttpServletRequest httpServletRequest=(HttpServletRequest)actionContext.get(StrutsStatics.HTTP_REQUEST);  
        // 获得request的Map  
        Map requestMap = (Map) actionContext.get("request");  
        // 创建一个类作为实例  
        Person person = new Person();  
        // 以下两行的语句作用相同  
        httpServletRequest.setAttribute("person", person);  
        requestMap.put("person", person);  
        // 其他代码  
        // ......  
        return invocation.invoke();  
    }  

Java代码 
// 本类将演示在Action中对HttpServletRequest和request的Map进行操作(静态方法获得ActionContext) 
publicclass MyAction extends ActionSupport {  
 
    @Override 
    public String execute() throws Exception {  
        // 获得ActionContext  
        ActionContext actionContext = ActionContext.getContext();  
        // 获得HttpServletRequest  
        HttpServletRequest httpServletRequest=(HttpServletRequest)actionContext.get(StrutsStatics.HTTP_REQUEST);  
        // 获得request的Map  
        Map requestMap = (Map) actionContext.get("request");  
        // 创建一个类作为实例  
        Person person = new Person();  
        // 以下两行的语句作用相同  
        httpServletRequest.setAttribute("person", person);  
        requestMap.put("person", person);  
        // 其他代码  
        // ......  
        return SUCCESS;  
    }  

Java代码 
// 本类将演示在Action中使用ServletRequestAware获得HttpServletRequest(注意:要使用ServletConfigInterceptor拦截器) 
publicclass MyAction extends ActionSupport implements ServletRequestAware {  
 
    private HttpServletRequest request;  
      
    //此方法是接口ServletRequestAware的方法  
    publicvoid setServletRequest(HttpServletRequest request) {  
        this.request = request;  
    }  
 
    @Override 
    public String execute() throws Exception {  
        // HttpServletRequest已在该类的字段中准备好,可直接使用 
        // ......  
        return SUCCESS;  
    }  

Java代码 
// 本类将演示在Action中使用ServletRequestAware获得request的Map(注意:要使用ServletConfigInterceptor拦截器) 
publicclass MyAction extends ActionSupport implements RequestAware {  
 
    Map<String, Object> request;  
 
    // 该方法是接口RequestAware的方法  
    publicvoid setRequest(Map<String, Object> request) {  
        this.request = request;  
    }  
 
    @Override 
    public String execute() throws Exception {  
        // request的Map已在该类的字段中准备好,可直接使用  
        // ......  
        return SUCCESS;  
    }  

Java代码 
<!DOCTYPE html>  
<html>  
    <head>  
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
        <title>JSP Page</title>  
    </head>  
    <body>  
        <!-- 本JSP将演示在JSP中对request的Map的使用 -->  
        <!-- 本JSP为MyAction对应的JSP -->  
 
        <!-- request的Map是Struts2自动在ActionContext中存入的值(key为request),所以使用“#”来访问ActionContext,从中读取request  -->  
        <s:property value="#request"/>  
        <!-- 以下两行均是访问request的Map中key为“name”的值  -->  
        <s:property value="#request.name"/>  
        <s:property value="#request[‘name‘]"/>  
    </body>  
</html> 

3. Parameters,即GET请求或POST请求的参数
    Parameters为GET或POST等请求时浏览器向服务器传递而来的参数。在传统的Java Web项目中,使用HttpServletRequest.getParameter()等方法来获取参数,并且可以直接使用HttpServletRequest.getParameterMap()来获得一个封装了参数的Map。而在Struts2中,Struts2直接把上述Map存放到了ActionContext中,key为“parameters”。另外,ActionContext还直接提供了ActionContext.getParameters()方法来获得这个Map。因此,在Struts2的各个部件中操作parameters的方法和操作request的Map的方法十分相似,本段不再详述。
4. HttpServletSession类和session的Map
    传统Java Web项目中的session是我们都熟悉的,我们用它来记录一个用户的会话状态。Struts2把HttpServletSession封装到了一个Map中,即“session的Map”,这类似对request的处理。然而为了节省系统资源,我们在不需要session的时候不会创建session。可能正是因为这个缘故,Struts2中没有把HttpServletSession放入ActionContext中,如果你的程序需要使用HttpServletSession,应该先获得HttpServletRequest,然后使用getSession()或getSession(boolean b)来获得它,同时决定是否需要创建session。对于session的Map,Struts2仍然把它放入了ActionContext中(key为"session"),但是不要担心,这个Map的机制使得只有put新值时才会创建session。总之,Struts2中对HttpServletSession的操作要先通过HttpServletRequest来获得它,而对session的Map的操作与对request的Map的操作如出一辙,本段不再详述。
5. ServletContext和application的Map
    传统的Java Web项目中,ServletContext用来存放全局变量,每个Java虚拟机每个Web项目只有一个ServletContext。这个ServletContext是由Web服务器创建的,来保证它的唯一性。ServletContext有一些方法能操作它的attributes,这些操作方法和操作一个Map类似。于是,Struts2又来封装了:它把ServletContext的attributes封装到了一个Map中,即“application的Map”,并且也放入的ActionContext中(key为application),因此,对application的Map的操作就如果对request的Map操作,本段不再详述。
    至于对ServletContext的操作,与HttpServletRequest的操作类似:Struts2将ServletContext放到了 ActionContext中,并且ServletConfigInterceptor提供了对ServletContext的注入接口ServletContextAware。因此,本段不再详述。
    注意:在Ognl表达式中使用“#application”可以得到application的Map,而不是ServletContext。然而在JSP嵌入的Java代码中(比如“<% application.getAttribute(""); %>”),application为ServletContext,而不是Map。

 

ActionContext详解

标签:class   style   代码   java   html   使用   数据   com   方法  
 



(0)


(1)



    

举报


   

   



评论

一句话评论(0)


共0条  




 

登录后才能评论! 
 


 


   
 
   


分享档案

更多>


2015年12月05日 (1216)
 2015年12月04日 (2383)
 2015年12月03日 (2446)
 2015年12月02日 (2378)
 2015年12月01日 (1974)
 2015年11月30日 (2179)
 2015年11月29日 (1976)
 2015年11月28日 (1895)
 2015年11月27日 (2540)
 2015年11月26日 (2374)



文章周排行

更多>


1.史上最详细的CocoaPods安装教程  2014-10-23
2. "The identity used to sign the executable is no longer valid"错误解决方法  2015-07-20
3.利用Wireshark截取数据包,并对数据包进行解析  2014-05-10
4. Xcode7 真机调试步骤以及遇到的问题解决办法  2015-07-20
5.常用浏览器user_agent大全  2015-05-10
6.升级Xcode之后VVDocumenter-Xcode不能用的解决办法  2015-06-18
7.学习笔记:Caffe上配置和运行MNIST  2015-06-05
8. Xcode插件之Alcatraz的安装和遇到的问题  2015-05-08
9. markdown 语法之字体、字号、颜色以及背景色  2015-05-25
10. setOnPageChangeListener 过时了怎么办?  2015-07-23


最新新闻

更多


1. 《光环:守护者》12月免费DLC内容详情公开  2015-12-05
2.传雅虎董事会未就剥离阿里股份作出决定  2015-12-05
3.美快餐连锁Chipotle大肠杆菌疫情扩大至9州  2015-12-05
4.三星移动换帅自救 新掌门人称明年会很艰难  2015-12-05
5. PS4首批PS2游戏名单公布 画质猛增  2015-12-05
6. Steam人民币商店给力促销:年度大作半价  2015-12-05
7. [视频]看看孩子们对电子宠物机Tamagotchi的反应如何  2015-12-05
8.游戏制作人怒喷科乐美!小岛秀夫被限行事件持续发酵  2015-12-05
9. IBM推Swift Sandbox网页工具 可直接编写Swift代码  2015-12-05
10. URL地址错误让人误以为扎克伯格已从Facebook“离职”  2015-12-05

   

 

  


 

 
   



友情链接

国之画  cnbeta    CSDN   博客园   百度统计   站长统计  
阳和移动开发   汇智网    易捷博客网    天码营    HarriesBlog    程序员客栈    情怀   



关于我们 - 联系我们 - 留言反馈

© 2014 bubuko.com 版权所有 鲁ICP备09046678号-4

打开技术之扣,分享程序人生!

               
 鲁公网安备 37021202000002号
 



 


 

 


关闭




关闭


 
   












  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值