访问request、session和application对象

本文转载自:http://ajava.org/readbook/open/struts2/4346.html

 

在传统的Web开发中,经常会用到Servlet API中的HttpServletRequest、HttpSession和ServletContext。Struts 2框架让我们可以直接访问和设置action及模型对象的数据,这降低了对HttpServletRequest对象的使用需求,但在某些应用中,我们可能会需要在action中去访问HttpServletRequest对象以及其他两种对象,例如,用户登录成功后,我们应该将用户信息保存到Session中。

Struts 2提供了多种方式来访问上述的三种对象,归结起来,可以划分为两大类:与Servlet API解耦的访问方式和与Servlet API耦合的访问方式。

3.4.1  与Servlet API解耦的访问方式
为了避免与Servlet API耦合在一起,方便Action类做单元测试,Struts 2对HttpServletRequest、HttpSession和ServletContext进行了封装,构造了三个Map对象来替代这三种对象,在Action中,直接使用HttpServletRequest、HttpSession和ServletContext对应的Map对象来保存和读取数据。

要获取这三个Map对象,可以使用com.opensymphony.xwork2.ActionContext类(参看第4章4.2节)。

ActionContext是action执行的上下文,在ActionContext中保存了action执行所需的一组对象,包括parameters、request、session、application和locale等。ActionContext类定义了如下方法,用于获取HttpServletRequest、HttpSession和ServletContext对应的Map对象。

Ø  public Object get(Object key)ActionContext类没有提供类似getRequest()这样的方法来获取封装了HttpServletRequest的Map对象。要得到请求Map对象,你需要为get()方法传递参数“request”。

Ø  public Map getSession()获取封装了HttpSession的Map对象。

Ø  public Map getApplication()获取封装了ServletContext的Map对象。

我们看例3-11。

例3-11  通过ActionContext来获取request、session和application对象的LoginAction1

package org.sunxin.struts2.ch03.action.way1;

import java.util.Map;

import org.sunxin.struts2.ch03.model.User;

import com.opensymphony.xwork2.Action;

import com.opensymphony.xwork2.ActionContext;

public class LoginAction1 implements Action

{  

  private User user;

 

  public User getUser()

  {

    return user;

  }

  public void setUser(User user)

  {

    this.user = user;

  }

  @SuppressWarnings("unchecked")

  @Override

  public String execute() throws Exception

  {

    if("zhangsan".equals(user.getUsername())

&& "1234".equals(user.

getPassword()))

    {

      ActionContext context = ActionContext.getContext();

      Map request = (Map)context.get("request");

      Map session = context.getSession();

      Map application = context.getApplication();

     

      //在请求中放置欢迎信息。

      request.put("greeting", "欢迎您来到程序员之家");

     

      //在session中保存user对象

      session.put("user", user);

     

      //统计用户访问量,在application中保存用户访问量数据

      Integer count = (Integer)application.get("counter");

      if(null == count)

        count=1;

      else

        count++;

      application.put("counter", count);

     

      return SUCCESS;

    }

    else

    {

      return ERROR;

    }

  }

}

在成功页面中,可以使用JSP内置的表达式语言来访问request、session和application范围的数据,代码如例3-12所示。
例3-12  success.jsp

<%@ page contentType="text/html;charset=GBK" %>

<html>

    <head><title>欢迎页面</title></head>

    <body>

        <h3>${sessionScope.user.username},${requestScope.greeting}。<br>

        本站的访问量是:${applicationScope.counter}</h3>

    </body>

</html>

如果页面能够正常显示我们保存在request、session和application对象中的数据(当然是能够正常显示的,要不然笔者也不会给出这个例子了。☺),就说明在Action中,对ActionContext返回的Map对象的操作,等价于对Servlet API中的HttpServletRequest、HttpSession和ServletContext对象的操作。
完整的代码请参看本书配套光盘中的ch03_4目录,测试时,输入URL:
http://localhost:8080/ch03_4/login1.jsp

利用请求对象来传递数据还有一种方式,你可以直接使用ActionContex类的put()方法将数据保存到ActionContext中,如下:

ActionContext.getContext().put("greeting", "欢迎您来到http://www. sunxin.org");

然后在结果页面中,从请求对象中取出greeting属性,如下:

${requestScope.greeting} 或者 <%=request.getAttribute("greeting")%>

ActionContext中保存的数据能够从请求对象中得到,这让人太不可思议了。其中的奥妙就在于Struts 2中的org.apache.struts2.dispatcher.StrutsRequestWrapper类,这个类是HttpServletRequest的包装类,它重写了getAttribute()方法(在页面中获取request对象的属性就要调用这个方法),在这个方法中,它首先在请求对象中查找属性,如果没有找到(如果你在ActionContext中保存数据,当然就找不到了),则到ActionContext中去查找。这就是为什么在ActionContext中保存的数据能够从请求对象中得到的原因。

当然具体的实现还有很多细节,感兴趣的读者可以跟踪一下Struts 2的源代码。

除了利用ActionContext来获取request、session和application对象这种方式外,Action类还可以实现某些特定的接口,让Struts 2框架在运行时向Action实例注入request、session和application对象。与之对应的三个接口和它们的方法如下所示:
Ø  org.apache.struts2.interceptor.RequestAware框架利用该接口,向Action实例注入request Map对象。该接口只有一个方法,如下:

—  public void setRequest(Map request)

Ø  org.apache.struts2.interceptor.SessionAware框架利用该接口,向Action实例注入session Map对象。该接口只有一个方法,如下:

—  void setSession(Map session)

Ø  org.apache.struts2.interceptor.ApplicationAware框架利用该接口,向Action实例注入application Map对象。该接口只有一个方法,如下:

—  void setApplication(Map application)

我们看例3-13。

例3-13  通过接口注入来获取request、session和application对象的LoginAction2

package org.sunxin.struts2.ch03.action.way1;

import java.util.Map;

import org.apache.struts2.interceptor.ApplicationAware;

import org.apache.struts2.interceptor.RequestAware;

import org.apache.struts2.interceptor.SessionAware;

import org.sunxin.struts2.ch03.model.User;

import com.opensymphony.xwork2.Action;

public class LoginAction2 implements Action, RequestAware, SessionAware, ApplicationAware

{  

  private Map request;

  private Map session;

  private Map application;

 

  …

  @SuppressWarnings("unchecked")

  @Override

  public String execute() throws Exception

  {

    if("zhangsan".equals(user.getUsername())

&& "1234".equals(user.

getPassword()))

    {

      //在请求中放置欢迎信息。

      request.put("greeting", "欢迎您来到程序员之家");

     

      //在session中保存user对象

      session.put("user", user);

     

      //统计用户访问量,在application中保存用户访问量数据

      Integer count = (Integer)application.get("counter");

      if(null == count)

        count=1;

      else

        count++;

      application.put("counter", count);

     

      return SUCCESS;

    }

    else

    {

      return ERROR;

    }

  }

  @Override

  public void setRequest(Map request)

  {

    this.request = request;

  }

  @Override

  public void setSession(Map session)

  {

    this.session = session;

  }

  @Override

  public void setApplication(Map application)

  {

    this.application = application;

  }

}

LoginAction2类实现了RequestAware、SessionAware和ApplicationAware接口,框架在运行时会调用这三个接口中的方法,向LoginAction2注入request、session和application对象。在execute()方法中不再需要访问ActionContext,因此我们删除了与之相关的代码。
登录成功页面无须改动。

完整的代码请参看本书配套光盘中的ch03_4目录,测试时,输入URL:
http://localhost:8080/ch03_4/login2.jsp

虽然利用Struts 2提供的request、session和application对象就可以对HttpServletRequest、HttpSession和ServletContext对象中的数据进行操作,但它们毕竟是Map类型,如果我们需要调用HttpServletRequest、HttpSession和ServletContext中的特定操作,例如获取请求方法的名字(调用HttpServletRequest中的getMethod()方法),那么可以使用下一节介绍的方式来获取Servlet环境中的对象。
3.4.2  与Servlet API耦合的访问方式
直接访问Servlet API将使你的Action与Servlet环境耦合在一起,我们知道对于HttpServletRequest、HttpServletResponse和ServletContext这些对象,它们都是由Servlet容器来构造的,与这些对象绑定在一起,测试时就需要有Servlet容器,不便于Action的单元测试。但有时候,我们又确实需要直接访问这些对象,那么当然是以完成任务需求为主。

要直接获取HttpServletRequest和ServletContext对象,可以使用org.apache.struts2. ServletActionContext类,该类是ActionContext的子类,在这个类中定义下面两个静态方法:

Ø  public static HttpServletRequest getRequest()得到HttpServletRequest对象。

Ø  public static ServletContext getServletContext()得到ServletContext对象。

此外,ServletActionContext类还给出了获取HttpServletResponse对象的方法,如下:

Ø  public static HttpServletResponse getResponse()ServletActionContext类并没有给出直接得到HttpSession对象的方法,HttpSession对象可以通过HttpServletRequest对象来得到。

除了上述的方法调用得到HttpServletRequest和ServletContext对象外,还可以调用ActionContext对象的get()方法,传递ServletActionContext.HTTP_REQUEST和ServletActionContext.SERVLET_CONTEXT键值来得到HttpServletRequest和ServletContext对象,如下所示:

Ø  ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);得到与ServletActionContext.HTTP_REQUEST键值绑定的HttpServletRequest对象。

Ø  ActionContext.getContext().get(ServletActionContext.SERVLET_CONTEXT);得到与ServletActionContext.SERVLET_CONTEXT键值绑定的ServletContext对象。

同样的,也可以向ActionContext的get()方法传递ServletActionContext.HTTP_ RESPONSE键值来得到HttpServletResponse对象,如下:

Ø  ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE);建议读者采用第一种方式来获取HttpServletRequest和ServletContext对象,这样简单而又清晰。

我们看例3-14。

例3-14  通过ServletActionContext来获取HttpServletRequest和ServletContext对象的LoginAction3

package org.sunxin.struts2.ch03.action.way2;

import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import org.sunxin.struts2.ch03.model.User;

import com.opensymphony.xwork2.Action;

public class LoginAction3 implements Action

{  

  ...

  @Override

  public String execute() throws Exception

  {

    if("zhangsan".equals(user.getUsername())

&& "1234".equals(user.

getPassword()))

    {

      HttpServletRequest request = ServletActionContext.getRequest();      

      HttpSession session = request.getSession();

      ServletContext context = ServletActionContext.getServletContext();

     

      /*ActionContext ctx = ActionContext.getContext();

      HttpServletRequest request = (HttpServletRequest)ctx.get(Servlet ActionContext.HTTP_REQUEST);       

      HttpSession session = request.getSession();

      ServletContext context = (ServletContext)ctx.get(ServletAction Context. SERVLET_CONTEXT);*/

     

      //在请求中放置欢迎信息。

      request.setAttribute("greeting", "欢迎您来到程序员之家");

     

      //在session中保存user对象

      session.setAttribute("user", user);

     

      //统计用户访问量,在application中保存用户访问量数据

      Integer count = (Integer)context.getAttribute("counter");

      if(null == count)

        count=1;

      else

        count++;

      context.setAttribute("counter", count);

     

      return SUCCESS;

    }

    else

    {

      return ERROR;

    }

  }

}

完整的代码请参看本书配套光盘中的ch03_4目录,测试时,输入URL:

http://localhost:8080/ch03_4/login3.jsp

除了利用ServletActionContext来获取HttpServletRequest对象和ServletContext对象这种方式外,Action类还可以实现ServletRequestAware和ServletContextAware接口,由Struts 2框架向Action实例注入HttpServletRequest和ServletContext对象。
org.apache.struts2.interceptor.ServletRequestAware接口只有一个方法,如下所示:

Ø  void setServletRequest(HttpServletRequest request)org.apache.struts2.util.ServletContextAware接口也只有一个方法,如下所示:

Ø  void setServletContext(ServletContext context)ServletRequestAware接口和ServletContextAware接口不属于同一个包,前者在org.apache.struts2.interceptor包中,后者在org.apache.struts2.util包中,这很让人迷惑。

我们看例3-15。

例3-15  通过接口注入来获取HttpServletRequest和ServletContext对象的LoginAction4

package org.sunxin.struts2.ch03.action.way2;

import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;

import org.apache.struts2.util.ServletContextAware;

import org.sunxin.struts2.ch03.model.User;

import com.opensymphony.xwork2.Action;

public class LoginAction4 implements Action, ServletRequestAware, ServletContextAware

{

  private HttpServletRequest request;

  private ServletContext context;

  @Override

  public String execute() throws Exception

  {

    if ("zhangsan".equals(user.getUsername())

&& "1234".equals(user.

getPassword()))

    {

      HttpSession session = request.getSession();

     

      //在请求中放置欢迎信息。

      request.setAttribute("greeting", "欢迎您来到程序员之家");

      //在session中保存user对象

      session.setAttribute("user", user);

      //统计用户访问量,在application中保存用户访问量数据

      Integer count = (Integer) context.getAttribute("counter");

      if (null == count)

        count = 1;

      else

        count++;

      context.setAttribute("counter", count);

      return SUCCESS;

    }

    else

    {

      return ERROR;

    }

  }

  @Override

  public void setServletRequest(HttpServletRequest request)

  {

    this.request = request;

  }

  @Override

  public void setServletContext(ServletContext context)

  {

    this.context = context;

  }

}

LoginAction4类实现了ServletRequestAware和ServletContextAware接口,框架在运行时会调用这两个接口中的方法,向LoginAction4注入HttpServletRequest和ServletContext对象。在execute()方法中不再需要访问ServletActionContext,因此我们删除了与之相关的代码。
完整的代码请参看本书配套光盘中的ch03_4目录,测试时,输入URL:
http://localhost:8080/ch03_4/login4.jsp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验:内置对象使用 一、实验目的 1、掌握各个内置对象的含义; 2、理解并熟练应用sessionapplication对象。 二、实验内容 1、设计聊天室,在聊天室中,需要通过JSP内置对象application来实时保存特定数量的当前聊天信息。 聊天室的设计包括:用户进行登录,选择聊天室,进行聊天,退出聊天室。 在聊天室中,用户只需输入一个用户名就可以进入聊天室,但是如果当前有人在使用该用户名,那么就必须换一个唯一的用户名。 具体要求:  用户登录成功后,程序会要求用户选择聊天室。可以不设置用户自行建立聊天室的功能,而且在聊天中途不能从一个聊天室切换到另一个聊天室。  进入聊天室后,用户可以从用户信息窗口看到该聊天室中所有用户的用户名,也可以在聊天窗口中看到随时更新的聊天信息。用户可以给所有人或某一个聊天用户发送公共的聊天信息,这个聊天内容大家都可以看到。用户也可以给某个用户发送私人的聊天信息,这种信息属于私聊信息,只有发送者和接收者可以看到。此外,聊天窗口还会出现一些系统公告,比如某某上站、某某离开等消息,另外用户还可以自己定义聊天信息和聊天用户信息刷新的时间间隔。  在用户单击“退出”按钮后,页面关闭,同时applicationsession中保存的信息都将丢失。 三、实验方法 1、用户登录信息使用request对象getParameter()方法得到用户登陆的一些信息; 2、公聊信息可以使用application对象,私聊信息使用session对象。 3、聊天的信息要不断刷新页面,使用户实时看到聊天信息。 4、用户退出时,有两种情况需要考虑:一是用户点击“退出”按钮,二是关闭浏览器,强制退出窗口,可查阅windows感知浏览器关闭的事件的相应方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值