Web应用的控制器而言(Action是控制器),不访问Servlet API几乎是不可能的

前言

Struts2框架的设计初衷就是各种解耦,所以,Struts2的Action没有与任何Servlet API耦合,这样带来的好处就是我们在测试Action时会更加的简单、方便;但是话又说回来了,对于Web应用的控制器而言(Action是控制器),不访问Servlet API几乎是不可能的,而Action并没有那么“轻易”让你去使用Servlet API。

在Action中如果想要使用Servlet API,基本上只有以下三种方法:

  • 通过ActionContext类访问
  • Action直接访问
  • 通过ServletActionContext访问

这篇文章就对这三种方法进行总结。

通过ActionContext类访问

Struts2提供了ActionContext类,Struts2的Action可以通过该类来访问Servlet API。下面是ActionContext类中几个常用的方法:

  • Object get(Object key):该方法类似于调用HttpServletRequest的getAttribute(String name)方法
  • Map getApplication():返回一个Map对象,该对象模拟了该应用的ServletContext实例
  • static ActionContext getContext():静态方法,获取系统的ActionContext实例
  • Map getParameters():获取所有的请求参数;类似于调用HttpServletRequest对象的getParameterMap()方法
  • Map getSession():返回一个Map对象,该Map对象模拟了HttpSession实例
  • void setApplication(Map application):直接传入一个Map实例,将该Map实例里的key-value对转换成application的属性名、属性值
  • void setSession(Map session):直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名、属性值

下面通过一个简单的实例来说明如何使用 ActionContext 。

public String execute() throws Exception
{
    if (getUserName() == null || getPassword() == null)
    {
        return INPUT;
    }

    // 获取ActionContext对象
    ActionContext ac = ActionContext.getContext();

    // 通过ActionContext访问application范围的属性值
    Integer counter = (Integer)ac.getApplication().get("counter");
    if (counter == null)
    {
        counter = 1;
    }
    else
    {
        counter += 1;
    }

    // 通过ActionContext设置application范围的属性
    ac.getApplication().put("counter", counter);

    if (getUserName().equals("jellythink")
            && getPassword().equals("123456"))
    {
        ActionContext.getContext().getSession().put("user", getUserName());
        ac.put("tip", "服务器提示:您已经成功登陆");
        return SUCCESS;
    }
    else
    {
        ac.put("tip", "服务器提示:登陆失败");
        return ERROR;
    }
}

通过前台JSP页面,我们可以访问这些属性值:

<body> 本站访问次数为:${applicationScope.counter}<br/> ${sessionScope.user},您已登陆!<br/> ${requestScope.tip} </body> 

通过 ActionContext 这种方法访问的前提是必须先要获取 ActionContext 对象,它彻底的与Servlet API进行了分离,使用这种方法简单易用。

Action直接访问

虽然Struts2提供了 ActionContext 来访问Servlet API,但这种访问毕竟不是直接获得Servlet API的实例,为了可以在Action中直接访问Servlet API,Struts2还提供了以下几个接口:

接口名称 接口说明
ServletContextAware 实现该接口的Action可以直接访问Web应用的ServletContext实例
ServletRequestAware 实现该接口的Action可以直接访问Web应用的HttpServletRequest实例
ServletResponseAware 实现该接口的Action可以直接访问服务器响应的HttpServletResponse实例

下面通过一段简单的代码来说说这几个接口的具体使用:

public class LoginAction extends ActionSupport implements ServletResponseAware, ServletRequestAware, ServletContextAware {
    private String userName;
    private String password;
    private HttpServletResponse response;
    private HttpServletRequest request;
    private ServletContext sc;

// 实现ServletResponseAware接口的方法,设置response属性值
public void setServletResponse(HttpServletResponse response) {
    this.response = response;
}

// 实现ServletRequestAware接口的方法,设置request属性值
public void setServletRequest(HttpServletRequest request) {
    this.request = request;
}

// 实现ServletContextAware接口的方法,设置sc属性值
public void setServletContext(ServletContext sc) {
    this.sc = sc;
}

// ......

public String execute() throws Exception {
    // ...... 
    Integer counter = (Integer)sc.getAttribute("counter");
    if (counter == null)
    {
        counter = 1;
    }
    else
    {
        counter += 1;
    }

    sc.setAttribute("counter", counter);

    if (getUserName().equals("jellythink")
            && getPassword().equals("123456"))
    {
        HttpSession session = request.getSession();
        session.setAttribute("user", getUserName());
        request.setAttribute("tip", "服务器提示:您已经成功登陆");
        return SUCCESS;
    }
    else
    {
        request.setAttribute("tip", "服务器提示:登陆失败");
        return ERROR;
    }
}

这种方法使用起来也比较方便,但是必须要实现对应的三个接口。

通过ServletActionContext访问

上面的两种方法要么不是直接访问Servlet API,要么就是需要继承其它的接口。为了能直接访问Servlet API,Struts2还提供了一个ServletActionContext工具类,该工具类提供了以下几个静态方法:

声明 说明
static PageContext getPageContext() 取得Web应用的PageContext对象
static HttpServletRequest getRequest() 取得Web应用的HttpServletRequest对象
static HttpServletResponse getResponse() 取得Web应用的HttpServletResponse对象
static ServletContext getServletContext() 取得Web应用的ServletContext对象

通过 ServletActionContext 工具类,我们就无需实现接口,就可以直接访问Servlet API,但是这样会加强了Action和Servlet API的耦合,不利于Action的再利用。

总结

上面介绍的这三种方法各有各的有点,具体如下:

方法 优点 缺点
通过ActionContext类访问 Action和Servlet API完全解耦 并不能调用原生的Servlet API
Action直接访问 可以调用原生的Servlet API 需要实现对应的接口
通过ServletActionContext访问 可以调用原生的Servlet API 增加了耦合

基于此,在实际开发过程中,就看你喜欢用哪种了。反正我喜欢用 Action直接访问 这种方式,虽然需要实现对应的接口,但是还是比较方便的。

果冻想-一个原创技术文章分享网站。

2016年01月23日 于呼和浩特。

你可能感兴趣的:(Web应用的控制器而言(Action是控制器),不访问Servlet API几乎是不可能的)