在使用struts框架中,常用ServletActionContext.getRequest()得到request對象,如今就看看ServletActionContext.getRequest()源碼: java
/** * 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等相應的信息 session
(4)ActionContext類中get()方法,在context獲取key爲HTTP_REQUEST = "com.opensymphony.xwork2.dispatcher.HttpServletRequest"對應的對象。 app
到這裏分析完成獲取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對象。 this
(3)DefaultActionInvocation的構造函數中,給變量extraContext賦值。 spa
(4)DefaultActionInvocation的init()方法中建立ActionContext對象,而且賦值給變量invocationContext。 .net
如今看看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);
這就是根源了。