手写Spring框架---MVC实现

目录

预备

自研框架MVC的实现

MVC架构草图:

大致流程

实现思路

自定义注解

JavaBean

请求的拦截-建立DispatcherServlet

责任链处理请求

RequestProcessor矩阵

Render矩阵


  • 预备

  • 在DispatcherServlet:
    • 解析请求路径和请求方法
    • 依赖容器,建立并维护Controller方法与请求的映射
    • 用合适的Controller方法去处理特定的请求
  • 参照SpringMVC,仅通过DispatcherServlet进行请求派发这样可以让系统模块更加明确,该类的任务有:
    • 拦截全部请求
    • 解析请求
    • 派发给对应的Controller里面进行处理
  • 通过下面的注解可以拦截到全部请求

  • 由于给DispatcherServlet标记了@WebServlet("/"),所以在tomcat启动之后会将DispatcherServlet给加载进来

  • 因为设置了/匹配所有的的url-pattern,而且在tomcat插件中的设置了项目的根路径,<path>/${project.artifactId}</path>可以获取项目的名字,这样设置之后以项目名为根路径的请求都会经由DispatcherServlet来处理,里面的service方法就是用来处理请求的

  • 相关的请求就会交给DispatcherServlet来处理,在DispatcherServlet加载到tomcat里面之后,在首次接收外部请求的时候,会调用里面init方法来完成自身的初始化,初始化之后调用service来处理相关的请求
  • 后续的请求再到来时不会再执行初始化方法,直接调用service方法来处理请求
  • HttpServletRequest里面包含了请求路径和请求方法以及请求里面的业务参数
  • 通过类似简单工厂方法的模式解析请求方法和请求路径,按照请求路径和请求方法转发到对应的controller方法处理
  • 在实际的使用中可以选择将返回的数据转换为json格式返回给前端,或者也可以生成相关的页面视图返回给前端去做渲染
  • 下面的会对jsp请求也会进行拦截,如果我们在页面中转发到jsp,就依然会被拦截到这个类里

  • 原因在tomcat的web.xml中,反斜杠是Servlet中特殊的匹配模式,优先级最低,比*.jsp优先级低,但是反斜杠星号属于路径匹配,优先级比*.jsp高

  • 自研框架MVC的实现

  • MVC架构草图:

  • 大致流程

  • 获取http请求和需要回发的http响应对象,之后将他们委托给RequestProcessorChain处理
  • 我们只处理get和post方法的请求,RequestProcessorChain参照的是责任链模式的后置处理器的处理逻辑,里面保存了处理RequestProcessor接口的多个不同的实现类,之所以会有多个不同的实现类对应为DispatcherServlet是项目里面所有请求的唯一入口
  • DispatcherServlet[ 调度Servlet ]的作用是将请求分发到不同的处理器
  • 这些请求里即会有获取jsp页面的请求,也会有获取静态资源的请求、直接获取json数据的请求等,针对不同的请求会使用不同的RequestProcessor来处理
  • Spring MVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)

  • 简要分析执行流程
    • 1-DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心
    • 用户发出请求,DispatcherServlet接收请求并拦截请求
    • 假设请求的url为:http://localhost:8080/SpringMVC/hello
    • 如上url拆分成三部分:
      • http://localhost:8080服务器域名
      • SpringMVC部署在服务器上的web站点
      • hello表示控制器
    • 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
    • 2-HandlerMapping为处理器映射;DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler
    • 3-HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello
    • 4-HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
    • 5-HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
    • 6-Handler让具体的Controller执行
    • 7-Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView
    • 8-HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
    • 9-DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
    • 10-视图解析器将解析的逻辑视图名传给DispatcherServlet
    • 11-DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
    • 12-最终视图呈现给用户
  • 实现思路

    • 自研框架实现思路定义DispatcherServlet分发器
    • 创建责任链对象实例
    • 通过责任链模式来依次调用请求处理对请求进行处理
    • 对处理结果进行渲染
  • 自定义注解

    • @RequestMapping 标识controller的方法和请求路径和请求方法的映射问题

    • @RequestParam 请求方法参数名

    • @ResponseBody 用于标记自动对返回值进行json处理

  • JavaBean

    • ControllerMethod 待执行的Controller及其方法实例和参数的映射

    • ModelAndView 存储处理完后的结果数据以及显示该数据的视图

    • RequestMethod 框架目前支持的请求方法

    • RequestPathInfo 储存http请求路径和请求方法

  • 请求的拦截-建立DispatcherServlet

    • 初始化容器
    • 初始化请求处理器责任链
    • 通过责任链模式来依次调用请求处理器对请求进行处理
    • 对处理结果进行渲染

    • init方法
      • 对常驻变量进行初始化
      • servlet是程序执行的入口:对容器进行初始化并将相关的bean加载进来,同时完成AOP相关逻辑的织入,以及相关的IoC依赖注入等操作
      • 因为后面是采用责任链模式来实现RequestProcessor矩阵的,要将对应的处理器添加到处理器列表中
      • 将RequestProcessor矩阵按序添加到缓存列表里
      • 之所以按照图示的顺序进行添加,是因为我们的请求经过编码和路径的处理之后才能进行后续的处理
      • 将ControllerRequestProcessor放在最后是因为它的处理会比较耗时,需要将请求和controller的方法实例进行匹配
    • service方法
      • 首先创建责任链对象实例
      • 然后通过责任链模式来依次调用请求处理器对请求进行处理
        • 通过迭代器遍历注册的请求处理器实现类列表
        • 直到某个请求处理器执行后返回false为止
        • 期间如果出现异常,则交由内部异常渲染器处理
      • 最后对处理结果进行渲染
        • 如果请求处理器实现类均未选择合适的渲染器,则使用默认的
        • 调用渲染器的render方法对结果进行渲染
  • 责任链处理请求

  • 以责任链的模式执行注册的请求处理器
  • 委派给特定的Render实例对处理后的结果进行渲染

  • RequestProcessor矩阵

    • PreRequestProcessor处理器(请求预处理器):主要负责对请求的编码以及对路径做一些前置处理

    • 剩余的处理器都会去解析请求,以看看请求是否由该处理器去处理的
    • StaticResourceRequestProcessor处理器(静态资源处理器):对静态资源请求

    • 利用的tomcat默认请求派发器RequestDispatcher处理
    • JspRequestProcessor处理器(JSP处理器):对jsp页面的访问请求进行处理(不仅过controller直接访问页面的请求)

    • 利用的tomcat的jspServlet处理
    • ControllerRequestProcessor处理器(Controller处理器):将请求派发到对应的controller方法里面进行处理
      • 针对特定请求,选择匹配的Controller方法进行处理
      • 解析出请求里的参数及其对应的值,并赋值给Controller方法的参数
      • 选择合适的Render,为后续请求处理结果的渲染做准备

      • 建立Controller方法与请求的映射关系
        • 请求中包含的信息有路径和请求参数,所以需要根据这些信息找到对应的Controller方法
        • 利用RequestPathInfo存储请求的信息,ControllerMethod存储Controller以及方法的信息
        • 建立的映射关系就是RequestPathInfo与ControllerMethod的,这样就可以根据请求定位到对应的方法
      • 然后利用ConverterUtil给需要执行的方法参数赋值
      • 最后利用反射执行获取执行的结果,根据结果设置结果渲染器
  • Render矩阵

    • 渲染,处理了相关的请求之后,需要将结果以不同的形式给展现出来,并且处理的过程中可能会出现各种各样的异常,也需要去做体现
    • Render负责对结果进行包装并展现
    • 当处理器处理完之后就会调用特定的实现了Render接口的实现类,对处理结果进行展现

    • DefaultResultRender(默认结果渲染器):当请求处理成功后,用户只需要返回一个成功的状态码
      • 如果请求处理器实现类均未选择合适的渲染器,则使用默认的结果渲染器
      • 主要将处理的结果状态码返回,默认为200

    • JsonResultRender(Json结果渲染器):用户发送的请求是想要获取json格式的返回结果
      • 当方法上面使用@ResponseBody 注解时,利用Gson将结果转换成Json数据返回

    • ViewResultRender(视图解析器):将逻辑视图转换成用户可以看到的物理视图,类似于ModelAndView对象
      • 视图解析器则根据返回结果的不同,而进行跳转
      • 如果是String数据,则创建一个ModelAndView对象,并将数据加入到视图地址
      • 如果是ModelAndView,则会解析其中的视图地址和数据
      • 针对其他情况,则直接抛出异常

    • InternalErrorResultRender(异常结果渲染器):对异常的处理
      • 以责任链的模式处理请求,期间如果出现异常,则交由内部异常渲染器处理
      • 设置状态码500和异常信息

    • ResourceNotFoundResultRende(找不到路径渲染器):资源无法找到的异常
      • 在根据请求路径转发到Controller时,找不到对应的对象或者方法,则使用该渲染器
      • 返回404和请求的路径及方法

  • 测试成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/39446.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端学习记录~2023.7.17~CSS杂记 Day9

前言一、浮动1、使盒子浮动起来2、清除浮动3、清除浮动元素周围的盒子&#xff08;1&#xff09;clearfix 小技巧&#xff08;2&#xff09;使用 overflow&#xff08;3&#xff09;display: flow-root 二、定位1、定位有哪些2、top、bottom、left 和 right3、定位上下文4、介绍…

ACME申请SSL证书

1.开放443端口 firewall-cmd --permanent --add-port443/tcp # 开放443端口 firewall-cmd --reload # 重启防火墙(修改配置后要重启防火墙)2.安装ACME # 安装acme curl https://get.acme.sh | sh -s email你的邮箱地址 # 别名 alias acme.sh~/.acme.sh/acme.sh3.使用ACME申请…

【面试笔试避坑指南】一

从这篇文章开始 进行笔试的训练环节&#xff0c;我会在 本专栏详细介绍笔试的易错点&#xff0c;帮助大家精准避坑。 1.有如下一段代码&#xff08;unit16_t为2字节无符号整数&#xff0c;unit8_t位1字节无符号整数&#xff09;&#xff1b; 请问x.z.n在大字节序和小字节序机器…

【MySQL异常解决】MySQL执行SQL文件出现【Unknown collation ‘utf8mb4_0900_ai_ci‘】的解决方案

MySQL执行SQL文件出现【Unknown collation ‘utf8mb4_0900_ai_ci‘】的解决方案 一、背景描述二、报错原因三、解决方案3.1 升级 MySQL 数据库版本3.2 修改字符集为 一、背景描述 从服务器MySQL中导出数据为SQL执行脚本后&#xff0c;在本地电脑执行导出的SQL脚本&#xff0c;…

【HarmonyOS】Stage模型二维码/条码生成与解析

HarmonyOS的官方API中提供了QRCode组件&#xff08;QRCode-基础组件-组件参考&#xff08;基于ArkTS的声明式开发范式&#xff09;-ArkTS API参考-HarmonyOS应用开发&#xff09;&#xff0c;这个组件有个缺点只能用于显示二维码&#xff0c;无法显示条码与解析码内容&#xff…

【UE】运行游戏时就获取鼠标控制

问题描述 我们经常在点击运行游戏后运行再在视口界面点击一下才能让游戏获取鼠标控制。其实只需做一个设置就可以在游戏运行后自动获取鼠标控制。 解决步骤 点击编辑器偏好设置 如下图&#xff0c;点击“播放”&#xff0c;再勾选“游戏获取鼠标控制” 这样当你运行游戏后直…

idea创建spark教程

1、环境准备 java -version scala -version mvn -version spark -version 2、创建spark项目 创建spark项目&#xff0c;有两种方式&#xff1b;一种是本地搭建hadoop和spark环境&#xff0c;另一种是下载maven依赖&#xff1b;最后在idea中进行配置&#xff0c;下面分别记录两…

ELK-日志服务【redis-配置使用】

目录 环境 【1】redis配置 【2】filebeat配置 【3】对接logstash配置 【4】验证 【5】安全配置&#xff1a;第一种&#xff1a;kibana-nginx访问控制 【6】第二种&#xff1a;在ES-主节点-配置TLS 【7】kibana配置密码 【8】logstash添加用户密码 环境 es-01,kibana 1…

中国国债发行数据集(2002-2023)

国债是由国家发行的债券&#xff0c;由于国债的发行主体是国家&#xff0c;所以它具有最高的信用度&#xff0c;被公认为是最安全的投资工具。国债按照交易市场的不同分为三类&#xff0c;即银行间市场国债、交易所市场国债和柜台市场国债&#xff1b;按照交易方式的不同分为三…

vue树组件循环表格

最近做项目需要实现循环表格这个需求&#xff0c;其中实用到了循环组件&#xff0c;特此记录一下&#xff0c;这是需要实现的功能&#xff0c;如下图&#xff1a; vue中实现组件循环 父组件 <template><div><ul><li v-for"(item,index) in aside…

【HCIA】10.VLAN间通信

VLAN间通信的解决方法 使用路由器的物理接口 路由器三层接口作为网关&#xff0c;转发本网段前往其它网段的流量。路由器三层接口无法处理携带VLAN Tag的数据帧&#xff0c;因此交换机上联路由器的接口需配置为Access。路由器的一个物理接口作为一个VLAN的网关&#xff0c;因此…

2023-07-14:讲一讲Kafka与RocketMQ中存储设计的异同?

2023-07-14&#xff1a;讲一讲Kafka与RocketMQ中存储设计的异同&#xff1f; 答案2023-07-14&#xff1a; 在Kafka中&#xff0c;文件的布局采用了Topic/Partition的方式&#xff0c;每个分区对应一个物理文件夹&#xff0c;且在分区文件级别上实现了顺序写入。然而&#xff0…

Qt Creator常用快捷键及技巧

文章目录 1.[Qt Creator常用快捷键及技巧提升编码效率]2.win10上安装QT &#xff0c;选择安装组件3.qt配置过程中主要注意的几点4.目录结构附&#xff1a;网友整理快捷方式&#xff1a; 1.[Qt Creator常用快捷键及技巧提升编码效率] (https://blog.csdn.net/luoyayun361/artic…

nginx+lua+redis环境搭建(文末赋上脚本)

目录 需求背景 环境搭建后nginx和redis版本 系统环境 搭建步骤 配置服务器DNS 安装ntpdate同步一下系统时间 安装网络工具、编译工具及依赖库 创建软件包下载目录、nginx和redis安装目录 下载配置安装lua解释器LuaJIT 下载nginx NDK&#xff08;ngx_devel_kit&#xff09…

三菱q以太网简单cpu通讯

产品概述 捷米特JM-ETH-QnA是一款经济型的以太网通讯处理器&#xff0c;是为满足日益增多的工厂设备信息化需求&#xff08;设备网络监控和生产管理&#xff09;而设计&#xff0c;用于三菱Q2A/Q2AS1/Q3A/Q4A等多个QnA系列PLC的以太网数据采集&#xff0c;非常方便构建生产管理…

前端uni-app自定义精美全端复制文本插件,支持全端文本复制插件 可设置复制按钮颜色

随着技术的发展&#xff0c;开发的复杂度也越来越高&#xff0c;传统开发方式将一个系统做成了整块应用&#xff0c;经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改&#xff0c;造成牵一发而动全身。 通过组件化开发&#xff0c;可以有效实现…

Qt的三大优势,打造高效工业软件开发:

强大的跨平台特性&#xff1a;Qt拥有优良的跨平台支持&#xff0c;可以在众多操作系统上运行&#xff0c;包括Microsoft Windows、Linux、Solaris、HP-UX、FreeBSD、QNX等等。这使得开发者可以轻松地将应用程序部署到不同的平台上&#xff0c;提高开发效率和覆盖范围。 面向对…

“体验家”亮相第六届IAIC成都国际医美产业大会

6月23日-25日&#xff0c;第六届IAIC成都国际医美产业大会暨“医美之都”高峰会议在成都世纪城国际会议中心成功举行。本次大会邀请了来自国家药品监督管理局、部分省市地区的相关领导莅临指导&#xff0c;以及来自全国100医美行业头部平台&#xff0c;近2000位医美产业领军代表…

什么是统一建模语言(UML)UML与UML类图的基本概念

什么是统一建模语言UML&#xff08;Unified Modeling Language&#xff09; UML&#xff08;统一建模语言&#xff09;是一种通用的建模语言&#xff0c;用于描述软件系统的结构、行为和交互。它提供了一组符号和规则&#xff0c;用于创建可视化的图形模型&#xff0c;帮助开发…

ios 启动页storyboard 使用记录

本文简单记录ios启动页storyboard 如何使用和注意事项。 xcode窗口简介 以xcode14为例&#xff0c;新建项目如下图&#xff0c;左边文件栏中的LaunchScreen.storyboard 为默认启动页布局。窗口中间部分是storyboard中的组件列表&#xff0c;右侧为预览&#xff0c;可以看到渲…