您的位置:首页 > 编程语言 > Java开发

struts2总结:草稿

2015-12-24 10:28 211 查看
Struts2部分

1,说明整个Struts2的流程,越详细越好(10分)

初始化:

struts2是由过滤器驱动的:核心过滤器StrutsPrepareAndExecuteFilter在web应用启动的时候被服务器创建,并驻留服务器内存;

并调用init方法进行初始化;

过程包括:

a  其中对核心分发器 Dispatcher dispatcher
=
init.initDispatcher(config);进行初始化,核心分发器Dispatcher在被创建的过程中

   需要接收两个参数;new
Dispatcher(filterConfig.getServletContext(),
params);即对核心过滤器配置的初始化参数和

配置文件的加载顺序;private static final String
DEFAULT_CONFIGURATION_PATHS =
"struts-default.xml,struts-plugin.xml,struts.xml";

struts.xml配置文件解析器:XmlConfigurationProvider---

静态注入:将struts框架工作所需的对象,包括:

;通过如下方法进行注值;

org.apache.struts2.config.BeanSelectionProvider.register(ContainerBuilder,
LocatableProperties);

需要注入的是,这些值的注入都有一个特点:比如;

<bean
type="com.opensymphony.xwork2.ActionProxyFactory"
name="xwork"

class="com.opensymphony.xwork2.DefaultActionProxyFactory"/>

<bean
type="com.opensymphony.xwork2.ActionProxyFactory"
name="struts"

class="org.apache.struts2.impl.StrutsActionProxyFactory"/>

都有一个公共的接口:com.opensymphony.xwork2.ActionProxyFactory,并针对该接口有多个实现;struts内部肯定是通过接口

引用调用实现类的方法,这又是面向接口编程,大大提高了程序的扩展性;如果你要改写这些配置,

只要在你的struts.xml配置文件中进行配置,但是前提有一个你必须实现它的接口,并将type定义为该接口,将你的实现类

定义为class,并取和上面相同的名称,达到覆盖的效果;

struts2拦截器的创建机制:只有使用到的拦截器才会被创建,这个很好理解,是为了内存消耗的考虑,你没事叫人过来干嘛,

叫过来,又叫人回去,啥事也不干,你不是有病吗?

1
还是由struts2的核心配置文件解析器XmlConfigurationProvider进行解析;

将解析到的一个个interceptor-ref节点封装成InterceptorMapping,多个InterceptorMapping组成一个集合

List<InterceptorMapping>
interceptors;多个集合构成一个

InterceptorStackConfig拦截器栈映射对象;

然后交给ObjectFactory统一创建,具体的是由StrutsObjectFactory进行创建;

protected void loadInterceptorStacks(Element element,
PackageConfig.Builder context) throws ConfigurationException
{

  
 //这句代码的意思是,看看配置文件中哪些拦截器栈被引用了,引用了,就进一步的

  
 //追踪拦截器栈中的拦截器

    NodeList
interceptorStackList =
element.getElementsByTagName_r("interceptor-stack");

       
for (int i = 0; i <
interceptorStackList.getLength(); i++) {

           
Element interceptorStackElement = (Element)
interceptorStackList.item(i);

           
InterceptorStackConfig config =
loadInterceptorStack(interceptorStackElement, context);

           
context.addInterceptorStackConfig(config);

       
}

    }

这最后所有的对象都会跑到ContainerImpl这个容器中,这是struts2的核心容器;即IOC容器;

配置文件默认解析顺序为

default.properties(struts默认的常量信息)--->struts-default.xml--->struts-plugin.xml--->struts.xml;

如果其中有相同信息则后者覆盖前者,因此我们要覆盖struts默认的常量最好是放在struts.xml中的constant元素中;

当然一些插件为了覆盖struts的默认常量也会在对应的struts-plugin.xml中定义常量;并最终汇总到struts.xml中;

总结:核心过滤器的init方法主要做的事:

1 初始化配置文件;

2 初始化核心分发器:Dispatcher

3 初始化PrepareOperations:

   他的作用

    
a:
准备struts的执行环境,具体来说就是创建ActionContext;

    
b:对request进行包装;

    
c:action路径的寻址和过滤;

4 初始化ExecuteOperations

   
他的作用:

   
a:执行静态资源请求;

   
b:执行action;

   
 

拦截器:只有在action中引用到了,才会在应用加载时创建;

即某个拦截器类出现在interceptor-ref中,才会在初始化的时候被创建;

核心过滤器的init方法的作用;

1
加载并解析配置文件,解析顺序为struts-default.xml,struts-plugin.xml,struts.xml;

 
如果这三个文件中有相同内容,则后者覆盖前者;配置文件加载后创建struts基本元素:即<bean
type=*,class=*>

 
结果集合拦截器(只有被引用到的拦截器才会被创建,即interceptor-ref的)

 
需要注意的是<bean>节点对应的元素,type和class的关系,type:

 
是父类或者接口,而class是对应的实现类,我们说过配置文件是有加载顺序的,我们要覆盖struts的默认配置

 
可以在struts.xml,但是覆盖有一个前提,你的实现类,type必须和默认中的type相同;

 
实现类自己定义,因为在struts调用你的实现类是通过type对应的引用来调用的,实际上的实现类是由你提供的'

 
这是完全的面向接口(父类)编程,符合开闭原则;比如说

   <bean
type="com.opensymphony.xwork2.ObjectFactory" name="struts"

  
class="org.apache.struts2.impl.StrutsObjectFactory"
/>这是struts中的默认配置,你要修改他的创建模式;

  
就必须和他继承相同的父类;比如spring集成struts的插件中的struts-plugin.xml配置文件的配置;

   
<bean type="com.opensymphony.xwork2.ObjectFactory"
name="spring"

   
class="org.apache.struts2.spring.StrutsSpringObjectFactory"
/>

   
在struts中一定有这么一行代码:

   
ObjectFactory objectFactory;并提供相应的set,get方法

   
然后在使用到的地方直接就是

   
objectFactory.buildBean();//至于这个buildBean怎么执行不管,但是你的实现类一定要有这个方法;

   
否则就会导致整个框架的混乱

   
开闭原则:

   
实现类你爱怎么实现怎么实现,这是开的一方面;

   
但是你必须得保证,我父类有的方法一定要有实现;

   
或者说我的buildBean一定要能执行;这是闭的一方面;

   
同时配置文件中的内容允许覆盖也正是体现了这点,如果你都不允许他人覆盖你的配置,把什么都写死了,三大框架整合就是

   
个笑话.

   
一句话:开闭原则就是对于扩展性我完全开放,但是对于我struts整个的执行流程,谁都不能动,这是我的根基;

2
当请求到来的时候,首先经过核心过滤器的doFilter方法;这个方法实现了以下功能;

  
a:初始化action执行环境,ActionContext;

    
对请求url进行解析,并判断你的url是否是需要经过struts的核心;

   
如果需要做进一步的处理,如果不需要执行chain.doFilter放行;

   
当然这一步是粗粒度的进行判断,接下来对请求进行包装,解析出对应的action;

   
并在ActionMapping中找看是否存在对应的action映射;

   
如果不存在,继续判断是否是要使用到struts的静态资源,即路径中有

   
"/struts/":对应于org.apache.struts2.template中的静态资源;

   
"/static/"对应于org.apache.struts2下的static包中的静态资源;

    
如果有调用静态资源处理器进行处理,如果没有直接放行;

    如果
actionMapping中有对应的action;

    
执行execute.executeAction(request, response,
mapping);方法,进入struts的核心

    
调用核心分发器的serviceAction方法创建值栈对象ValueStack和contextMap;

    
并创建出ActionProxy,由ActionProxy创建出ActionInvocation,即核心控制单元,他采用的是command设计模式进行设计;;

    
由ActionInvocation控制拦截器和action,

    
和result的执行;

    
在执行proxy.invoke方法就回到ActionInvocation,由ActionInvocation

    
负责拦截器的执行,拦截器执行完成后,执行目标action的目标方法,

    
并返回一个路由串,即结果视图,然后又回到ActionInvocation,继续执行Result中的代码,

    
result根据配置文件中配置的结果视图类型和页面跳转地址,

    
这时候通常还得调用jsp等模板对结果进行处理,---是否使用到标签用OGNL解析器进行处理,

    
形成最终的数据;

    
然后重新回到ActionInvocation,继续调用

    
拦截器的清理工作,拦截器都执行完成后,
响应消息写入到response缓冲区,由服务器取出,

    
以http响应格式输出到浏览器供浏览器解析,

    
核心过滤器的doFilter方法执行结束,

    
本次请求结束;ActionContext中的数据被清空;

    
我们发现核心过滤器和其他过滤器共同构成一个职责链设计模式,整个职责链由tomcat服务器进行控制;

    
每个过滤器完成自己的功能:1要么直接返回数据到页面
2要么执行完自己的功能后通知下一个过滤器执行;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: