请求处理-源码分析

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 注解 

自定义请求数据转换器convert

posted @   Dabo丶  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示