演变
JSP Model1
JSP+JavaBean
在一个项目中,如果业务流程比较简单的时候,可以把控制器的功能交给视图,项目架构中只有视图和模型,没有控制器。
Model1模式的基础是JSP,它由JSP和JavaBean组成,JSP从HTTPRequest中获取所需要的数据,并调用JavaBean进行业务逻辑的处理,然后通过HTTPResponse将结果返回给前端浏览器。可见,Model1一定程度上实现了MVC,只不过将控制层和视图层统一定位到JSP页面,JavaBean依然充当模型组件。这种模式下JSP身兼多职,既要负责视图层的数据展示,又要负责业务流程控制,结构较为混乱,也不是我们所希望的松耦合架构,所以在大型项目中或者当业务流程比较复杂的时候不建议这样做。
JSP Model2
JSP+Servlet+JavaBean
当业务流程比较复杂的时候,就需要把业务流程控制交给专门的控制器,JSP只专注于视图的渲染展现即可。这种模式就是JSP Model2,即JSP+Servlet+JavaBean,也就是典型的MVC设计模式。
相比于Model1,Model2是将控制层单独划分出来,以Servlet的形式存在于项目架构中,负责业务流程的控制,接收请求,创建所需的JavaBean组件,并将处理后的数据返回给视图(JSP/HTML)进行结果渲染展示。这样的结构比较清晰,效果明显优化很多,并且结合Spring的IoC和AOP,也是一个松耦合的架构模式。所以,除非项目特别简单,一般情况下推荐使用JSP Model2。
MVC的处理过程:
首先视图提供系统与用户交互的界面,并发送用户的输入给控制器;
控制器接收到用户的请求,根据判断,决定调用哪个模型的哪个方法进行处理;
模型被控制器调用,根据控制器的指令进行相应的业务逻辑处理,并返回处理结果(数据);
控制器根据返回的结果,调用相应的视图来渲染、格式化模型返回的数据;
视图响应给客户端浏览器。
MVC处理流程及优缺点
优点:
可以多视图共享多个模型,大大提高了代码的复用性;
MVC的三个模块相互独立,松耦合架构;
控制器提高了应用程序的灵活性和可配置性;
有利于项目的管理和维护。
缺点:
原理较复杂,实现起来固然没有JSP+JavaBean的方式来得快;
增加了系统结构和实现的复杂性;
视图对模型数据的访问效率较低。
简介
Spring Web 模型视图控制器(MVC)框架是围绕DispatcherServlet
设计的,该框架将请求分配给处理程序,并具有可配置的处理程序 Map,视图分辨器,语言环境,时区和主题分辨器,以及对文件上传的支持。默认处理程序基于@Controller
和@RequestMapping
注解,提供了多种灵活的处理方法。随着 Spring 3.0 的引入,@Controller
机制还允许您通过@PathVariable
注解和其他功能来创建 RESTful 网站和应用程序。
原则
开放扩展,封闭修改;Spring Web MVC 核心类中的某些方法标记为final
。作为开发人员,您不能覆盖这些方法来提供自己的行为。这不是随意进行的,而是要牢记这一原则。
Spring MVC运行原理
-
客户端发出HTTP请求,Web应用服务器接收此请求。如匹配DispatcherServlet的请求映射路径,则Web容器将该请求转交给DispatcherServlet处理;
-
DispatcherServlet拿到请求之后,根据请求的信息(URL、请求参数、HTTP方法等)及HandlerMapping的配置找到处理请求的处理器(Handler);
-
当DispatcherServlet找到相应的Handler之后,通过HandlerAdapter对Handler进行封装,再以统一的适配器接口调用Handler。HandlerAdapter可以理解为真正使用Handler来干活的人。
-
在请求信息真正到达调用Handler的处理方法之前的这段时间,Spring MVC还完成了很多工作,它会将请求信息以一定的方式转换并绑定到请求方法的入参,对于入参的对象会进行数据转换、数据格式化以及数据校验等。这些都做完以后,最后才真正调用Handler的处理方法进行相应的业务逻辑处理。
-
处理器完成业务处理之后,将一个ModelAndView对象返回给DispatcherServlet,其中包含了逻辑视图名和模型数据信息。
-
DispatcherServlet通过ViewResolver将逻辑视图名解析为真正的视图对象View,可以是JSP、HTML、XML、PDF、JSON等等,得到真正的视图对象之后,DispatcherServlet会根据ModelAndView对象中的模型数据对View进行视图渲染。最终客户端获得响应消息。
Spring MVC框架的特点
-
角色划分清晰。Model、View、Controller各司其职,耦合度较低。
-
灵活的配置功能。Spring的核心是IoC和AOP,统一可以实现在MVC上,把各种类当作Bean组件配置在Spring容器中。
-
提供了大量的接口和实现类,方便各种场景的开发。
-
真正做到与View层的实现无关。
-
结合Spring的依赖注入,更好地应用了面向接口编程的思想。
-
可以与Spring天衣无缝的整合
DispatcherServlet
DispatcherServlet其实就是个Servlet(它继承自HttpServlet基类),同样也需要在你web应用的web.xml配置文件下声明
DispatcherServlet
依赖的bean
bean的类型 | 作用 |
---|---|
HandlerMapping | 处理器映射。它会根据某些规则将进入容器的请求映射到具体的处理器以及一系列前处理器和后处理器(即处理器拦截器)上。具体的规则视HandlerMapping 类的实现不同而有所不同。其最常用的一个实现支持你在控制器上添加注解,配置请求路径。当然,也存在其他的实现。 |
HandlerAdapter |
处理器适配器。拿到请求所对应的处理器后,适配器将负责去调用该处理器,这使得DispatcherServlet 无需关心具体的调用细节。比方说,要调用的是一个基于注解配置的控制器,那么调用前还需要从许多注解中解析出一些相应的信息。因此,HandlerAdapter 的主要任务就是对DispatcherServlet 屏蔽这些具体的细节。 |
HandlerExceptionResolver | 处理器异常解析器。它负责将捕获的异常映射到不同的视图上去,此外还支持更复杂的异常处理代码。 |
ViewResolver | 视图解析器。它负责将一个代表逻辑视图名的字符串(String)映射到实际的视图类型View 上。通常你需要配置InternalResourceViewResolver 类提供的prefix 属性,使其指向视图文件所在的目录。 这里需要理解的一个事情是,一旦你在web应用上下文WebApplicationContext 中配置了某个特殊bean以后(比如InternalResourceViewResolver ),实际上你也覆写了该bean的默认实现。比方说,如果你配置了InternalResourceViewResolver ,那么框架就不会再使用beanViewResolver 的默认实现。 |
LocaleResolver& LocaleContextResolver | 地区解析器 和 地区上下文解析器。它们负责解析客户端所在的地区信息甚至时区信息,为国际化的视图定制提供了支持。 |
ThemeResolver | 主题解析器。它负责解析你web应用中可用的主题,比如,提供一些个性化定制的布局等。 |
MultipartResolver | 解析multi-part的传输请求,比如支持通过HTML表单进行的文件上传等。 |
FlashMapManager | FlashMap管理器。它能够存储并取回两次请求之间的FlashMap 对象。后者可用于在请求之间传递数据,通常是在请求重定向的情境下使用。 |
逻辑视图和物理视图
逻辑试图:控制器方法返回一个字符串,或者是通过 ModelAndView.setViewName(String viewName) 方法设置一个视图名,此时的视图成为逻辑视图,因为前端控制器需要通过视图解析器来解析逻辑视图名,得到一个视图对象,然后才响应给客户端。
物理视图:在控制器方法中直接通过 ModelAndView.setView(View v)方法设置视图对象,然后返回ModelAndView给前端控制器,这时的视图就是物理视图,因为它前端控制器不需要再使用视图解析器来解析它,直接将视图内容响应给客户端。
定制DispatcherServlet的配置
定制DispatcherServlet的配置,具体的做法,是在web.xml文件中,Servlet的声明元素上添加一些Servlet的初始化参数(通过init-param元素)
可选参数 | 解释 |
---|---|
contextClass | 任意实现了WebApplicationContext接口的类。这个类会初始化该servlet所需要用到的上下文对象。默认情况下,框架会使用一个XmlWebApplicationContext对象。 |
contextConfigLocation | 一个指定了上下文配置文件路径的字符串,该值会被传入给contextClass 所指定的上下文实例对象。该字符串内可以包含多个字符串,字符串之间以逗号分隔,以此支持你进行多个上下文的配置。在多个上下文中重复定义的bean,以最后加载的bean定义为准 |
namespace | WebApplicationContext的命名空间。默认是[servlet-na |