百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

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

toyiye 2024-06-21 12:19 12 浏览 0 评论

简介

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

@Override
protected 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 整体的一个请求流程粗略的过了一遍,主要分下面几个步骤

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

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码