开发者学堂课程【Java Web开发系列课程 - Struts2框架入门:ActionContext 一】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/537/detail/7305
ActionContext 一
内容介绍:
一、ActionContext 对象笔记
二、ActionContext 理解
一、ActionContext 对象笔记
Struts1 的 Action 必须依赖于 web 容器,他的 execute 方法会自动获得HttpServletRequestHttpServletResponse 对象,从而可以跟 web 容器进行交互。
Struts2 的 Acticn 不用依赖于 web 容器,本身只是一个普通的 java 类而已。但是,在 web 开发中我们往往需要获得 request、session、applicatipr 等对象。这时,可以通过 Actincontext 米处理。
ActianContext 正如其名,是 Actipn 执行的=下文。他内部有个 map 属性,它存放了 Action 执行时需要用到的对家。
在每次执行 Action 之前者会剑建新的 Actioncontext 对象,所以 Actincontext 是线程安全的。新 new 的 ActionContext 是保存在一个 Threadloal 变量中,即买用Threadloca 模式 Threadlocal 变量为每个线程提供独立的变量值的副本,使每个线程都可以独立的使用自己的副本,而不会知其他线程发生冲突。
通过 ActionContext 获取的 session,requestapplication 产不是直正的
HttpServletRequestHttpServletResponseServletContext 对象,而是将这三个对象里面的值重新包装成了 map 对家。
这样的封装,我们及获取了我们需要的值,司时避免了跟web容器直接打交道,实现了完全的解偶。
测试代码:
public class TestActionContextAction extends ActionSupport
privates String uname ;
public String execute( ) throws Exception {
ActionContext ac = ActionContext.getContext ( );
System.cut.println(ac) ;
//在此处定义断点
return this.SUCCESS;
}
二、ActionContext 理解
1、什么是 ActionContext?
ActionContext 是 map 结构的容器,ActionContext 是 Action 的上下文,存放Action 执行过程中的数据信息。
ActionContext 存放 Action 的数据、ActionInvocation request 的数据、session 的数据、application 的数据、locale 的数据、conversion errors 等。
每次请求时会为当前线程创建一个新的 ActionContext。而 ActionContext 采用了ThreadLocal 的方式来存放 ActionContext,所以 ActionContext 是线程安全。
protected void postInit( Dispatcher dispatcher,
FilterConfigfilterConfig) {
}
public void doFilter(Servlet Request req, ServletResponse res, FilterChain chain) throws IOEx
HttpServletRequest request = (HttpServlet Request) req;
HttpServletResponse response = (HttpServlet Response) res;
try {
prepare. setEncodingAndlocale(request, response)
prepare. createActionContext (request, response);
prepare. assignDispatcherToThread (
if excludedPatterns ! = null && prepare. isUrlExcluded
(request, excludedPatterns) ) {
chain. doFilter(request, response);
} else {
request = prepare. wrapRequest(request);
ActionMapping mapping prepare. findActionMapping
(request, response, true);
if (mapping == null) {
boolean handled execute. executeStaticResource
Request( request, response);
if (!handled) {
chain.doFilter(request, response);
} else {
* Creates the action context and initializes the thread local
*/
publicActionContextcreateActionContext (HttpServletRequest request, HttpServlet Response res
Actioncontext ctx;
Integer counter = 1;
IntegeroldCounter= (Integer) request. getAttribute(CLEANUP
RECURSION_ COUNTER)
if (oldcounter != null) {
counter = oldCounter + 1
}
ActionContext oldContext = ActionContext. getContext( );
if (oldcontext ! = null) {
// detected existing context, so we are probably In a forward
ctx new ActionContext(new HashMap< string, Object> (oldContext. getContextMapo));
} else {
Valuestack stack = dispatcher. getContainer( ) . get Instance (ValuestackFactory. class) . cr
stack. getContext( ). putall(dispatcher. createContextMap
(request, response, null, servI
ctx = new ActionContext(stack. getContext());
}
request.setAttribute(CLEANUP RECURSION COUNTER, counter)
ActionContext.setContext(ctx);
return ctx;
2、获取 ActionContext
ActionContext getContext()获取。由于ActionContext是线程安全的,并且是通过静态方法获取的,所以在本线程中的非Action类中也可以访问。(有些公共数据处理完可以直接放置)
*注意点:ActionContext 是基于请求创建的,所以在非请求的线程中是不能使用ActionContext 对象的。如:filter 的 init()方法。
* 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. get Factory( ) . createvaluestack( );
// context new Actioncontext(vs, getContext())
// setContext(context);
//}
}
3、ActionContext 的简图
//Cleans up a request of thread locals
public void cleanupRequest(Httpservlet Request request) {
Integer counterval = (Integer) request.getAttribute(CLEANUP _RECURSION_COUNTER)
if (counterval != null) {
counterval !=1;
request.setAttribute(CLEANUP_ RECURSION_ COUNTER, counterval);
if(counterval > e) {
if (log.isDebugEnabled( ) ) {
log.debug(skipping cleanup counter ="+counterval);
}
return;
}
}
// always clean up the thread request, even if an action hasn't been
try {
dispatcher.cleanUpRequest (request);
} catch (IOException e) {
if (LOG.isWarnEnabled( )) {
LOG. warn( " Cannot clean up the request, some files can still
StrutsConstants. STRUTS_ MULTIPART SAVEDIR);
}
} finally {
Actioncontext.setContext(null)
Dispatcher. setInstance(null);
}

