前面已经了解到ActionContext是Action执行时的上下文,里面存放着Action在执行时需要用到的对象,我们也称之为广义值栈。

Struts2在每次执行Action之前都会创建新的ActionContext,在同一个线程里ActionContext里面的属性是唯一的,这样Action就可以在多线程中使用。

1:ActionContext的线程安全性

那么Struts2是如何保证ActionContext的线程安全性呢?

看看ActionContext对象的代码,示例如下:

1
2
3
4
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里面就有。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
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的静态方法就可以获取到相应的对象。示例如下:

java代码:

1
2
3
4
5
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接口,示例代码如下:

java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
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。

(转)ActionContext和ServletActionContext的更多相关文章

  1. ActionContext和ServletActionContext区别

    1. ActionContext 在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息, ...

  2. 【struts2】ActionContext与ServletActionContext

    1 再探ActionContext 我们知道,ActionContext是Action执行时的上下文,里面存放着Action在执行时需要用到的对象,也称之为广义值栈.Struts2在每次执行Actio ...

  3. Struts2中ActionContext及ServletActionContext介绍(转载)

    1. ActionContext 在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息, ...

  4. ActionContext和ServletActionContext小结(转)

    ActionContext和ServletActionContext小结 1. ActionContext 在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Act ...

  5. Struts中ActionContext和ServletActionContext的比较

    一.ActionContext在Struts2开发中除了将请求参数自动设置到Action的字段中,往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息,甚至需要直 ...

  6. ActionContext和ServletActionContext小结

    1. ActionContext 在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息, ...

  7. ActionContext 与 ServletActionContext获取Session的异同

    1. ActionContext 在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息, ...

  8. Struts2中ActionContext和ServletActionContext

    转自:http://blog.sina.com.cn/s/blog_6c9bac050100y9iw.html 在Web应用程序开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在A ...

  9. Actioncontext跟ServletActionContext的区别---未完待续

    //public class BaseAction extends ActionSupport{ public static HttpServletRequest getRequest(){ retu ...

随机推荐

  1. 这是通过 Open Live Writer(是个博客编辑器) 发布的

    Open Live Writer  是开源的win10上的博客编辑器

  2. derby

    /** * @Title: T.java * @Package test * @Description: TODO please write your description <BR> * ...

  3. [转]jquery 鼠标放在图片上显示图片的放大镜效果jqzoom_ev-2.3

    本文转自:http://blog.csdn.net/weizengxun/article/details/6768183 鼠标放在图片上显示图片的放大镜效果使用jqzoom实现,本例版本2.3 效果图 ...

  4. Murano Weekly Meeting 2016.05.17

    Meeting time: 2016.May.17 1:00~2:00 Chairperson:  Kirill Zaitsev, from Mirantis Meeting summary:   1 ...

  5. 织梦更新列表页提示Fatal error: Call to a member function GetInnerText() on a non-object 解决方法

    今天在做一个站时用到了自定义模型,遇到了些问题,在更新列表页时提示: Fatal error: Call to a member function GetInnerText() on a non-ob ...

  6. OAuth2.0和企业内部统一登录,token验证方式,OAuth2.0的 Authorization code grant 和 Implicit grant区别

    统一登录是个很多应用系统都要考虑的问题,多个项目的话最好前期进行统一设计,否则后面改造兼容很麻烦: cas认证的方式:新公司都是老项目,用的是cas认证的方式,比较重而且依赖较多,winform的项目 ...

  7. mysql 将null转代为0(转)

    1.如果为空返回0 select ifnull(null,0) 2.如果为空返回0,否则返回1 select if(isnull(col),0,1) as col. MYSQL 中的IFNULL函数 ...

  8. JavaScript 函数 (function)

    //声明(有参数.有返回值) function fun() { var name = '小黑'; ) { name = arguments[]; //接受参数 } alert(name); retur ...

  9. Android Process & Thread

    Native Service and Android Service Native Service:In every main() method of NativeService, which is ...

  10. 将Android工程打成jar包之后对资源的调用。

    Android工程不能完整的打包成jar包.这个主要是R文件导致的,但是我们可以将除了资源文件中的所有东西都打到jar包中.Activity.View等等类. 提供jar包的同时,还需要提供资源文件. ...