/** * The ActionContext is the context in which an {@link Action} is executed. Each context is basically a * container of objects an action needs for execution like the session, parameters, locale, etc. <p> * <p/> * The ActionContext is thread local which means that values stored in the ActionContext are * unique per thread. See the {@link ThreadLocal} class for more information. The benefit of * this is you don't need to worry about a user specific action context, you just get it: * <p/> * <ul><code>ActionContext context = ActionContext.getContext();</code></ul> * <p/> * Finally, because of the thread local usage you don't need to worry about making your actions thread safe. * * @author Patrick Lightbody * @author Bill Lynch (docs) */ public class ActionContext implements Serializable { static ThreadLocal actionContext = new ThreadLocal();
1. Pay some attention to the comment.
2. The usage of ThreadLocal is some sort of weird, I've never seen this before, as listed above.No where to call customized initialValue()? or just call the default protected initialValue()? and no generics applied here?
3. Comtemplate: As an architect, how would you design a data structure for the ActionContext's mission? Imaging that you have no idea of ActionContext's source.
PART 2:
Map<String, Object> context; /** * Creates a new ActionContext initialized with another context. * * @param context a context map. */ public ActionContext(Map<String, Object> context) { this.context = context; }
As we've seen, struts 2 utilize a Map to store context information. Further, what concrete Map? ConcurrentHashMap? Why this context map is not ThreadLocal variable?
PART 3:
From the getContext() method, we see the downcast, now we have an idea of why no generics applied, and finally we know the concrete type of actionContext. And since the whole actioncontext is ThreadLocal, it's not necessary to make the Map<String, Object> context ThreadLocal any more.
/** * 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(); // Don't do lazy context creation, as it requires container; the creation of which may // precede the context creation //if (context == null) { // ValueStack vs = ValueStackFactory.getFactory().createValueStack(); // context = new ActionContext(vs.getContext()); // setContext(context); //} }
PART 4:
/** * Constant for the name of the action being executed. */ public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name"; /** * Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}. */ public static final String VALUE_STACK = ValueStack.VALUE_STACK; /** * Constant for the action's session. */ public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session"; /** * Constant for the action's application context. */ public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application"; /** * Constant for the action's parameters. */ public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters"; /** * Constant for the action's locale. */ public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale";Why hard coded these kind of constants? for what sake?