其他分享
首页 > 其他分享> > Spring 请求方法的调用原理(Controller)和请求参数的获取的原理

Spring 请求方法的调用原理(Controller)和请求参数的获取的原理

作者:互联网

1、请求映射原理

本质还是httpServlet

​ 从requestMapping中寻找请求方法

就可以获取到请求的方法

​ 拿到这个方法后最终会调用DispatchServlet

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

​ 然后调用AbstractHandlerMethodAdapter的handleInternal()方法,被RequestMappingHandlerAdapter实现

@Override
protected ModelAndView handleInternal(HttpServletRequest request,
                                      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    ModelAndView mav;
    checkRequest(request);

    // Execute invokeHandlerMethod in synchronized block if required.
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                mav = invokeHandlerMethod(request, response, handlerMethod);
            }
        }
        else {
            // No HttpSession available -> no mutex necessary
            mav = invokeHandlerMethod(request, response, handlerMethod);
        }
    }
    else {
        // No synchronization on session demanded at all...
        mav = invokeHandlerMethod(request, response, handlerMethod);
    }

​ 主要调用invokeHandlerMethod(request, response, handlerMethod);方法

invocableMethod.invokeAndHandle(webRequest, mavContainer);

​ 再调用invokeAndHandle()方法

Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);


@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
                               Object... providedArgs) throws Exception {

    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Arguments: " + Arrays.toString(args));
    }
    return doInvoke(args);
}

​ 在通过doInvoke(args);实现方法的调用

@Nullable
protected Object doInvoke(Object... args) throws Exception {
    Method method = getBridgedMethod();
    try {
        if (KotlinDetector.isSuspendingFunction(method)) {
            return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
        }
        return method.invoke(getBean(), args);
    }
    .......

method.invoke(getBean(), args);这就是通过反射实现方法的调用

2、请求参数注解处理原理

原理图

  1. 先得到请求的request

  1. 在获取可以处理请求的方法的Mapping映射器

     DispatcherServlet中的
         doDispatch方法
            // Determine handler for the current request.
            mappedHandler = getHandler(processedRequest);
    
  2. 判断每个参数带有注解是哪个,是否存在相应的解析器

    • 寻找合适的处理适配器

       DispatcherServlet中的
           doDispatch方法		
              // Determine handler adapter for the current request.
              HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
      

第一步
DispatcherServlet中的
    doDispatch方法  
        // Actually invoke the handler.
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

第二步
RequestMappingHandlerAdapter中的
    handleInternal方法
    	// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
	invokeHandlerMethod方法
        invocableMethod.invokeAndHandle(webRequest, mavContainer);

第三步
ServletInvocableHandlerMethod中的
    invokeAndHandle方法
    	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

第四步
InvocableHandlerMethod类中的
	invokeForRequest方法
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);//获取请求的参数

第五步
InvocableHandlerMethod类中的
    getMethodArgumentValues方法
            if (!this.resolvers.supportsParameter(parameter)) {//寻找处理相关注解的处理器,并保存到缓存中 supportsParameter(parameter)从这里进入的
                throw new IllegalStateException(formatArgumentError(parameter, 								"No suitable resolver"));
            }
        	try {
            args[i] = this.resolvers.resolveArgument(parameter, 	mavContainer, 					request, this.dataBinderFactory);
        }

第六步
HandlerMethodArgumentResolverComposite类中的
    	@Nullable
        private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter 														parameter) {
            HandlerMethodArgumentResolver result = 	
                this.argumentResolverCache.get(parameter);//从缓存中获取,开始肯定没有
            if (result == null) {
                //增强for循环中选择合适的处理器  27个
                for (HandlerMethodArgumentResolver resolver :
                     this.argumentResolvers) {
                    if (resolver.supportsParameter(parameter)) {
                        result = resolver;
                        //保存到缓存中
                        this.argumentResolverCache.put(parameter, result);
                        break;
                    }
                }
            }
            return result;
        }

标签:args,请求,Spring,Object,request,mavContainer,方法,原理,parameter
来源: https://www.cnblogs.com/shuisanya/p/16380192.html