Spring Web MVC 框架介绍
Spring Web MVC框架是围绕着DispatchServlet设计的,DispatchServlet负责将web请求分发到handlers,在这个分发过程中包括可配置的handler映射,视图处理,本地化,时区及主题和文件上传。默认情况的handler是基于@Controller和@RequestMapping两种注释,提供了灵活的处理方法。在Spring3.0之后,@Controller机制同样允许创建Restful的网络站点和应用,通过@PathVariable注释以及其它的特性。
面向拓展是Spring Web MVC的核心原则,Spring的原则是”Open for extension,closed for modification“。
在Spring Web MVC中一些核心类被标记为”final“。由于开发者无法对这些方法进行重写。
针对这个原则的解释在Expert Spring Web MVC中有比较详细的解释。另外在Bob Martin的文章”The Open-Closed Principle(PDF)“中也有解释。
在使用Spring MVC时不能针对final方法添加切面。比如,不能够对AbstractController.setSynchronizedOnSession()添加切面。在”Understandding AOP proxies“有针对AOP代理以及为何不能添加切面的原因。
在Spring Web MVC中,你可以使用任何对象作为命令或表单后台对象,你不需要去实现框架特定的接口或者基类。Spring的数据绑定非常灵活。例如Spring中将类型不匹配视为验证失败而不是系统错误。因此不需要将业务对象复制为表对象中无类型的字符串来处理无效的提交,或者将字符串转化为业务对象。因此将业务对象直接和表对象绑定更加方便。
Spring的视图处理也非常灵活。Controller一般用来映射处理数据和视图,当然它可以直接用来应答流并完成请求。视图名称处理可以通过文件拓展或者通过bean名称甚至自定义的ViewResolverl实现的接受头文件类型协议来完成。MVC中的M指的是映射接口,此接口代表了视图技术的完整抽象。可以和常见视图模板茹JSP、Velocity和FreeMarker记性集成,甚至直接生成XML、JSON、Atom以及气态的多种内容类型。Map可以简单的转化成正确的类型,例如JSP的请求类型,Velocity的模板等。
Spring Web MVC的特点
Spring的网络模块包括许多独特的网络支持特性:
1)清晰的角色分层。控制器、验证器、命令对象、表单对象、模型对象、DispatchServlet、处理映射,视图方案。
2)强大直观的框架和应用类JavaBean的配置,配置包括能够简单的在上下文中引用,例如表单网络控制器到业务对象和验证器。
3)适配性、非入侵性、灵活性。可以定义任意的Controller方法,并通过参数注解(如@RequestParam、@RequestHeader、@PathVariable)
4)可复用的业务代码,不需要冗余业务代码。使用业务对象作为命令或者表单对象而不需要通过扩展框架基类实现。
5)可定制的绑定和验证。类型不一致被作为应用层的验证错误,从而不需要人工进行类型解析和转换来判断数据错误。
6)自定义的handler映射和视图处理。handler映射和视图处理策略包括简单的URL配置到复杂的特定目的地策略。Spring相比web MVC在集成技术上更加灵活。
7)简单强大的JSP标签库,可以方便的进行数据绑定和主题设置。自定义的标签可以灵活的使用标签代码。
8)Bean的整个生命周期包含当前的HTTP请求或者HTTP会话中。这并非是Spring MVC本身的特性,而是Spring实用的WebApplicationContext容器的特新。
其他MVC实现的即插即用
在一些工程中,非Spring的MVC实现可能更加合适。许多团队需要来综合评估他们当前的技术和工具积累,例如JSF。
如果不想使用Spring WebMVC,而是希望能够使用Spring其它的功能,你可以将Spring集成到先用的web MVC中。通过使用ContextLoaderListener来开启Spring的根应用,并通过ServletContext属性来访问一些特性。此时,从web层面上看,仅仅是将Spring作为类库,将Spring的根应用上下文作为入口。
DispatcherServlet
Spring的web MVC框架和其它的需要MVC框架一样,都是基于请求驱动,并围绕着核心的分发到控制器和其它功能Servlet设计的。Spring的DispatcherServlet可以做的比这跟多。它能够完全的集成Spring的控制反转从而允许使用Spring的所有特性。
Spring Web MVC的DispatcherServlet的处理步骤在下图中展示。模式识别会将DispatcherServlet理解为前端控制器的表达式(这是Spring Web MVC和其它大多数热门网络框架共同具有的模式)。
DispatcherServlet是继承自HttpServlet的。为了使用DispatcherServlet需要将请求映射到的对应的handler上。下面是标准的JAVA EE Servlet的标准配置。
```
public class MyWebApplicationInitializer implements WebApplicationInitializer{
@override
public void onStartup(ServletContext container){
ServeletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/example/");
}
}
```
在前面的例子中,所有的请求都是以/example开始的,对应的请求都会被DispatcherServlet处理。WebApplicationInitializer是Spring MVC提供的接口,它可以保证基于代码的配置能够被识别并且能够自动的被Servlet容器初始化。有一个这种接口的抽象基类实现叫做AbstractAnnotationConfigDispatcherServletInitializer,它能够让注册DispatcherServ更加容易,比如见到你的通过制定Servlet映射和列出配置类。这其实是Spring MVC 应用的推荐模式。(还有一种叫做基于代码的Servlet容器初始化)
DispatcherServlet是继承与HttpServlet的Servlet,因此它会在web.xml中被声明。为了让dispatcherServlet工作,需要在web.xml中使用URL映射。下面是典型的JAVA EE的Servlet的配置,下面的例子展示了DispatchServlet的声明和映射。
下面的web.xml展示了上面的例子。
```
<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping>
</web-app>
ApplicationContext的功能中,ApplicationContext实例。在Web MVC框架中,每个DispatcherServlet拥有自己的WebApplicationContext,它继承与所有的在根WebApplicationContext中定义的bean。根WebApplicationContext应该包含所有的组件bean,这些bean需要在当前的DispatcherServlet上下文和其他的上下文中共享。这些集成的bean可以在特定的Servlet范围中被重写,并且可以根据指定的Servlet实例重新定义bean。
基于DispatcherServlet的初始化。Spring MVC会寻找名称为[servlet-name]-servlet.xml的配置文件,并且基于此来创建定义的bean,并且重写所有在全局作用域的具有相同名字的bean。
下面的文件为DispatcherServlet的一种配置。
<web-app>
<servlet>
<servlet-name>golfing</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>golfing</servlet-name>
<url-patter>/golfing/*</url-pattern>
</servlet-mapping>
</web-app>
基于上面的配置,需要定义对应的bean配置文件,该文件的名称应当为/WEB-INF/golfing-servlet.xml,该文件会包含所有的Spring Web MVC的组件。当然可以通过修改Servlet的初始化参数来改变配置文件的位置。
当前对于单个的DispatcherServlet也可以仅仅只有一个根上下文。
可以通过设定contextConfigLocation初始化参数来改变配置文件位置。
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listern-class>
</listener>
</web-app>
WebApplicationContext是ApplicationContext的扩展。它提供了处理主题的功能,并且它可以获取相关的Servlet引用。WebApplicationContext限制在ServletContext之中,并且通过在RequestContextUtils中使用静态方法可以方便的获取到WebApplicationContext。
同样我们可以通过基于java代码的配置实现。
public class GolfingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
@override
protected class<?>[] getRootConfigClasses(){
return new Class[]{GolfingAppConfig.class};
}
@Override
protected Class<?>[] geteServletConfigClasses(){
return new Class[]{GolfingWebConfig.class};
}
@Override
protected String[] getServletMappings(){
return new String[]{”/golfing/*“};
}