Struts2中ActionContext介紹 轉(zhuǎn)(溺水的魚)
在Web應(yīng)用程序開發(fā)中,除了將請求參數(shù)自動設(shè)置到Action的字段中,我們往往也需要在Action里直接獲取請求(Request)或會話(Session)的一些信息, 甚至需要直接對JavaServlet Http的請求(HttpServletRequest),響應(yīng)(HttpServletResponse)操作.我們需要在Action中取得request請求參數(shù)"username"的值:
ActionContext context = ActionContext.getContext();
Map params = context.getParameters();
String username = (String) params.get("username");
ActionContext(com.opensymphony.xwork.ActionContext)是Action執(zhí)行時的上下文,上下文可以看作是一個容器(其實我們這里的容器就是一個Map而已),它存放放的是Action在執(zhí)行時需要用到的對象
一般情況,我們的ActionContext都是通過:ActionContext context = (ActionContext) actionContext.get();來獲取的.我們再來看看這里的actionContext對象的創(chuàng)建:static ThreadLocal actionContext = new ActionContextThreadLocal();,ActionContextThreadLocal是實現(xiàn)ThreadLocal的一個內(nèi)部類.ThreadLocal可以命名為"線程局部變量",它為每一個使用該變量的線程都提供一個變量值的副本,使每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本沖突.這樣,我們ActionContext里的屬性只會在對應(yīng)的當(dāng)前請求線程中可見,從而保證它是線程安全的.
下面我們看看怎么通過ActionContext取得我們的HttpSession:
Map session = ActionContext.getContext().getSession();
ServletActionContext
ServletActionContext(com.opensymphony.webwork. ServletActionContext),這個類直接繼承了我們上面介紹的ActionContext,它提供了直接與JavaServlet相關(guān)對象訪問的功能,它可以取得的對象有:
1, javax.servlet.http.HttpServletRequest:HTTPservlet請求對象
2, javax.servlet.http.HttpServletResponse;:HTTPservlet相應(yīng)對象
3, javax.servlet.ServletContext:Servlet 上下文信息
4, javax.servlet.ServletConfig:Servlet配置對象
5, javax.servlet.jsp.PageContext:Http頁面上下文
下面我們看看幾個簡單的例子,讓我們了解如何從ServletActionContext里取得JavaServlet的相關(guān)對象:
1, 取得HttpServletRequest對象:
HttpServletRequest request = ServletActionContext. getRequest();
2, 取得HttpSession對象:
HttpSession session = ServletActionContext. getRequest().getSession();
ServletActionContext和ActionContext有著一些重復(fù)的功能,在我們的Action中,該如何去抉擇呢?我們遵循的原則是:如果ActionContext能夠?qū)崿F(xiàn)我們的功能,那最好就不要使用ServletActionContext,讓我們的Action盡量不要直接去訪問JavaServlet的相關(guān)對象.在使用ActionContext時有一點要注意:不要在Action的構(gòu)造函數(shù)里使用ActionContext.getContext(),因為這個時候ActionContext里的一些值也許沒有設(shè)置,這時通過ActionContext取得的值也許是null.
如果我要取得Servlet API中的一些對象,如request,response或session等,應(yīng)該怎么做?這里的execute不像Struts 1.x的那樣在參數(shù)中引入."開發(fā)Web應(yīng)用程序當(dāng)然免不了跟這些對象打交道.在Strutx 2.0你可以有兩種方式獲得這些對象:非IoC(控制反轉(zhuǎn)Inversion of Control)方式和IoC方式.
非IoC方式
要獲得上述對象,關(guān)鍵Struts 2.0中com.opensymphony.xwork2.ActionContext類.我們可以通過它的靜態(tài)方法getContext()獲取當(dāng)前Action的上下文對象. 另外,org.apache.struts2.ServletActionContext作為輔助類(Helper Class),可以幫助您快捷地獲得這幾個對象.
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
HttpSession session = request.getSession();
如果你只是想訪問session的屬性(Attribute),你也可以通過ActionContext.getContext().getSession()獲取或添加session范圍(Scoped)的對象.
IoC方式
要使用IoC方式,我們首先要告訴IoC容器(Container)想取得某個對象的意愿,通過實現(xiàn)相應(yīng)的接口做到這點.具體實現(xiàn),請參考例6 IocServlet.java.
例6 classes/tutorial/NonIoCServlet.java
package tutorial;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
publicclass NonIoCServlet extends ActionSupport {
private String message;
public String getMessage() {
return message;
}
@Override
public String execute() {
ActionContext.getContext().getSession().put("msg", "Hello World from Session!");
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
HttpSession session = request.getSession();
StringBuffer sb =new StringBuffer("Message from request: ");
sb.append(request.getParameter("msg"));
sb.append("<br>Response Buffer Size: ");
sb.append(response.getBufferSize());
sb.append("<br>Session ID: ");
sb.append(session.getId());
message = sb.toString();
return SUCCESS;
}
}
例6 classes/tutorial/IoCServlet.java
package tutorial;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
publicclass IoCServlet extends ActionSupport implements SessionAware, ServletRequestAware, ServletResponseAware {
private String message;
private Map att;
private HttpServletRequest request;
private HttpServletResponse response;
public String getMessage() {
return message;
}
publicvoid setSession(Map att) {
this.att = att;
}
publicvoid setServletRequest(HttpServletRequest request) {
this.request = request;
}
publicvoid setServletResponse(HttpServletResponse response) {
this.response = response;
}
@Override
public String execute() {
att.put("msg", "Hello World from Session!");
HttpSession session = request.getSession();
StringBuffer sb =new StringBuffer("Message from request: ");
sb.append(request.getParameter("msg"));
sb.append("<br>Response Buffer Size: ");
sb.append(response.getBufferSize());
sb.append("<br>Session ID: ");
sb.append(session.getId());
message = sb.toString();
return SUCCESS;
}
}
例6 Servlet.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h2>
<s:property value="message" escape="false"/>
<br>Message from session: <s:property value="#session.msg"/>
</h2>
</body>
</html>
例6 classes/struts.xml中NonIocServlet和IoCServlet Action的配置
<action name="NonIoCServlet" class="tutorial.NonIoCServlet">
<result>/Servlet.jsp</result>
</action>
<action name="IoCServlet" class="tutorial.IoCServlet">
<result>/Servlet.jsp</result>
</action>
運(yùn)行Tomcat,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Action/NonIoCServlet.action?msg=Hello%20World! 或http://localhost:8080/Struts2_Action/IoCServlet.action?msg=Hello%20World!
在Servlet.jsp中,我用了兩次property標(biāo)志,第一次將escape設(shè)為false為了在JSP中輸出<br>轉(zhuǎn)行,第二次的value中的OGNL為"#session.msg",它的作用與session.getAttribute("msg")等同.