14.请求映射的原理

当所有的请求来了时,会先进入DispatcherServlet类中的doDispatch进行处理
如请求路径是:http://localhost:8080/hello?id=12时
DispatcherServlet类的代码片段如下:
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ....
        //重点1.根据请求请求路径:hello,去查找是哪个类进行处理该请求
        mappedHandler = getHandler(processedRequest);
                        1.1该方法中的细节:遍历handlerMappings,判断哪个程序处理链可以处理该请求
                            protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
                               if (this.handlerMappings != null) {
                                   //重点2.handlerMappings有五项选择:
                                   //1.RequestMappingHandlerMapping
                                   //2.WelcomePageHandlerMapping
                                   //3.beanNameHandlerMapping
                                   //4.routerFunctionMapping
                                   //5.SimpleUrlHandlerMapping
                                  for (HandlerMapping mapping : this.handlerMappings) {
                                     HandlerExecutionChain handler = mapping.getHandler(request);
                                     if (handler != null) {
                                        return handler;
                                     }
                                  }
                               }
                               return null;
                            }
        ...
        //重点3.获取处理程序的适配器
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 
                        2.1该方法中的细节:遍历handlerAdapters,获取执行该程序的适配器
                            protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
                               if (this.handlerAdapters != null) {
                                   //重点4.handlerAdapters有四项选择,和handlerMappings对应
                                   //1.RequestMappingHandlerAdapter
                                   //2.HandlerFunctionAdapter
                                   //3.HttpRequestHandlerAdapter
                                   //4.SimpleControllerHandlerAdapter
                                  for (HandlerAdapter adapter : this.handlerAdapters) {
                                     if (adapter.supports(handler)) {
                                        return adapter;
                                     }
                                  }
                               }
                               throw new ServletException("No adapter for handler [" + handler +
                                     "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
                            } 
                            
         ....
         重点5.执行控制方法 
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                         重点6.handle方法细节:一层套一层最终会调用到:
                          mav = invokeHandlerMethod(request, response, handlerMethod); 
                              重点7invokeHandlerMethod方法细节
                              protected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
                                      ...
                                      //重点8.设置参数解析器,argumentResolvers 有27项选择,细节如下截图,用来解析各种类型的请求参数
                                      //springmvc目标方法能写多少种参数类型。取决于参数解析器。
                                      if (this.argumentResolvers != null) {
                                        invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
                                     }
                                     //重点9.设置返回值处理器,控制方法helloControler可以返回多少中类型,去接于返回值处理器支持多少种,返回值处理器详情见截图
                                     if (this.returnValueHandlers != null) {
                                       invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
                                    }
                                    ...
                                    //重点10.执行目标方法
                                    invocableMethod.invokeAndHandle(webRequest, mavContainer);
                                                //重点11.该方法的细节如下:
                                                public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,Object... providedArgs){
                                                    //重点12.执行目标方法的地方
                                                    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
                                                            //重点13.该方法的详细信息如下:
                                                                public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
                                                                       Object... providedArgs) throws Exception {
                                                                       //重点14.确定目标方法参数值
                                                                       Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
                                                                       if (logger.isTraceEnabled()) {
                                                                          logger.trace("Arguments: " + Arrays.toString(args));
                                                                       }
                                                                       //重点15.反射执行目标方法
                                                                       return doInvoke(args);
                                                                }
                                                }
                                                    
                              }
                             
    }
    
    重点15:如何确认目标方法参数值的
    获取目标参数值的方法详情,是重点14方法的详情分
            protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {
                   //重点16.获取目标方法的参数列表,获取的是参数列表的详细信息,如参数类型,所标注的注解等,但此时还没有拿到参数值!
                   MethodParameter[] parameters = getMethodParameters();
                   if (ObjectUtils.isEmpty(parameters)) {
                      return EMPTY_ARGS;
                   }
                   Object[] args = new Object[parameters.length];
                   for (int i = 0; i < parameters.length; i++) {
                      ....  
                     重点16.检查哪种参数解析器可以解析当前参数(supportsParameter方法里会遍历27种参数解析器,确定哪种参数解析器可以解析当前参数) 
                      if (!this.resolvers.supportsParameter(parameter)) {
                         throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
                      }
                      //重点17:找到适应的参数解析器,解析当前参数
                      try {
                         args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
                      }
                      ....
                   return args;
                }
参数解析器细节,用来解析各种带标签的请求参数
参数解析器实现的接口如下:

返回值处理器

posted @ 2022-05-11 21:49  努力的达子  阅读(64)  评论(0编辑  收藏  举报