![7cfb89027a8ffec74845bc717a78cf9eb23f7502](https://yqfile.alicdn.com/7cfb89027a8ffec74845bc717a78cf9eb23f7502.png?x-oss-process=image/resize,w_1400/format,webp)
在这里,就不详细谈相关的原理和实现细节了,感兴趣的话,可以读一下这方面的书籍。
我在网上看到一篇不错的关于讲述怎么实现一个 MVC 框架的文章,在此,分享给各位读者,也许能帮助到你。
原文内容如下。
我今天主要带大家实现一个迷你版的 Spring MVC ,本项目将在一个干净的 web 工程开发,不引入 Spring,完全通过原生 JDK 来实现。
具体的工程代码结构如下图。
![18db4f642f664ac3fcb66fbab18a0790db833d1a](https://yqfile.alicdn.com/18db4f642f664ac3fcb66fbab18a0790db833d1a.png?x-oss-process=image/resize,w_1400/format,webp)
相关代码说明:
-
在 annotation 包下,我将提供自定义的注解,为了方便理解,会与 Spring MVC 保持一致。
-
为了模拟 Spring MVC 的方法调用链,我这里提供 Controller/Service/Dao 层进行测试。
-
提供自定义的 DispatcherServlet 来完成核心逻辑处理。
一、自定义注解
先给各位读者解释一下 JDK 提供了几个元注解:
-
@Documented : JavaDoc文档
-
@Target:标志此注解可以修饰在哪些地方,类,成员变量,方法...
-
@Retention:Annotation的生命周期,一般情况下,我们自定义注解的话,显然需要在运行期获取注解的一些信息。
我这边自定义的注解主要是模拟 Spring MVC ,具体实现如下。
1、@Controller提供控制器
2、@Qualifier提供依赖注入
3、@RequestMapping提供URL地址处理映射
4、Dao层注解
![b718afec7a713b6155a3b3e22753581e1ecf4353](https://yqfile.alicdn.com/b718afec7a713b6155a3b3e22753581e1ecf4353.png?x-oss-process=image/resize,w_1400/format,webp)
5、Service层注解
![261668e54e0f0f8d21792d2f9a58796b54119f45](https://yqfile.alicdn.com/261668e54e0f0f8d21792d2f9a58796b54119f45.png?x-oss-process=image/resize,w_1400/format,webp)
二、核心控制器
在 Spring MVC 中,DispatcherServlet 是核心类,下面我的代码主要用来实现它。首先来说,Spring MVC 中的 DispatcherServlet 说到底,还是 HttpServlet 的子类,因此我这边自定义的 DispatcherSerlvet 也需要继承 HttpServlet。
1、pom.xml 加入 servlet 依赖
![ba5f273f8335d4dc7ff5247b744f4386cd8817ca](https://yqfile.alicdn.com/ba5f273f8335d4dc7ff5247b744f4386cd8817ca.png?x-oss-process=image/resize,w_1400/format,webp)
2、定义 DispatcherServlet
![5c6d7683e162d1b30676e598d65ba7691ed52690](https://yqfile.alicdn.com/5c6d7683e162d1b30676e598d65ba7691ed52690.png?x-oss-process=image/resize,w_1400/format,webp)
代码中的 @WebServlet 用处是什么呢?其实,以前我们定义一个 Servlet ,需要在 web.xml 中去配置,不过在 Servlet 3.0 后出现了基于注解的 Servlet 。
仔细观察,你会发现,这个 DispatcherServlet 是自启动,而且传入了一个参数。
要知道,在 Spring MVC 中,要想基于注解,需要在配置中指明扫描的包路径,就像这个样子。
为了方便,我这里就通过初始化参数直接将需要扫描的基包路径传入。
a、初始化流程
![cd98c7293828494274b55b44ece78a5534b715c4](https://yqfile.alicdn.com/cd98c7293828494274b55b44ece78a5534b715c4.png?x-oss-process=image/resize,w_1400/format,webp)
-
我们应该去扫描基包下的类,得到信息 A。
-
对于 @Controller/@Service/@Repository 注解而言,我们需要拿到对应的名称,并初始化它们修饰的类,形成映射关系 B。
-
我们还得扫描类中的字段,如果发现有 @Qualifier 的话,我们需要完成注入。
-
我们还需要扫描 @RequestMapping,完成 URL 到某一个 Controller 的某一个方法上的映射关系 C。
其实,Spring MVC 的处理流程,就是类似这样的!
b、扫描基包
![a1d5ac1725fa39cdbc85d68505b84fa6beec2b6c](https://yqfile.alicdn.com/a1d5ac1725fa39cdbc85d68505b84fa6beec2b6c.png?x-oss-process=image/resize,w_1400/format,webp)
注意,基包是 X.Y.Z 的形式,而 URL 是 X/Y/Z 的形式,需要转换。
c、实例化
![2cf1cce9537f70686c86ca3e8b49e7ad3b74d125](https://yqfile.alicdn.com/2cf1cce9537f70686c86ca3e8b49e7ad3b74d125.png?x-oss-process=image/resize,w_1400/format,webp)
从这里你可以看出,我们完成了被注解标注的类的实例化,以及和注解名称的映射。
d、依赖注入
![bb2f422b11196250b0866f2e1cdc9f21ca6ebbd1](https://yqfile.alicdn.com/bb2f422b11196250b0866f2e1cdc9f21ca6ebbd1.png?x-oss-process=image/resize,w_1400/format,webp)
e、URL映射处理
![95fd878eb1bd5aff0d3de39300b3fcc8134086a2](https://yqfile.alicdn.com/95fd878eb1bd5aff0d3de39300b3fcc8134086a2.png?x-oss-process=image/resize,w_1400/format,webp)
f、doGet/doPost
![e7a4eea9667f52f0046abfa034d70be89e1b8e1d](https://yqfile.alicdn.com/e7a4eea9667f52f0046abfa034d70be89e1b8e1d.png?x-oss-process=image/resize,w_1400/format,webp)
三、让它跑起来
1、Controller层
![f0b2fb633730b742165ff597f2debab309eafd53](https://yqfile.alicdn.com/f0b2fb633730b742165ff597f2debab309eafd53.png?x-oss-process=image/resize,w_1400/format,webp)
2、Service层
![0aeaae6eaa4e935084a2a151ad1b1bd2e3ce9f07](https://yqfile.alicdn.com/0aeaae6eaa4e935084a2a151ad1b1bd2e3ce9f07.png?x-oss-process=image/resize,w_1400/format,webp)
![552eabd335fcda67f50ca9593ce2a8474f63b3d8](https://yqfile.alicdn.com/552eabd335fcda67f50ca9593ce2a8474f63b3d8.png?x-oss-process=image/resize,w_1400/format,webp)
3、Dao层
![6d7b5e9ed26aa32c1743c09e45c4bf6c54780fd5](https://yqfile.alicdn.com/6d7b5e9ed26aa32c1743c09e45c4bf6c54780fd5.png?x-oss-process=image/resize,w_1400/format,webp)
![942955ad4d6c5bdfc2157bf2f0b729e0023b5ae2](https://yqfile.alicdn.com/942955ad4d6c5bdfc2157bf2f0b729e0023b5ae2.png?x-oss-process=image/resize,w_1400/format,webp)
4、运行结果
![1f6037ac5b07e88bcac0c0a1d5134918c6c2be10](https://yqfile.alicdn.com/1f6037ac5b07e88bcac0c0a1d5134918c6c2be10.png?x-oss-process=image/resize,w_1400/format,webp)
到这里,一个迷你版的 Spring MVC 就开发完成了。
原文发布时间为: 2018-10-21
本文作者:Java面试那些事儿
本文来自云栖社区合作伙伴“Java面试那些事儿”,了解相关信息可以关注“Java面试那些事儿”。