开发者学堂课程【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 T
est
A
ction
C
ontext
A
ction
extends A
c
tionSu
pport
privates String
u
n
ame
;
public
S
tring
execute
(
)
throws
Exception
{
ActionContext ac = ActionContext.getContext ( );
S
ystem
.
cut
.
println
(
ac
)
;
/
/在此处定义断点
ret
u
rn thi
s
.S
U
CCESS
;
}
二、ActionContext 理解
1、什么是 ActionContext?
ActionContext 是 map 结构的容器,ActionContext 是 Action 的上下文,存放Action 执行过程中的数据信息。
ActionContext 存放 Action 的数据、ActionInvocation request 的数据、session 的数据、application 的数据、locale 的数据、conversion errors 等。
每次请求时会为当前线程创建一个新的 ActionContext。而 ActionContext 采用了ThreadLocal 的方式来存放 ActionContext,所以 ActionContext 是线程安全。
protected void
post
I
nit( Dispatcher dispatcher,
FilterConfigfilterConfig)
{
}
public void doFilter(Servlet Request re
q
, ServletResponse res, FilterChain chain) throws
IO
Ex
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
pub
lic void cleanupRequest(Httpservlet Request request)
{
Integer counterval = (Integer) request.getAttribute(CLEANUP
_
RECURSION
_
COUNT
ER)
if
(counterval
!
= null)
{
counterval
!=1;
request.setAttribute(CLEANUP_ RECURSION_
COUNTER, counterval)
;
if(counterval >
e
)
{
if (log.isDebugEnabled( ) )
{
l
og.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
{
Act
i
oncontext
.
setContext(null)
Dispatcher. setInstance(null)
;
}