前言
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日 于呼和浩特。