龙空技术网

SpringMVC核心组件&请求流程&源码

一往无前生活家38u 414

前言:

今天小伙伴们对“mvc获取url的组件是什么”大约比较关怀,你们都想要剖析一些“mvc获取url的组件是什么”的相关知识。那么小编也在网络上搜集了一些关于“mvc获取url的组件是什么””的相关知识,希望我们能喜欢,小伙伴们快快来学习一下吧!

简介

SpringMVC的核心都是围绕着前端调度器-DispatcherServlet设计的,DispatcherServlet负责请求统一的调度,实际的工作交给相应的组件执行,各司其职,如下图:

SpringMVC请求流程

组件DispatcherServlet

DispatcherServlet-前端调度器 负责拦截前端的请求 然后分发到各个处理器的方法中

HandlerMapping

处理器映射器负责通过请求的url 匹配 对应的执行器链。

HandlerAdapter

处理器适配器,负责执行处理器的具体方法,返回ModelAndView

ModelAndView

封装视图和数据

ViewReslover

解析ModelAndView 返回view

现在大部分项目都是前后端分离以JSON的方式进行数据交互,所以后面我们重点讲解DispatcherServlet、HandlerMapping、HandlerAdapter 这三个组件。

源码

DispatcherServlet 类图

dispatcherServlet 是Servlet的一个实现类吗,所以在请求进来时会进入到Servlet#Service方法,然后根据类图 一顿分析 可以得出 请求会进入到 DispatcherServlet#doService方法

doService

入口函数:org.springframework.web.servlet#doService

@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {    logRequest(request);    .....省略代码    try {        // 调度逻辑找到了 继续跟        doDispatch(request, response);    }    .....省略代码}
doDispatch

请求调度开始:org.springframework.web.servlet#doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {    ..... 代码省略     HandlerExecutionChain mappedHandler = null;    try {        ModelAndView mv = null;        Exception dispatchException = null;        try {            // 检查是否为文件上传            processedRequest = checkMultipart(request);            multipartRequestParsed = (processedRequest != request);            // 根据reaquest 获取处理器链             //  HandlerExecutionChain 对象 除了处理器handler 还包含拦截器等其他信息            mappedHandler = getHandler(processedRequest);            if (mappedHandler == null) {                // url没有对应的处理器 返回404  noHandlerFound 此处简单逻辑大家自己跟一下就好了                noHandlerFound(processedRequest, response);                return;            }            // 根据处理器获取到处理器适配器 为后面执行处理器准备            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());            ..... 代码省略             //  执行处理器链 中 拦截器的 preHandle 方法            if (!mappedHandler.applyPreHandle(processedRequest, response)) {                // false直接返回                return;            }            //  处理器适配器执行具体的 处理器方法 返回 ModelAndView            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());            if (asyncManager.isConcurrentHandlingStarted()) {                return;            }            // 设置viewName            applyDefaultViewName(processedRequest, mv);            //  执行处理器链 中 拦截器的 postHandle 方法            mappedHandler.applyPostHandle(processedRequest, response, mv);        }        catch (Exception ex) {            dispatchException = ex;        }        catch (Throwable err) {            // As of 4.3, we're processing Errors thrown from handler methods as well,            // making them available for @ExceptionHandler methods and other scenarios.            dispatchException = new NestedServletException("Handler dispatch failed", err);        }        // 5.解析并渲染视图ModelAndView 正常执行拦截器afterCompletion 方法        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);    }    catch (Exception ex) {        // 异常执行拦截器afterCompletion 方法        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);    }    catch (Throwable err) {        // 异常执行拦截器afterCompletion 方法        triggerAfterCompletion(processedRequest, response, mappedHandler,                new NestedServletException("Handler processing failed", err));    }    ..... 代码省略 }
processDispatchResult

渲染视图:org.springframework.web.servlet#processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,            @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,            @Nullable Exception exception) throws Exception {    .....省略代码    if (mv != null && !mv.wasCleared()) {        // 渲染视图         render(mv, request, response);        if (errorView) {            WebUtils.clearErrorRequestAttributes(request);        }    }    .....省略代码    if (mappedHandler != null) {        // 执行拦截器 afterCompletion 方法        mappedHandler.triggerAfterCompletion(request, response, null);    }}protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {    ...    View view;    String viewName = mv.getViewName();    if (viewName != null) {        // 此处会获取 视图解析器 viewResolvers 解析视图        view = resolveViewName(viewName, mv.getModelInternal(), locale, request);        if (view == null) {            throw new ServletException("Could not resolve view with name '" + mv.getViewName() +                    "' in servlet with name '" + getServletName() + "'");        }    }    ...    try {        if (mv.getStatus() != null) {            response.setStatus(mv.getStatus().value());        }        // 渲染视图        view.render(mv.getModelInternal(), request, response);    }    catch (Exception ex) {        if (logger.isDebugEnabled()) {            logger.debug("Error rendering view [" + view + "]", ex);        }        throw ex;    }}
总结

本文将SpringMVC 整体的一个请求流程粗略的过了一遍,主要分下面几个步骤

DispatcherServlet#doDispatch: 前端控制器开始调度请求流程.getHandler(processedRequest): 根据request 获取处理器 mappedHandler( HandlerExecutionChain 对象包括拦截器)getHandlerAdapter(mappedHandler.getHandler()): 根据处理器获取处理器适配器 hamappedHandler.applyPreHandle(): 执行mappedHandler中拦截器的preHandle 方法ha.handle(): 处理器适配器 执行 处理器方法 返回视图mappedHandler.applyPostHandle() 执行mappedHandler中拦截器的postHandle 方法processDispatchResult():解析视图然后进行视图渲染 返回给客户端

标签: #mvc获取url的组件是什么