请求处理-源码分析
Spring Boot 请求和请求参数处理解析
源码分析
上面请求和请求参数处理解析中已经解析到
DispatcherServlet - > doDispatch - > mappedHandler = getHandler(processedRequest);
找到请求应该由哪个个Handler处理(就是找到对应的Controller方法)如下图
续接上文
为当前Handler 找一个适配器 HandlerAdapter;
// DispatcherServlet - > doDispatch - >
// Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
/** * Return the HandlerAdapter for this handler object. * @param handler the handler object to find an adapter for * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error. */ protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { 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"); }
适配器HandlerAdapter一共4个 其中最常用的两个
RequestMappingHandlerAdapter支持方法上标注@RequestMapping
HandlerFunctionAdapter支持函数式编程
在四个中找到对应的HandlerAdapter ---> RequestMappingHandlerAdapter
真正的执行handler,就是根据刚才找到的适配器 RequestMappingHandlerAdapter 执行 handle
// DispatcherServlet - > doDispatch - >
// Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
执行到RequestMappingHandlerAdapter类 --> handleInternal()方法 -->
mav = invokeHandlerMethod(request, response, handlerMethod);// 执行目标方法
解析invokeHandlerMethod()方法中的步骤
/** * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView} * if view resolution is required. * @since 4.2 * @see #createInvocableHandlerMethod(HandlerMethod) */ @Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 需要执行的方法又封装一下 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 把所有的参数解析器方法封装类中 if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); }
// 把所有返回值处理器放到封装类中
if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); }
invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } // 执行真正的目标方法 进入此方法 往下看 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
ServletInvocableHandlerMethod类 --> invokeAndHandle()方法中主要执行下面
解析参数 赋值参数 执行目标方法
@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); }
InvocableHandlerMethod类 -- > invokeForRequest()方法主要执行下面
// 获取方法参数值
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
确定目标方法的每一个值
/** * Get the method argument values for the current request, checking the provided * argument values and falling back to the configured argument resolvers. * <p>The resulting array will be passed into {@link #doInvoke}. * @since 5.1.2 */ protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } // 声明一个object数组,长度是Controller方法接收参数的个数 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 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; }
参数详解1 判断所有解析器是否有支持解析这个参数
/** * Whether the given {@linkplain MethodParameter method parameter} is * supported by any registered {@link HandlerMethodArgumentResolver}. */ @Override public boolean supportsParameter(MethodParameter parameter) { return getArgumentResolver(parameter) != null; }
this.argumentResolvers -> 所有参数解析器集合
遍历所有解析器找到解析这个参数的解析器,放入缓存,返回解析器
/** * Find a registered {@link HandlerMethodArgumentResolver} that supports * the given method 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
在缓存中找到这个参数适配的解析器,根据解析器解析参数赋值到执行方法的参数上,boot版本2.7.1现在一共有27个解析器
/** * Iterate over registered * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} * and invoke the one that supports it. * @throws IllegalArgumentException if no suitable argument resolver is found */ @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 获取适配的解析器 先从缓存中取有的话直接返回解析器 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); }
// 核心代码 根据适配的解析器解析参数 20多个解析器的解析方法都不一致 return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }
注释:
27个参数解析器(spring-boot-2.7.1.jar)
确定将要执行的目标方法的每一个参数的值是什么;
SpringMVC目标方法能写多少种参数类型。取决于参数解析器
其中
RequestParamMethodArgumentResolver 对应的注解 @RequestParam
RequestAttributeMethodArgumentResolver 对应的注解 @RequestAttribute
MatrixVariableMethodArgumentResolver 对应的注解 @MatrixVariable
PathVariableMethodArgumentResolver 对应的注解 @PathVariable.
等等,在源码中都可以在注释中看到对应哪些注解或者类型的参数
27个参数解析器都实现HandlerMethodArgumentResolver,这个接口中有两个方法
supportsParameter()方法是判断能否解析这个参数,不能返回false,能执行resolveArgument()这个方法
15个返回值处理器(spring-boot-2.7.1.jar)
Controller方法的返回值可以写15种
一共类型
ModelAndView、Model、View、ResponseEntity、ResponseBodyEmitter、StreamingResponseBody、HttpEntity、HttpHeaders、Callable、DeferredResult、ListenableFuture、CompletionStage、WebAsyncTask、有 @ModelAttribute 且为对象类型的、@ResponseBody 注解
其中最常用的ModelAndView,Model,View、@ResponseBody 注解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?