spring MVC是遵循MVC架构思想,基于Spring Container Core和AOP等技术,实现的轻量级web框架,用于简化我们日常Web开发。

处理请求的过程是用了前端控制器处理模式:

总体流程
首先用户发送请求 ——> DispacherServlet,接收请求分发给对应的处理器。
DispacherServlet ——> HandlerMapping,HandlerMapping根据请求URL找到对应的HanderMethod(Controller方法)和HandlerInterceptor。
DispacherServlet ——> HandlerAdapter,根据handler找到适合的适配器(包含很多resolver)。
HandlerAdapter ——> 处理器方法的调用,调用各种处理器和HanderMethod(Controller方法)完成请求的处理,并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);
ModelAndView 的逻辑视图名——> ViewResolver,ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
View——>渲染,View 会根据传进来的Model 模型数据进行渲染,此处的Model 实际是一个Map 数据结构,因此 很容易支持其他视图技术;
返回控制权给DispatcherServlet,由DispatcherServlet 返回响应给用户,到此一个流程结束。
因为现在都是前后端分离项目,5-6步可以忽略。
下面为具体步骤:
使用的也是JUC中的ThreadPoolExecutor创建线程池,这里需要说明下任务类型是NioEndpoint$SocketProcessor,类的继承&实现结构如下:

,使用的是ThreadPoolExecutor#execute直接执行TaskThread$WrappingRunnable,没用使用常用的submit。submit会把Runnable/Callable统一封装成FutureTask方便通过它拿到结果,所以他们的调用栈不一样。
tomcat请求的调用栈

注意:run后面的行为-1,说明不是java程序调用应该是JVM调用的,本来前面的调用栈是通过ThreadPoolExecutor的runWorker中的task.run()发起进而执行任务的,但是因为FutureTask需要收集结果所以需要执行FutureTask中的run。
从标准public service方法中接收标准的HTTP请求,并将其发送到此类中定义的doMethod方法。

根据request的Method进入不同的方法处理,这里笔者发起的是post请求所以进入的是doPost。
处理请求,发布事件,而不管结果如何。

可以看到初始化了上下文,核心调用doService方法。
公开dispatcherservlet-specific的请求属性,委托公开给doDispatch实际调度。

可以看到设置了许多request属性比如handler、view对象,包括applicationcontext(从容器中拿到自定义处理类),实际调度进入doDispatch处理。
进入getHandler(processedRequest)

按序遍历所有的HandlerMapping,找到请求的HandlerExecutionChain。
下面我们看看HandlerMapping是怎么通过请求映射到具体的HandlerExecution。
RequestMappingHandlerMapping#getHandlerInternal
可以看到根据lookupPath找到具体的HandlerMethod。

这里根据HandlerMethod获得了RequestMappingHandlerAdapter,可以看到里面包含很多resolver用来处理请求和响应。

最近面试的小伙伴很多,对此我整理了一份Java面试题手册:基础知识、JavaOOP、Java集合/泛型面试题、
Java异常面试题、Java中的IO与NIO面试题、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、
Memcached、MongoDB、Spring、SpringBoot、SpringCloud、RabbitMQ、Dubbo、MyBatis、ZooKeeper、数据结构、算法、
Elasticsearch、Kafka、微服务、Linux等等。可以分享给大家学习。【持续更新中】领取方式【999】就可以领取资料了