2013-02-04 13:01:52.0|分类: struts源码分析|浏览量: 1679
在使用struts框架中,经常使用ServletActionContext.getRequest()获得request对象,现在就看看ServletActionContext.getRequest()源码:
/** * Gets the HTTP servlet request object. * * @return the HTTP servlet request object. */ public static HttpServletRequest getRequest() { return (HttpServletRequest) ActionContext.getContext().get(HTTP_REQUEST); }注释:这里很简单继续调用ActionContext中getContext()方法获取 ActionContext对象,在调用 ActionContext对象中get()获取request对象,下面详细看看:
public class ActionContext implements Serializable { static ThreadLocal actionContext = new ThreadLocal(); Map<String, Object> context; public ActionContext(Map<String, Object> context) { this.context = context; } /** * Returns the ActionContext specific to the current thread. * * @return the ActionContext for the current thread, is never <tt>null</tt>. */ public static ActionContext getContext() { return (ActionContext) actionContext.get(); } public Object get(String key) { return context.get(key); }注释:(1)ActionContext类首先定义了一个类型ThreadLocal的actionContext对象,这样保证每个线程获得actionContext对象时安全。 (2)ActionContext类中getContext()方法,获取相应线程上ActionContext对象 (3)ActionContext类中定义了类型Map<String, Object>的context对象,context中保存了request,actionMapping等相应的信息 (4)ActionContext类中get()方法,在context获取key为HTTP_REQUEST = "com.opensymphony.xwork2.dispatcher.HttpServletRequest"对应的对象。 到这里分析完成获取request的整个过程,那是怎么添加进来的呢? DefaultActionProxy中的execute()方法:
public String execute() throws Exception { ActionContext nestedContext = ActionContext.getContext(); ActionContext.setContext(invocation.getInvocationContext()); 。。。 retCode = invocation.invoke()这里设置ActionContext对象,然后执行action,看来很很合理啊!
public class DefaultActionInvocation implements ActionInvocation { protected ActionContext invocationContext; protected Map<String, Object> extraContext; public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) { DefaultActionInvocation.this.extraContext = extraContext; DefaultActionInvocation.this.pushAction = pushAction; } public ActionContext getInvocationContext() { return invocationContext; } public void init(ActionProxy proxy) { this.proxy = proxy; Map<String, Object> contextMap = createContextMap(); // Setting this so that other classes, like object factories, can use the ActionProxy and other // contextual information to operate ActionContext actionContext = ActionContext.getContext(); if (actionContext != null) { actionContext.setActionInvocation(this); } createAction(contextMap); if (pushAction) { stack.push(action); contextMap.put("action", action); } invocationContext = new ActionContext(contextMap); invocationContext.setName(proxy.getActionName()); 。。。。 } protected Map<String, Object> createContextMap() { Map<String, Object> contextMap; if ((extraContext != null) && (extraContext.containsKey(ActionContext.VALUE_STACK))) { // In case the ValueStack was passed in stack = (ValueStack) extraContext.get(ActionContext.VALUE_STACK); if (stack == null) { throw new IllegalStateException("There was a null Stack set into the extra params."); } contextMap = stack.getContext(); } else { // create the value stack // this also adds the ValueStack to its context stack = valueStackFactory.createValueStack(); // create the action context contextMap = stack.getContext(); } // put extraContext in if (extraContext != null) { contextMap.putAll(extraContext); } //put this DefaultActionInvocation into the context map contextMap.put(ActionContext.ACTION_INVOCATION, this); contextMap.put(ActionContext.CONTAINER, container); return contextMap; }注释:(1)DefaultActionInvocation类变量extraContext类型为Map<String, Object>,保存整个actionContext相应的信息。 (2)DefaultActionInvocation类变量invocationContext,保存了ActionContext对象。 (3)DefaultActionInvocation的构造函数中,给变量extraContext赋值。 (4)DefaultActionInvocation的init()方法中创建ActionContext对象,并且赋值给变量invocationContext。 现在看看DefaultActionInvocation的创建的方法:请看《刨根问底-struts-serviceAction()创建并执行action》,现在我们就简单的看形参 Map<String, Object> extraContext开始创建的地方: Dispatcher中serviceAction()方法:
Map<String, Object> extraContext = createContextMap(request, response, mapping, context); 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); // parameters map wrapping the http parameters. ActionMapping parameters are now handled and applied separately Map params = new HashMap(request.getParameterMap()); // session map wrapping the http session Map session = new SessionMap(request); // application map wrapping the ServletContext Map application = new ApplicationMap(context); Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context); if (mapping != null) { extraContext.put(ServletActionContext.ACTION_MAPPING, mapping); } return extraContext; } 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; }上面的代码其实不难,就是各种map之间的关系,及其处理。请看:extraContext.put(StrutsStatics.HTTP_REQUEST, request); 这就是根源了。
|