springboot请求处理流程

最近在看尚硅谷雷神的springboot2,整理一下,方便自己理解,有的地方有可能出错

05、Web开发 · 语雀雷神原文档

1、SpringMVC常用组件

DispatcherServlet:前端控制器,统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求

HandlerMapping:处理器映射器根据请求的url、method等信息查找Handler,即控制器方法

Handler:处理器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理 HandlerAdapter:处理器适配器,通过HandlerAdapter对处理器(控制器方法)进行执行 ViewResolver:视图解析器,进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、 RedirectView

View:视图 ,将模型数据通过页面展示给用户

2、执行流程

1) 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。

2) DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:(包括判断是否为文件上传解析,如果是进行包装)

3) 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及 Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。

springboot请求处理流程_第1张图片

springboot请求处理流程_第2张图片

HandlerMapping首先回根据请求方式进行匹配

0:所有标注了@RequestMapping的方法都会以map的形式储存在这里,保存了所有@RequestMapping 和handler的映射规则。

springboot请求处理流程_第3张图片

里面除了我们定义的方法之外还有两个默认的error映射,其匹配规则是增强循环,直到遍历到对应的url

1:针对欢迎页的HandlerMapping,能访问到index.html;

4) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。

HandlerMapping中找到能处理请求的Handler(Controller.method()),找到方法后我们需要对其方法的参数进行解析,即要找到合适的HandlerAdapter对参数进行解析

springboot请求处理流程_第4张图片

0 - 支持方法上标注@RequestMapping  1 - 支持函数式编程的

确定将要执行的目标方法的每一个参数的值是什么;SpringMVC目标方法能写多少种参数类型。取决于参数解析器HandlerMethodArgumentResolver。

springboot请求处理流程_第5张图片

当前解析器是否支持解析这种参数(常用参数注解:@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody,常用参数:Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)支持就调用 resolveArgument

解析参数:挨个判断所有参数解析器那个支持解析这个参数

resolver.supportsParameter(parameter)如果为true,调用各自 HandlerMethodArgumentResolver 的 resolveArgument 方法即可

5) 如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】

1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】

2、先来顺序执行 所有拦截器的 preHandle方法

     如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle

     如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;

3、如果任何一个拦截器返回false。直接跳出不执行目标方法

4、所有拦截器都返回True。执行目标方法

5、倒序执行所有拦截器的postHandle方法。

6、前面的步骤有任何异常都会直接倒序触发 afterCompletion

7、页面成功渲染完成以后,也会倒序触发 afterCompletion

6) 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定 的响应信息

b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

执行方法流程

springboot请求处理流程_第6张图片

InvocableHandlerMethod通过遍历找到能解析参数的resolver并解析

1、使用改方法getMethodArgumentValues2、HandlerMethodArgumentResolver挨个判断所有参数解析器那个支持解析这个参数3、调用各自 HandlerMethodArgumentResolver 的 resolveArgument 方法即可

将所有的数据都放在 ModelAndViewContainer;包含要去的页面地址View。还包含Model数据

7) Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。

8) 此时将开始执行拦截器的postHandle(...)方法【逆向】。processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

9) 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行 HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model 和View,来渲染视图。

10) 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。

11) 将渲染结果返回给客户端。

备注:

1、spring默认关闭restful风格

开启需要在application.yml文件进行设置

springboot请求处理流程_第7张图片

2、自定义类参数解析(接4)

使用ServletModelAttributeMethodProcessor 这个参数处理器

首先判断是否为简单类型,接下来web数据绑定器,将请求参数的值绑定到指定的JavaBean里面

WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);

WebDataBinder :web数据绑定器,将请求参数的值绑定到指定的JavaBean里面

WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中GenericConversionService

Converters支持数据转换类型,也可以自定义,通过重写 WebMvcConfigurer里面的addFormatters方法

springboot请求处理流程_第8张图片

3、视图解析流程

(1)目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址

方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer,也就是说,一切在处理中获得的值都会被打包进去mv容器中

任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。

processDispatchResult 处理派发结果(页面改如何响应)

springboot请求处理流程_第9张图片

1、render(mv, request, response); 进行页面渲染逻辑

()根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】

所有的视图解析器尝试是否能根据当前返回值得到View对象

得到了 redirect:/main.html --> Thymeleaf new RedirectView()

ContentNegotiationViewResolver 里面包含了下面所有的视图解析器,内部还是利用下面所有视图解析器得到视图对象。

view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作

RedirectView 如何渲染【重定向到一个页面】

1、获取目标url地址

2、response.sendRedirect(encodedURL);

视图解析:

返回值以 forward: 开始: new InternalResourceView(forwardUrl); --> 转发request.getRequestDispatcher(path).forward(request, response);

返回值以 redirect: 开始: new RedirectView() -- render就是重定向

返回值是普通字符串: new ThymeleafView()--->

4、使用日志查看详情

springboot请求处理流程_第10张图片

5、文件上传请求流程

​​​​​​​1、请求进来使用文件上传解析器判断(isMultipart)并封装(resolveMultipart,返回MultipartHttpServletRequest)文件上传请求

2、参数解析器来解析请求中的文件内容封装成MultipartFile

3、将request中文件信息封装为一个Map;MultiValueMap FileCopyUtils。实现文件流的拷贝

6、异常处理流程:

1、执行目标方法,目标方法运行期间有任何异常都会被catch、而且标志当前请求结束;并且用 disp

2、进入视图解析流程(页面渲染?)

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

atchException ​​​​​​​

3、mv = processHandlerException;处理handler发生的异常,处理完成返回ModelAndView;

定制错误处理逻辑

  • 自定义错误页
    • error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页
  • @ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
  • @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error
  • Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
    • response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
    • springboot请求处理流程_第11张图片

      ​​​​​​​

     

你可能感兴趣的:(java,spring,springboot)