概述
SpringMVC作为控制层框架,具体的作用就不在此赘述了,本文主要针对其处理请求流程的原理来做一次较为细致的讲解
首先来看经典的MVC的三层架构,下面是一个模拟请求的调用和返回,我们把重点放在中间的控制层:
SpringMVC就是用于管理这一层,负责将视图层发来的请求发送给下一层,然后再将结果返回,听起来很简单,但是真的这么简单吗?接下来,我们就来渐进式的分析,来研究其工作的原理
准备工作
首先我们选用的是springboot的2.1.4发布版,查看一下依赖树,发现springmvc的版本是5.1.6的版本,正好可以和现在网络上大部分针对3.x版本的源码讲解做一个比较
这里为了不做多余的功夫,一切从简,就只添加了以下的类:
具体的类信息如下
@RestController
public class DemoController {
private final DemoService demoService;
public DemoController(DemoService demoService) {
this.demoService = demoService;
}
@RequestMapping("hi")
public String sayHi() {
return demoService.getInfo();
}
}
@Service
public class DemoService {
public String getInfo() {
return "Hello World...";
}
}
我们启动测试一下:
一切正常,接下来我们就要开始着手分析
工作原理
从刚才的测试我们会发现,我们发送了一个请求(url)给springmvc,然后springmvc就执行了我们定义的sayHi()方法,接着我们的浏览器就收到了响应,这个过程究竟是怎么实现的呢?别急,我们在sayHi()方法处打上断点,进入调试模式
我们依然发起localhost:8080/hi
这个请求,程序停在了断点位置,同时也得到了一条调用链。我们沿着调用链从启动位置向上找,我们忽略所有core包下的内容,只找web包下的类,发现请求经过HttpServlet层层封装,最终交给了一个叫DispatcherServlet的类来处理
DispatcherServlet – doService()
这个DispatcherServlet内部有一个doService方法,我们就以此作为起点,来分析这个请求的过程是怎么样的
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// 保留属性快照,以便恢复
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this