struts1的本质是一个servlet+jsp+自定义tag+javaBean;
struts1的核心控制器是一个servlet
struts1的流程:当Web服务器启动的时容器先将ActionServlet装载进虚拟机并实例化,接着调用ActionServlet的init()方法,首先初始化内部的国际化,然后初始化额外的配置(getServletConfig().getInitParameter("config");getServletConfig().getInitParameter("convertNull"););接着初始化ActionServlet,是通过用digester去解析web.xml文件并把web.xml里面的属性转换成Java对象,并封装到ActionServlet里。(如图)
web.xml(用流) ActionServlet
| |
| |
parse(input)<-----------digester--------->push(object)
| |
| |
xml------------------------------------>java object然后初始化链(initChain):首先检查用户有没有在web.xml配置chainConfig,如果没有就用默认的org.apache.struts.chain.chain-config.xml文件,然后用digester去解析这个文件。并初始化struts1的处理类。
接着就是初始化moduleConfig:主要是用digester去解析struts-config.xml文件,并把这个文件里面的一些属性一Java 对象的形式封装到ModuleConfig。然后初始化 initModuleMessageResources(moduleConfig);
initModulePlugIns(moduleConfig);
initModuleFormBeans(moduleConfig);
initModuleForwards(moduleConfig);
initModuleExceptionConfigs(moduleConfig);
initModuleActions(moduleConfig);
struts2的核心是是拦截器,而这拦截器又是典型的AOP实现。
struts2的核心控制器本质是个过滤器,所以要遵循servlet的规范,当web服务器加载的时候,去调用web.xml配置的struts2的过滤器的init方法,在该方法中首先创建Daspatcher对象,然后Daspatcher调用自己的init方法,这才开始struts2的真正的初始化,struts2为每个配置文件都提供了一个处理类(属性文件有属性文件的处理类,xml文件有xml的处理类,客户配置的文件有客户配置的处理类),体现了单一职责原理,而这些处理类都公用了一个父类,这又体现了策略模式。
然后把这些处理类全部封装到configurationManager对象中,接着创建一个容器,把当前的对象(也就是daspatcher)注入到容器中。
进入doFilter方法
首先设计编码,默认为UTF-8(因为UTF-8是国际通用的)所以在用struts2写项目的时候不需要转码。接着创建一个ActionContext(首先构造一个ValueStack其实是OgnlValueStack,然后将request、session、ServletContext等用相应的map集合封装起来,然后把这些封装的map对象用另一个map封装,这样就达到了与servlet的解耦,接着声明一个attr map集合,将request、session、servletContext所相应的map集合封装起来,这就是为什么attr的map可以实现在request、session、application中轮询值的原因。最后将attr的map集合放进那个上面另一个map中,再把这个map放到ActionContext中)。再创建一个ActionMapping,它是通过ActionMapper来指定的。(ActionMapper是用来决定是不是要调用一个Action来处理这个请求)。再接着创建ActionProxy(ActionProxy通过ConfigurationManager询问框架的配置的文件找到需要调用的Action类)接着创建AcitonInvocation实例,同时ActionInvocation通过代理模式调用Action,在调用Aciton之前根据配置加载Action相关的所以Interceptor(把这些拦截器以栈的形式,进行调用),最后返回结果result.