一、传统Model和MVC设计思想对比
Model1开发模式:整个Web应用几乎全部由jsp页面组成,jsp页面接受处理客户端请求,对请求处理后直接做出响应。用少量的JavaBean来处理数据库连接、数据库访问等操作。
Model2是基于MVC架构的设计模式,Servlet作为前端控制器,负责接收客户端发送的请求。在Servlet中只包含控制逻辑和简单的前端处理;然后调用JavaBean来完成实际的逻辑处理;最后,将其转发到相应的JSP页面来处理显示逻辑。
MVC思想将一个应用分成三个基本部分:Model(模型)、View(视图)和Controller(控制器),这三个部分以最少的耦合协同工作,从而提高应用的可扩展性及可维护性。
MVC的特点:
·多个视图可以对应一个模型。按MVC设计模式,一个模型对应多个视图,可以减少代码的复制及代码的维护量,这样,一旦模型发生改变,也易于维护。
·模型返回的数据与显示逻辑分离。模型数据可以应用任何的显示技术,例如,使用jsp页面、Velocity模版等。
·应用被分隔为三层,这降低了各层之间的耦合,提供了应用的可扩展性。
·控制层的概念,它把不同的模型和不同的视图结合在一起,完成不同的请求。
·不同的层各司其职,每一层的组件具有相同的特征,这有利于通过工程化和工具化的方法产生产生管理程序代码。
二、SpringMVC的优势
SpringMVC特点:
·SpringMVC拥有强大的灵活性、非侵入性和可配执性。
·SpringMVC提供了一个前端控制器DispatcherServlet,开发者无须额外开发控制器对象
·SpringMVC分工明确,包括控制器、验证器、命令对象、模型对象、处理程序映射视图解析器,等等,每一个功能实现由一个专门的对象负责完成
·SpringMVC可以自动绑定用户输入,并正确地转换数据类型
·SpringMVC使用一个名称/值的Map对象实现更加灵活的模型数据传输
·SpringMVC内置了常见的校验器,可以校验用户输入,如果校验不通过,则重定向会输入表单。输入校验是可选的,并且支持编程方式及声明方式
·SpringMVC支持国际化,支持根据用户区域显示多国语言,并且国际化的配置非常简单
·SpringMVC支持多种视图技术,最常见的有jsp技术以及其他技术,包括Velocity和FreeMarker
·Spring提供了一个简单而强大的jsp标签库,支持数据绑定功能,使得编写jsp页面更加容易。
三、详解DispatcherServlet
protected void initStrategise(ApplicationContext context){
initMultipartResolver(context); //初始化上传文件解析器
initLocaleResolver(context); //初始化本地解析器
initThemeResolver(context); //初始化主题解析器
initHandlerMappings(context); //初始化处理器映射器,将请求映射到处理器
initHandlerAdapters(context); //初始化处理器适配器
initHandlerExceptionResolvers(context); //初始化处理器异常解析器,如果执行过程中遇到异常将交给HandleExceptionResolver来解析
initRequestToViewNameTranslator(context); //初始化请求到视图名称解析器
initViewResolvers(context); //初始化视图解析器,通过ViewResoler解析逻辑视图名到具体视图实现
initFlashMapManager(context); //初始化flash映射管理器
}
DispatcherServlet装配每种组件的细节:
·本地化解析器。只允许一个实例
(1)查找名为localeResolver、类型为LocaleResolver的Bean作为该类型组件。
(2)如果没有找到,则使用默认的实现类AcceptHeaderLocaleResolver作为该类型组件。
·主题解析器。只允许一个实例
(1)查找名为themeResolver、类型为ThemeResolver的Bean作为该类型组件。
(2)如果没有找到,则使用默认的实现类FixedThemeResolver作为该类型组件。
·处理器映射器。允许多个实例
(1)如果detectAllHandlerMappings的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为HandlerMapping的Bean,将它们作为该类型组件。
(2)如果detectAllHandlerMappings的属性为false,则查找名为handlerMapping、类型为HandlerMapping的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则使用BeanNameUrlHandlerMapping实现类创建该类型的组件。
·处理器适配器。允许多个实例
(1)如果detectAllHandlerAdapters的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为HandlerAdapter的Bean,将它们作为该类型组件。
(2)如果detectAllHandlerAdapters的属性为false,则查找名为handlerAdapter、类型为HandlerAdapter的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则使用DispatcherServlet.properties配置文件中指定的三个实现类分别创建一个适配器,并将其添加到适配器列表中。
·处理器异常解析器。允许多个实例
(1)如果detectAllHandlerExceptionResolvers的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为HandlerExceptionResolver的Bean,将它们作为该类型组件。
(2)如果detectAllHandlerExceptionResolvers的属性为false,则查找名为handlerException-Resolver、类型为HandlerExceptionResolver的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则查找DispatcherServlet.properties配置文件中定义的默认实现类,注意,该文件中没有对应处理器异常解析器的默认实现类,用户可以自定义处理器异常解析器的实现类,将之添加到DispatcherServlet.properties配置文件当中。
·视图名称解析器。只允许一个实例
(1)查找名为viewNameTranslator、类型为RequestToViewNameTranslator的Bean作为该类型组件。
(2)如果没有找到,则使用默认的实现类DefaultRequestToViewNameTranslator作为该类型的组件。
·视图解析器。允许多个实例
(1)如果detectAllViewResolvers的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为ViewResolver的Bean,将它们作为该类型组件。
(2)如果detectAllViewResolvers的属性为false,则查找名为viewResolvers、类型为ViewResolver的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则查找DispatcherServlet.properties配置文件中定义的默认实现类InternalResourceViewResolver作为该类型的组件。
·文件上传解析器。只允许一个实例
(1)查找名为muliipartResolver、类型为MuliipartResolver的Bean作为该类型组件。
(2)如果用户没有在上下文中显式定义MuliipartResolver类型的组件,则DispatcherServlet将不会加载该类型的组件。
·FlashMap映射管理器。
(1)查找名为FlashMapManager、类型为SessionFlashMapManager的Bean作为该类型组件,用于管理FlashMap,即数据默认存储在HttpSession中。
四、SpringMVC执行流程
1.SpringMVC应用开发步骤
(1)在web.xml文件中定义前端控制器DispatcherServlet来拦截用户请求。
(2)如果需要以POST方式提交请求,则定义包含表单数据的JSP页面。如果仅仅只是以GET方式发送请求,则无须经过这一步。
(3)定义处理用户请求的Handler类,可以实现Controller接口或使用@controller注解。
这一步是所有MVC框架中必不可少的,因为这个Dispatcherservlet就是MVC中的C,也就是前端控制器,该控制器负责接收请求,并将请求分发给对应的Handle,即实现Controller接口的java类。
Controller怎么接收到的用户请求:前端Servlet接收到用户请求后,通常会对用户请求进行简单预处理,例如解析、封装参数等,然后通过反射来创建Controller实例,并调用Controller的指定方式(实现Controller接口的是handleRequest方法,而使用基于注解的控制器可以是任意方法)来处理用户请求。
当Servlet拦截用户请求后,它如果知道创建哪个Controller接口的实例呢?
利用注解:例如使用注解@Controller描述一个类,并使用注解@RequestMapping(value="/hello")描述hello请求对应的方法。这样就可以知道让MVC框架知道创建哪个Controller接口的实例并调用哪个方法处理请求。
(4)配置Handle。两种方式一种是使用xml文件,一种是使用注解。
<!--配置Handle,映射“/hello”请求-->
<bean name="/hello" class="com.hu.controller"/>
//使用注解
@Controller
public class HelloController{
@RequestMapping(value="/hello")
public ModelAndView hello() {
}
}
2.SpringMVC执行的流程
(1)用户向服务器发送请求,请求被Spring的前端控制器DispatcherServlet截获。
(2)DispatcherServlet对请求URL(统一资源定位符)进行解析,得到URI(请求资源标识符)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象,包括Handler对象以及Handler对象对应的拦截器,这些对象会被封装到一个HandlerExecutionChain对象当中返回。
(3)DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。HandlerAdapte的设计符合面向对象中的单一职责原则,代码架构清晰,便于维护,最重要的是,代码可复用性高。HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法,例如hello方法。
(4)提取请求中的模型数据,开始执行Handler(Controller)。在填充Handler的入参过程中,根据配置,Spring将帮你做一些额外的工作。如消息转换。数据转换。数据格式化。数据验证。
(5)Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或视图名和模型。
(6)根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet
(7)ViewResolver结合Model和View来渲染视图
(8)将视图渲染结果返回给客户端