zoukankan      html  css  js  c++  java
  • 转:Struts2如何获取request、session和application对象

    转自:http://blog.sina.com.cn/s/blog_6345041c01015fgl.html   

    访问request、session和application对象

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

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

    1 与Servlet API解耦的访问方式

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

    要获取这三个Map对象,可以使用com.opensymphony.xwork2.ActionContext类(参看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对象的操作。

     

     

    利用请求对象来传递数据还有一种方式,你可以直接使用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对象。

    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();



    //在请求中放置欢迎信息。
    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;
    }
    }
    }

    除了利用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对象。

    积极的人,象太阳,照到哪里哪里亮,消极的人,象月亮,初一十五不一样。想法决定我们的生活,有什么样的想法,就有什么样的未来。对于刚刚进入职场的我们,会经历很多不同的心境变化,很多时候现实跟你想象的都大相庭径,良好的心态很重要!
  • 相关阅读:
    为什么 PCB 生产时推荐出 Gerber 给工厂?
    Fedora Redhat Centos 有什么区别和关系?
    【KiCad】 如何给元件给元件的管脚加上划线?
    MCU ADC 进入 PD 模式后出现错误的值?
    FastAdmin 生产环境升级注意
    EMC EMI 自行评估记录
    如何让你的 KiCad 在缩放时不眩晕?
    KiCad 5.1.0 正式版终于发布
    一次单片机 SFR 页引发的“事故”
    java基础之集合
  • 原文地址:https://www.cnblogs.com/wuxinyu/p/3115163.html
Copyright © 2011-2022 走看看