《经久不衰的Spring框架:SpringMVC 统括》

前言:经久不衰的Spring

这几年,前端技术更新换代速度之快,每一年“最火的前端技术”排行榜都会换一番场景,本当に信じかねる。是“只闻新人笑不见旧人哭”,还是“青山依旧在,几度夕阳红”,这些只有身处浪潮中才能慢慢体会。

跑偏了,赶紧回归正题。难道Java 相关技术没有变革?那肯定不是,这边说的只是Java 的企业级开发框架这块。记得笔者刚入职那年,就在使用SSH三大框架,时至今日,公司采用的SSM框架,这其中经久不衰的就是Spring了。常见的SSH三大框架,就是Spring、Struts、Hibernate,到后来半ORM框架ibatis 出现了,接着改名Mybatis,若将MVC框架替换为SpringMVC,即凑成了SSM框架(笔者目前在用的各框架版本是Spring 4.2.6、Hibernate 4.3.1、Mybatis 3.2.8)。

虽然是本人介绍Spring的第一篇文章,但这几大框架我不用多加介绍了,网上文章多如牛毛,我再描述,那就有点老生常谈的意味了。直接写一些开发工作中,遇到相关卡壳问题和经验总结,纯属记录,毕竟Java当前吃饭的饭碗。

SpringMVC 简介

  SpringMVC是一种基于Java的实现了 Web MVC 设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发。它和Struts一样是一个MVC框架,它是Spring当中的一个子框架,和Spring无缝集成,和Struts2类似。

  SpringMVC的前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

  大概概述下 SpringMVC的步骤:

    l 步骤1—— 对Http请求进行初步处理,查找与之对应的Controller处理类(方法) ——HandlerMapping

    l 步骤2—— 调用相应的Controller处理类(方法)完成业务逻辑 ——HandlerAdapter

    l 步骤3—— 对Controller处理类(方法)调用时可能发生的异常进行处理 ——HandlerExceptionResolver

    l 步骤4—— 根据Controller处理类(方法)的调用结果,进行Http响应处理 ——ViewResolver

  使用SpringMVC框架好处:进行更简洁的Web层的开发;天生与Spring框架集成(如IoC容器、AOP等);提供强大的约定大于配置的契约式编程支持;容易与其他视图技术集成;对静态资源的支持;支持Restful风格等等。

SpringMVC 与 Struts2

  这边并不会去过多得对两大框架进行对比,以免引发两方阵营得争论,只是简单介绍一下Struts2框架,并继续列举认可SpringMVC的理由。

  什么是Struts2?

  Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2是Struts的下一代产品,是在 Struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。

  为什么是SpringMVC?

  1、相比Struts2,SpringMVC与Spring更加贴合,DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。

  

  2、设计原则更加明朗。这条重要的设计原则被写在了spring官方的reference中SpringMVC章节的起始段: A key design principle in SpringWeb MVC and in Spring in general is the “Open for extension, closed for modification” principle. 并且重点很好地体现在SpringMVC的实现当中,可以扩展,但却不能改变。我曾经扩展过Spring的IOC、AOP功能,这一点SpringMVC应该和Spring一脉相承。

  

  3、组件化的设计方案和特定的设计原则让SpringMVC形散神聚,SpringMVC总是沿着一条固定的逻辑主线运行,却拥有多种不同的行为模式。

SpringMVC 关键部分

  废话不多说了,也该讲一些实际一点的东西了。

  一、前端控制器 -- DispatcherServlet

  ※所有J2EE项目都是从web.xml启动,阅读或构建一个J2EE项目,都应该先找web.xml开始。

  ※任何MVC框架都需要一个入口,SpringMVC的入口是在web.xml文件中的核心分发DispatcherServlet;

  ※DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。DispatcherServlet默认使用WebApplicationContext作为上下文,Spring默认配置文件为/WEB-INF/[servlet名字]-servlet.xml;

<servlet>
  <servlet-name>SpringMVC</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:mvc-config.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>SpringMVC</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

  二最简注解映射配置

  笔者使用的是SpringMVC4.x,不用像SpringMVC3.0 时代,配置一大堆的HandlerMapping、HandlerAdapter、Converter。

  对,没有错,你仅仅需要配置一句话:<mvc:annotation-driven/>

  <mvc:annotation-driven/>相当于注册了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter两个bean,配置一些messageconverter。即解决了@Controller注解的使用前提配置。

  三、静态资源最优处理  

  如果你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题,但是要多书写.do。

如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg的访问也就被拦截了。  

当然,想要restful风格的话,就必须采用后者,那么就动手来解决一下静态资源问题。

  方案一: 在Spring3.0.4以后版本提供了mvc:resources

  mvc:resources 的使用方法:

<mvc:resources location="/images/" mapping="/images/**"/>

<mvc:resources location="/js/" mapping="/js/**"/>

<mvc:resources location="/css/" mapping="/css/**"/>

  说明:/images/**映射到 ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period 可以使得静态资源进行web cache

  方案二 ,使用<mvc:default-servlet-handler/>

  说明:<mvc:default-servlet-handler/>  会把"/**" url,注册到SimpleUrlHandlerMapping的urlMap中,把对静态资源的访问由HandlerMapping转到 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler 处理并返回。

  DefaultServletHttpRequestHandler使用就是各个Servlet容器自己的默认Servlet。

  方案三:激活Tomcat的defaultServlet来处理静态文件

  web.xml中书写代码如下:

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>*.jpg</url-pattern>
  <url-pattern>*.gif</url-pattern>
  <url-pattern>*.png</url-pattern>
  <url-pattern>*.js</url-pattern>
  <url-pattern>*.css</url-pattern>
  <url-pattern>*.html</url-pattern>
</servlet-mapping> 

  说明:本人采用这种方式,Tomcat直接处理静态资源效率较高。缺点就是需要配置多个,每种文件配置一个,并且要写在DispatcherServlet的前面,让defaultServlet先拦截。

  四、视图映射配置

  这点没什么好说的,多种配置方式,直接上一种配置代码: 

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/project/" p:suffix=".jsp" />

  五、文件上传解析器

  SpringMVC实现多文件上传的方式有两种,一种是我们经常使用的以字节流的方式进行文件上传,另外一种是使用SpringMVC包装好的解析器进行上传,这两种方式对于实现多文件上传效率上却有着很大的差距,建议采用后者。

   部分配置如下:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <property name="defaultEncoding" value="utf-8"></property>
     <property name="maxUploadSize" value="10485760000"></property>
     <property name="maxInMemorySize" value="40960"></property>
</bean>  

  说明:这边不是文件上传专栏,不详细介绍。

  六、控制器扫描

  这部分其实应该归纳在Spring部分,但是SpringMVC也是基于Bean去操作的,需要扫描一下控制器Bean。

  配置代码如下:

<context:component-scan base-package="com.demo"  use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

  说明:这样配置的意思是只扫描com.demo 包下@Controller 注解标注的类,use-default-filters属性配置为false 是必须的。

编后语

  SpringMVC可以介绍的功能和内容无论从深度还是广度上,都远远不止本文提到的这些内容,这些只不过是最基础的部分。

  SpringMVC为Web开发提供了相当得便捷,但在用的过程中还是要理解它的实现原理和思路,再往深一层来说,它毕竟只是框架,它适合做什么、能够做什么、怎么做,这些都应该由你自己做主,不能被框架左右。

  后续的博文会书写Spring相关的一些技术点总结以及经验之谈,敬请关注。

  “风萧萧兮易水寒 壮士一去兮不复还”

时间: 2024-08-02 23:01:09

《经久不衰的Spring框架:SpringMVC 统括》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: