目录
MVC三大组件
- Mode-View-Controller,把一个包含UI的应用分成了3层,每层负责各自的逻辑。
- Model(模型层):用于提供数据读写操作的业务逻辑,同时还包含数据的逻辑操作。
- View(视图层):面向用户的View视图层,用于根据数据数目为用户渲染可视化页面,渲染时数据一般来自Model层,用户操作后可以把数据提交给Controller层。
- Controller(控制层):用于接收用户的操作与数据,根据用户的操作调用不同的Model处理数据,同时控制展示给用户的View层。Controller层是View层和Model层的纽带。
以web项目为例,看一下整个MVC模型操作的执行周期
- 用户使用浏览器通过URL访问页面
- Controller层获取URL上的相关信息,决定使用哪个Model层组件处理数据以及逻辑,并把URL中相关参数提交给Model层
- Model层组件的处理逻辑处理用户相关的参数,可能还会从其他数据源获取相关数据,把处理之后的数据添加到自己的属性中
- 处理完成返回Controll层,Controller层根据相关参数选择返回的View层
- View层根据Model层中属性渲染页面,返回HTML给浏览器,浏览器渲染HTML后展示给用户。
整个操作的过程中流向是固定的环状,这也是MVC的一个优点,简化流程。
MVC设计的优点
- 低耦合:通过Controller层解耦Model层和View层,可另Model层和View层两部分单独做修改而不会影响另一部分。例如可以任意改动View以展示不同的页面,同时Model和Controller层无须做任何改动,反之亦然。
- 高复用:基于View层的改动不影响Model层,可以为Web应用添加不同的View,如移动端页面和桌面端页面不同,可以复用统一到Model层
- 高维护:拆分View层和Model层,使得每层之间数据流向单一,没有图状数据流向,更易于开发与维护。不同层可以交由不同的开发人员负责,功能越单一,实现的效率越高。
体现MVC思想的场景
计算机硬件体系拆分为CPU、显卡和内存、CPU是处理器逻辑,使用内存存取数据,显卡负责控制显示,显示数据来源也是通过内存获取的。
Spring MVC对MVC的支持
1. Spring MVC对控制器的支持
a. 控制器核心
DispatcherServlet是Spring MVC的核心,包含Model处理逻辑的查找、Model处理逻辑的执行、View的查找以及View的渲染等控制器核心逻辑。Model处理逻辑的查找和Model处理逻辑的执行二者相互独立,查找通过Mapping映射器完成(控制器负责通过HandlerMapping查找Handler),查找返回的结果是Model的执行逻辑的封装-Handler(处理器), 查找到Handler之后再交由HandlerAdapter处理。在处理器执行的前后,还可以插入拦截器组件,通过拦截器实现类似于面向切面的功能,拦截器可以在处理器的执行前、执行后、完成时分别执行一段逻辑,用来为所有处理器添加相同的逻辑。
b. 处理器查找
(1)直接URl映射
(2) BeanName与URL映射
(3) @RequestMapping映射(最常用的一种方式)
c. 处理器执行
(1) HttpRequestHandler
(2) Controller接口Handler
(3) @RequestMapping定义的HandlerMethod
@Controller
public class MyRequestMapping{
@RequestMapping(path="/myRequestMapping", method=RequestMethod.GET)
public String requestMappingGet(String name, Map<String, Object> model){
model.put("name", name);
return "defaultView"
}
}
- 请求参数的自动绑定,在@RequestMapping中,请求参数可以自动绑定到处理方法的参数中。
- Model模型的自动绑定。参数中声明了Map类型的model,此时RequestMappingHandlerAdapter会自动会其生成Model模型并绑定到方法参数中,供处理器逻辑对其数据进行存取。
- 视图的自动查找。通过返回String类型的试图名,一般是视图文件名,RequestMappingHandlerAdapter可以自动查找相应名称的视图,并与参数中的Model模型数据自动绑定。
- 添加了参数绑定、返回值处理等功能,不需要再暴露原始的请求和响应,即可完成请求与响应的处理,使得开发者只需要关注自己需要的请求参数和要返回的结果,而无须对原始请求和响应做加工。
d. 拦截器
在查找处理器时,HandlerMapping并不直返回Handler,而是返回Handler的执行链HandlerExecutionChain.该执行链中封装的有需要应用到该Handler上的所有拦截器,拦截器的类型通过HandlerInterceptor接口的实现。在执行处理器前,会先执行HandlerInterceptor的preHandle前置处理方法,如果该方法返回false, 则中断处理流程;如果返回true,则继续后续的拦截器处理,直到所有拦截器都返回true,才会开始执行handler。在执行处理器后,会有两种结果
- 正常执行完成,此时拦截器会先执行拦截器里的postHandle方法,触发处理器执行后的操作,之后还会执行拦截器里的afterCompletion,代表整个处理动作完成。
- 在执行时发生了错误,此时不执行postHandle方法,而是直接执行afterCompletion方法,并把发生的错误作为参数传递给该方法。
e. 视图查找与模型绑定
控制器(DispatcherServlet拿到处理器执行的结果。处理器的执行是通过HandlerAdapter的handle方法执行的,而其返回结果就是ModelAndView类型(这个类型就是视图与模型的绑定关系).
渲染时,首先根据ModelAndView视图或者拿到视图名查找视图,之后再从ModelAndView中获取Model模型数据,通过调用视图的渲染方法传入模型数据执行视图的渲染操作,渲染后把渲染的结果通过HTTP的Response返回给用户。
2. Spring MVC对模型的支持
由于视图的渲染时,需要对模型数据进行读取,而渲染方法传入的模型数据是Map类型,所以Spring MVC模型相关的类型就是围绕着Map而产生的。
模型的相关类型以及使用方式
(1) Map接口
@RequestMapping(path="/mapModel")
public String mapModelBinding(Map<String, Object> map){
model.put("name", "Map类型的Model");
return "defaultView"
}
(2) Model接口
@RequestMapping(path="/modelModel")
public String mapModelBinding(Model model){
model.put("name", "Model类型的Model");
return "defaultView"
}
(3) ModelMap 类
@RequestMapping(path="/modelModel")
public String modelMapModelBinding(ModelMap modelMap){
modelMap.put("name", "ModelMap类型的Model");
modelMap.put("date", new Date());
return "defaultView"
}
(4) 直接创建Model并作为返回值返回
Spring MVC会对处理器方法中的返回值自动处理,如果返回值类型是Model接口类型或者Map接口类型,Spring MVC会自动把返回值的所有属性添加到请求周期中产生的Model模型中,此时的Model模型是我们自己创建的。
@RequestMapping(path="/defaultView")
public Map createModel(){
Map<String, Object> model = new HashMap<>();
//也可以是
ModelMap model = new ModelMap();
model.put("name", "自行创建Model");
return model;
}
此时的视图名并没有返回,视图名来源于请求路径,这里的请求路径是defaultView,所以视图名也是defaultView.
(5) 处理方法标记@ModelAttribute注解
(6) 直接返回ModelAndView
这种方式更加直接,直接返回包括视图和模型的类型,模型是任意的Map类型,视图支持String类型的视图名和View类型。这种类型和Controller接口中处理方法的返回值是相同的,也是Spring MVC的HandlerAdapter的处理结果,所以这种类型是比较底层的类型,示例代码如下:
@RequestMapping(path="/defaultView")
public ModelAndView modelAndViewModelBinding(){
Map<String, Object> model = new HashMap<>(2);
model.put("name", "ModelAndView类型");
return new ModelAndView("defaultView", model);
}
第一个参数是视图名,第二个参数是模型
3. Spring MVC对视图的支持
根据视图名通过视图解析器解析出对应的视图。
视图类型
1) 内部资源视图InternelResourceView
(2) 重定向视图RedirectView
(3) 模板引擎视图
视图查找解析
Spring MVC提供了ViewResolver接口用以通过视图名查找并解析视图。该接口有resolveViewName方法,返回View视图。接受String类型的视图名,以该视图名进行查找。还有Locale类型的地区参数,用于进行国际化。Spring MVC的控制器支持多个ViewResolver,查找视图时进行遍历查找,直到找到相应的视图,如果没有找到则报错提示没有查找到相应的视图。Spring MVC支持几下几种查找与解析策略。
(1) BeanName视图解析
(2) 模板引擎视图解析
(3) 内部资源视图解析
(4) 直接指定视图