Struts2基本原理

框架可以分为3个部分:核心控制器FilterDispatcher、业务控制器Action和用户实现的企业业务逻辑组件。

基本流程:
1. 客户端浏览器发出HTTP请求
2. 根据web.xml配置,该请求被FilterDispatcher接收
3. 根据struts.xml配置,找到需要调用的Action类和方法,并通过IoC方式,将值注入给Action。
4. Action调用业务逻辑组件处理业务逻辑,包含表单验证。
5. Action执行完毕,根据structs.xml中的配置找到对应的返回结果result,并跳转到相应页面
6. 返回HTTP响应到客户端浏览器

工作原理:
1. 客户端发起一个指向servlet容器的请求(如:Tomcat)
2. 这个请求会经过几个过滤器,到达FilterDispatcher过滤器
3. FilterDispatcher是struts2的核心,在处理用户请求时,它和请求一起相互配合访问struts2的底层框架结构。在web容器启动时,struts2框架会自动加载配置文件里面的相关层数,并转换成相应的类,如:ConfigurationManager, ActionMapper 和 ObjectFactory。 ConfigurationManager存有配置文件的一些基本信息,ActionMapper存有action的配置信息。在请求过程中得所有对象(如:Action,result,interceptors等)都是通过ObjectFactory来创建的。过滤器会通过ActionMapper类来查找请求中需要用到的Action。
4.如果找到需要调用Action,过滤器会把请求交给ActionProxy。ActionProxy为Action的代理对象。ActionProxy通过ConfigurationManger询问框架的配置文件,找到需要调用的Action类。
5. ActionProxy创建一个ActionInvocation的实例。ActionInvocation在ActionProxy层之下,表示了Action的执行状态,或者说控制Action的执行步骤。它持有Action实例和所有的Interceptor。
6. ActionInvocation实例使用命名模式来调用。在ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。通过ActionInvocation.invoke()方法按序调用所有的Interceptor后,调用Action的实现。并在返回时,再次调用Interceptor。
7. Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(不总是,也可能是另一个Action链)一个需要被表示的JSP或者FreeMarker的模板。在表示中的过程中可以使用struts2框架中的标签。



完整步骤与类的调用过程

1.客户端发送一个HTTP请求,tomcat接收后,查看web.xml,找到配置文件中的FilterDispatcher

2.FilterDispatcher中包含了ConfigurationManager和ActionMapper对象,ConfigurationManger中含有struts.xml, default-struts.xml等配置文件中得信息,ActionMapper中含有Action的信息。ActionMapper会查找本次请求需要调用的Action。如果没有找到就执行静态的资源请求。如果找到了action,就会调用dispatcher中得serviceAction方法。

在serviceAction方法中,会通过容器的反射机制获得ActionProxyFactory对象,通过工厂模式的方式创建一个ActionProxy实例。然后调用ActionProxy的execute方法。

3.struts调用的ActionProxy类为StructActionProxy,其中包含一个ActionInvocation对象,ActionProxy就调用ActionInvocation的invoke()方法。

4.默认调用的是DefaultActionInvocation类。ActionInvocation中持有从ActionMapper中获得的与本次请求相关的action类的信息,如namespace,name,需要调用的方法名method等。还持有与这个Action相关的所有Interceptor(protected Iterator<InterceptorMapping> interceptors;一个迭代器)。

在invoke方法中,会依次调用每一个Interceptor,实现方式是:
首先,判断迭代器是否还有下一个Interceptor(hasNext()方法),如果有就获得这个Interceptor调用它的intercept()方法,该方法的参数就是ActionInvocation本身。在Interceptor中又会再一次调用ActionInvocation的invoke方法,使得ActionInvocation能够调用下一个Interceptor。这样就完成了在调用Action之前的全部拦截工作。在调用完成全部的Interceptor之后,ActionInvocation开始调用Action。

在invokeAction()方法中,通过反射机制来获得需要调用的method方法
method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);

其中:methodName是方法名,EMPTY_CLASS_ARRAY是常量Object[],说明该方法没有参数。
然后调用这个method方法:  methodResult = method.invoke(action, EMPTY_OBJECT_ARRAY); 并返回结果集


ActionInvocation根据结果集从配置文件中找到对应的返回结果。


由于invokeAction()方法是在最后一个Interceptor中调用ActionInvocation的invoke方法中被调用的,因此程序返回到最后一个Interceptor中,此时Interceptor就可以在请求返回时进行拦截操作。最后一个Interceptor返回的是倒数第二个Interceptor中调用invoke方法处,以此类推,就实现了与请求进入时顺序相反的拦截操作。例如ExceptionInterceptor拦截器的实现:在请求进入前给请求加上try/catch异常捕获块,在请求返回时,处理异常。


try{
    result =  invocation.invoke();
}catch(Exception e){
      … //异常处理操作。
}

猜你喜欢

转载自mir-tempo.iteye.com/blog/2111296