其实 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. 【webpack系列】从零搭建 webpack4+react 脚手架(一)

    搭建一个React工程的方式有很多,官方也有自己的脚手架,如果你和我一样,喜欢刨根究底,从零开始自己一行一行代码创建一个React脚手架项目,那你就来对地方了.本教程是针对React新手,以及对web ...

  2. POSIX-Data Structure

    struct sigevent The <signal.h> header shall define the sigeventstructure, which shall include ...

  3. c++继承学习

    继承分类: 虚表继承 class D{ public : d(){ } ~d(){ } private: }; 单重继承 class D{ public : d(){ } ~d(){ } privat ...

  4. 3步永久性激活pycharm 亲测有效

    ----------破解后,有效时间会到2099年------------ 1.下载JAR包:此JAR包的目的就是让截获截止时间并骗过pycharm 链接:https://pan.baidu.com/ ...

  5. VS 2013Ultimate 开发过程中遇到的问题——listbox的隐藏问题,combobox.textchanged的中文问题

    最近项目有需求,就是把一个combobox让它可以根据用户输入的汉字就行模糊查询出匹配的下拉框内容,很简单,是吧 但是!!!在开发中真是遇到了不少问题呢. 一.实现流程 1)我的实现思维是这样的,先把 ...

  6. web应用、HTTP协议及web框架简介

    1. web应用 1.1 web应用程序 Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件 B/S模式(浏览器/服 ...

  7. nginx配置前端代理

    #user nobody;worker_processes 1; #error_log logs/error.log;#error_log logs/error.log notice;#error_l ...

  8. List使用linq的OrderBy方法排序,并按照两个字段排序的写法

    SfaMember.GetList(searchInfo, 0, 1000, out Allcount).Where(item => item.bOpen == true).OrderBy(it ...

  9. java拦截处理System.exit(0)

    在使用TestNG做单元测试时,需要测试的代码中出现System.exit(0),导致单元测试还未结束程序就停止了.解决方法如下: public class TestMain { public sta ...

  10. phantomjs api文档

    phantomjs实现了一个无界面的webkit浏览器.虽然没有界面,但dom渲染.js运行.网络访问.canvas/svg绘制等功能都很完备,在页面抓取.页面输出.自动化测试等方面有广泛的应用. 详 ...