Spring MVC请求处理过程源码简析

  1. Spring MVC简介

Spring MVC是目前使用的比较广泛的一个MVC框架,通过Spring MVC可以很轻松地构建一个完整的Web应用程序。并且Spring MVC对其他的框架有很好的兼容性,比如可以通过集成MyBatis框架去更好地和数据库进行交互。一个Web应用最核心的功能就是对到来的请求进行响应,下面我们通过Spring MVC的源码来分析下Spring MVC具体是怎样去响应一个请求的。(Spring MVC的源码位于Spring-framework下面的Spring-webmvc中)。

  1. 请求处理流程

在使用Spring MVC框架的时候,我们一般会在web.xml中配置一个DispatcherServlet作为Spring MVC的入口去映射所有的请求。DispatcherServlet的继承关系如图2-1所示。

图2-1

图2-1

  1. Servlet

Servlet这个接口其实很简单,里面总共定义了5个方法,如图3-1所示。

图3-1

  1. GenericServlet

GenericServlet是java中对Servlet的默认实现,在实现Servlet接口的同时实现了ServletConfig接口。GenericServlet的结构如图4-1所示。

图4-1

在GenericServlet中提供了无参的init方法。GenericServlet在类中首先实现了init(ServletConfg config)这个带参数的init方法,如图4-1所示。在方法中将config传递到了类中,这样在类中可以直接使用ServletConfig中的各种方法。然后调用了无参的init方法,无参的init方法是一个模版方法,主要提供给子类覆盖。这样之后的子类就可以专注于业务逻辑,从而不用再去关心对ServletConfg的处理。

图4-2

在GenericServlet中还提供了两个log方法,一个用于打印日志,另一个用于输出异常。主要通过传递给ServletContext来实现的。

  1. HttpServlet

HttpServlet顾名思义就是用Http协议实现的Servlet。HttpServlet中实现的方法如图5-1所示。我们在自己重写Servlet的时候一般基于这个类实现逻辑,HttpServlet帮助我们屏蔽了很多Http协议实现的具体细节。

图5-1

HttpServlet中最主要的功能其实就是对service方法实现。在service方法中首先将ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse。然后在方法中对Http的请求类型进行判断,不同的请求类型分发给不同的方法去处理。比如Get请求分发给doGet方法处理,Post请求分发给doPost方法处理。HttpServlet中提供了七种请求类型的处理,doGet、doPost、doPut、doDelete、doOptions、doTrace、doHead。

  1. HttpServletBean

在HttpServletBean类中(类中的方法如图6-1所示),并没有发现service方法,HttpServletBean主要的作用其实是参与了请求的创建的工作,并没有涉及请求的处理工作。HttpServletBean在继承了HttpServlet的同时实现了EnvironmentCapable,EnvironmentAware这两个接口,使得HttpServletBean具有感知以及提供Environment的能力。

图6-1

在图6-2中,我们可以看到HttpServletBean的init方法的具体实现,首先通过BeanWrapper设置相关的初始化属性。然后调用initServletBean这个模版方法,子类通过这个模版方法初始化。

图6-2

  1. FrameworkServlet

从HttpServletBean中,我们可以知道它的子类也就是FrameworkServlet的初始化入口方法是initServletBean方法,通过对方法(如图7-1)的分析可以看到,这个方法主要是完成了WebApplicationContext和FrameworkServlet的初始化工作。

图7-1

在FrameworkServlet类中,主要重写了service、doGet、doPost、doPut、doDelete、doOptions、doTrace方法,意味着除了doHead方法,其他的所有请求的方法都进行了重写。对这些方法进行分析(如图7-2),可以看到除了doOptions和doTrace方法外,FrameworkServlet将这些方法都交给了processRequest这个方法进行处理。processRequest方法是FrameworkServlet对请求进行处理的核心类。

图7-2

在processRequest方法中对一个请求进行处理,主要有三个步骤,第一个步骤首先是在doService方法之前将当前请求的LocaleContext和ServletRequestAttributes在处理请求之前放到LocaleContextHolder以及RequestHolder,并在请求处理完成后恢复。然后调用了doService模版方法具体处理一个请求,这个方法会在接下来的DispatcherServlet中具体实现。最后在请求处理完成后恢复LocaleContext和ServletRequestAttributes以及发布ServletRequestHandledEvent消息。

  1. DispatcherServlet

       DispatcherServlet是Spring MVC对请求进行处理的最核心的类。通过之前的分析可以知道,DispatcherServlet对请求处理的核心方法是doService方法。doService方法中首先判断请求是不是一个include请求,如果是,则通过attributesSnapshot对请求的属性进行一个备份。然后对请求设置了WebApplicationContext、localResolver、themeSource等属性(如图8-1所示),接下来调用doDispatch方法对请求进行一个具体的处理。最后如果这个请求是一个异步的请求,则将attributesSnapshot中保存的值重新设置回请求中。

图8-1

在doDispatch方法中主要完成了四件事情,首先是根据请求找到相应的Handler,然后根据Handler找到对应的HandlerAdapter,HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法。最后调用processDispatchResult去找到view并渲染输入给用户。

  1. 总结

通过对上述Spring MVC处理请求涉及到的类的源码简单分析,我们可以对Spring MVC对请求的处理流程有一个更清楚的认识。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值