spring web功能的实现原理
2020-03-30 11:58:20 0 举报
为你推荐
查看更多
spring mvc的实现原理详解
作者其他创作
大纲/内容
实现
DispatcherServlet是spring实现web功能的核心类,其UML图可参考:https://www.processon.com/diagraming/5e7af1a9e4b027d999ca655bDispatcherServlet的实现便是通过继承HttpServlet(实现了Servlet接口),重写了相关的请求处理的方法(init方法和service方法)完成自己的web容器的实现。其具体实现原理如下:
<接口>LastModified
+ long getLastModified(HttpServletRequest)
7). 执行拦截器链的preHandle;8). 执行适配器handle方法,调用handler的处理器执行业务逻辑处理,得到ModlerAndView;9). 根据返回的ModlerAndView,执行applyDefaultViewName,判断如果ModlerAndView为空,或者没有视图,则生成默认视图;10). 执行拦截器链的postHandle;(此处如果启用了异步执行任务(asyncManager.isConcurrentHandlingStarted()),则此处直接return,进入finally代码块)11). 如果之前的处理中出现异常,则进行异常视图处理;12). 视图渲染,根据视图跳转页面;13). 执行拦截器链的afterCompletion;14). 执行AsyncHandlerInterceptor 的 afterConcurrentHandlingStarted15). 如果是MultipartContent类型的request,则cleanup MultipartContent
二、servlet的生命周期
handler的示例如下:
一、概念
三、DispatcherServlet
1.首先DispatcherServlet作为一个servlet一个具体实现,当通过java configuration或web.xml的方式配置到web服务器之后,web服务器在启动之后,会调用其初始化方法,该初始化方法在HttpServlet中进行了重写,并调用了无参init()方法,DispatcherServlet的第二级父类HttpServletBean中进行了重写,在重写方法里面完成了将自身这个servlet实例转换为spring的BeanWrapper,然后进行属性注入,如:contextConfigLocation等。并在该方法中调用了自身的两个空方法:1.initServletBean()和 initBeanWrapper(BeanWrapper),这两个方法的实现有子类完成;2.在DispatcherServlet的直接父类FrameworkServlet中,完成了initServletBean的重写,在该方法中实现了spring的servlet子容器的创建,参考initWebApplicationContext方法(注意该方法最后调用了onRefresh方法,该方法的具体实现在DispatcherServlet中)。此外,在initWebApplicationContext方法中还将在ContextLoaderListener中创建的spring容器作为子容器的parent进行设置;3.同时在FrameworkServlet也完成sevice的重写,以及doGet,doPost的重写,但最终都调用了processRequest方法,processRequest中最终调用了抽象方法doService,在子类中实现;并实现了destory方法,进行spring上下文容器的close()操作;4.DispatcherServlet重写了父类两个方法:doService和onRefresh。doService最终将实现委托给了doDispatch,onRefresh则委托给了initStrategies。initStrategies中进行了spring实现web功能需要用到的全局变量的设置,如关键的视图解析器,HandlerMappings。HandlerAdapters,主题资源等,,这些都定义在DispatcherServlet的属性中。而doDispatch方法是spring实现控制器路由映射的核心。5.在doService中,首先将spring的ApplicationContext、localeResolver,themeResolver,themeSource等属性添加到Request中,然后调用doDipatch;6.在doDispatch中,真正完成了spring的请求处理过程。 1). MultipartContent类型的request处理; 2). 根据request信息寻找对应的Handler,即根据配置的HandlerMapping和request路径,找到匹配的Handler(即我们说的mvc中的controller); 3). 如果找到对应的handler,则添加相应的请求拦截器到执行链(包括跨域cors请求的处理); 4). 如果没有找到对应的handler,则进行相应的错误处理,请求结束; 5). 根据当前的Handler寻找对应的HandlerAdapter,这是典型的适配器设计模式。因为spring中定义了各种类型的Handler,其api的处理入口方法不一致,因此需要一个统一定义的适配器来统一接口,以便在doDispatch中调用; 6). 缓存处理,Last-Modified+ If-Unmodified-Since。UML类图如下:
<接口>HandlerInterceptor
当web应用终止时,会调用servlet的destroy方法,我们可以在该方法中进资源释放等操作,如数据库连接,关闭文件输入输出流等;然后同时会销毁Servlet实例,以及相关联的ServletConfig对象。
关于异步web请求处理,请参考:https://www.cnblogs.com/bjlhx/p/10444814.html
servlet容器加载servlet类,把servlet类的class加载到内存中;创建一个servletConfig对象,包含了servlet的初始化配置信息,包括ServletContext(上下文);servlet容器冲击Servlet对象,并将ServletConfig作为参数调用该对象的init方法,进行初始化。
四. 关于拦截器链
3.销毁阶段
继承
Handler
接口和类
+ operation1(params):returnType- operation2(params)- operation3()
<接口>AsyncHandlerInterceptor
LastModified接口
属性依赖
preHandle:Handler处理之前执行postHandle:Handler处理之后执行;afterCompletion: 完成视图渲染之后执行;afterConcurrentHandlingStarted:当处理程序启动异步请求时,DispatcherServlet会退出,如下图,而不会像通常对同步请求那样调用postHandle和afterCompletion,因为请求处理的结果(例如ModelAndView)此时可能尚未准备好,并且将从另一个线程同时生成。 在这种情况下,afterConcurrentHandlingStarted在将在doDispatch的finally代码块执行,从而允许实现在将线程释放到Servlet容器之前执行诸如清除线程绑定属性之类的任务。
<类>HandlerAdapter实例
- Handler实例
+ getLastModified,调用Handler实例的getLastModified
六. 总结
2.运行阶段
综上所述,其实mvc的关键就是在于其在强大的spring容器的扩展性上,实现的基于HandlerMapping和HandlerAdapter的请求处理分发逻辑。与其他许多Web框架一样,Spring MVC围绕前端控制器模式进行设计,在该模式下,其核心DispatcherServlet提供了用于请求处理的共享逻辑实现,而实际工作是由可配置的委托组件执行的,这些委托组件依托于强大的spring 容器的可扩展性和可配置性上。 因此该模型非常灵活,并支持多种工作流程。
在上文的执行逻辑中,提到了执行链,其实就是一个封装了Handler和拦截器链的对象,doDispatch中对拦截器链的执行都是通过该对象代理执行的,如下图:
五. 关于执行链
<接口>HandlerAdapter
当服务器接收到一个请求,会根据配置的servlet路径匹配到对应的Servlet实例对象,并生成ServletRequest和ServletResponse对象,作为参数调用Servlet实例的service方法,无论是post,还是get,还是其他方法都会通过service方法进行处理。
逻辑如下:
1.初始化阶段
0 条评论
回复 删除
下一页