ActionContext类位于com.opensymphony.xwork2中,提供一系列相关方法用于访问保存在ServletContext、HttpSession、HttpServletRequest中的信息,并且存储在Map中。需要注意的是,该类并没有提供获取ServletContext、HttpSession、HttpServletRequest等对象的方法。ActionContext类的常用方法见下表:
方法
|
解释
|
public Map getParameters()
|
从请求对象(HttpServletRequest)中获取请求参数
|
public Map getApplication()
|
获取ServletContext中保存的Attribute
|
public Map getSession()
|
获取HttpSession中保存的Attribute
|
那么,这些信息是在什么时候保存进去的呢?从源代码中分析,所有秘密都隐藏在
org.apache.struts2.dispatcher. Dispatcher类中,该类中定义了一个createContextMap()方法,代码如下:
代码清单29
:Dispatcher.
createContextMap()
方法
public Map<String,Object> createContextMap(HttpServletRequest request, HttpServletResponse response,
ActionMapping mapping, ServletContext context) {
// request map wrapping the http request objects
Map requestMap =
new RequestMap(request);//存放request中所有的Attribute
// parameters map wrapping the http paraneters.
Map params =
null;
if (mapping !=
null) {
params = mapping.getParams();
}
Map requestParams =
new HashMap(request.getParameterMap());//存放request中所有的Parameter
if (params !=
null) {
params.putAll(requestParams);
}
else {
params = requestParams;
}
// session map wrapping the http session
Map session =
new SessionMap(request);//存放Session中所有的Attribute
// application map wrapping the ServletContext
Map application =
new ApplicationMap(context);//存放ServletContext所有的Attribute
Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
return extraContext;
}
接下来又调用了另一个重载的createContextMap()方法,该方法不仅保存Attribute,而且保存request,response和servletContext对象,请看源代码:
代码清单
30
:重载的Dispatcher.
createContextMap()
方法
public HashMap<String,Object> createContextMap(Map requestMap,
Map parameterMap,
Map sessionMap,
Map applicationMap,
HttpServletRequest request,
HttpServletResponse response,
ServletContext servletContext) {
HashMap<String,Object> extraContext =
new HashMap<String,Object>();
extraContext.put(ActionContext.PARAMETERS,
new HashMap(parameterMap));
extraContext.put(ActionContext.SESSION, sessionMap);
extraContext.put(ActionContext.APPLICATION, applicationMap);
Locale locale;
if (
defaultLocale !=
null) {
locale = LocalizedTextUtil.localeFromString(
defaultLocale, request.getLocale());
}
else {
locale = request.getLocale();
}
extraContext.put(ActionContext.LOCALE, locale);
//extraContext.put(ActionContext.DEV_MODE, Boolean.valueOf(devMode));
extraContext.put(StrutsStatics.HTTP_REQUEST, request);
extraContext.put(StrutsStatics.HTTP_RESPONSE, response);
extraContext.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
// helpers to get access to request/session/application scope
extraContext.put("request", requestMap);
extraContext.put("session", sessionMap);
extraContext.put("application", applicationMap);
extraContext.put("parameters", parameterMap);
AttributeMap attrMap =
new AttributeMap(extraContext);
extraContext.put("attr", attrMap);
return extraContext;
}
可以看出,在第一个createContextMap()方法得到的所有Map类型的数据最终又被保存在了另一个Map中,ActionContext就是从这个Map中获取数据的。
在ActionContext类中定义了一个静态方法public static ActionContext getContext()用于获取自己的一个实例,不能new此类的对象。
下面的示例演示了ActionContext类的基本用法,即从请求参数中读取id和name的值,并且将值保存到Session中,然后跳转到session.jsp页面将id和name的值显示出来。
先定义ServletAction类,代码如下:
代码清单
31
:
ServletAction.java
package com.lizanhong.chapter3;
import java.util.Map;
import java.util.Set;
import com.opensymphony.xwork2.ActionContext;
public
class ServletAction {
public String execute(){
ActionContext ac = ActionContext.
getContext();
Map paramMap = ac.getParameters();
String[] ids = (String[]) paramMap.get("id");
String[] names = (String[]) paramMap.get("name");
Map sessionMap = ac.getSession();
sessionMap.put("id", ids[0]);
sessionMap.put("name", names[0]);
return "toSession";
}
}
注:通过getParameters()方法获取到的请求参数类型都是String[],必须根据实际情况取值。如果只有一个值的话,取出数组中第0个元素即可。
以下是ServletAction在struts.xml中的配置。
代码清单
33
:在
struts.xml
中的配置
<action name="servletAction" class="com.lizanhong.chapter3.ServletAction">
<result name="toSession">/session.jsp</result>
</action>
在session.jsp页面中,使用表达式语言(EL)显示保存在Session中的id和name值。
代码清单
33:session.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'session.jsp' starting page</title>
</head>
<body>
${id }<br>
${name }
</body>
</html>
请求参数通过表单页面idname.jsp提供。
代码清单
34
:
idname.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'idname.jsp' starting page</title>
</head>
<body>
<form action="
servletAction.action" method="post">
ID:<input name="id"><br>
Name:<input name="name"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
通过http://localhost:8081/Struts2Demo/idname.jsp地址访问即可,图24是表单输入效果,图25是表单提交后将请求发送给Action,最后显示在session.jsp中的效果:
(图24)
(图25)
ActionContext类是xwork提供的,struts2定义了一个新类org.apache.struts2. ServletActionContext,该类继承自ActionContext:
代码清单
35
:
ServletActionContext.java
的定义
public class ServletActionContext extends ActionContext implements StrutsStatics {
}
ServletActionContext类和ActionContext相比扩展了更多的方法,主要是一些静态方法,该类的源代码如下:
代码清单
36
:
ServletActionContext.java
的完整定义
public
class ServletActionContext
extends ActionContext
implements StrutsStatics {
private
static
final
long
serialVersionUID = -666854718275106687L;
public
static
final String
STRUTS_VALUESTACK_KEY = "struts.valueStack";
public
static
final String
ACTION_MAPPING = "struts.actionMapping";
@SuppressWarnings("unused")
private ServletActionContext(Map context) {
super(context);
}
public
static ActionContext getActionContext(HttpServletRequest req) {
ValueStack vs = getValueStack(req);
if (vs !=
null) {
return
new ActionContext(vs.getContext());
}
else {
return
null;
}
}
public
static ValueStack getValueStack(HttpServletRequest req) {
return (ValueStack) req.getAttribute(
STRUTS_VALUESTACK_KEY);
}
public
static ActionMapping getActionMapping() {
return (ActionMapping) ActionContext.getContext().get(
ACTION_MAPPING);
}
public
static PageContext
getPageContext() {
return (PageContext) ActionContext.getContext().get(PAGE_CONTEXT);
}
public
static
void setRequest(HttpServletRequest request) {
ActionContext.getContext().put(HTTP_REQUEST, request);
}
public
static HttpServletRequest
getRequest() {
return (HttpServletRequest) ActionContext.getContext().get(HTTP_REQUEST);
}
public
static
void setResponse(HttpServletResponse response) {
ActionContext.getContext().put(HTTP_RESPONSE, response);
}
public
static HttpServletResponse
getResponse() {
return (HttpServletResponse) ActionContext.getContext().get(HTTP_RESPONSE);
}
public
static ServletContext
getServletContext() {
return (ServletContext) ActionContext.getContext().get(SERVLET_CONTEXT);
}
public
static
void setServletContext(ServletContext servletContext) {
ActionContext.getContext().put(SERVLET_CONTEXT, servletContext);
}
}
注意粗体部分,getPageContext()方法返回PageContext的引用,getRequest()方法返回HttpServletRequest的引用,getResponse()方法返回HttpServletResponse的引用,getServletContext()方法返回ServletContext的引用。我们将代码清单31修改成代码清单37所示:
代码清单
37
:
ServletAction.java
的修改版
public
class ServletAction {
public String execute(){
String id = ServletActionContext.
getRequest().getParameter("id");
String name = ServletActionContext.
getRequest().getParameter("name");
Map sessionMap = ServletActionContext.
getContext().getSession();
sessionMap.put("id", id);
sessionMap.put("name", name);
System.
out.println("id=" + sessionMap.get("id"));
System.
out.println("name=" + sessionMap.get("name"));
return "toSession";
}
}
3.3.2 通过IOC访问Servlet对象
在Struts2中,可以通过IOC(依赖注入)将Servlet对象注入到Action中,这一切都是由一组接口决定的,这一组接口有一个共同点,名称都由Aware结尾。以下是这些接口的解释说明:
接口定义
|
作用
|
public
interface ApplicationAware {
public
void setApplication(Map application);
}
|
以Map类型向Action注入保存在ServletContext中的Attribute集合。
|
public
interface SessionAware {
public
void setSession(Map session);
}
|
以Map类型向Action注入保存在HttpSession中的Attribute集合。
|
public
interface ServletResponseAware {
public
void setServletResponse(HttpServletResponse response);
}
|
向Action中注入HttpServletResponse对象
|
public
interface ServletRequestAware {
public
void setServletRequest(HttpServletRequest request);
}
|
向Action中注入HttpServletRequest对象
|
public
interface RequestAware {
public
void setRequest(Map request);
}
|
以Map类型向Action注入保存在HttpServletRequest中的Attribute集合。
|
public
interface CookiesAware {
void setCookiesMap(Map cookies);
}
|
以Map类型向Action注入Cookie中的数据集合。
|
public
interface ParameterAware {
public
void setParameters(Map parameters);
}
|
向Action中注入请求参数集合。
|
为了将相关Servlet对象注入到Action中,只要让Action实现这些接口就可以了,Struts2会自动将数据及对象注入Action。代码清单38是对代码清单37的再次修改版:
代码清单
38
:
ServletAction2.java
public
class ServletAction2
implements CookiesAware,ParameterAware, RequestAware, SessionAware, ServletRequestAware, ServletResponseAware, ApplicationAware {
private Map sessionMap;
private HttpServletRequest request;
private HttpServletResponse response;
private Map applicationMap; //只是定义,代码中没有使用,起演示说明作用
private Map cookieMap; //只是定义,代码中没有使用,起演示说明作用
private Map requestMap; //只是定义,代码中没有使用,起演示说明作用
private Map parameterMap; //只是定义,代码中没有使用,起演示说明作用
public
void setSession(Map session) {
this.sessionMap = session;
}
public
void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public
void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public
void setApplication(Map application) {
this.applicationMap = application;
}
public
void setCookiesMap(Map cookies) {
this.cookieMap = cookies;
}
public
void setParameters(Map parameters) {
this.parameterMap = parameters;
}
public
void setRequest(Map request) {
this.requestMap = request;
}
public String execute(){
String id =
this.request.getParameter("id");
String name =
this.request.getParameter("name");
sessionMap.put("id", id);
sessionMap.put("name", name);
return "toSession";
}
}
该Action的配置如下:
代码清单
40
:
ServletAction2
的配置
<action name="servletAction2" class="com.lizanhong.chapter3.ServletAction2">
<result name="toSession">/session.jsp</result>
</action>