刨根問底struts得到request(ServletActionContext.getReq...

在使用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);

這就是根源了。

相關文章
相關標籤/搜索