- HandlerMapping中找到能处理请求的Handler(Controller.method())
- 为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
- 适配器执行目标方法并确定方法参数的每一个值
第一个:支持方法上标注的@RequestMapping
第二个:支持函数式编程
.....
2、执行目标方法 2.1 DispatcherServlet -- doDispatch// Actually invoke the handler. //DispatcherServlet -- doDispatch mv = ha.handle(processedRequest, response, mappedHandler.getHandler());2.2 RequestMappingHandlerAdapter--handleInternal
=====RequestMappingHandlerAdapter类中的handleInternal方法========== mav = invokeHandlerMethod(request, response, handlerMethod); //执行目标方法 =====invokeHandlerMethod的关键代码=========================== if (this.argumentResolvers != null) {//设置参数解析器 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) {//设置返回值处理器 invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
设置参数解析器:
参数解析器:确定将要执行的目标方法的每个参数的值是什么
SpringMVC目标方法能写多少种参数类型,取决于参数解析器。
supportParameter:当前解析器是否支持这种参数
支持就调用resolveArgument
设置返回值处理器:
2.3 invokeAndHandleinvocableMethod为ServletInvocableHandlerMethod对象
invokeForRequest:真正执行目标方法
=====ServletInvocableHandlerMethod中invokeAndHandle方法中的核心代码============== Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs); this.setResponseStatus(webRequest);2.4 invokeForRequest
=====invokeForRequest方法===== public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //获取方法参数所有的值 Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } //反射执行Controller中的方法 return this.doInvoke(args); }2.5 getMethodArgumentValues:确定每个参数的值
上一步获取参数值的具体代码
============InvocableHandlerMethod类========================== protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } //核心代码,args是最终确定好的值 Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } //1、遍历26个参数解析器是否支持parameter类型的参数 if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { //2、开始解析参数值 args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { // Leave stack trace for later, exception may actually be resolved and handled... if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw ex; } } return args; }
上图代码的细节:
2.5.1 判断所有参数解析器是否支持当前参数找到能解析的解析器,加入缓存,方便下一步解析该参数时直接获取。
======if (!this.resolvers.supportsParameter(parameter))底层实现===== @Nullable private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }2.5.2 解析参数的值
解析请求的值给到参数。
======args[i] = this.resolvers.resolveArgument====== public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { HandlerMethodArgumentResolver resolver = this.getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } else { return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); } } =====最终调用AbstractNamedValueMethodArgumentResolver的resolveArgument方法=====
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)