3.5.3 Action直接访问ServletAPI
虽然 Struts 2 提供了 ActionContext 来访问 Servlet API,但这种访问毕竟不能直接获得Servlet API实例,为了在Action中直接访问Servlet API,Struts 2还提供了如下系列接口。
ServletContextAware:实现该接口的 Action 可以直接访问 Web 应用的 ServletContext实例。
ServletRequestAware:实现该接口的Action可以直接访问用户请求的HttpServletRequest实例。
ServletResponseAware:实现该接口的 Action 可以直接访问服务器响应的HttpServletResponse实例。
下面以ServletResponseAware为例,介绍如何在Action中访问HttpServletResponse对象。本应用将通过HttpServletResponse为系统添加Cookie对象,本应用将继续使用如图3.14所示的登录页面,该页面提交给如下的Action处理。
程序清单:codes\03\3.5\access-servlet-api\WEB-INF\src\org\crazyit\struts2\action\LoginAction.java
// 处理用户请求的Action public class LoginAction implements Action , ServletResponseAware { // 需要访问的HttpSerlvetResponse对象 private HttpServletResponse response; // 封装请求参数的两个属性 private String username; private String password; // username属性的getter和setter方法 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } // password属性的setter和getter方法 public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } // 实现ServletResponseAware接口必须实现的方法 @Override public void setServletResponse(HttpServletResponse response) { // 在该方法内就可以访问该Web应用对客户端的响应对象 this.response = response; } //处理用户请求的execute方法 public String execute() throws Exception { // 创建一个Cookie对象 Cookie c = new Cookie("user" , getUsername()); // 设置Cookie对象的最大生存时间 c.setMaxAge(60 * 60); // 使用HttpServletResponse添加Cookie对象 response.addCookie(c); return SUCCESS; } }
通过查看Struts 2的API文档,发现要实现ServletResponseAware接口,仅要求实现如下方法。
public void setServletResponse(HttpServletResponse response):实现此方法时,该方法内有一个HttpServletResponse参数,该参数就代表了Web应用对客户端的响应。我们在setServletResponse(HttpServletResponse response)方法内访问到Web应用的响应对象,并将该对象设置成 Action 的成员属性,从而允许在 execute 方法中访问该HttpServletResponse对象。
与此类似的是,如果一个Action实现了ServletRequestAware接口,则必须实现如下方法。
public void setServletRequest(HttpServletRequest request):通过实现此方法,从而允许Action直接访问HttpServletRequest对象。
为了直接访问Servlet API,Struts 2提供了一个ServletActionContext,这个类包含了如下几个静态方法。
PageContext getPageContext():取得Web应用的PageContext对象。
HttpServletRequest getRequest():取得Web应用的HttpServletRequest对象。
HttpServletResponse getResponse():取得Web应用的HttpServletResponse对象。
ServletContext getServletContext():取得Web应用的ServletContext对象。
借助于ServletActionContext类的帮助,开发者也可以在Action中直接访问Servlet API,避免Action类需要实现XxxAware接口——虽然如此,但该Action依然与Servlet API直接耦合,一样不利于程序解耦。
提示:
可以通过 ServletActionContext 类的帮助,从而以更简单的方式来直接访问Servlet API。
当该Action处理完用户请求后,Web应用向客户机中添加了一个Cookie对象。下面的JSP页面通过表达式来访问Cookie值,该JSP页面的代码如下。
程序清单:codes\03\3.5\access-servlet-api\WEB-INF\content\welcome.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK" />
<title>成功页面</title>
</head>
<body>
从系统中读取的Cookie值:${cookie.user.value}
</body>
</html>
当用户输入用户名、密码,并单击“提交”按钮后,重复刷新上面的 JSP 页面,将看到如图3.16所示的页面效果。
图3.16 通过HttpServletResponse添加Cookie
必须指出的是,虽然可以在Action类中获取HttpServletResponse,但希望通过HttpServletResponse来生成服务器响应没有太大意义,因为Action只是控制器,即如果在Action中书写如下代码:
// 试图在Servlet中直接生成输出的代码 response.getWriter().println("Hello World");
上面代码在标准Servlet中会生成对客户端的输出,但在Struts 2的Action中没有任何实际意义。
提示:
即使我们在Struts 2的Action类中获得了HttpServletResponse对象,也不要尝试直接在Action中生成对客户端的输出!