最近在看尚硅谷雷神的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执行链对象的形式返回。
HandlerMapping首先回根据请求方式进行匹配
0:所有标注了@RequestMapping的方法都会以map的形式储存在这里,保存了所有@RequestMapping 和handler的映射规则。
里面除了我们定义的方法之外还有两个默认的error映射,其匹配规则是增强循环,直到遍历到对应的url
1:针对欢迎页的HandlerMapping,能访问到index.html;
4) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
HandlerMapping中找到能处理请求的Handler(Controller.method()),找到方法后我们需要对其方法的参数进行解析,即要找到合适的HandlerAdapter对参数进行解析
0 - 支持方法上标注@RequestMapping 1 - 支持函数式编程的
确定将要执行的目标方法的每一个参数的值是什么;SpringMVC目标方法能写多少种参数类型。取决于参数解析器HandlerMethodArgumentResolver。
当前解析器是否支持解析这种参数(常用参数注解:@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中
执行方法流程
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文件进行设置
2、自定义类参数解析(接4)
使用ServletModelAttributeMethodProcessor 这个参数处理器
首先判断是否为简单类型,接下来web数据绑定器,将请求参数的值绑定到指定的JavaBean里面
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
WebDataBinder :web数据绑定器,将请求参数的值绑定到指定的JavaBean里面
WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中GenericConversionService
Converters支持数据转换类型,也可以自定义,通过重写 WebMvcConfigurer里面的addFormatters方法
3、视图解析流程
(1)目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址
方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer,也就是说,一切在处理中获得的值都会被打包进去mv容器中
任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。
processDispatchResult 处理派发结果(页面改如何响应)
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、使用日志查看详情
5、文件上传请求流程
1、请求进来使用文件上传解析器判断(isMultipart)并封装(resolveMultipart,返回MultipartHttpServletRequest)文件上传请求
2、参数解析器来解析请求中的文件内容封装成MultipartFile
3、将request中文件信息封装为一个Map;MultiValueMap
6、异常处理流程:
1、执行目标方法,目标方法运行期间有任何异常都会被catch、而且标志当前请求结束;并且用 disp
2、进入视图解析流程(页面渲染?)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
atchException
3、mv = processHandlerException;处理handler发生的异常,处理完成返回ModelAndView;
定制错误处理逻辑