一、Spring MVC 3.0介绍
Spring MVC 是一个典型的 MVC 框架,是 Spring 内置的Web框架,可以作为应用项目的展示层,继Spring 2.0对Spring MVC进行重大升级后,Spring 2.5又为Spring MVC引入了注解驱动功能,再到3.0时代,全面支持REST 的网络服务和更容易的网络编程。这一系列的变革,无疑吸引着我们走进 Spring MVC 3.0 的世界。REST功能是Spring MVC 3.0新增的,它通过不带扩展名的URL来访问系统资源。REST是把访问的所有资源看成静态的,一个或一组,每个不同的URL地址都是一个静态资源。 那么 Spring MVC 3.0 是如何支持 REST 的呢?简单的说, 它是通过 @RequestMapping 及 @PathVariable 注解 提供的,在 @RequestMapping 中指定 value 与 method ,就可以处理对应的请求。另外 spring mvc 框架还做了很多很多工作。 二、Spring MVC流程 大象根据官方文档的介绍,以及自己的理解,画了一个 Spring MVC 的流程结构图,大家可以参考下。
![](https://i-blog.csdnimg.cn/blog_migrate/1002be989497c8b69884faf1cc6aa0e4.jpeg)
2、 DispatcherServlet会从HandlerMapping对象中查找与请求匹配的Controller,并将结果返回给DispatcherServlet。 3、 DispatcherServlet将请求转发给目标Controller,如果定义有拦截器,则会经过这些拦截器处理。 4、标Controller处理完成业务逻辑后,会返回一个结果给DispatcherServlet。
5、 DispatcherServlet 根据结果查询 ViewResolver ,找到与之对应的视图对象,同样将结果返回给 DispatcherServlet 。 6、 DispatcherServlet 根据指定的显示结果,调用模板对象渲染 view 。
7、将view返回给客户端。 根据上面的说明,可以很很明显的看出, Spring MVC 的核心是 Servlet ,并且创建的 Controller 其实也是一个 Servlet 。 三、 Spring 与 struts2 比较 另一个非常有名的 MVC 框架是 Struts2 , Spring MVC 的核心是 Servlet ,而 Struts2 的核心则是 Filter 。下表列出 Spring MVC 与 Struts2 的主要区别与比较结果。
![](https://i-blog.csdnimg.cn/blog_migrate/c69affb51043c6eb4021a7d19170c843.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/c96d4320be80add88890a42e2da2d415.jpeg)
四、线程安全 由于 Spring MVC 默认是 Singleton 的,所以会产生一个潜在的安全隐患。根本核心是 instance 变量保持状态的问题。 这个问题有两种解决办法:
a) 在控制器中不使用实例变量
b) 将控制器的作用域从单例改为原型 这两种做法有好有坏,第一种,需要开发人员拥有较高的编程水平与思想意识,在编码过程中力求避免出现这种 BUG ,而第二种则是容器自动的对每个请求产生一个实例,由 JVM 进行垃圾回收,因此做到了线程安全。使用第一种方式的好处是实例对象只有一个,所有的请求都调用该实例对象,速度和性能上要优于第二种,不好的地方,就是需要程序员自己去控制实例变量的状态保持问题。第二种由于每次请求都创建一个实例,所以会消耗较多的内存空间。 五、配置文件 Spring MVC 是 Spring 的一个组成部分,所以配置文件就会变得简单许多。以下就是本例子中最重要的几个配置文件。 1 、 pom.xml 管理项目依赖,编译,发布,插件配置等等。所有的依赖包都由配置决定,另外所需依赖包的其它依赖,无需配置, maven 会自动获取并进行管理,这无疑帮我们减少了很多工作量,再也不用为到处找 jar 包,或版本不一致而头疼了。
定义依赖版本属性
![](https://i-blog.csdnimg.cn/blog_migrate/dae54a7e9e05782a0853f44c2fc57304.jpeg)
Spring 依赖,本例是一个很基础的例子,所以有这些就够了,以后有扩展再增加。
![](https://i-blog.csdnimg.cn/blog_migrate/057d9fed5310d2bc2fd42a55ffd3e65c.jpeg)
MyBatis 依赖, iBatis 从 3.0 版之后就改名为 MyBatis 。这个例子,大象没有使用 Hibernate ,而是采用更轻量级的 MyBatis 来作为持久层框架,使用很简单,也很灵活。另外,本例还用到了一个 mybatis-spring 插件,这是因为 spring 3.0.5 仅支持 ibatis 2.0 ,所以需要这个插件来处理底层数据源等工作。
![](https://i-blog.csdnimg.cn/blog_migrate/841386d0eede13d36900fb4e7f96f5b0.jpeg)
本例用到了 AOP ,所以需要这两个依赖
![](https://i-blog.csdnimg.cn/blog_migrate/7ba77065727014d601274fa0d9b43476.jpeg)
2、web.xml 与 ssh2 的 web.xml 主要的区别就是替换 Struts2 的启动配置,改为 Spring MVC 的设置,配置如下:
![](https://i-blog.csdnimg.cn/blog_migrate/282c537e3c74ef8e6e38d167a7a6ff6f.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/b4ba3c5d9584ec8c0c8b2f38aafa0851.jpeg)
3 、 servlet-context.xml Spring MVC 启动时的配置文件,包含组件扫描、 url 映射以及设置 freemarker 参数,让 spring 不扫描带有 @Service 注解的类。为什么要这样设置?因为 servlet-context.xml 与 service-context.xml 不是同时加载,如果不进行这样的设置,那么, spring 就会将所有带 @Service 注解的类都扫描到容器中,等到加载 service-context.xml 的时候,会因为容器已经存在 Service 类,使得 cglib 将不对 Service 进行代理,直接导致的结果就是在 service-context 中的事务配置不起作用,发生异常时,无法对数据进行回滚。另外能够将 REST URL 解析为请求映射的是 DefaultAnnotationHandlerMapping 这个类,它在启动时,对 Controller 中所有标注了 @RequestMapping 注解的方法,都放到了一个 HandlerMapping 对象中,当有请求时,就在这个对象中进行查找是否有与之匹配路径的处理方法,有则执行,没有就会输出一个 Not Page Found 警告信息。
![](https://i-blog.csdnimg.cn/blog_migrate/af1a6cacf81b34af1a4dc6392439dde7.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/4e635c19b4636558e67d0990cade37c5.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/376da13ddc305ab481cd6e4e1d32fc9c.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/38b5395d39210638574476c4ea99406f.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/0413e88a91b4b447dab0a8f8a5bab855.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/4885d255f02e4b6f66648d8c2025f115.jpeg)