• 转: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对象。

    积极的人,象太阳,照到哪里哪里亮,消极的人,象月亮,初一十五不一样。想法决定我们的生活,有什么样的想法,就有什么样的未来。对于刚刚进入职场的我们,会经历很多不同的心境变化,很多时候现实跟你想象的都大相庭径,良好的心态很重要!
  • 相关阅读:
    linux安装mongodb数据库./mongod -f mongodb.conf失败或者error
    idea项目提交
    spring5.x日志问题log4j
    IDEA使用apache-tomcat-9.0.16控制台Tomcat日志中文乱码问题
    笔记本网线连服务器内网ip配置
    vue项目启动操作
    win10窗口打开一直处于最小化状态问题
    停止 WinDefend Microsoft Defender Antivirus Service
    关于apt命令和yum命令区别
    20200924-4 代码规范
  • 原文地址:https://www.cnblogs.com/wuxinyu/p/3115163.html
Copyright © 2020-2023  润新知