其实 Spring MVC 是一个基于请求驱动的 Web 框架,并且也使用了前端控制器模式来进行设计,再根据请求映射规则分发给相应的页面控制器进行处理,具体工作原理见下图。

在这里,就不详细谈相关的原理和实现细节了,感兴趣的话,可以读一下这方面的书籍。

我在网上看到一篇不错的关于讲述怎么实现一个 MVC 框架的文章,在此,分享给各位读者,也许能帮助到你。

原文内容如下。

我今天主要带大家实现一个迷你版的 Spring MVC ,本项目将在一个干净的 web 工程开发,不引入 Spring,完全通过原生 JDK 来实现。

具体的工程代码结构如下图。

相关代码说明:

  1. 在 annotation 包下,我将提供自定义的注解,为了方便理解,会与 Spring MVC 保持一致。
  2. 为了模拟 Spring MVC 的方法调用链,我这里提供 Controller/Service/Dao 层进行测试。
  3. 提供自定义的 DispatcherServlet 来完成核心逻辑处理。

一、自定义注解

先给各位读者解释一下 JDK 提供了几个元注解:

  • @Documented : JavaDoc文档
  • @Target:标志此注解可以修饰在哪些地方,类,成员变量,方法...
  • @Retention:Annotation的生命周期,一般情况下,我们自定义注解的话,显然需要在运行期获取注解的一些信息。

我这边自定义的注解主要是模拟 Spring MVC ,具体实现如下。

1、@Controller提供控制器

2、@Qualifier提供依赖注入

3、@RequestMapping提供URL地址处理映射

4、Dao层注解

5、Service层注解

二、核心控制器

在 Spring MVC 中,DispatcherServlet 是核心类,下面我的代码主要用来实现它。首先来说,Spring MVC 中的 DispatcherServlet 说到底,还是 HttpServlet 的子类,因此我这边自定义的 DispatcherSerlvet 也需要继承 HttpServlet。

1、pom.xml 加入 servlet 依赖

 

2、定义 DispatcherServlet

代码中的 @WebServlet 用处是什么呢?其实,以前我们定义一个 Servlet ,需要在 web.xml 中去配置,不过在 Servlet 3.0 后出现了基于注解的 Servlet 。

仔细观察,你会发现,这个 DispatcherServlet 是自启动,而且传入了一个参数。

要知道,在 Spring MVC 中,要想基于注解,需要在配置中指明扫描的包路径,就像这个样子。

为了方便,我这里就通过初始化参数直接将需要扫描的基包路径传入。

a、初始化流程

其实,在 init 中,我们主要是完成了什么呢?

  • 我们应该去扫描基包下的类,得到信息 A。
  • 对于 @Controller/@Service/@Repository 注解而言,我们需要拿到对应的名称,并初始化它们修饰的类,形成映射关系 B。
  • 我们还得扫描类中的字段,如果发现有 @Qualifier 的话,我们需要完成注入。
  • 我们还需要扫描 @RequestMapping,完成 URL 到某一个 Controller 的某一个方法上的映射关系 C。

其实,Spring MVC 的处理流程,就是类似这样的!

b、扫描基包

注意,基包是 X.Y.Z 的形式,而 URL 是 X/Y/Z 的形式,需要转换。

c、实例化

从这里你可以看出,我们完成了被注解标注的类的实例化,以及和注解名称的映射。

d、依赖注入

以前,我们总是说Spring IOC,上面不就是在做这个事情么?

e、URL映射处理

我们需要把 URL 提取出来,映射到 Controller 的 Method 上。

f、doGet/doPost

在 doPost 方法中,非常简单,我们只需要提取出 URL,通过 URL 映射到Method 上,然后通过反射的方式进行调用即可。

三、让它跑起来

1、Controller层

2、Service层

 

 

3、Dao层

 

4、运行结果

 

到这里,一个迷你版的 Spring MVC 就开发完成了。

老司机教你用原生JDK 撸一个 MVC 框架!!!的更多相关文章

  1. 纯手工撸一个vue框架

    前言 vue create 真的很方便,但是很多人欠缺的是手动撸一遍.有些人离开脚手架都不会开发了. Vue最简单的结构 步骤 搭建最基本的结构 打开空文件夹,通过 npm init 命令生成pack ...

  2. 【Bugly干货分享】老司机教你 “飙” EventBus 3

    Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. EventBus对于Android ...

  3. 老司机教你下载tumblr上视频和图片的正确姿势

    本文面向初学者. 很多同学问我:“我非常想学Python编程,但是找不到兴趣点”. 还有的同学呢,找到了很好的兴趣点,但是无从下手,“玄魂老师,我想下载tumblr上的视频, 怎么下载,Python能 ...

  4. 徒手生撸一个验证框架,API 参数校验不再怕!

    你们之中大概率早已练就了代码的拷贝.粘贴,无敌的码农神功,其实做久了业务功能开发,练就这两个无敌神功,那是迟早的事儿.今天先抛一个小问题,来打通你的任督二脉,就是很好奇的问一下:业务功能开发中,输入参 ...

  5. 靓仔,整合SpringBoot还在百度搜配置吗?老司机教你一招!!!

    导读 最近陈某公司有些忙,为了保证文章的高质量可能要两天一更了,在这里陈某先说声不好意思了!!! 昨天有朋友问我SpringBoot如何整合Redis,他说百度谷歌搜索了一遍感觉不太靠谱.我顿时惊呆了 ...

  6. 老司机教你如何正确地在大陆安装 BlackArch

    BlackArch 官方有一个比较完整的安装指南文档,其地址为 https://blackarch.org/blackarch-install.html 正如其第一行所述的那样 This tutori ...

  7. 线上Bug无法复现怎么办?老司机教你一招,SpringBoot远程调试不用愁!

    前言 在部署线上项目时,相信大家都会遇到一个问题,线上的 Bug 但是在本地不会复现,多么无奈. 此时最常用的就是取到前端传递的数据用接口测试工具测试,比如 POSTMAN,复杂不,难受不? 今天陈某 ...

  8. 老司机教你在windows不用软件隐藏重要文件

    每个人电脑里面都有些秘密,但是别人需要使用你的电脑时,有可能会看到,但是我们又不想让别人发现时,我们可以将其隐藏,那么别人就不会看到了.360文件保险柜.腾讯电脑管家等等.使用软件繁琐软件过大还会拖慢 ...

  9. PHP原生实现简易的MVC框架

    目录结构: —|controller —|Home.php —|model —|view —|welcome.php —|index.php 基本原理: 首页 index.php 通过获得地址栏中的路 ...

随机推荐

  1. How does rt.jar works?

    转载自:https://stackoverflow.com/questions/30222702/how-does-java-link-lib-rt-jar-to-your-app-at-runtim ...

  2. 【Vue】动态加载Html片段

    在编写Vue页面的时候,会碰到这么一个需求.由于页面组件比较多,不可能一次性将所有的页面都打包,只能按需获取相应的页面进行显示. 比如有一个App页面,需要异步获取html片段通过v-html指令加载 ...

  3. Motrix for Mac(百度网盘加速/全能下载软件) v1.3.7最新版!

    Motrix for Mac最新版第一时间在本站上线!Mac上最强大实用百度网盘加速器Motrix for Mac分享给您!Motrix for Mac是一款非常优秀的下载工具,采用Aria 2作为核 ...

  4. 利用 Saltstack 远程执行命令

    Saltstack的一个比较突出优势就是具备执行远程命令的功能. 操作方法与func (https://fedorahosted.org/func/)相似,可以帮助运维人员完成集中化的操作平台. ht ...

  5. 我们为什么不用 Select * 吗?

    应用程序慢如牛,原因多多,可能是网络的原因.可能是系统架构的原因,还有可能是数据库的原因. 那么如何提高数据库SQL语句执行速度呢?有人会说性能调优是数据库管理员(DBA)的事,然而性能调优跟程序员们 ...

  6. BZOJ 4710

    枚举几个同学分到了 对于每种特产求一个方案数(经典做法)乘起来 然后容斥 #include<bits/stdc++.h> using namespace std; #define rep( ...

  7. PHP序列号生成函数和字符串替换函数代码

    /** * 序列号生成器 */ function snMaker($pre = '') { $date = date('Ymd'); $rand = rand(1000000,9999999); $t ...

  8. VB读写进程的内存

    在窗体部分简单测试了ReadProcessMemory和WriteProcessMemory对另一个程序进程的读写. 由于临时项目变动,又不需要了,所以直接封类,删工程.以下代码没有一个函数经过测试, ...

  9. 1、搭建 maven 环境

    1.创建 Maven 工程 这里需要注意的: 创建时,需要将 maven 工程的打包方式设置为 war,因为我们创建的是一个web工程 创建后,可能会报错,会提示没有 web.xml 文件,这是因为 ...

  10. 开发中少不了的Fun -- 获取地址栏URL参数

    假设这是一个url地址 http://localhost:8080/a/b/c?a=1&b=2#abc,里面包含的部分: protocol: 'http:', // 协议 host: 'loc ...