Struts工作原理的一些理解

Struts工作原理

 

首先看看struts官方给出的图解,如下:

 

接下来一个个的来看看这个图解里面的的意义所在:

1、  ActionContextCleanUp,在FilterDispatcher源码中有这样一句话:

 finally
 {
            ActionContextCleanUp.cleanUp(req);
 }

 

在ActionContextCleanUp中有这样的代码:

req.setAttribute(CLEANUP_PRESENT,Boolean.TRUE),如果FilterDispatcher检测到这个属性,就不会清除ActionContext中的内容了,而由ActionContextCleanUp后续的代码来清除,保证了一系列的Filter访问正确的ActionContext。在这里ActionContextCleanUp会在doFilter方法中添加一个计数器counter初始化为1,标志着后续的过滤器就不在回清除ActionContext,而是在最后交予之前的ActionContextCleanUp来清理。

2、  Other filter(SiteMesh,etc),调用的先后顺序是这样的,首先是ActionContextCleanUp,然后才是其他的一些Filter,可以在web.xml中这样配置:

<?xml version="1.0" encoding="UTF-8"?>

<filter>

    <filter-name>ActionContextCleanUp</filter-name>

    <filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class>

</filter>

<filter>

    <filter-name>sitemesh</filter-name>

    <filter-class>com.opensymphony.webwork.sitemesh.FreeMarkerPageFilter</filter-class>

</filter>

<filter>

    <filter-name>webwork</filter-name>

    <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>

</filter>

<filter-mapping>

    <filter-name>ActionContextCleanUp</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

<filter-mapping>

    <filter-name>sitemesh</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

<filter-mapping>

    <filter-name>webwork</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

 

 

3、  FilterDispatcher,这是struts核心Filter,主要负责功能有:

  • 执行Actions
  • 清除ActionContext
  • 维护静态内容
  • 清除request生命周期内XWork的interceptors

过滤器首先通过ActionMapper对象判断某个请求是否被映射到Action,如果有配置相应的映射,则终止过滤链,进入Action。

如果之前没有ActionContextCleanUp的计数器提示,这里将自动清除ActionContext,上面也见到,如果ActionContextCleanUp设置计数器标志为1,这这里将不进行ActionContext清理,交由ActionContextCleanUp清理。

维护一些路html,js,css这样一些静态页面的内容请求等。

另外,FilterDispatcher的核心在于ActionMapper,进入FilterDispatcher之后默认会调用init()然后是doFilter()方法,解析配置文件,得到uri,如果有Action配置,进入Action。请求分发完成。

4、  ActionProxy,这是一个动态代理接口,通过调用execute()方法实现代理。有如下的一个方法调用流程DefaultActionInvocation()->init()->createAction()。

(1) 首先来看看ActionProxy:

public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) { 

     ActionInvocation inv = new DefaultActionInvocation(extraContext, true); 

     container.inject(inv); 

     return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); 

} 

 

(2)然后DefaultActionInvocation的init()方法中初始化ActionContext,

// 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);    

 } 

 

(3)并为每一个Request请求创建一个新的Action,存入stack中,

createAction(contextMap);   

if (pushAction) {    

stack.push(action);     

contextMap.put("action", action);     

}     

invocationContext = new ActionContext(contextMap);     

invocationContext.setName(proxy.getActionName());  

 

(4)初始化拦截器Interceptor List,

 // get a new List so we don't get problems with the iterator if someone changes the list    

List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());    、

 interceptors = interceptorList.iterator();  

 

(5)上面createAction()采用跟spring一样的ioc工厂方式创建,将Action写入到配置文件中,首先build相应的bean(action),然后放入到Map中以键值对方式存储,用到时取出。如:

o = appContext.getBean(beanName); 

(6)再然后就是核心的调用invoke方法,遍历调用interceptor。调用invokeAction(),遍历调用Action,采用java反射实现Action中方法的调用:

//java反射机制得到要执行的方法    

 method = getAction().getClass().getMethod(methodName, new Class[0]);  

 

如果没有指定调用的method方法(在struts.xml中配置的method属性),这默认去调用do+Xxx方法处理请求。如:

try {                   

String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);                

method = getAction().getClass().getMethod(altMethodName, new Class[0]);          

} 

 

(7)Action执行完毕,就是接下来的Result.

5、  Result,同Action一样,以工厂模式在java反射基础上创建相应的Result实现HttpServletResponse返回跳转。

另外,struts2还涉及到OGNL标签,国际化等内容,在这里不涉及那么多。

 

posted @ 2014-04-25 11:30  vindanear  阅读(807)  评论(1编辑  收藏  举报