关于servlet、springmvc、struts2执行原理的一些想法

最近一直困扰在 servlet、springmvc、strus2 他们的区别与联系,这一类的问题中,今天做一下思路的梳理

servlet是个什么东西

当我们查阅资料的时候,大致会查到一些类似于:“Servlet是sun公司提供的一门用于开发动态web资源的技术…”。
没错,这些东西看起来很烦。
所以我们直接从servlet生命周期看:

何时创建:默认第一次访问时创建 执行init方法
何时销毁:服务器关闭时销毁 执行destroy方法
经过一些方法:service方法

那我们来描述一下具体做了什么:

当servlet容器(不知道servlet容器是什么?举例:tomcat,熟悉不)接收到一个请求时,servlet容器会针对这个请求创建servletRequest和servletResponse对象。

然后调用service方法。并把这两个参数传递给service方法。Service方法通过servletRequest对象获得请求的信息。并处理该请求。

再通过servletResponse对象生成这个请求的响应结果。然后销毁servletRequest和servletResponse对象。

我们不管这个请求是post提交的还是get提交的,最终这个请求都会由service方法来处理。

所以我们大概知道了这个过程,其实无非就是为我们的web程序进行 “接收参数-处理-返回结果”,这样的一个过程。
这么一想,嗯,好像servlet没有那么神圣了…

我们再从servlet的生命周期看,结合一个例子(至于继承的HttpServlet,它其实就是 HTTP 实现 javax.servlet.Servlet 接口的 Java 类)
在这里插入图片描述
web.xml配置:
在这里插入图片描述
当我们第一次访问 /demo1 时候,那 init() 方法就调用了,然后会调用 service方法(doGet、doPost);
因为只调用一次init(),所以接下来我们无论访问多少次 /demo1,也都只是复用这个 ServletDemo1.
那由此产生疑问,其他的人访问 /demo1,是否会产生新的servlet?
不会。
servlet 为单例
说一不二

springmvc又是个什么东西

一个表现层的框架。
对servlet进行了封装。

我们来看一下springmvc的执行流程(图都是这些图,我也没办法,凑合看吧):

描述:
1、用户发送请求至前端控制器DispatcherServlet

2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、DispatcherServlet调用HandlerAdapter处理器适配器

5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、Controller执行完成返回ModelAndView

7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet

8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器

9、ViewReslover解析后返回具体View

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、DispatcherServlet响应用户

嗯…看完好像大概是了解了它的执行流程,但是说实话这玩意好像和背书没啥区别
仔细想一想,好像 springmvc 和 servlet 做的事情好像没啥太大区别
那么
springmvc怎么就可以像servlet一样的工作呢?

那我们刚才看到了 servlet的demo中,web,xml 是对servlet有配置的
好,我们去看一下 springmvc 项目的 web,xml

在这里插入图片描述
哎呦,这是什么,貌似似曾相识,是 servlet 的配置,那这个 DispatchServlet 好像是似曾相识,那我们回过头去看 springmvc 的执行流程。
是了,是中央控制器,是 springmvc 的核心
然后我们点击它进去看一下,这货是个什么

在这里插入图片描述
它继承了一个名字叫做 FramworkServlet 的类
这货又是啥 ???问号三连
读一下代码,发现还是不知道他是干啥的(你说菜不菜)
在点进去看下

在这里插入图片描述
HttpServletBean ?
???问号三连
读了下代码,你懂得(你说菜不菜)
好,我们接着往下看吧

在这里插入图片描述
啊,有没有遇见春天的感觉,终于有一个认识的了
HttpServlet!!!
原来是你
(HttpServlet 三连:你是谁?我跟你很熟吗?你了解我?)
额…我确实还是不知道springmvc的代码具体做了什么
但是有一点是明确了,DispatchServlet 是继承自 HttpServlet !!
所以说,springmvc 的核心还是一个servlet .
我个人的理解来说,springmvc 框架本身维护着一个servlet,那么所有访问连接都是在这个 servlet中进行操作,springmvc通过自身的请求映射,找到所要访问的方法上。所以springmvc是基于方法的

之前一直听人说 springmvc默认是单例,一直不大理解,如今看来,springmvc 基于servlet,而 servlet 是单例,所以 springmvc 默认是单例

再来看Struts2是个什么东西

与springmvc 类似,是一个表现层的框架。

有了前面的思路,我们可以想到,这货既然能跟 springmvc 做相同的事,那它是不是基于servlet
走,看一下web.xml
翻来覆去看了N遍(N=2)
发现居然没有 servlet 标签
这就证明,strust2 不是基于 servlet,它只是类似于 servlet

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

还是来看一下执行流程吧:
在这里插入图片描述
从上图可以看出,一个请求在Struts2框架中的处理大概分为以下几个步骤:
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求;
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin);
ActionContextCleanUp主要是延长Action中属性的生命周期,包括自定义属性,以便在jsp页面中进行访问,让actionContextcleanup过滤器来清除属性,不让action自己清除。
  3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action;
  4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;
  5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类;
  6、ActionProxy创建一个ActionInvocation的实例。
  7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
  8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper。

结合代码看一下
在这里插入图片描述
嗯…好像大致是看懂了(哦?真的吗)
没错,strus2所做的操作与servlet类似,那他怎么做到不依赖于 servlet 呢?
下面是我借鉴来的一段分析:

①启动服务器(tomcat)将会自动加载配置文件,加载过程如下:
服务器启动,init()方法被执行
在这里插入图片描述
②客户端初始化一个指向Servlet容器(WEB容器)的请求;

③这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:(SiteMesh Plugin)。

④接着StrutsPrepareAndExecuteFilter被调用,StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action。

在这里插入图片描述

⑤如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
在这里插入图片描述

⑥ActionProxy创建一个ActionInvocation的实例。ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。拦截器默认执行defaultStack里面有一系列的interceptor。

⑦一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper,响应的返回是通过我们在web.xml中配置的过滤器

⑧如果ActionContextCleanUp是当前使用的,则FilterDispatecher将不会清理threadlocal ActionContext;如果ActionContextCleanUp不使用,则将会去清理threadlocals。


以上是分析过程,我们可以看到,在 ⑤ 以前,请求参数都是以 HttpServletRequest 形式存在的,直到“ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类” 这一步骤时,struts2 将 HttpServletRequest 的参数转为自己的域对象中的参数,之后再执行请求。
那也就是说,请求在真正到达 Servlet 之前,就被 Struts2 自己过滤掉了
这样就可以做到与 servlet 的解耦
(struts2的思想是这样的,所以我们在编程时尽量避免直接访问 servlet API, 至于如何使用 request 等对象,可以参照这一篇文章就好像我们尽量不把 springmvc 配置成多例一样。)
之后 ActionInvocation 会找到具体 Action 类来执行
所以我们可以看到,在运用struts2的时候,我们可以用 Action类 的属性(必须提供set、get 方法)通过值栈进行数据的传递。
也就是所谓是属性驱动
所以 struts2 是基于类来做开发,那么,既然是类,类是属性肯定不能让其在线程之间共享,所以strus2是多例的
,无法配置成单例(配置成单例还怎么用,所有的请求返回结果一致吗?)

至此,思路基本上算是屡的清晰了一些,springmvc、struts2 项目的代码没有贴出来,不过不重要,今天主要是屡清楚思路。
这两个框架现在在项目中的运用还是很多的,随便找一下就可以找出来很多的代码。
有说的不对的地方,还请路过的大神指正。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值