SpringBoot请求处理过程

2022-12-01 08:57:38

SpringBoot学习笔记

学习资料

视频:【尚硅谷】SpringBoot2零基础入门教程

文档:SpringBoot2核心技术与响应式编程

源码:SpringBoot2核心技术与响应式编程

请求处理过程

1. 查找处理此接口的处理器 mappedHandler = getHandler(processedRequest); 即寻找是哪个接口方法处理本次请求
    1.1 循环遍历所有的处理器(处理器如下图1.1)

2. 查找处理器适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 用于处理步骤1找到的接口方法,实质相当于一个反射器
    2.1 循环遍历所有的处理器适配器(如下乳2.1)

3. 依次遍历拦截器interceptor,执行其preHandle方法。
    3.1 若任一拦截器的preHandle返回false,就自此拦截器(包含)逆向执行前面所有拦截器的afterCompletion方法,并且程序就此结束不会再执行后面的步骤

4. 处理器适配器处理接口方法获取ModelAndView类型对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    4.1 给要执行的接口方法配上所有的“参数解析器”和所有的“返回值处理器”等,后面的逻辑中会用到
    4.2 执行接口方法 invocableMethod.invokeAndHandle(webRequest, mavContainer)
        4.2.1 获取接口方法的入参 getMethodArgumentValues(request, mavContainer, providedArgs)
            4.2.1.1 遍历所有的“参数解析器”(如图4.2.1.1),调用每个“参数解析器”的supportsParameter(parameter)方法,如果返回true就用这个“参数解析器”
            4.2.1.2 调用此“参数解析器”的resolveArgument(parameter, mavContainer, webRequest, binderFactory)方法获取接口方法的入参,这里面有一段逻辑很重要就是“数据转换”,即根据请求头中的数据类型(例如:application/json;charset=UTF-8)找到合适的“数据转换器”将请求中的数据转换为我们接口方法入参指定的数据类型
            注意1:遍历所有“数据转换器”(如下图),通过其canRead方法来判断其能否将请求头数据类型(例如:application/json;charset=UTF-8等)转换为目标类型(接口方法的入参的类型),如果可以就用其read方法将数据转换为目标类型
            注意2:我们的接口入参通常用@RequestBody注解,这里对应的参数解析器是 RequestResponseBodyMethodProcessor
            注意3:要将方法返回值按照我们自己的格式读入,需要自定义的数据转换器并重写canRead和read方法
        4.2.2 调用接口方法进行逻辑处理,返回结果(这里就是我们写的Controller)
        4.2.3 查找合适的“返回值处理器”处理接口方法的返回值
            4.2.3.1 循环遍历所有的“返回值处理器”(如图4.2.3.1),调用“返回值处理器”的supportsReturnType(returnType)方法,如果返回true就用这个“返回值处理器”
            4.2.3.2 调用“返回值处理器”的handleReturnValue(returnValue, returnType, mavContainer, webRequest)方法将返接口方法的返回值转换成我们需要的类型(例如:application/json或*/*等)并返回
            注意1:数据转换逻辑在“spring-webmvc包下的AbstractMessageConverterMethodProcessor类的writeWithMessageConverters方法”,数据转换先遍历所有数据转换器(图同4.2.1注意1)调用每一个转换器的canWrite方法看是否可以将返回值转换为request中指明的类型(例如:application/json或*/*等),如果可以就将此转换器放入列表,再次校验列表中的转换器并排序,再循环遍历列表将首个canWrite目标类型的转换器拿出来调用其write方法将返回值转换为目标类型
            注意2:我们的接口返回值通常用@ResponseBody注解,这里对应的返回值处理器是 RequestResponseBodyMethodProcessor,数据转换器是MappingJacksonHttpMessageConverter,底层调用的是jackson;如果我们的接口没有@ResponseBody而且是返回字符串,对应的返回值处理器就是 ViewNameMethodReturnValueHandler
            注意3:要将方法返回值按照我们自己的格式输出,需要自定义的数据转换器并重写canWrite和write方法
        4.2.4 获取“模型视图”对象 getModelAndView(mavContainer, modelFactory, webRequest),模型就是返回的数据,视图就是页面,将mav对象渲染
            4.2.4.1 将本次请求的请求对象request中的所有参数放入mav对象中的defaultModel中
            4.2.4.2 循环遍历所有的“视图解析器”(如图4.2.4.2),调用其resolveViewName如果得到的view视图对象不为null就返回这个视图
        注意1:接口返回值如果是@ResponseBody则返回值的json字符串将会以字符数组的形式存放在response对象中,而mav=null;如果接口返回一个字符串,SpringBoot会首先调用“内容协商解析器 ContentNegotiatingViewResolver”(图4.2.4.2中列表第一个),在此处理器中依次调用其余三种处理器分别看此字符串是否是Spring上下文的bean名、、内部资源的路径(页面),如果某个处理器处理得到的view非null就将view放入候选list备用

4. 执行“拦截器 interceptor”的 postHandle 方法

5. 执行“拦截器 interceptor”的 afterCompletion 方法

注意1:如果要页面跳转或页面转发,modelAndView中会有内容,如果是@ResponseBody就要返回json字符串,返回内容是response对象中

图1.1
图1.1
图2.1
图2.1
图4.2.1.1
图4.2.1.1
图4.2.1注意1
图4.2.1注意1
图4.2.3.1
图4.2.3.1
图4.2.4.2
图4.2.4.2

  • 作者:Louzen
  • 原文链接:https://blog.csdn.net/Louzen/article/details/126107327
    更新时间:2022-12-01 08:57:38