当前位置: 首页 > 后端技术 > Java

SpringMVC执行过程及源码详解

时间:2023-04-01 15:16:26 Java

SpringMVC中各组件的初始化过程在之前的文章中分享过:初始化过程1.DispatcherServlet,SpringMVC的一个公共组件:前端控制器,处理请求和统一响应,是整个过程控制的中心。调用其他组件处理用户请求HandlerMapping:处理器映射器,根据请求的url、method等信息找到Handler,即controller方法Handler:Processor,Handler在DispatcherServlet的控制下处理具体的用户请求HandlerAdapter:Processor处理器适配器通过HandlerAdapter执行处理器(控制器方法)。ViewResolver:视图解析器,不需要工程师开发,由框架提供,用于执行视图解析。视图:视图通过页面向用户展示模型数据。2.DispatcherServlet(前端控件IDEA中快捷键Ctrl+Shift+Alt+U可以查看继承图图TDA[Servlet]A==>B[GenericServlet]B==>C[HttpServlet]C==>D[HttpServletBean]D==>E[FrameworkServlet]E==>F[DispatcherServlet]从上图可以看出DispatcherServlet的顶层接口是Servlet3.调用组件处理请求$\color{#F00}{虽然我们看的是不同的类如果通过继承或者实现把中的调用过程放在同一个类中}$$\color{#F00}{其实我们看的是同一个类中的方法调用。}$1Servlet接口从Servlet接口开始一步步分析,在Servlet接口中,有下图中的五个抽象方法。快捷键:Alt+7用户每次发送请求,Servlet容器都会调用service()方法处理该请求}2.GenericServletabstractclasspublicabstractclassGenericServletimplementsServlet,ServletConfig,java.io.Serializable{//可以看到Servlet中的service()方法没有实现@Overridepublicabstractvoidservice(ServletRequestreq,ServletResponseres)抛出ServletException、IOException;}GenericServlet在Servlet中没有实现service()方法,所以继续按照继承结构进行梳理3.HttpServle抽象类可以看到又调用了service(request,response)方法,如下图.请求方法有以下依据req.getMethod()获取请求方法并调用对应的doGet、doPut等方法,继续往下看4.HttpServletBean抽象类可以发现HttpServletBean并没有重写service()方法,并使用了父类HttpServle中的方法5.FrameworkServlet抽象类FrameworkServlet中重写了doGet等方法,使用该类中重写的方法可以看出,不管service中的逻辑如何,processRequest(request,response)方法被执行,所以我们只需要检查这个方法6.DispatcherServlet类6.1执行流程图为什么doDispatcher()是整个流程控制的中心,它调用其他组件来处理用户请求?然后看下面的流程:可以理解为用户向服务器发送请求,请求被SpringMVC前端控制器DispatcherServlet捕获。执行流程图。大家可以参考下图看看接下来的流程。图6.2中的步骤2和3。处理器映射器在此步骤中返回到处理器执行链。当前包含拦截器的类重写了父类中的doservice()方法,发现该方法的核心是doDispatcher方法。关键是我们看到这个方法实现了图6.3中的4、5、6、7步。Adapter1.包含拦截器的执行逻辑接下来是拦截器的前端方法。首先看一下拦截器的执行顺序,方便理解后面的代码流程。请欣赏源码流程:上图中的适配器方法拦截器的前置方法对应上图的逻辑处理(上图详解)。顺序是实际调用处理程序方法并返回ModelAndView对象。拦截器的post-method是图6.4中的第8、9、10步>进入这个Method查看拦截器最后执行的方法,返回给用户5.总结1.简要总结1.所有SpringMVC请求都是通过DispatcherServlet统一分发。DispatcherServlet在将请求分发给Controller之前,需要借助SpringMVC提供的HandlerMapping定位到具体的Controller。2、HandlerMapping接口负责完成客户端请求到Controller的映射。3、Controller接口会处理用户请求,这与JavaServlets扮演的角色是一致的。一旦Controller处理了用户请求,它将ModelAndView(数据和视图)对象返回给DispatcherServlet前端控制器。从宏观上看,DispatcherServlet是整个Web应用的控制器;从微观上看,Controller是单个Http请求处理过程中的控制器,ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。4、返回的视图需要负责通过ViewResolver接口(视图解析器)在web应用中找到View对象,从而渲染相应的结果给客户端。二、详细总结1、用户向服务器发送请求,请求被SpringMVC前端控制器DispatcherServlet捕获2、DispatcherServlet解析请求URL,获取请求资源标识符(URI),确定映射对应请求URI3.根据URI,调用HandlerMapping获取Handler配置的所有相关对象(包括Handler对象和Handler对象对应的拦截器),最后以HandlerExecutionChain执行链的形式返回目的。4.DispatcherServlet根据获取到的Handler选择合适的HandlerAdapter。5.如果HandlerAdapter获取成功,此时会执行拦截器的preHandler(…)方法[转发]6.提取Request中的模型数据,填写Handler入参,开始执行Handler(Controller)方法来处理请求。在填充Handler的输入参数的过程中,根据你的配置,Spring会帮你做一些额外的工作:6.1.HttpMessageConveter:将请求消息(如Json、xml等)转换为对象,并将对象转换为指定的Response信息6.2HttpMessageConveter:将请求消息(如Json、xml等)转换为对象,并将对象转换为指定的响应信息6.3数据转换:对请求报文进行数据转换。例如将String转换为Integer、Double等。6.4数据格式化:对请求报文的数据进行格式化。如将字符串转换为格式化数字或格式化日期等。6.5数据校验:校验数据的合法性(长度、格式等),并将校验结果存入BindingResult或Error7.Handler执行后,返回一个ModelAndView给DispatcherServlet对象。8、此时拦截器的postHandle(...)方法[reverse]会开始执行。9.根据返回的ModelAndView(此时会判断是否有异常:如果有异常则执行HandlerExceptionResolver进行异常处理)选择合适的ViewResolver进行视图分析,根据Model渲染视图和查看。10.渲染视图后,执行拦截器[reverse]的afterCompletion(…)方法。11、将渲染结果返回给客户端。