【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了

本文涉及到类:

  • AnnotationDrivenBeanDefinitionParser
  • RequestMappingHandlerMapping
  • AbstractHandlerMapping
          |--AbstractHandlerMethodMapping
              |--RequestMappingInfoHandlerMapping
  • DispatcherServlet




为什么我们的类中使用了@Controller,方法上使用了@RequestMapping,那么就可以处理请求了呢?
系统启动时,如果碰到<mvc:annotation-driven/>标签,则会实例化一个AnnotationDrivenBeanDefinitionParser类,这个类在实例化时,会实例化一个名为RequestMappingHandlerMapping 的类,这个类实现了InitializingBean接口的afterPropertiesSet()方法,所以当这个类实例化后,便会调用afterPropertiesSet方法,这个方法又调用了他的父类AbstractHandlerMethodMapping的afterPropertiesSet方法,然后调用initHandlerMethods()方法,在方法中,主要这么两步:

  • 第一步:会拿出容器中注册的bean,然后调用isHandler方法判断是不是handler,如下图:
    【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了
    如果满足条件,可以作为handler,那么就调用detectHandlerMethods方法获取handler(controller)中获取可以作为处理请求的方法,可以作为处理请求的方法的条件就是看方法上是否有@RequestMapping,具体过程和源码看下图:
    【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了
    那么getMappingForMethod做了什么,看下图:

    【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了


    通过上面图片的中的几步,就找到了RequestMapping注解对应的方法,并把注解中的属性值全部保存在了RquestMappingInfo对象中了。
  • 第二步:通过handlerMethodsInitialized(getHandlerMethods())方法,将url和用来处理的方法绑定了起来,如下
    【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了

经过上面的处理后,当我们在浏览发送请求后,便就会进入DispatcherServlet了,我们前面讲过,进入doDispatch后,会去拿到处理请求的handler,其实就是从上面的这个this.mappingRegistery中去拿,下面看看是怎么拿到:
DispatcherServlet#doDispatch->getHandler(reqeust)方法=>AbstractHandlerMethodMapping#getHandlerInternal()方法->lookupHandlerMethod方法,看下图:
【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了
图中lookupPath就是从浏览器中获取的路径部分,就是这部分:【稀里糊涂学speingmvc】为什么写了@Controller和@RequestMapping就可以处理请求了
在启动时,会把@RequestMapping中写的路径全都放到mappingRegistry这个map中了(在上面都有),然后请求来时,当浏览器发送请求时,便从请求中截取出路径部分,然后看看是不是在这个map中能找到对应的handler,如果能找到对应的handler,那么在后面就可以调用这个handler中的方法来处理请求。

现在大家应该对于为什么写了@Controller和@ReqeustMapping就可以直接处理浏览器的请求有所了解了吧。也知道为什么@RequestMapping的value为什么跟浏览器中请求的关系了吧。

文章如果有不对的地方,还请指出,一同进步。谢谢。

小提示:在获取handler时,用到了ReentrantReadWriteLock,这是一种处理多线程的可重入锁,他可以实现读写分离,有兴趣的可以百度了解下,这属于java的核心内容