ActionContext和ServletActionContext

原创 2016年06月01日 15:27:55

ActionContextAction执行时的上下文,里面存放着Action在执行时需要用到的对象,我们也称之为广义值栈
Struts2在每次执行Action之前都会创建新的ActionContext,在同一个线程里ActionContext里面的属性是唯一的,这样Action就可以在多线程中使用。
1:ActionContext的线程安全性
那么Struts2是如何保证ActionContext的线程安全性呢?
看看ActionContext对象的代码,示例如下:

public class ActionContext implements Serializable {  
static ThreadLocal actionContext = new ThreadLocal();  
……  
}

ThreadLocal又称为“线程局部变量”,它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。
存放在ActionContext里的数据都存放在这个ThreadLocal的属性中,而这个属性只会在对应的当前请求线程中可见,从而保证数据是线程安全的。
2:访问的是Map

回顾前面在使用ActionContext来访问Session中数据的程序,你会发现,其实在程序里面访问的是一个Map,而非HttpSession对象,这是为什么呢?

   原来,Struts2框架将与Web相关的很多对象重新进行了包装,比如将HttpSession对象重新包装成了一个Map对象,里面存放着Session中的数据,提供这个Map给Action使用,而不用Action直接和底层的HttpSession打交道。也正是因为框架的包装,让Action可以完全的和Web层解耦。

   但是要注意一点,ActionContext不能在普通的Java应用程序中使用。

在以前的学习中,介绍了Action和Servlet API是解耦的,因此可以在Java应用程序中调用Action的execute方法来进行测试。但是如果使用了ActionContext来获取session数据,那么就不能这样运行了。因为ActionContext包装的都是Web的数据,在Java应用程序中运行的时候,没有Web的环境和响应的数据,因而会抛出空指针的异常。

访问其它的Web对象的值也是与此类似的,你通过ActionContext去访问的都是包装后的Map。

3:使用SessionAware接口

Struts2还提供另外一种简单的方式,使用SessionAware接口来访问存储于ActionContext中的数据,该接口通过使用IoC/DI来为Action注入Session Map,就可以在程序里面直接使用这个Map来操作数据了。

(1)在Action中不再需要访问ActionContext了,取而代之,Action实现SessionAware接口,该接口告知Struts2在Action执行之前要设置Session Map,是通过servletConfig 拦截器来实现的,这个拦截器在defaultStack里面就有。示例代码如下:

public class OgnlAction extends ActionSupport implements SessionAware{  
    private Map<String, Object> session;  
    @Resource
    public void setSession(Map<String, Object> session) {  
        this.session = session;  
    }  

    public String execute(){  
        session.put("sessionTestKey", "测试SessionAware");  
        return this.SUCCESS;  
    }  
}
**Action类实现SessionAware接口**
这个接口要求Action类实现一个方法setSession(Map<String, Object> session),通过这个方法注入Session的数据
在execute方法中,通过这个私有属性就可以操作会话中的数据,注意一点,这个Map中的值也是与HttpSession联动的。

为了能够在普通的Java应用中运行并测试Action,推荐大家使用SessionAware的方式来访问HttpSession。因为这样一来,在通过main方法运行或测试的时候,可以直接调用setSession方法,传入模拟的会话数据,就不会出现execute方法中抛出空指针的异常了。
因此,推荐大家使用SessionAware的方式来访问HttpSession 4:使用其它包装接口

跟SessionAware类似,你可以使用RequestAware来获取包装请求对象的attribute中的值的Map;使用ApplicationAware来获取包装ServletContext对象的attribute中的值的Map;使用ParameterAware来获取包装请求对象的参数中的值的Map,等等,这里只罗列这几个常见和常用的,还有更多的请参见Struts2的API文档。
在实际应用开发中,光是获取数据就够了吗?答案显然是否定的,有些时候,根据功能需要,在Action中必须要能获取到Servlet相关的API,比如要操作Cookie。这个时候,就需要用ServletActionContext了。

1:ServletActionContext概述

这个类直接继承了ActionContext,当然也继承了它父类的很多功能,比如:对OgnlValueStack、Action名字等的访问。更重要的是,它还提供了直接访问Servlet的相关对象的功能,它可以取得的对象有:

**HttpServletRequest:请求对象
HttpServletResponse:响应对象
ServletContext:Servlet上下文信息
PageContext:Http页面上下文**

2:基本使用
直接使用ServletActionContext的静态方法就可以获取到相应的对象。示例如下:

HttpServletRequest request = ServletActionContext.getRequest();  
HttpServletResponse response = ServletActionContext.getResponse();  
ServletContext servletContext = ServletActionContext.getServletContext();  
PageContext pageContext = ServletActionContext.getPageContext();  
HttpSession session = ServletActionContext.getRequest().getSession();

这里要注意的是HttpSession对象的获取,是在取得HttpRequest对象过后,通过HttpRequest对象来获取会话对象。当然,取得相应的对象后,就直接使用这些对象的方法来进行开发,这里就不去赘述了
3:通过IoC/DI的方式来获取相应的Servlet对象

   还可以通过IoC/DI的方式来获取相应的Servlet对象,对应关系是:

ServletRequestAware:通过这个接口来获取HttpServletRequest对象
ServletResponseAware:通过这个接口来获取HttpServletResponse对象

用ServletRequestAware来示例一下。

(1)修改Action,让其实现ServletRequestAware接口,示例代码如下:

public class OgnlAction extends ActionSupport implements ServletRequestAware{  
    private HttpServletRequest request = null;  
    @Resource
    public void setServletRequest(HttpServletRequest request) {  
        this.request = request;  
    }  

    public String execute(){          
        request.setAttribute("request", "Request的属性值");  
        request.getSession().setAttribute("sessionTestKey", "测试SessionAware");  
        return this.SUCCESS;  
    }     
}

ActionContext和ServletActionContext

根据前面的讲述,你会发现,ActionContext和ServletActionContext有着一些重复的功能,都能够获取到Web对象的数据,但是又有些不同。

   通常情况下,可以这么认为:ActionContext主要负责值的操作;ServletActionContext主要负责获取Servlet对象。

那么在Action中,该如何去抉择呢?建议的原则是:

优先使用ActionContext
只有ActionContext不能满足功能要求的时候,才使用ServletActionContext

总之,要尽量让Action与Web无关,这对于Action的测试和复用都是极其有好处的。

   另外还有一点需要注意:在使用ActionContext时,不要在Action的构造函数里使用ActionContext.getContext(),因为这个时候ActionContext里的一些值也许还没有设置,这时通过ActionContext取得的值也许是null。
版权声明:本文为博主原创文章,未经博主允许不得转载。

关于在Struts2中ActionContext是何时创建的

首先我们要知道ActionContext是线程安全的,在每次执行Action之前都会创建新的ActionContext,也就是说在同一个线程里ActionContext里的属性是唯一的,这样我的Act...
  • u011496144
  • u011496144
  • 2017年07月10日 17:03
  • 334

struts2框架中ActionContext对象详解

一、了解OGNL表达式:       (1) Object Graphic Navigation language(对象图形导航语言)的缩写,它是一种功能性极强的表达式语言,使用它可以存取任意属性,调...
  • super_YC
  • super_YC
  • 2017年03月12日 21:07
  • 1984

struts中的action和Action类以及struts2中如何在Action类中获得servlet api的域对象

1.Struts2的学习中大家都会遇到action和与action对应的Action类,那么什么是action什么是action对应的Action类呢? 例如struts.xml的配置文件如下: ...
  • nihaowoshiyudong
  • nihaowoshiyudong
  • 2016年12月30日 10:37
  • 1092

关于ActionContext.getContext()取得的值是什么,和struts2如何获取request,session,appliaction作用域

关于ActionContext.getContext()取得的值,和struts2如何获取request,session,appliaction作用域...
  • u011768325
  • u011768325
  • 2015年05月13日 11:02
  • 2127

从struts2的action中看ActionContext的存储结构

本篇将建立测试用例,在action中以打断点的形式查看ActionContext中的数据结构。 不管多线程的情况,就以当前线程来说 一、预先了解 在ActionConext中,每一个线程都有一些数...
  • q291611265
  • q291611265
  • 2015年08月05日 21:05
  • 1546

Action Context中值栈(value Stack )栈上下文(Stack context)的个人理解

Action Context就是Stack Context栈上下文; Stack Context、ActionContext或者OGNL上下文都是一个东西:Ognl.getValue(exp,con...
  • itelyder
  • itelyder
  • 2015年10月20日 00:22
  • 3006

简单的访问计数器

思路:表单每次访问action,就会把上下文中的counter参数加一,jsp文件用来显示次数 LoginAction.java文件内容 package action; import com.o...
  • u010513756
  • u010513756
  • 2015年09月18日 16:06
  • 3849

Struts2中ActionContext、Ognlcontext、OgnlValueStack对象关系图,ognl表达式根元素分析

关系图: Action: public String execute() throws Exception{ List list = new ArrayList(); List li...
  • zyw23zyw23
  • zyw23zyw23
  • 2017年05月25日 18:46
  • 328

ActionContext上下理解:

ActionContext上下理解
  • qq_39491642
  • qq_39491642
  • 2017年12月15日 14:09
  • 14

为什么el中能访问action的属性

今天一个哥们学习struts2,尝试使用OGNL,由于关联性吧,就又跳到EL上面,结果神奇的事情发生,他用EL表达式从request域里面居然拿到了action钟的属性,这个天崩地裂的,大家都知道st...
  • Marvel__Dead
  • Marvel__Dead
  • 2017年03月02日 22:14
  • 888
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ActionContext和ServletActionContext
举报原因:
原因补充:

(最多只允许输入30个字)