URL如何进入SpringMVC的Controller方法中

请求时如何找到具体的Controller的方法的

  1. doGet等是如何而来
    FrameworkServlet继承于HttpServletBean,HttpServletBean继承于HttpServlet
  2. doGet、doPost、doPut、doDelete等http请求均会调用processRequest
    FrameworkServlet部分相关源码如下:
@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}
	
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
	...
	doService(request, response);
	...
}
  1. processRequest调用DispatcherServlet的doService
  2. doService调用doDispatch
    • doDispatch调用applyPreHandle,执行所有HandlerInterceptor拦截器的preHandle方法
    • doDispatch中代码mv = ha.handle(processedRequest, response, mappedHandler.getHandler());调用Controller的方法,如何调用,后面指出
    • doDispatch调用applyPostHandle,执行所有HandlerInterceptor拦截器的postHandle方法
    • doDispatch调用processDispatchResult
      • processDispatchResult调用triggerAfterCompletion
      • triggerAfterCompletion方法执行所有HandlerInterceptor拦截器的afterCompletion方法
  • DispatcherServlet部分相关源码如下
 protected void initStrategies(ApplicationContext context) {
       ...
        this.initHandlerMappings(context);
        this.initHandlerAdapters(context);
	...
    }
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   ...
     try {
         this.doDispatch(request, response);
     }
     ...
 }

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   		...
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
             return;
         }
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
         if (asyncManager.isConcurrentHandlingStarted()) {
             return;
         }
         this.applyDefaultViewName(processedRequest, mv);
         mappedHandler.applyPostHandle(processedRequest, response, mv);
	...
     this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
     ...
}

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HandlerInterceptor[] interceptors = getInterceptors();
	if (!ObjectUtils.isEmpty(interceptors)) {
		for (int i = 0; i < interceptors.length; i++) {
			HandlerInterceptor interceptor = interceptors[i];
			if (!interceptor.preHandle(request, response, this.handler)) {
				triggerAfterCompletion(request, response, null);
				return false;
			}
			this.interceptorIndex = i;
		}
	}
	return true;
}
	
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
     HandlerInterceptor[] interceptors = this.getInterceptors();
      if (!ObjectUtils.isEmpty(interceptors)) {
          for(int i = interceptors.length - 1; i >= 0; --i) {
              HandlerInterceptor interceptor = interceptors[i];
              interceptor.postHandle(request, response, this.handler, mv);
          }
      }
    }
    
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
        ...
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }
        }
    }
    
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
         ...
         interceptor.afterCompletion(request, response, this.handler, ex);
         ...
    }

doDispatch中代码mv = ha.handle(processedRequest, response, mappedHandler.getHandler());调用Controller的方法

  1. ha为HandlerAdapter接口
  2. 具体实现使用RequestMappingHandlerAdapter
  3. RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
//AbstractHandlerMethodAdapter的方法    
   public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       return this.handleInternal(request, response, (HandlerMethod)handler);
   }
@Nullable
   protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception;
  1. 之后调用handleInternal的抽象方法(实际调用RequestMappingHandlerAdapter的handleInternal),内部再次调用invokeHandlerMethod方法
  protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
     this.checkRequest(request);
      ModelAndView mav;
      if (this.synchronizeOnSession) {
          HttpSession session = request.getSession(false);
          if (session != null) {
              Object mutex = WebUtils.getSessionMutex(session);
              synchronized(mutex) {
                  mav = this.invokeHandlerMethod(request, response, handlerMethod);
              }
          } else {
              mav = this.invokeHandlerMethod(request, response, handlerMethod);
          }
      } else {
          mav = this.invokeHandlerMethod(request, response, handlerMethod);
      }
     ...
  }
  @Nullable
  protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
      ...
          ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
      ...
          invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
      ...
}
  1. 在此调用 invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);(ServletInvocableHandlerMethod类)
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
    ...
 }
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
   Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
   if (this.logger.isTraceEnabled()) {
       this.logger.trace("Arguments: " + Arrays.toString(args));
   }
   return this.doInvoke(args);
}
  1. 调用invokeForRequest,再调用doInvoke
@Nullable
    protected Object doInvoke(Object... args) throws Exception {
        ReflectionUtils.makeAccessible(this.getBridgedMethod());
        try {
            return this.getBridgedMethod().invoke(this.getBean(), args);
       ...
  1. 使用return this.getBridgedMethod().invoke(this.getBean(), args);将controller对应,并传递参数(modelFactory.initModel(webRequest, mavContainer, invocableMethod); //参数通过此传递进入invocableMethod)
    controller是从哪里找到的,是在handlerMethod中传递过来的。最早在doDispatch中

HandlerInterceptor拦截器的说明

public interface HandlerInterceptor {
	//进入controller前进行判断,如果此处放回false,则直接返回
	//用途:如token的验证
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
	//controller执行方法返回后执行此操作
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
	//执行操作返回前进入到此方法,可以对其进行加工等
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

参考

  • https://www.cnblogs.com/fangjian0423/p/springMVC-request-mapping.html#reference
  • https://blog.csdn.net/sunsiwenvip/article/details/80230050

你可能感兴趣的:(URL如何进入SpringMVC的Controller方法中)