springboot : 深入浅出spring mvc

spring mvc架构及最简单的应用

标签(空格分隔): springmvc springboot RestController RequestMapping EnableAutoConfiguration


最简单的例子

理论结合实践才能理解的更透彻,对于程序员来说,代码就是最好的实践,所以把代码例子放在开头。

例子主要参考SPRING BOOT : HELLO WORLD WITH MAVEN - 2018,是一个简单到不能再简单的例子。

ps:这里用的其实是spring boot的例子。spring boot和spring mvc的区别可以参考What is difference between spring MVC and spring boot?简单(不一定准确)来说spring boot的核心就是spring mvc,spring boot在spring mvc的核心上添加了自动配置的功能,简化了spring mvc的使用。

文本编辑器新建一个pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

修改groupId和artifactId(如果不修改,直接导入到IDE,项目的名字就叫做myproject,很难看),然后import到IDE中(我用的是Eclipse)。

新建一个个java文件

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class Example {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Example.class, args);
    }

}

架构

架构图

avatar

这个图来源于Overview of Spring MVC Architecture,图中把需要用户自己实现的部分用紫色的方框表现出来,理论和实践结合起来,所以让人觉得特别的清晰。

文章中还对架构图中的每一个部分基于一个请求的流程做了描述,如下:

1. DispatcherServlet receives the request.
2. DispatcherServlet dispatches the task of selecting an appropriate controller to HandlerMapping. HandlerMapping selects the controller which is mapped to the incoming request URL and returns the (selected Handler) and Controller to DispatcherServlet.
3. DispatcherServlet dispatches the task of executing of business logic of Controller to HandlerAdapter.
4. HandlerAdapter calls the business logic process of Controller.
5. Controller executes the business logic, sets the processing result in Model and returns the logical name of view to HandlerAdapter.
6. DispatcherServlet dispatches the task of resolving the View corresponding to the View name to ViewResolver. ViewResolver returns the View mapped to View name.
7. DispatcherServlet dispatches the rendering process to returned View.
8. View renders Model data and returns the response.

图是好图,文字说明好像也还可以,但是我总还是觉得不够清晰,然后再参考了下面两个图


1

以及

[站外图片上传中...(image-b66d03-1535359398625)]

综合起来理解应该就已经比较清晰。(这个也我在老程序员的一点套路之方法论中提到过的,看不明白的时候就多看几个人的描述)。

理论联系实际,从例子的角度说一下架构

  1. HandlerMapping负责根据请求返回处理该请求的controller,结合例子,对于http://localhost:8080/这个请求,HandlerMapping会选中Example这个controller来进行处理。

  2. HandlerAdapter负责调用controller中的具体的函数,结合例子,对于http://localhost:8080/这个请求,HandlerAdapter会调用home函数。
    代码中的两个注解@RestController和 @RequestMapping("/")在上述的两个过程中起到了关键的作用,有他们的存在,HandlerMapping才能找到正确的controller,HandlerAdapter才能调用正确的函数去处理 http://localhost:8080/ 这个请求。

  3. so far,请求已经被处理,现在进入到返回处理结果的阶段。代码中的@RestController注解在这个阶段起了关键的作用,@RestController实际上是等价于 @Controller and @ResponseBody的组合

 @Controller
 @ResponseBody

其中@Controller表明Example是一个controller,HandlerMapping在找controller的时候就会考虑是不是要选Example(实际上Controller本质也是一个Bean,只是在Bean的基础上加了点东西以便HandlerMapping能区分是普通的Bean还是一个Controller);@ResponseBody则是指示框架跳过 view 相关的东西,直接把home的返回值作为http response的body。
这里详细说一下view。所谓的view简单来说,就是给html里面的变量赋值(这个动作有些文章会描述成渲染)的功能模块(这个模块有很多种实现,Thymeleaf就是其中的一种实现。也正因为有很多的实现,所以需要一个View Resolvers就是用来选view的,举个简单的例子,jsp页面就需要选jsp对应的view来处理),变量和变量值是controller的函数返回到 model里面的,,view根据model的内容修改html,完成后把它作为http response 的body返回。经过这样的说明,应该能理解为什么说本文中例子是不经过框架的view相关的处理的了吧。

其它

仔细点看就会发现,到目前为止,例子中还有点东西没交代。这是因为剩下的这点东西和spring mvc已经没有什么关系了,它们是纯粹属于spring boot在配置方面起作用的东西,包括@EnableAutoConfiguration和SpringApplication.run(Example.class, args),下面简单讲一下.
@EnableAutoConfiguration会扫描classpath下面的jar对他们进行自动的配置,这也是我理解的spring boot之所以很方面的一个最重要的原因。
至于SpringApplication.run(Example.class, args),值得一提的是第一个参数Example.class。为什么要用Example.class作为参数?让我们把@EnableAutoConfiguration改成@SpringBootApplication,或者会更好理解一些,@SpringBootApplication等价于@Configuration, @EnableAutoConfiguration 和 @ComponentScan的组合

@Configuration
@EnableAutoConfiguration
@ComponentScan

这三个东西里面只要关心@Configuration,就能解决第一个参数是Example.class的问题。如果简单的把@Configuration看成是一个xml,那么使用Example.class作为SpringApplication.run的参数,本质上相当于为程序指定了一个xml配置。

尾声

上面好像把一个简单的例子搞得不简单了,但是如果按照结合框架原理来领会最简单的例子这种路线来学习,一旦最简单的例子领悟了,那么整个框架用起来也已经不会有什么太大的问题了,至于碰到具体的需求,直接stackoverflow.com,在绝大多数情况下都能知道应该怎么做了。

所以对于搞应用开发而不是搞底层引擎的程序员来说,花点时间找找资料理解一下自己要用的东西的架构原理,对于使用来说也是很有好处的,学习成本并不高,很值得去做的。反正我是觉得挺管用的。

本文使用我另外的文章 老程序员的一点套路之开源学习 里面介绍的方法进行学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容