springMVC(javaweb 开发框架)
1、MVC三层架构:模型(service、dao)、视图(JSP等)、控制器(Controller)
什么是mvc?
* MVC 是模型、视图、控制器的简写,是一种软件设计规范
* 是将业务逻辑、数据、显示分离的方法来组织代码
* MVC主要的作用就是降低了控制器(Controller)和视图 (View) 之间的双向耦合度
* MVC不是一种设计模式、MVC是一种架构模式。当然不同的MVC存在着差异
Model(数据模型):提供要展示的数据。因此包含数据和行为、可以认为是领域模型或者JavaBean组件,不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(Service)。也就是模型提供了模型数据查询和模型数据的状态更新等,包括业务数据和义务。
**View(视图):**负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
**Controller(控制器):**接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作
最典型的MVC 就是: JSP + Servlet + JavaBean
任何项目里面的架构是演变过来的。不是直接搭建好的!!!
1.2、Model1时代
- 在web早期的开发中,通常采用的都是Model1。
- Model1中,主要分为两层,视图层和模型层。
Model1优点:架构简单,比较适合小型项目开发;
Model1缺点:JSP职责不单一,职责过重,不便于维护;
1.3、Model2时代
Model2把一个项目分成三部分,包括视图、控制、模型。
- 用户发请求
- Servlet接收请求数据,并调用对应的业务逻辑方法
- 业务处理完毕,返回更新后的数据给servlet
- servlet转向到JSP,由JSP来渲染页面
- 响应给前端更新后的页面
职责分析:
Controller:控制器
- 取得表单数据
- 调用业务逻辑
- 转向指定的页面
Model:模型
- 业务逻辑
- 保存数据的状态
View:视图
- 显示页面
Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。
传统的javaweb开发:
一个请求资源路径(url) 对应一个控制器(Controller) ,每次请求之后都会自动根据所请求的资源找到对应的Servlet类,执行相应的业务。
SpringMVC 开发(DispatcherServlet):
和传统的开发模式不同,SpringMVC 底层有一个核心对象:DispatcherServlet 前端控制器(分发器),使用了SpringMVC 框架之后,所有的请求都会执行 DispatcherServlet 这个对象,不再去直接执行对应的Controller,而是先通过 DispatcherServlet 前端控制器找到该请求路径(URL) 对应的控制器,前端控制器再去调用该控制器执行具体业务。
官网SpringMVC的原理如下图所示:
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
SpringMVC执行流程深入理解:
实线表示为框架帮我们实现, 虚线表示需要我们自己来实现!!!!!!!
springmvc 中的 DispatcherServlet 请求路径一般设置为 “/” 项目的根路劲,只要在项目中发送请求就 会调用 该DispatcherServlet
Springmvc 在执行的过程中,在调用指定的组件的时候。会先进入指定的拦截器 !!!
1、用户在前端浏览器上发送请求到前端控制器DispatcherServlet,如果是第一次请求的会先创建该前端控制器对象(并且只会加载一次,servlet是伪单例的(构造器没有私有化))再去执行 init()方法,从spring容器中按照类型注入的方式来对 前端控制器中的组件来完成依赖注入,组件依赖注入完毕之后再去执行 doService()方法。如果不是第一次请求的话,则直接执行doService()方法将用户具体请求的url资源名,传给处理器映射器
2、处理器映射器 根据用户请求的url地址去springmvc 自己的容器中去映射对应的控制器,将映射结果封装成 目标方法 返回给前端控制器(DispatcherServlet),前端控制器将目标方法 传给 处理器适配器 再去容器中适配对应的控制器(在调用对应的控制器之前会进行一次拦截)
3、控制器根据用户的具体请求,去spring的容器中获取对应的业务逻辑层对象查询数据。
4、业务层对象将查询出的模型数据返回给控制器
5、控制器再将模型数据 返回给 处理器适配器
6、处理器适配器接收到模型数据之后,先判断响应结果是 异步请求还是同步请求,(有没有@ResponseBody注解)如果是异步请求,直接将JSON数据写回给浏览器,如果是转发的话 就将 模型数据到 模型视图对象(ModelAndView)中去,模型视图对象主要的就是封装渲染数据和展示页面的,将封装好的模型视图对象(ModelAndView)传给前端控制器(DispatcherServlet)(在传给前端控制器之前在进行一次拦截)
7、前端控制器(DispatcherServlet)再将模型视图对象传给视图层进行解析
8、视图层解析模型视图对象,拼接字符串获取的需要渲染的视图,并将数据渲染到该视图上去、再返回给前端控制器
9、前端控制器将视图解析器返回的页面视图响应给浏览器端呈现给用户
10、在springmvc整个的执行过程中只要发生了异常,就会进入自定义的全局异常处理类(ControllerAdvice ExceptionHandler)
在前端浏览器上第一次请求我们的 DispatchServlet 前端控制器(核心组件),会创建该DispatchServlet对象的实例,再执行 DispatchServlet 中的 init ()方法 , 从 spring 容器中 按照 类型注入 来获取 DispatchServlet 中的属性对应的组件 来进行 依赖注入 !!!
如果不是 第一次请求的话,各大 组件依赖 注入完毕,直接执行 doService()方法 来完成后续操作!!!
SpringMvc 底层也有自己的一个容器:WebXmlApplicationContext ,和 spring的 ApplicationContext 容器是父子关系,
SpringMVC 的容器 是继承了 Spring容器的,spring容器是父容器,springmvc容器是子容器!!!
springmvc 在需要使用到某个功能组件的时候,先去自己的WebXmlApplicationContext容器中去找,如果没有则去spring容器中去找
springmvc可以获取 spring容器中的bean,而spring则无法获取 springmvc容器中的bean !!!!
一般的话像 Controller 层对象 一般都是存放在 springmvc 的容器中 来共 springmvc 中的 处理器适配去 去调用!!!
Service 层 和 Dao 层对象,一般则是放在 spring容器中,因为 像一些事务的处理呀和 mybatis 核心对象的生成 不是加上注解之后就
会立即生效,而是先生成代理对象,一般这些代理对象一般都在 spring 容器中注册!!!