主要是自己学习整理记录,自用。。。
springmvc 工作流程图
这个图大家都见过,但是还是很疑惑它的很多是如何去实现的,还有我controller的方法是如何注入的,为什么我写个
@GetMapping("/test1")
public AjaxResult<List<String>> test1(user user) {
System.out.println(user.getName());
System.out.println(user.getTelephone());
List<String> list = new ArrayList<>();
String s = "This is a test";
list.add(s);
return AjaxResult.success(list);
}
它就能根据请求帮我们把user对象封装好呢?
handlerMapping如何根据用户请求找到handler?
他是怎么通过适配器调到我这个方法的?
问题不要太多。。
尝试跟一下源码看看
在DispatcherServlet的doService()方法中
在gethandler()中找到对应的handler,只不过返回的是HandlerExecutionChain。看一下这HandlerExecutionChain里面包含什么
进入getHandler()
这里有9个handlerMapping,遍历去找handler,找到了就退出
那它是怎么找的呢?
我们可以看到很多url请求的路径都被保存在mappingRegistry的一个map里面,可以找到当前url对应的方法
返回到getHandler()方法 ,获取HandlerExecutionChain
可以看到是拿到所有已经注册的interceptor,看看是不是MappedInterceptor类型或者子类,是就进一步匹配,估计是拿请求url跟定义好的拦截条件作比较,看看是否符合条件。符合就加进去。如果不是就MappedInterceptor,就直接加入list。
回到DispatcherServlet的doDispatch(),去找adapter
可以看到也是有4个adapter,遍历去查看能适配该handler的adapter
拿到adapter,执行到这里,看到applyPreHandle,在执行handler之前执行什么东西,点进去看看
是拿到拦截器集合去遍历执行拦截方法 prehandle(),并根据方法执行返回值判断是否结束拦截链。
到这开始去执行handler(也就是我们写在controller里的方法)
进去
但是springMVC是如何帮我们传递参数的呢?
比如我们一般写在controller的代码
我们会在方法参数里面传入一个对象,甚至还有一个modelAndView对象。会自动注入进来
像这样,我们给它发一个请求,为什么SpringMVC就能自动帮我们把字段封装成一个User对象呢?我明明什么都没有干。。。(惊呆了老铁)
让我们一层一层调进去康康
看到这其实就能猜到了,它拿到了参数的class对象
然后后面其实就是通过反射去获取构造函数(这边拿到的是空参构造器,所以构造出来的对象也都是没有给属性赋值的空对象),然后就是通过构造函数创建一个实例对象给attribute
然后一波疯狂点,终于看到
其实就是拿到user对象的参数,去到request里面保存的parameterMap里面去找,看有没有同名的key。有的话就返回对应的value,然后赋值。
(中途还有亿点细节,我只是说了我看完后的总结)
这样就完成了user对象属性的封装。
封装好参数对象自然就可以去开始执行controller了
走doInvoke(),带上args参数
然后找到了这样一句贼长的代码
三元运算符前面会判断它是不是isKotlinType(具体啥玩意咱也不知道)
然后就会执行三元运算符后面的这个。method.invoke(this.getBean,args);是不是老乡见老乡,两眼泪汪汪,可算是见到熟悉的你的,就是使用反射调用该方法。
F7跟进,就直接跳转到我们最初的起点。直接一整个泪目了,带着封装好的参数回到了梦开始的地方,想想看之前写下springMVC controller的代码,也不知道它是怎么传递过来的,怎么根据请求参数,人家就能帮我们封装好对象,现在总算有点眉目了。
然后就是快乐地执行CRUD搬砖的过程
然后返回到DispatcherServlet执行拦截器的postHandle方法。
处理解析ModelAndView
在这个方法里面,最后还有对拦截器的afterCompletion方法的调用。
至此拦截器就全部执行完了。
小菜鸡水平有限就这样草草地过了一下。无了。