在web开发中ActionContext和ServletActionContext的比较

来源:互联网 发布:我知谁掌管明天 背景 编辑:程序博客网 时间:2024/05/01 22:05

1.ActionContext

ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文可以看作是一个容器(其实我们这里的容器就是一个Map而已),它存放的是Action在执行时需要用到的对象。也称之为广义值栈。Struts2在每次执行Action之前都会创建新的ActionContext,在同一个线程里ActionContext里面的属性是唯一的,这样Action就可以在多线程中使用。

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

actionContext对象的创建过程是

<span style="font-size:14px;">static ThreadLocal actionContext = new ActionContextThreadLocal()。</span>
ActionContextThreadLocal是实现ThreadLocal的一个内部类。ThreadLocal可以命名为"线程局部变量",它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。这样ActionContext里的属性只会在对应的当前请求线程中可见,从而保证它是线程安全的。

1.1.ActionContext的线程安全性

ThreadLocal又称为“线程局部变量”,它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

存放在ActionContext里的数据都存放在这个ThreadLocal的属性中,而这个属性只会在对应的当前请求线程中可见,从而保证数据是线程安全的。

1.2.通过ActionContext取得相关对象

取得session:Map session = ActionContext.getContext().getSession();
取得request:Map request = (Map)ActionContext.getContext().get("request");
在Action中取得request请求参数"username"的值:
若有一个提交过来的username,那么通过param.get("username")可以取值。值得注意的是param.get("username")是一个String数组,Struts就是这样设计的。既然是String数组就需要这样取值:

<span style="font-size:14px;">String value[] = (String[])param.get("username");String username = "";for(int i=0;i<value.length;i++){ username +=value[i];}</span>

2.ServletActionContext概述

在实际应用开发中,光是获取数据就够了吗?答案显然是否定的,有些时候,根据功能需要,在Action中必须要能获取到Servlet相关的API,比如要操作Cookie。这个时候,就需要用ServletActionContext了。

2.1 ServletActionContext概述

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

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

2.2 基本使用

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

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

2.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;        public void setServletRequest(HttpServletRequest request) {          this.request = request;      }            public String execute(){                  request.setAttribute("request", "Request的属性值");          request.getSession().setAttribute("sessionTestKey", "测试SessionAware");          return this.SUCCESS;      }     }  

(2)对应的结果页面也需要稍作修改,要把Action中设置的值显示出来,示例如下:

<%@ taglib prefix="s" uri="/struts-tags"%>  Request的属性值:<s:property value="#request['request']"/>  <br>  会话的属性值:<s:property value="#session['sessionTestKey']"/>  

  当然,你也可以以同样的方式去使用ServletResponseAware,这里就不去赘述了。

3. ActionContextServletActionContext

  根据前面的讲述,你会发现,ActionContext和ServletActionContext有着一些重复的功能,都能够获取到Web对象的数据,但是又有些不同。通常情况下,可以这么认为:ActionContext主要负责值的操作;ServletActionContext主要负责获取Servlet对象。那么在Action中,该如何去抉择呢?建议的原则是:

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

  总之,要尽量让Action与Web无关,这对于Action的测试和复用都是极其有好处的。另外还有一点需要注意:在使用ActionContext时,不要在Action的构造函数里使用ActionContext.getContext(),因为这个时候ActionContext里的一些值也许还没有设置,这时通过ActionContext取得的值也许是null。


0 0