struts1是jsp + tag + servlet组成的,struts1最核心的是ActionServlet。
web.xml是所有的web程序的最基本的入口。
struts1定义了一个标准的servlet,继承ActionServlet。
在tomcat启动的时候,就加载web.xml文件执行servlet.class,找到这个映射的文件调用ActionServlet,在这个类中继
承了HttpServlet对象,它具有servlet的生命周期,所以先执行init()方法,
首先初始化内置文件,如与系统日志相关的日志、警告和错误消息。
然后初始化Struts的核心web.xml中actionServlet的配置。如config
从中我知道只要将struts-config.xml放在web/inf目录下面,就可以把web.xml里的struts-config.xml删除掉,因为我
看到ActionServlet源码默认有字符串类型的web/inf/struts-config路径,通过字符串的加载的好处是可以减少对代码的
依赖性。
执行initServlet()方法,这个方法主要是通过digester类解析web.xml,对servletMapping 属性进行初始化。
在这里我学到了disgester框架,digester是一个经常使用的工具,是将xml文件转换成java对象。以前我们是通过DOM
或SAX把xml转换成java对象。现在就可以通过digester框架把xml直接转换成java对象。disgester出现的目的就是以简
单的方式把xml转换成Ojbect对象。
初始化Struts1里面的Chain(链)框架,给用的到的方法都去初始化一次,通过command执行链中的每一个方 法。在这里
我学到了什么是链框架。链框架是组织执行一些复杂的处理流程。链框架的好处有:如果某个环节失败了,那这条链就会中
断。这样可以减少不必要的执行。还有链框架可以在链中插入节点,一个节点就代表要执行的一个任务,节点由command
表示。ActionCommandBase是节点的父类。链框架体现了开关原则,所谓的开关原则就是对外扩展是开放的,对内修改
是封闭的,比如说客户有需求的时候,就可以直接在节点中加入一个需求,而不需要对其他节点进行修改。
现在讲一下Struts的执行流程
将当前ActionServlet加入到上下文ServletContext()中获取ModuleConfig实例。然后初始化ModuleConfig对象,封装
所有的struts-config.xml的信息,在initModuleConfig里通过Disgester把Struts-config.xml转换成moduleConfig对
象。这样的好处是moduleConfig里面就全部都是字符串。生成链的每一个节点。比如说初始化formBean,拿到配置的
formbean,处理formbean扩展,判断是否设定formbean的类型。然后检查是不是动态formbean。
因为初始化只会执行一次,所以初始化之后会通过freeze()方法冻结MoudleConfig实例,拿初始化参数,它会判断还有
没有其他的struts-config.xml文件,如果有,就把当前struts-config.xml进行一次初始化操作。然后销毁掉这个对象,
并释放内存。
现在我来讲一下Struts处理请求
在Struts里,.do发生的请求被actionServlet拦截下来,如果是get请求,就调用doGet方法,如果是post请求,就调用
doPost方法。doGet和doPost都会调用process方法,统一处理。process方法的主要工作有三点:
1. 根据请求信息获知所请求的模块名称,从ServletContext中获得与请求模块对应的的 ModuleConfig对象,并存储到
request中。
2. 根据模块信息获得相应的RequestProcessor对象,一个模块对应一个RequestProcessor对 象,
RequestProcessor对象将关联与所属模块对应的ModuleConfig对象。
3. 调用RequestProcessor对象的process方法,将request和response作为参数传递给它。
看了源代码才知道struts真正的处理请求不是ActionServlet,而是链。像Struts1处理一个请求就用到了职责链模式,根
据用户的配置确定要不要执行链上面的命令,比如需不需要校验,用不用ActionForm。这个链上面的每个节点就是一个命
令,只做一件事情,体现了单一职责原则。如果要添加一个新的命令,加到链就行了,不用修改其它的命令,对修改某个命
令是封闭的,体现了开放封闭原则。
然后再说一下动态action处理流程
首先说明一下,DispatchAction继承于BaseAction。而BaseAction是继承Action,因此DispatchAction也是一个普通
的Action。
首先拿到用户配好的参数,
然后找到拿出来是哪个方法名,取出用户传过来的值。
如果方法名为空,就抛出一个异常。否则通过反射机制,填充一个字符串过来,拿到一个方法,然后强制调用这个方法。
现在讲一下LocalAction
继承LocalAction,必须要调用super方法。它直接从form对象里拿到一个属性(一个国家的语言),强制放到一个session
里。因为它在执行方法的直接session好了,所以在设多个语言的时候就不用一个一个的写了,自动加载进去。
通过看属性文件,我发现了一个apptch框架,在这个框架里学到了很多验证框架,比如有Email验证,日期验证。
propertyUtils属性工具类,我通过看源代码知道了propertyUtils属性工具类是-动态的拿到某个字段的读写方法,且能动
态的设计。
现在讲一下Struts标签库中的Link标签:
在struts标签库源码里面,<html:link>标签里面配置了四个跳转属性(action,page,href,forward),每个属性值都有自己
的作用,例如action会自动添加上下文路径和.do到用户传过来的路径里。这个标签完全是可以自定义多个参数的,关键就
在name属性上,原来使用这个name属性就可以将一个Map类型的变量放入request、session、application、page
四种范围的容器内,然后取个key值,填在name属性里就可以了 ,Struts将自动读取这个Map类型对象的所有key和key
所定义的对象,然后自动生成HTML代码 。