我们之前学习了Struts1、Struts2、SpringMVC,他们都属于前端框架,都是对MVC模式的实现,下面对比学习一下这三个框架。
现在用的比较多的是Struts2、SpringMVC, Struts1官方已经停止更新,现在用的也比较少,Struts2其实并不是Struts1的升级,而是继承了WebWork的血统,集成了二者的优点,是在 struts 1和WebWork的技术基础上进行了合并的全新框架,Struts1和Struts2在体系结构上有着较大的差别。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
之前看过一些文章,分别对三种框架进行了较详细的剖析,基于此分别介绍比较一下这三种框架。
一、Struts1
Struts1框架是apache公司的开源子项目,是基于mvc逻辑分层的web层框架实现。是出现最早的web层框架,应用最广发。Struts1框架重点关注的是控制层,对于视图层只是提供了大量的标签,对于model层的影响微乎其微,现在用的也越来越少了。
工作原理:
1、服务器启动,Web应用启动时就会加载web.xml初始化actionServlet和记载struts配置文件(struts-config.xml),读配置信息到内存中,供以后action调用。
2、用户通过客户端向服务器发出一个请求,http://localhost:8080/struts_login/login.do
3、tomcat会创建出HttpRequest和HttpResponse实例,并根据用户的Method请求方式,调用中央控制器的doGet或者doPost方法。我们已经在web.xml配置了所有符合某特定格式的请求都将由struts指定的Servlet来处理。比如:只要是以.do结尾的请求(*.do)都由 org.apache.struts.action.ActionServlet来对其进行处理.ActionServlet会拿到用户的请求,并且去分析这个URL,ActionServlet中央控制器会截下 /login. 截下来之后,它是为了去struts-config.xml这个配置文件里面找<action>标签path属性的值等于所截部分的那个 Action,将Action标签里面的信息放在ActionMapping里面。
4、根据ActionMapping中的name名称查找ActionForm,如果配置了ActionForm,那么就到request或session中查找,如果在request或session中存在已经创建的ActionForm,那么将返回;如果不存在,那么会根据ActionForm的完成路径采用反射进行创建,再将创建好的ActionForm放到reqeust或session中。
5、首先执行ActionForm中的reset方法进行重置,然后得到表单中所有输入域的name名称,再调用request.getParameterValues(),根据name名称得到相应的值,最后将表单中的数据全部放到一个map中,map中的key为表单输入域的名称,map的value位表单输入域的值(字符串数组),接下来调用一个第三方组件BeanUtils,将Map中的值,根据ActionForm中的setter方法设置到ActionForm上。
6、根据Action的完成类名称到Map中查找,如果存在就在返回Action对象,否则根据Action类的完整名称采用反射去创建,再将创建好的Action放到Map中。所以struts1的Action是单实例的,存在线程安全问题。找到对应的action之后,ActionServlet会把表单提交的数据给存放(生成对应调用 set/get方法)到struts-config中相应的action标签的name属性值指定的actionform类中(若有, [actionform的子类,并且在form-bean标签中配置了,若要进行数据验证可以在actionform中覆盖validate方法,推荐使用js,减轻服务器负担]),同时把actionform和当前HttpServletrequest 对象注入到代调用的action方法中。
7、执行用户自定义的Action中的Execute方法,将ActionMapping,ActionForm,request,response传递过去,将ActionForward返回给ActionServlet。
8、根据返回的ActionForward完成转向,ActionForward对象根据此action配置的<forward>匹配name进而调转到对应path的jsp页面上,返回结果给客户端。
二、Struts2
Struts2其实并不是Struts1的升级,而是继承了WebWork的血统,集成了二者的优点,是在 struts 1和WebWork的技术基础上进行了合并的全新框架,是基于Filter拦截实现的。
工作原理:
1、Tomcat服务器启动,Web应用启动时,首先会加载web.xml文件,然后初始化Filter过滤器,初始化org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter监听程序。这时,会把Struts2的配置文件读到内存里面(如果是Struts2与Spring集成,会是Listner先启动,Spring完成Struts2的Action的创建,不耽误Struts2文件的初始化)供以后Action调用。
2、用户访问浏览器,发送请求,指向Servlet容器。
3、容器tomcat会创建出HttpRequest和HttpResponse实例;并通过web.xml文件映射请求,截取并获取控制器的名称。
4、然后容器调用StrutsPrePareAndExecutionFilter,StrutsPrepareAndExecuteFilter通过ActionMapper来决定获取Action的信息。
5、如果ActionMapper决定需要调用某个Action,StrutsPrepareAndExecuteFilter把请求的处理交给Action的代理ActionProxy;
6、控制器调用ActionProxy
7、ActionProxy通过ConfigurationManager读取strut.xml配置文件来获取action和interceptor的信息,找到需要调用的Action类。
8、ActionProxy把request请求传递给ActionInvocation对象。
9、ActionInvocation实例使用命令模式来调用,依次调用action和interceptor。
10、根据action的配置信息,产生result,result信息返回给actionInvocation。
11、返回结果给客户端。
特点:
1、线程模式,每一次请求都会产生一个新的实例处理请求,多线程环境下没有数据同步问题。
2、引入数据的依赖注入【页面表单数据注入到Action的注入、实例对象的注入,通过set方法注入】
3、基于AOP的拦截器,可以在每次请求前后灵活控制。
4、配置文件支持表单式,基于约定大于配置,简化配置。
5、内置以插件形式支持ajax如dojo,支持多种末班展示jsp、freemarker,veiocity等。
三、SpringMVC
SpringMVC是基于Servlet拦截实现的,主要由前端控制器(DispatcherServlet)、映射处理器(HandlerMapping)、适配器(HandlerAdapter)、拦截器(HandlerInterceptor)、控制器(Controller)、视图解析器(ViewResolver)、视图(View)这几部分构成。
工作原理:
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet。
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3-4、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
5、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
6、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
7、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。
特点:
1、线程模式:单例模式,效率好。
2、基于方法级别的拦截,而不是基于类。更细粒度的灵活控制。
3、通过注解简化了多配置,但同时在代码中增加了很多和业务不相干的代码。
四、比较
这三个框架中,Struts1的效率三者当中最高。但是Struts1内部是面向抽象类编程,而不是面向接口编程的。Struts2提供了一个名为ActionSupport的基类,虽然不是必须的,但是要想使用Struts2的功能,基本上都会继承它。SpringMVC是面向接口编程,需要实现一个接口(配置文件时)。
1、Struts1的入口点是Servlet,Struts2的入口点是Filter,SpringMVC入口点是Servlet。
2、Struts2是类级别的拦截,每个请求创建一个action,然后通过调用setter方法把Request中的数据注入;SpringMVC是基于方法的拦截,一个方法对应一个Request上下文,而方法同时又跟一个URL对应。
3、Struts2的类属性被所有方法共享,这就无法用注解标识其所属方法了,方法之间独立,但是所有Action变量是共享的。SpringMVC的方法之间基本独立,共享Request数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量。
4、interceptor实现机制:struts2有自己的拦截器机制,SpringMVC用的是独立的AOP方式。虽然struts的配置能继承,但是struts的配置文件量还是比spring mvc大,从使用上来说spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。
5、SpringMVC的配置是基于IOC容器的,一方面方便SpringMVC进行扩展和增强,另一方面有利于与Spring整合;而Struts2与Spring的整合,需要Spring提供了第三方包。
6、Struts2里面可以没有HttpServletRequest和HttpServletResponse,只有getter、setter或ActionContext里的数据,这样就会使Action比较独立。整个web与Action无关,这个action可以在任何环境下独立运行,也就是说,它可以最大限度的被重用。而SpringMVC不像Struts2那样隐藏了HttpServletRequest和HttpServletResponse,而是将它们做为了形参传入控制器的方法中。
7、Struts1的Action与SpringMVC的Controller一样,都是单例的,不是线程安全的。这就意味着,每个Request请求,系统都会用原有的instance去处理。这虽然减少了对象的创建和垃圾收集的时间,但是处理多线程调用时,Controller不是线程安全的,而Struts2是线程安全的。
小结
感觉SpringMVC实现起来更加的清晰一些,而且紧跟时代潮流。Struts2使整个Controller彻底与Web容器解耦,可以方便地进行单元测试。而摆脱了Servlet束缚的Controller,也为整个编程模型赋予了全新的定义。这样的改造不仅使得表达式引擎能够得到最大限度的发挥,同时使得整个Controller看起来更像是一个POJO,从面向对象的角度来看,POJO模式无疑也是所有程序员所追求的一个目标。三个框架虽然都是对MVC模式的实现,有各自的实现思路工作流程,各有各的优点,但也要顺应时代潮流才行。