Struts2之获取request,response,session,application对象

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

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

与Servlet API解耦的访问方式

方法一:通过ActionContext操作

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

要获取这三个Map对象,可以使用com.opensymphony.xwork2.ActionContext类。

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

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

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

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

通过ActionContext来获取request、session和application对象

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ServletAPI的测试页面</title>
</head>
<body>
<h3>${sessionScope.name},${requestScope.greeting}。<br>  

        本站的访问量是:${applicationScope.counter}</h3>  
    <s:form action="servletAPI1" namespace="/">
        <table>
            <tr>
                <td>登录帐号</td>
                <td><s:textfield name="name" /></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><s:password name="pwd" /></td>
            </tr>


            <tr>
                <td><input type="submit" value="提交" s /></td>
                <td><s:reset value="重置" /></td>
            </tr>
        </table>
        <!--显示所有校验失败信息-->
        <s:fielderror />

    </s:form>
    <br>

    <s:debug></s:debug>
</body>
</html>

/**
 * 
 */
package action;

import java.util.Map;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;

import com.opensymphony.xwork2.ActionContext;

import lombok.Getter;
import lombok.Setter;

/**
 * @author Administrator 测试Action中获取request,session,application
 */
@Namespace("/")
@Result(name = "success", location = "/servletAPI.jsp")
public class ServletAPIAction {
    @Getter
    @Setter
    private String name; // 封装帐号(uid)请求参数属性
    @Getter
    @Setter
    private String pwd;

    /**
     * 通过ActionContext获取
     * 
     * @return
     */
    @Action(value = "servletAPI1")
    public String actionContex() {
    ActionContext actionContext = ActionContext.getContext();
    @SuppressWarnings("unchecked")
    Map<String, Object> request = (Map<String, Object>) actionContext.get("request");
    Map<String, Object> session = actionContext.getSession();
    Map<String, Object> application = actionContext.getApplication();
    // 在请求中放置欢迎信息。
    request.put("greeting", "欢迎您来到影梧的博客");
    // 在session中保存password属性
    session.put("password", pwd);
    // 统计用户访问量,在application中保存用户访问量数据
    Integer count = (Integer) application.get("counter");
    if (null == count)
        count = 1;
    else
        count++;
    application.put("counter", count);
    return "success";

    }

}

方法二:IOC(控制反转)获取servletAPI

Action类还有另一种获得ServletAPI的解耦方式,这就是我们可以让他实现某些特定的接口,让Struts2框架在运行时向Action实例注入request、session和application对象。这种方式也就是IOC(控制反转)方式,实现RequestAware,SessionAware,ApplicationAware接口即可,这三个接口每个都有一个相关的set方法。

实例如下:

/**
 * 
 */
package action;

import java.util.Map;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionContext;

import lombok.Getter;
import lombok.Setter;

/**
 * @author Administrator 测试Action中获取request,session,application
 */
@Namespace("/")
@Result(name = "success", location = "/servletAPI.jsp")
public class ServletAPIAction implements RequestAware,SessionAware,ApplicationAware{
    @Getter
    @Setter
    private String name; // 封装帐号(uid)请求参数属性
    @Getter
    @Setter
    private String pwd;

    private Map<String, Object> request;  
    private Map<String, Object> session;  
    private Map<String, Object> application;  

    /**
     * 通过实现接口RequestAware,SessionAware,ApplicationAware来注入
     * @return
     */
    @Action(value = "servletAPI2")
    public String requestAware() {

    // 在请求中放置欢迎信息。
    request.put("greeting", "欢迎您来到影梧的博客");
    // 在session中保存password属性
    session.put("name", name);
    session.put("password", pwd);
    // 统计用户访问量,在application中保存用户访问量数据
    Integer count = (Integer) application.get("counter");
    if (null == count)
        count = 1;
    else
        count++;
    application.put("counter", count);
    return "success";
    }

    @Override
    public void setApplication(Map<String, Object> application) {
    this.application = application;
    }

    @Override
    public void setSession(Map<String, Object> session) {
    this.session = session;
    }

    @Override
    public void setRequest(Map<String, Object> request) {
    this.request = request;
    }

}

与Servlet API耦合的访问方式

直接访问Servlet API将使你的Action与Servlet环境耦合在一起,我们知道对于HttpServletRequest、HttpServletResponse和ServletContext这些对象,它们都是由Servlet容器来构造的,与这些对象绑定在一起,测试时就需要有Servlet容器,不便于Action的单元测试。但有时候,我们又确实需要直接访问这些对象。

方法一:通过ServletActionContext类获取

ServletActionContext类是ActionContext的子类,在这个类中定义下面静态方法:
1、public static HttpServletRequest getRequest()
得到HttpServletRequest对象。

2、public static ServletContext getServletContext()
得到ServletContext对象。

此外,ServletActionContext类还给出了获取HttpServletResponse对象的方法,如下:
3、public static HttpServletResponse getResponse()

注意:ServletActionContext类并没有给出直接得到HttpSession对象的方法,HttpSession对象可以通过HttpServletRequest对象来得到。


/** * 通过ServletActionContext类获取 * @return */ @Action(value = "servletAPI3") public String servletActionContext() { ActionContext actionContext = ActionContext.getContext(); HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); ServletContext application = ServletActionContext.getServletContext(); HttpSession session = request.getSession(); // 在请求中放置欢迎信息。 request.setAttribute("greeting", "欢迎您来到影梧的博客"); // 在session中保存password属性 session.setAttribute("name", name); session.setAttribute("password", pwd); // 统计用户访问量,在application中保存用户访问量数据 Integer count = (Integer) application.getAttribute("counter"); if (null == count) count = 1; else count++; application.setAttribute("counter", count); return "success"; }

方法二:通过ActionContext来获取相关对象:

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

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

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

 /**
     * 通过ActionContext类获取
     * @return
     */
    @Action(value = "servletAPI4")
    public String actionContext() {

    ActionContext actionContext = ActionContext.getContext();
    HttpServletRequest request = (HttpServletRequest) actionContext.get(ServletActionContext.HTTP_REQUEST);
    HttpServletResponse response = (HttpServletResponse) actionContext.get(ServletActionContext.HTTP_RESPONSE);
    ServletContext application = (ServletContext) actionContext.get(ServletActionContext.SERVLET_CONTEXT);
    HttpSession session = request.getSession();
    // 在请求中放置欢迎信息。
    request.setAttribute("greeting", "欢迎您来到影梧的博客");
    // 在session中保存password属性
    session.setAttribute("name", name);
    session.setAttribute("password", pwd);
    // 统计用户访问量,在application中保存用户访问量数据
    Integer count = (Integer) application.getAttribute("counter");
    if (null == count)
        count = 1;
    else
        count++;
    application.setAttribute("counter", count);
    return "success";
    }

方法三:通过ServletRequestAware和ServletContextAware接口

实现ServletRequestAware和ServletContextAware接口,由Struts 2框架向Action实例注入HttpServletRequest和ServletContext对象。

public class ServletAPIAction implements ServletRequestAware, ServletContextAware{
    private HttpServletRequest reqest;  
    private ServletContext context;  
    private HttpServletResponse response;  

  /**
     * 通过ServletRequestAware和ServletContextAware接口进行注入
     * @return
     */
    @Action(value = "servletAPI5")
    public String servletRequestAware() {

    // 在请求中放置欢迎信息。
    reqest.setAttribute("greeting", "欢迎您来到影梧的博客");
    HttpSession session = reqest.getSession();
    // 在session中保存password属性
    session.setAttribute("name", name);
    session.setAttribute("password", pwd);
    // 统计用户访问量,在application中保存用户访问量数据
    Integer count = (Integer) context.getAttribute("counter");
    if (null == count)
        count = 1;
    else
        count++;
    context.setAttribute("counter", count);
    return "success";

    }

    @Override
    public void setServletContext(ServletContext context) {
    this.context = context;
    }


    @Override
    public void setServletRequest(HttpServletRequest request) {
    this.reqest = request;
    }
  @Override
    public void setServletResponse(HttpServletResponse response) {
    this.response = response;
    }

总结

通过上面五种方式的讲解我们可以看出,获得servletAPI的方式基本都差不多,通常我们建议大家采用第一种方式来获取HttpServletRequest和ServletContext对象,这样简单而又清晰,并且降低了和servletAPI的耦合度,这样也方便进行单元测试

获取response方法总结

方法一:

对应以上解耦方法一 actionContext.get(“request”)
对应以上解耦方法二 RequestAware接口
都获得的是struts2对应HTTPServletRequest的Map数据

private HttpServletResponse response;
Set<String>keys=request.keySet();
    //枚举所有的key值。实际上只有一个key:struts.valueStack
    for(String key:keys)
    System.out.println(key);
    //获得OgnlValueStack对象
    OgnlValueStack stack=(OgnlValueStack)request.get("struts.valueStack");
    //获得HttpServletResponse对象
    response= (HttpServletResponse)stack.getContext().get(StrutsStatics.HTTP_RESPONSE);
    response.getWriter().write("reponse");

方法二:ServletActionContext直接get

HttpServletResponse response = ServletActionContext.getResponse();

方法三:ActionContext直接get

HttpServletResponse response = (HttpServletResponse) actionContext.get(ServletActionContext.HTTP_RESPONSE);

方法四:ServletResponseAware

用其get方法直接注入

 @Override
    public void setServletResponse(HttpServletResponse response) {
    this.response = response;
    }

参考

Struts2中获取request,session,application对象

细谈struts2(六)获取servletAPI和封装表单数据

点赞

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注