springMVC原理解释

来源:互联网 发布:怎么选对戒 知乎 编辑:程序博客网 时间:2024/06/06 05:55

这是Spring团队贡献给我们的一种MVC的实现方式——前端控制器。

这里写图片描述

Front controller前端控制器 负责 分发、调度

Controller控制器 负责 业务数据抽取

View Template 负责页面呈现

首先,http请求由客户端发送给服务端的前端控制器,前端控制器知道该请求应该由谁来进行处理,将该请求分发给相应的控制器;之后,控制器知道业务逻辑的细节,调用相关的业务逻辑,生成业务数据即model,并将业务数据返回给前端控制器;此时,前端控制器再将控制器返回的业务数据发送给业务视图;然后,业务视图来呈现最后的业务页面,将该呈现页面返回给前端控制器;最后,前端控制器将呈现页面返回给浏览器端。

那为什么叫“前端控制器”(调度器)呢?打个比方,以上场景与医院前台类似,接受求医信息,分发挂号到不同的科室,不同的科室了解不同的业务细节。

这里写图片描述

MVC的核心思想是 业务数据抽取 同 业务数据呈现 分离!

MVC是一种架构模式:程序分层,分工合作;既相互独立,又协同工作。

MVC是一种思考方式:需要将什么信息展现给用户(C)?如何布局(V)?调用哪些业务逻辑(M)?

好,我们回到SpringMVC框架,这里需要提到它的几个概念。首先我们来看九大静态概念。

springMVC的九大静态概念

首先是DispatcherServlet,它正式SpringMVC对前端控制器的实现。

用户的请求正式通过springMVC的DispatcherServlet进行了分发,到达相应的Controller;Controller进而生成我们需要的业务数据model;这个model由Controller返回给DispatcherServlet进行传递,传递给相应的View,来完成最终的页面呈现。

这里写图片描述

第二个概念是Controller。

这个不多讲,它调用业务逻辑,生成相应的model

这里写图片描述

第三个概念是HandlerAdapter。首先,什么是Handler?Handler是在DispatcherServlet内部使用的一个类,它其实就是Controller的一个表现形式。在SpringMVC中并没有一个inteface叫做Controller,而是只有一个annotation(注解),@Controller,用以springMVC识别Controller。

既然没有Controller这样一个interface或者abstract class,那么springMVC的DispatcherServlet如何来知道各个Controller呢?那就是Handler。在springMVC的DispatcherServlet调用的各个控制器都是以Handler形式出现的。

那什么是HandlerAdapter呢?好吧,听名字就应该知道,这是一个适配器模式。它的作用就是将各种类型的Handler,是配成springMVC的DispatcherServlet可以使用的Handler。

这样,springMVC的DispatcherServlet就可以轻松调用控制器。
这里写图片描述

第四个概念是HandlerIntercepter。HandlerIntercepter是一个拦截器。(Intercepter是拦截器的意思)它在需要被拦截对象的两侧加入一些料。HandlerIntercepter是一个interface。

以下是HandlerIntercepter接口中的三个方法。

HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。   (1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法。该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。   (2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2 里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。   (3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。 我们的系统日志的拦截在这个方法中,可以记录日志的相关的参数,检测方法的执行。

如果我们定义了实现HandlerIntercepter接口的类,就可以在我们真正调用Controller之前,调用Controller之后,以及最终我们的Mdoel发送到了页面或者说View完成了呈现之后可以做很多事情。

第五个概念是HandlerMapping。Hanldler是DispatcherServlet调用Controller的一个中间过渡对象。mapping则是前端控制器DispatcherServlet与各个控制器之间的映射。所以,HandlerMapping的第一个作用就是,当一个请求到达前端控制器DispatcherServlet时,告诉前端控制器DispatcherServlet这个请求应该由哪个控制器来响应。

这里写图片描述

HandlerMapping的第二个作用是,用HandlerIntercepter来包裹Controller。

在HandlerMapping执行完之后,它会给DispatcherServlet一个HandlerAdapter。这个HandlerAdapter里面就包含了(1)某个具体的Controller的实例以及(2)这个Controller需要被包裹的HandlerIntercepter。它们会构成一个执行的链条往下走。

这里写图片描述

第六个概念是HandlerExecutionChain。前面我们说了,HandlerMapping执行完之后返回的HandlerAdapter中包含了Controller和HandlerIntercepter,它们之间构成了一个执行链条。首选,要执行的是所有HandlerIntercepter里面的preHandle,然后再调用Controller里面的某个业务方法,之后执行HandlerIntercepter里面的postHandle,最后是afterCompletion。
这里写图片描述

这里,我插一句。这个看似复杂的机制在springMVC中实现时其实就是利用反射进行实现的。

第七个概念是 ModelAndView。它是springMVC中对Model的一种表现形式。当然,springMVC中还有Model类,另外也可以用Java中的Map类来实现Model的功能。如果你在Controller中见过有人用Map、Model这样的类,springMVC都会讲它们统统转换为ModelAndView。因此,这里我们把ModelAndView认为是一个Model的具体表现。

第八个概念是ViewResolver(视图解析器)。它负责告诉DispatcherServlet需要用哪个视图来进行视图的呈现。因此ViewResolver的作用就是根据我们的配置找出那一个视图对象。比如JSTL、JSP等等。

第九个概念是View。负责呈现页面

好吧,我们把这些概念串联一起,梳理一下springMVC的基本概念的原理过程:

DispatcherServlet处于核心的地位,它是整个springMVC的MVC实现的桥梁。Controller是springMVC的C;View是用户想看到的东西,即V。访问的过程如下:

Request从浏览器端过来,首选到达DispatcherServlet。因为它是一个servlet,所有Request都可以拦截得到。DispatcherServlet拦截到一个Request之后,它回去找相应的Controller,怎么找呢?通过HandlerMapping。因此,DispatcherServlet就把这个功能代理给了HandlerMapping。HandlerMapping根据自己的配置,这可以用注解来做。通过注解的方式告诉HandlerMapping,那一个Controller是我们要的。因此HandlerMapping可以很容易地找到相应的Controller,对了,还能找到HandlerInterceptor。

HandlerMapping找到了我们的Controller和HandlerInterceptor,把它们形成了我们的HandlerExecutionChain——一个执行链条。就这样,一个Handler或者说HandlerAdapter(一个适配器)返回给我们的DispatcherServlet。接下来,DispatcherServlet将会调用这个返回的一般化的处理器Handler或者HandlerAdapter。

写Controller的目的是什么?当然是生成我们的模型——ModelAndView。ModelAndView为我们的页面呈现提供一些显示的“料”。模型ModelAndView生成之后,被返回给DispatcherServlet。接着需要显示,但DispatcherServlet可不回去自己管显示的事情。这个时候,视图解析器出现了,视图解析器ViewResolver告诉我们哪个视图是用来解析当前这种场景的。因此,DispatcherServlet通过调用ViewResolver的方法返回我们的View对象。 然后,ModelAndView我们模型数据被传递给我们的View,完成了我们的呈现。DispatcherServlet返回给用户,这样用户就可以在浏览器端看到用户界面了。

这里写图片描述

好吧,也许你还是觉得过程好复杂。但是,SpringMVC已经为我们做了许多。DispatcherServlet好重要啊!但是SpringMVC框架已经为我们实现了,我们要做的仅仅是配置一下就可以了。HandlerMapping复杂的映射过程也不需要我们知道,我们只要用注解配置就可以了。Controller,这个还是自己得写点东西吧,springMVC才不知道你的业务逻辑是卖皮鞋,还是卖保险呢。HandlerInterceptor是一个接口,需要就实现相应的接口方法,不需要就不写了,毕竟不是所有的应用场景都需要在Controller的前后做点什么。Handler/HandlerAdapter如此紧密的联系需要你过问吗,springMVC自己搞定。ModelAndView仅仅是个类,用来存存数据,甚至可以用Map相关的类对象来存储,你别说你不会,一个key一个数可以了,springMVC或者说DispatcherServlet会自己把这个Map转换成ModelAndView。最后,视图解析器都是现成的,跟HandlerMapping差不多,你只需要知道是哪一种类型就可以了。

所以总结下来,我们所需要写的仅仅是Controller;HandlerInterceptor根据应用场景可以写也可以不写;ModelAndView不是必需的,可以给也可以不给;View等、HandlerMapping等配置的问题而已。Handler/HandlerAdapter不需要管。所以,我们只须要shixianController,其他配置一下就OK了。

下面这个图是从另外一个角度对上述概念进行了模块划分。我们只需要 注意的是,DispatcherServlet处于核心位置,相当于一个懂得放权的好老板,它只需要调度就可以了。

这里写图片描述

老板DispatcherServlet对员工HandlerMapping说:“你告诉我须要调哪个Controller啊”

老板DispatcherServlet对员工Handler说:“你让Controller工作吧”

老板DispatcherServlet对员工ViewResolver说:“你告诉我谁是我需要的View啊”

老板DispatcherServlet对员工View说:“你去把数据呈现以下,把页面做出来吧”

。。。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 密封胶皮圈松了怎么办 汽筒里胶皮垫密封不严怎么办 磁耦气缸脱磁了怎么办 无杆气缸行程大怎么办 c4d中模型变成线怎么办 内径槽异性需要车一刀怎么办 轴承太紧影响转速怎么办 电动车前轮蝶刹抱死怎么办 摩托三轮车油刹抱死怎么办 手动档汽车离合抱死怎么办 别克gl8后轮吃胎怎么办 扭力梁后轮吃胎怎么办 非独立悬挂吃胎怎么办 货车半轴法兰盘裂纹怎么办 小天才平板裂屏了怎么办 新车撞了个坑怎么办 新车碰了个坑怎么办 汽车顶被砸了个坑怎么办 途观l前减震异响怎么办 锦明8代声音太大怎么办 手机网页无法加载插件怎么办 微信公众号被投诉怎么办 住了酒店的尾房怎么办 喜欢前任的闺蜜怎么办 闺蜜给介绍对象怎么办 喜欢对象的发小怎么办 山东省直医保卡丢失怎么办 高铁票如果错过了怎么办 动车错过了时间怎么办 长途动车错过了怎么办 动车如果错过了怎么办 没有取票错过了怎么办 动车出站没检票怎么办 火车晚点耽误了下班车怎么办 动车票中途丢了怎么办 购买二手房异地铁路公积金怎么办 沈阳公积金卡丢了怎么办 住宅专项维修资金用完了怎么办 广州出租车丢了东西怎么办 广州的士丢了东西怎么办 网上找兼职被骗了怎么办