前言:经久不衰的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相关的一些技术点总结以及经验之谈,敬请关注。

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

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

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. pho

    PDO(PHP Data Object) 是PHP 5新出来的东西,在PHP 6都要出来的时候,PHP 6只默认使用PDO来处理数据库,将把所有的数据库扩展移到了PECL,那么默认就是没有了我们喜爱的 ...

  2. IOS中单例NSUserDefaults的使用(转)

    一.了解NSUserDefaults以及它可以直接存储的类型 http://my.oschina.net/u/1245365/blog/294449 NSUserDefaults是一个单例,在整个程序 ...

  3. Nodejs之发送邮件nodemailer

    nodejs邮件模块nodemailer的使用说明 1.介绍 nodemailer是node的一个发送邮件的组件,其功能相当强大,普通邮件,传送附件,邮件加密等等都能实现,而且操作也十分方便. nod ...

  4. ubuntu系统内核替换

    此处将内核由高版本替换成低版本.替换前的系统为ubuntu 12.04 kernel 3.8.0. 替换后的内核版本为2.6.35. 首先下载需要替换的内核文件,下载链接:https://www.ke ...

  5. CentOS下架设Telnet服务器

    CentOS下架设Telnet服务器1.什么是Telnet?来自度娘的解释:Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户提供了在本地计算机 ...

  6. 安装MYSql Windows7下MySQL5.5.20免安装版的配置

    MySQL Windows安装包说明: 1.mysql-5.5.20-win32.msi:Windows 安装包,图形化的下一步下一步的安装. 2.mysql-5.5.20.zip,这个是window ...

  7. 数组(Array)资源

    上面的程序中在Java代码中定义了两个数组,Android并不推荐在Java代码中定义数组,因为Androd允许通过资源文件来定义数组资源. Android采用位于/res/values目录下的arr ...

  8. easyui-datagrid分页查询

    不想写语言描述了,直接代码吧! js: $(document).ready(function () { var driver_datagrid; $('#job').combobox({ url: ' ...

  9. C++中的RAII技法

    Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life ...

  10. node源码详解(七) —— 文件异步io、线程池【互斥锁、条件变量、管道、事件对象】

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource7 本博客同步在https://cnodejs.o ...