Spring MVC设计模式

时间:2024-09-02 10:04:20
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器 

使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。

MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:
Model(模型)
  表示应用程序核心(比如数据库记录列表)。
  是应用程序中用于处理应用程序数据逻辑的部分。
  通常模型对象负责在数据库中存取数据。
View(视图)
  显示数据(数据库记录)。
  是应用程序中处理数据显示的部分。
  通常视图是依据模型数据创建的。
Controller(控制器)
  处理输入(写入数据库记录)。
  是应用程序中处理用户交互的部分。
  通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据
  MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
  MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
  MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。

视图

视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Adobe Flash和像XHTML,XML/XSL,WML等一些标识语言和Web services.
MVC好处是它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。

模型

模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用像EJBs和ColdFusion Components这样的构件对象来处理数据库,被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。

控制器

控制器接受用户的输入并调用模型和视图去完成用户的需求,所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

MVC 从逻辑上把应用分为模型组件视图组件控制器组件。其中控制器组件又可以细分为:前端控制器组件和后端控制器组件

MVC 的基本工作流程:  

    首先是客户端(通常是浏览器)发出一个请求。第一个接受这个请求的组件一般是一个前端控制器。它将不同的请求交给不同的后端控制器来处理,而在后端控制器里面又可以调用相应的模型对象来处理具体的业务逻辑,最后再返回一个特定的视图响应给客户端。

  第一个接受这个请求的前端控制器叫 DispatcherServlet

  后端控制器叫 Controller

  负责处理请求 URL 和后端控制器映射的叫 HandMapping(它有多种类型,比较灵活,也是在一个 xml 文件上进行配置)

  负责业务逻辑处理的模型对象一般也是我们平常写的 DAO/DTO 组件(只是它最后的返回更灵活, Controller 返回一个 ModelAndView 对象给 DispatcherServlet , ModelAndView 可以携带一个视图对象,也可以携带一个视图对象的逻辑名。如果携带的是一个视图对象的逻辑名,那 DispatcherServlet 需要一个 ViewResolver 来查找用于渲染回应的视图对象。最后, DispatcherServlet 将请求分派给 ModelAndView 对象指定的视图对象。视图对象负责渲染返回给客户的回应。)

跑一个最简单的例子,让大家对构建 SpringMVC 的基本步骤有个直观的认识

(1) 建立动态 web 工程,导入 spring 的 jar 包。 
(2) 配置 DispatcherServlet

  DispatcherServlet 是 SpringMVC 的核心,将下面 Servlet 的注册信息登记在 web.xml 中

<servlet>
  <servlet-name> test </servlet-name>
  <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
  <load-on-startup> 1 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name> test </servlet-name>
  <url-pattern> *.do </url-pattern>
</servlet-mapping>

(3) 编写 Controller ,做核心配置文件,并配置 url 和 Controller 的映射

package com.wepull.test; 

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller{ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { request.setAttribute( "hello" , "welcome to spring!" ); return new ModelAndView( " welcome " ); } }

在 WEB-INF 下新建一 XML 文件 : test -servlet.xml. 注意,这里的 test 取决于 servlet 的名字 . 当 DispatcherServlet 载入后,它将试图从这个文件中载入应用上下文。

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 缺省映射处理器,不需要明确声明,但声明后就非常清楚使用的是哪个映射处理器 -->
  <bean id = "beanNameUrlMapping" class = "org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
  </bean>
  <!-- 这里的 name 属性有两个职责,既定义 Bean 的名字,也定义需要这个控制器处理的 URL 样式 -->
  <bean name = "/hello.do" class = "com.wepull.test.HelloController">
  </bean>
</beans>

上面可能有人奇怪,为什么不用 id 属性,而设置 name 属性。这里是因为 URL 中含有 XML id 属性非法字符——特别是斜杠( / ) ;

(4) 配置一个视图解析器将控制器与 JSP 结合起来。

  将解析器的配置片段加到上面的 test-servlet.xml 中

<bean id = "viewResolver"  class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
< property name = "prefix" value = "/WEB-INF/jsp/" />
< property name = "suffix" value = ".jsp" />
</bean>

  InternalResourceViewResolver 在 ModelAndView 返回的视图名前加上 prefix 属性配置的前缀 , 再在最后加上 suffix 属性配置的后缀。如 HelloController 返回的 ModelAndView 中视图名为 welcome, 所以 InternalResourceViewResolver 将在 /WEB-INF/jsp/welcome.jsp 处查找视图

(5) 编写呈现给用户的 jsp 文件。

 /WEB-INF/jsp/welcome.jsp

<%@ page contentType = "text/html; charset=UTF-8" %> 

<%@ page isELIgnored = "false" %> 

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %> 

<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > 

< html xmlns = "http://www.w3.org/1999/xhtml" > 

  < head > 

  < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" /> 

  < title > Hello World! </ title > 

  </ head > 

  < body > 

  < h2 > 

   ${hello} 

  </ h2 > 

  </ body > 

</ html > 

完成后启动服务器,在浏览器地址栏上输入 http://locahost:8080/projectName/hello.do       就可以访问了。

mvc中的映射关系HandlerMapping

  springMVC 里有个映射处理器 (HandlerMapping) 的概念。它实际上是一个处理器映射 Bean, 用来将一个控制器指定到一个 URL 上。 Spring 提供了三种有用的 HandlerMapping 的实现:

BeanNameUrlHandlerMapping 

       根据控制器的名字将控制器映射到 URL 

SimpleUrlHandlerMapping 

       用上下文配置文件中定义的属性集合将控制器映射到 URL 

CommonsPathMapHandlerMapping 

       使用控制器代码中的元数据将控制器映射到 URL  

mvc中的试图解析器ViewResolver

  springMVC 里还有个视图解析器 (ViewResolver) 的概念。它决定了 ModelAndView 对象的逻辑视图名如何解析成一个用于将结果渲染给用户的视图 Bean..Spring 有四种 ViewResolver 实现:

 InternalResourceViewResolver 

       将逻辑视图名解析成一个用模板文件 ( 如 JSP 和 Velocity 模板 ) 渲染的视图对象 

 BeanNameViewResolver 

       将逻辑视图名解析成一个 DispatcherServlet 应用上下文中的视图 Bean 

 ResourceBundleViewResolver 

       将逻辑视图名解析成一个 ResourceBundler 中的视图对象 

 XmlViewResolver 

       从一个 XML 文件中解析视图 Bean, 这个文件是从 DispatcherServlet 应用上下文中分离出来的。