spring-springmvc code-based

idea设置maven在下载依赖的同时把对应的源码下载过来。图0:
  • 1

这里写图片描述

主要实现零配置来完成springMVC环境搭建,当然现在有了springBoot也是零配置,但是很多同仁都是从spring3.x中的springMVC直接过渡到springBoot的,spring3.x的MVC大部分都是通过xml配置文件来完成(xml配置文件这种方式以下简称schema-based),其实在SpringBoot之前springMVC也是可以实现零配置文件(通过javaConfig和annotation实现0配置,以下简称code-based)。①并且在spring的官方文档里面的QUICK START里面的例子也是基于code-based的。后面会给出文档的附图。本文的重点在于通过spring官方文档来学习spring技术,而不去讨论schema-based与code-based孰优孰劣。
spring的两个重要的术语:

  1)、如果你的程序主要是通过配置文件(xml)来构建了,spring称这种编码风格为Schema-based。
  • 1

这个可以在官方文档来解释。②如spring对于AOP也提供两种风格实现,即Schema-based和@AspectJ-based(也就是xm方法l和Aspectj注解的方法)

 2)、如果你的代码是基于spring javaConfig来实现的spring称这种代码风格为code-based。
  • 1

搞清这个对阅读本文以及阅读spring文档都很重要。spring官网

图1:
这里写图片描述

spring官网首页(截图不全)。首页介绍了spring公司的主要项目,其中有几个我们耳熟能详的,譬如springBoot,springData,springCloud等等。可以点开每个项目看看基本的介绍,比如我们点开上面的spring framework项目。可以看到 图2:

这里写图片描述

这是spring Framework项目的主页,上面有个Introduction,就是产品介绍。大概意思就是spring framework是一个综合的程序,可以做企业级开发,是轻量级的等等。在Introduction上面有个QUICK START的按钮,意思是快速开始spring Framework的技术开发,点击后可以看到一个简单的应用。图3:

这里写图片描述

首先spring提供两种方法来开发spring Framework项目

①第一种是maven
②第二种是Gradle
上图红线标记地方可以切换,看不同方法的代码
  • 1
  • 2
  • 3

默认是maven,使用maven开发spring framework入门项目只需要通过maven去依赖spring-context(spring最核心的文件)。继而就可以使用基本的spring Framework技术了。从官方的这个quick start例子(红箭头标记的地方)可以看出spring还是推荐我们使用code-based这种编码风格的(解释了文章开头用①那段文字)。spring的code-based这种编码风格是基于spring javaConfig(springJavaConfig 如果没记错应该spring2.5以后的技术,这里不做讨论)。

这个QUICK START例子很简单,我们只需要看看,看看spring怎么编码的就够了。再回到这个页面的上面,可以看到我们所谓的spring framework到底包含了那些技术呢?就比如我们常常说J2EE,那么所谓的J2EE包含了那些技术呢?J2EE只是一个标准,包含了XML,JSP,SERVLET,JDBC等等等等技术,那么这里的spring framework只是一个项目,他也包含了很多技术。这些技术在文档里面已经说得非常清楚了。(在我从业的生涯当中也面试过不少程序员,很多初入行业的一问及spring便说:spring核心就是IOC和AOP。甚至很多程序员认为spring就只是AOP和IOC,这种认知是大错特错的),通过一张图来说明。
这里写图片描述

红色箭头地方说明了spring framework的核心构成:

1、Dependency Injection
  • 1

简称DI,依赖注入,很多人说这个就是IOC,严格来说是错的,官方叫做DI,那么DI和IOC的是什么关系呢?ICO叫做控制反转。是一种编程思想,也即是一种需要达到的目标(和spring无关,那么spring framework实现这种编程思想或者实现这种目标的技术手段叫做DI,也就是依赖注入。譬如小明说要发财,那么怎么实现发财呢?卖肾就能实现,这里的IOC相当于发财,卖肾相当于DI,小明相当于springframework)。

2、Aspect Oriented Programming.........
  • 1

(AOP技术,面向切面编程技术,AOP也是一种思想,spring framework实现AOP是基于AspectJ的技术。记得在spring早先他自己有一套AOP技术,但是貌似比较鸡肋就放弃了,引入了AspectJ技术来实现,关于AOP的一些东西,后续的文章再讨论)。

3、springMVC(本文要讨论的重点,下面会详细讨论)。

4、我们可以看到还有什么JDBC,JPA,JMS等等
  • 1
  • 2
  • 3

最后Much more表示还有更多。so,当以后有人问我们对spring的理解的时候千万别再说就是AOP和IOC,spring这家公司开发了很多项目,包括了springBoot,spring Framewok,spring Cloud……..,而IOC和AOP只是spring framewrok里面的两个核心技术。当然如果想学习更多的spring framework技术仅仅看这个quick start例子肯定不行,顾名思义,所谓quick start只是快速开始。如果需要查阅更多的spring framework文档——显然spring作为业界标杆,文档毋庸置疑肯定提供的很全面。文档——-图5:
这里写图片描述

点击红色箭头可以查阅详细的spring framework文档(5.x和4.x有一点点区别),5.x点进去之后会有一个小分类,小分类里面提供各种技术的文档链接。4.x点进去之后就是所有技术的文档,博主更习惯4.x的文档。以下是5.x的文档—图6:

这里写图片描述

5.x点进来之后会有一个小分类,比如上面的CORE一栏就包含了IOC,validation和AOP的文档,假设你想查阅spring MVC的文档可以点击Web Servlet那个链接
这里先点击Core,验证文章开头②处粗斜体所述。图7:

这里写图片描述

可以从左边的导航中找到AOP相关的文档(红色箭头),如果想系统的学习AOP可以查阅这个文档,非常详细。

spring为AOP提供了两种代码风格来实现,Schema-based---也就是XML方式,以及@AsepectJ----也就是基于ApsectJ的注解来实现
  • 1

当然本文主要讨论SpringMVC,所以需要查阅springMVC的文档,点击图6当中的Web Servlet链接,进入到spring Web文档页面。图8

这里写图片描述

进入SpringMVC的文档首页,红色箭头的Introduction(介绍)简单说明了springMVC技术基本信息。大概意思:

springMVC 依赖servlet API(说白了就是开发springMVC必须下载servlet-api.jar)
并且springMVC一开始就包含在spring framework体系里面。
springMVC的全称叫做Spring Web MVC。这个名字是来自其中一个叫做spring-webmvc
的模块(pom里面经常配置的一个依赖),但是常见的名字叫做spring MVC。。。。。。。
  • 1
  • 2
  • 3
  • 4

继而便开始介绍springMVC里面非常重要的一个类DispatcherServlet。图9:

这里写图片描述

上图首先简单介绍了一下这个类,继而给出了这个类在springMVC项目当中的配置,一共有两种方法,也就是文章开头说的基于code-based(javaConfig零配置,上图红色标记的)和schema-based(xml配置,黑色标记)。在springMVC的文档里面几乎给大部分的配置都列出了这两种风格的代码(有一些只有一种),但是所有的都是先介绍code-based。不知道可不可以理解为spring推荐我们使用code-based的coding风格,姑且这么认为吧。上图那种基于schema-based风格的配置是现在大部分的springMVC的都在用的。

再次说明一下,这两种风格无高下之分,更无优劣之别,就算有也不是本文讨论的。本文主要来讨论基于code-based的风格来实现springMVC。
  • 1

这样能够更好的去理解、学习springBoot(直接从schema-based跳到springBoot有点不好,但是现在网上对于springMVC code-based的资料比较少)。

重点是让初学者学会看spring文档,可以快速学习一些spring的技术。根据上图我们可以建立一个项目来做实验(本文使用idea来coding),pom文件里面添加相应的依赖。图10:
这里写图片描述

建立项目复制官网的代码:写一个类来实现WebApplicationInitializer 。图11:

这里写图片描述

附图12(继上图,代码过长一次截图不完):

这里写图片描述

MyWebApplicationInitializer这个类(以下简称Initializer)的主要作用就是来代替schema-based风格中的web.xml,熟悉spring web开发的人肯定知道web.xml主要做两个事情。

①配置一个listener来load spring的配置文件(就是通常取名叫做applicationContext.xml)
根据配置文件里面的信息来初始化spring的上下文环境。
 ②、配置一个servlet(DispatcherServlet)来load springMVC的配置文件。
 并且根据springMVC的配置文件信息来完成对springWEB的环境初始化。
  • 1
  • 2
  • 3
  • 4

观察Initializer这个类的代码—-它其实是通过spring javaConfig的技术同样来完成了上述的两件事情。具体代码可以下载文末提供的demo自行查看。

其实对于这个类,spring官网提供两种写法,第一种便是图11(也即是下图粉红色圈圈标记),另外一种写法(图中黑色箭头)附图:N

这里写图片描述

图N里面粉红色标记的代码也就是本例使用的,跟着下面这段文字spring解释了还有另一种写法,除了这种基于ServletContext API的写法之外还有一种便是去继承

(红色箭头标记)AbstractAnnotationConfigDispatcherServletInitializer 这个抽象类。点击黑色箭头标记的连接,spring给出了第二种写法的相应代码,

并且做了一段很长的说明,还把类之间的关系图给出来了。可以自行翻译(关于这种方法的写法本文没有实现,有兴趣的可以和我讨论哈)。N1(图有点长两次截):

这里写图片描述

续上图N2

这里写图片描述

再次说明这种方式本文不做讨论.回到图12的内容。其中的AppConfig.class相当于schame-based里面的spring和SpringMVC的配置文件。

简单说就是以前用xml来配置spring mvc的一些信息,现在用这个类AppConfig来替代那两个文件,这种技术就是开头我们说的spring javaConfig技术。他的主要代码。图13:

这里写图片描述

上文提到这个类Appconfig就相当于schema-based里面的springMVC的配置文件和spring核心的配置文件,因为他完全代替了这两个配置文件,故而这个类的代码才是本文讨论的重点。

如果熟悉`spring javaConfig`技术的话就会知道这个类可以任意命名。
而且他可以是没有任何依赖的(官网和本文中这个类是实现了一个`WebMvcConfigurer`接口)。
  • 1
  • 2

为什么这里我们会去实现一个接口呢?这是spring为了方便程序员开发,其实如果熟悉spring javaConfig技术完全可以不必要实现这个接口。

我看过很关于springBoot的文章就是没有实现这个接口,自行写的代码。这里附图一张我在百度找的一篇文章(讨论springBoot实现SpringMVC视图技术的文章,

他的`Appconfig`类就没有去实现任何接口) 图:14
  • 1

这里写图片描述

图14中就是通过code-based的方法配置了一个视图解析器,相当于schema-based中的下图代码。图15:
这里写图片描述

这是只是为了说明那个接口其实不必要去实现,可以完全自行写spring javaConfig,但是spring已经提供一个方便的接口那么最好还是实现一下。
implements这个接口后有18个方法需要去实现,这个18个方法可以完成绝大部分的环境配置。

标记①:如果有一些特殊的环境是这18个接口无法实现的,
那么你可以就在`Appcinfig`类当中自行通过`spring JavaConfig`的技术去实现
本文中就有一个对象是自行实现的,一个关于上传的配置,后面会有提及。
  • 1
  • 2
  • 3

那么这18个方法的作用和意义本文不会全部来讨论,只会讨论到一些在项目中会涉及到的和一些重要的方法,下一篇博客打算再来讨论。诚如上文所说现在这个Appconfig类就是为了替代spring的配置文件,那么怎么来替代呢?我们可以依次来分析。对于spring环境而言

❶扫描类,然后通过DI来完成注IOC。
  • 1

在schema-based中我们一般会在xml中写一个配置来完成<context:component-scan base-package="org.example.web"/>。那么在code-based的实现spring 官网已经给出非常详细的代码 图16:

这里写图片描述

在spring mvc的文档1.4节里面———-黑色箭头,spring提到:开启一个自动检测、搜索所有Controller bean,你需要在你的java config添加一个搜索组件。

继而给出了两种方案,分别是code-based(红色箭头)和schema-based(蓝色箭头)。本文的实验代码便是参考官网的这段code-based。

如此便完成了❶------自动扫描spring bean
  • 1

❷、开启对springMVC的支持,在springMVC的文档的1.11中有关于springMVC的所有配置说明 图17:

这里写图片描述

同样是两种方案,首先是code-based(蓝色箭头)

spring官网重要的说明:in javaconfig use the @EnableWebMvc annotaion
  • 1

继而是schame-based(黑色箭头)

spring官网重要的说明:in xml use the<mvc:annotaion-driven> element 
  • 1

对于熟悉schame-based的程序员来说黑色箭头处的代码应该已经非常亲切了。

如此便完成了第❷步,开启springMVC的支持这里稍微做点说明所谓开启springMVC的支持意思让程序员能够使用springMVC技术
比如springMVC中的视图转换、视图检测等等,最直观的:博主自己测试过,比如不加@EnableWebMvc这个annotation
程序可以正常启动并且能够访问,但是当controller中的方法返回一个XXX的字符串时候,程序员是无法跳转到XXX.jsp.
即使程序员配置了视图解析器也不行,但是加上@EnableWebMvc之后便可以。
  • 1
  • 2
  • 3
  • 4

❸、配置springmvc的视图解析器。一般javaweb项目里面使用都是jsp,所以我们首先配置一个jsp的视图解析器。查阅springmvc的文档的第1.12节—View Technologies

图N3

这里写图片描述

查阅1.12节—View Technologies(箭头1),展开后其实springmvc提供了很多视图技术,比如图中的Freemarkertilesjsp等等。

目前只需要配置对jsp的视图解析。
so 点击箭头2,继而点击View Resolvers(视图解析),看到spring给出了schema-based风格的jsp解析器配置代码。但是spring没有给出code-based的代码,其实spring的文档里面也有提到,只是在这里没有。仔细看这段xml配置,无非就是声明、注册了一个bean而已,如果换成code-based无非就是利用spring javaConfig的方法去声明、注册一个bean。这对熟悉spring javaconfig的人来说很简单。文章中图14里面的代码(网上我找的)就是通过spring javaconfig的方法,在Appconfig这个类中声明、注册了一个InternalResourceViewResolver的对象

注意,图14的代码是没有实现接口的
  • 1

图14的代码的效果相当于此处图N3红色箭头xml代码的效果。可是现在的程序中AppConfig类实现了一个接口。其实spring提供的这个接口当中有一个方法就是专门来注册视图解析器的。查阅这个类的源码注释有一个方法 configureViewResolvers
这个方法就是使用spring javaconfig 技术专门来实现对视图解析器的声明、注册用的。

关于这个方法的解释和说明(很重要)本文提供的代码有详细注释说明。可以下载代码查阅demo会在文章末尾提供的地址
  • 1

图18:

这里写图片描述

上图代码其实和图14的效果是一样的,

再次说明,图14没有实现接口
  • 1

上图的代码是实现了WebMvcConfigurer这个接口,通过接口中的一个方法来完成对象的声明、注册。查阅registry.jsp方法的源码,可以看到spring的代码其实和图14的几乎一样。

如此我们便完成了第❸步,对spring视图解析器的注册
  • 1

图19(spring的源码,可以对比一下图14百度上找的代码):

这里写图片描述

对于一个springmvc的项目而言,完成以上三步就完成了基本的配置,程序员可以定义controller,并且返回字符串,会跳转到对应的页面。于是便把项目发布tomcat跑起来看看结果。

本文的demo是通过maven的tomcat 插件来配置的,博主也推荐使用这种maven plugs的方法来开发web项目
  • 1

至此项目的结构图如下。图20

这里写图片描述

程序中定义了一个IndexController 其中有一个index方法,最后返回字符串”index”,并且web.xml是没有任何代码的。讲道理发布、启动tomcat后,访问index.xhtml程序会跳转到index.jsp。图21:

这里写图片描述

此处的index.xhtml是一个request请求,而非一个文件。博主之前开发程序便习惯把请求后缀取名.xhtml
  • 1

至此便完成了一个基于code-based的springmvc程序,就是所谓的零配置。其实和springBoot很相像了。通过这种查阅官方文档的方式去学习spring我觉得非常好,这样就会加深对spring体系的认知。当然我们仅仅是完成了对jsp视图的解析,通常项目当中还会对json处理。

当方法加了@ResponseBody后消息会自动转换成JSON格式响应给客户端。譬如在controller中定义了一个返回Map的方法。
如果给方法加上@ResponseBody,继而请求该方法,最后服务器会响应一个段JSON,就是由spring 转换的,不需要程序员写代码去转。
  • 1
  • 2

springmvc的官网给出了利用jackson技术来处理JSONXML。图22,分两次截图

这里写图片描述

继上图

这里写图片描述

如果使用jackson只需要加上上图中的配置,继而依赖好jackson的几个jar包便能处理JSON了。可是在国内一般都是用马云爸爸开发的fastJson居多,所以本文就来讨论在springmvc code-based中如何使用fastJson来处理JSON

1、首先在pom当中添加fastjson的依赖
2、查阅官方文档,消息转换(Message Converters,姑且这么翻译吧)这一节。图23:
  • 1
  • 2

这里写图片描述

上图红色标记区的信息已经说的非常详细了———如果我们需要使用自定义的转换器,那么必须去覆盖Appconfig当中的configureMessageConverters方法,并且以jackson为例,给出了重写configureMessageConverters方法的代码,从上图可以看出,spring官网代码的Appconfig类也是实现了WebMvcConfigurer接口的,和本文的例子一样。我们只需要在Appcnfig这个类中找到这个方法,继而重写然后定义、注册fastJson的转换器就可以了。上图的jackson的转换器叫做MappingJackson2XmlHttpMessageConverter那么如果我们重写这个方法,fastJson的转换器叫什么名字呢?其实比较简单。

文档有一段非常重要的话Customization of HttpMessageConverter can be achieved in Java config by overriding
  • 1

这段描述中可以猜spring要求自定义的转换器必去实现HttpMessageConverter这个接口。且事实就是如此。可以找到这个接口,在org.springframework.http.converter包下面就定义了这个接口,程序员也可以通过MappingJackson2XmlHttpMessageConverter这个类去找。
按住ctrl点击一路找过去就能找到HttpMessageConverter
找到这个接口后在idea下面打开这个类,继而选中接口名字。

idea中按ctrl+alt+b,可以查看该接口的所有实现类图24:
  • 1

这里写图片描述

只要fastJson的依赖,讲道fastjson如果想springmvc中处理方法放JSON那么fastJson肯定提供了一个符合spring`标准的消息转换类

上文提到spring的要去实现HttpMessageConvter接口
  • 1

这就是标准的魅力,一流公司卖标准,二流公司卖服务,三流公司卖产),像spring这种准一流公司,开发标准可谓轻车熟路,马云爸爸在电商界呼风唤雨,可是在code方面只能去实现spring的标准了,这样也好,程序员倒是很欢喜,试想如果没有这个标准,那么程序员在spring项目中用不同公司提供的技术去实json支持那么API完全就不会不同。。。。。。。。言归正常。

图24用蓝色标记的2箭头可以看到有一个叫FastJsonHttpMessageConverter的类,显然就是马云爸爸开发的,于是程序就变得简单了,我们只需要把图23中jackson的转换器改成fastJson的转换器便可。

注意的是图23中jackson处理的不仅仅是JSON。
  • 1

还对xmlbihernate做了处理,故而代码有点复杂(这个文档上有说明的,我想不到为什么还要对hibernate做处理,讲道理hibernate现在已经不怎么用了),本例中只需对JSON进行处理,代码相对就简单的多。图25

这里写图片描述

诚然fastJson也有也有很多配置,比如对于key是否加双引号啊等等配置,不在本文讨论的,可以查阅fastJson的文档。上图的代码注释里面就有一些fastJson的基本配置,其实这个转换器的默认配置已经可以满足基本开发需求了,比如字符集的处理,查阅源码可以看到他有默认的字符集设置UTF-8。图26

这里写图片描述

有小插曲,博主在查阅fastJson的源码过程当中发觉一个特别有趣的事,附图:N4
  • 1

这里写图片描述

天地良心,这是阿里巴巴的程注释
  • 1

至此code-basedsspringmvc项目对 fastjson支持已经配置好,可以启动tomcat检查一下是否能够正常处理json图27:

这里写图片描述

index.jsp页面用jQuery去发了一个ajax请求,可以看到在IndexControllerjson.xhtml是一个加了@ResponseBody的方法,并且返回了一个map

注意map当中是有中文的
  • 1

最后在客户端的JavaScriptsuccess方法中打印了服务器响应的消息。讲道理会正常返回JSON数据给浏览器。图28:

这里写图片描述

可以看到中文也是可以正常显示的,至此我们通过code-based的方式完成了对jspjson的处理。当然一般项目里面还会涉及到上传,由于篇幅原因,本文接下来只会对上传进行介绍,还有他的比如类型转换,验证等等下一篇博客再来介绍。关于springmvc的上传,文档中已经说得非常非常清楚了。查阅spring的文档,其中有一节就是专门讲文件处理。图29:

这里写图片描述

这段文字的大概意思是spring内置Mulitipart Request技术就包含了文件上传的处理,其中有一个可插拔的对象叫MultipartResolver可以支持文件上传请求。但是这个类只是一个接口,说白了就是一个标准,实现这个标准有两种方法,第一种(箭头标记‘第一种’)commons-fileupload这也是现在普遍用的方法。第二种(箭头标记‘第二种’)便是基于servlet3.0

    对于servlet3.0,如果我没记错tomcat7以上就是servlet3.0了。  
  • 1

对于这两种方法spring文档中都给了非常详细的说明。图30:

这里写图片描述

Ⅰ、commns-fileuplod实现,需要把相应的依赖写到pom中,然后在声明、注册一个做叫CommonsMultipartResolver(1蓝色箭头)的对象。

并且名字一定叫做multipartResolver(2蓝色箭头)
  • 1

这样就完成了对commons-fileupload的配置,意思是一个上传文件的请求就会由commons-fileupload的技术来处理。

这里说去注册一个CommonsMultipartResolver 对像,上文说过一个对象的声明、注册spring有两种方法`schema-based`和`code-based`
  • 1

本文讨论的是code-based,文章下面有通过code-based来注册、声明CommonsMultipartResolver的详细说明

Ⅱ、servlet3.0的方式就比较复杂,文档的大概意思❶需要我们在web.xml中的DisptcherServlet的节点中配置一个Multipart-config的节点。❷或者去配置一个叫做MultipartConfigElement类的对象,并且把这个对象给Servlet Registration

这里❷有点绕,下面会详细说明
  • 1

❸再或者你自己定义一个servlet在定义的servlet类上面加上@MultipartConfig

也就是有三个或者。。。spring真的牛逼呀,三个呀!!
  • 1

但是ⅠCommons-fleUpload和Ⅱservlet3.0最大的不同

注册处理文转件上传的转换器不同
Ⅰ、需要注册CommonsMultipartRver
Ⅱ、需要StandardServletMultipartResolveresolver          
但是名字都需要一样叫做multipartRelover(2蓝色箭头)

为什么需要叫这个名字,下次再讨论
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

首先讨论Ⅰcommons-fileupload上文所述,首先需要去注册、声明一个CommonsMultipartResolver 对象,如果是用schema-based的方式就很简单,直接在springmvc的配置文件中声明一个bean。

<bean id="xxx" class="xxx">

对于`code-based`方式,spring的文档中并未说明,其实去查阅`Appconfig`类中的那18个方法发现也没有一个方法提供了对该类`CommonsMultipartResolver` 的注册。回到上文说的。

如果接口中提供的方法不能满足程序开发需求了,则需要程序员自行通过spring javaConfig的技术去实现。
  • 1
  • 2
  • 3
  • 4
  • 5

对于这个类CommonsMultipartResolver 的注册,使用sping javaconfig技术来实现注册还是比较简单,查阅源码:

该类有一个不带参数的构造方法,即可以直接new图CommonsMultipartResolver 源码。图31:
  • 1

这里写图片描述

既然该类提供了无参的构造方法那么程序员只需要在Appconfig类当中通过spring javaConfig技术简单注册一下便可,代码比较简单。图(本文demo中的代码)32:

这里写图片描述

如此便完成了CommonsMultipartResolver的注册,关于上传文件的其他设置,比如文件大小的限制的等等如何设置呢?schema-based的方式是通过xml配置的。那么code-based的设置也比较简单的,查阅CommonsMultipartResolver的源码可以看到他提供各种API来设置这些信息,其中就有关于文件大小限制的设置。附图33:

这里写图片描述

查阅CommonsMultipartResolver源码,该类继承了一个CommonsFileUplaodSupport的父类,查看这个父类。图34:

这里写图片描述

这个父类里面提供了很多上传文件的设置,setMaxUploadSIze。。。。顾名思义、设置文件最大上限。所以我们可以在实例化CommonsMultipartResolver之后调用这些方法去做相应的设置。图35:

这里写图片描述

可以根据具体的应用去设置具体的值,本文不再做讨论了。
  • 1

至此,关于springmvc第Ⅰ种方案处理文件上传请求的对象CommonsMultipartResolver的注册已经完成了。那么剩下我们的controller中的代码如何写呢?查阅springmvc文档1.4.3节中可以看到对应代码。图36:

这里写图片描述

上述代码表示,我们HTML页面需要提供一个上传的表单,继而controller中提供一个方法。文档上面有一段话非常的精髓。

The next step is to create a controller that handles the file upload. This controller is very similar to a normal annotated @Controller, except that we use MultipartHttpServletRequest or MultipartFile in the method parameters:
  • 1

大概的意思就是-创建一个处理文件上传的controller。这个controller和一个正常加了@Controllercontroller没很大区别,无非就是这个处理文件上传的controller需要使用MultipartHttpServletRequestMultipartFile作为方法参数而已。

是把文件当成一个普通参数,继而加上指定的注解便可以了。同时也体现了spring性感到骨子里的特点:

无侵入性,不破坏封装,轻量级,低耦合等等....
  • 1

我记得struts2的文件上传需要程序员定义几个全局变量,并且对于这些全局变量要有规定的方法与之对应,这样程序员的代码便有了依赖了。比起spring的这种处理,spring还是做得好多了)。。。。言归正传,写完这些之后启动tomcat测试一下文件上传。图37:

这里写图片描述

至此已经彻底完成了springmvc处理jsp,处理JSON,处理文件,处理正常参数。当然文件上传是基于ⅠCommons-fileUpload的这种方式。记得上文提到还有第Ⅱ种方式来。

基于servlet3.0
  • 1

Ⅱ、基于Servlet3.0来处理文件上传,首先给出一个schema-based的代码

在web.xml中配置对应挡标签  图38:
  • 1

这里写图片描述

这种配置其实和spring没有关系,意思就是就算开发一个servlet+jsp项目也可以用这个配置。然而这种方法需要去配置xml与spring的code-based不符,故而本文不再做讨论。

     直接用code-base方式实现springmvc基于servlet3.0的文件上传的程序
  • 1

上文说到实现spring上传的方法有3个或者,第❶个或者就是如上图配置(不是零配置),第❷和❸种其实都差不多。本文重点在第❷个。但是第❷个或者spring只是简单的说明了一下,并没有详细的代码,需要我们自己去查阅spring的源码。
1、MultipartConfigElement查阅这代码的源码发现他有三个构造方法

这里写图片描述
仔细查阅源码,其实三个构造方法无非就是对上传信息的设置,比如第一个构造方法要求我们提供文件保存的位置,第二个构造方法的四个参数spring源码的注释写的非常清楚了,这里稍微解释一下。图:

这里写图片描述

具体用哪种方法程序员自己考虑,本文例子代码使用的第一个构造方法,仅仅传入了一个文件保存路径。

 如果这个类被实例化出来了,跟着要怎么办呢?直观的看spring文档对于这个类的说明比较模糊如图40:
  • 1

这里写图片描述

就简单的一句话便描述完了,意思是把这个对像给一个Servlet Registration。很迷茫?到底意思呢?大胆的猜一下,在程序初始化的时候MyWebApplicationInitializer中的onStartup方法程序不是通过ServletRegistration.Dynamic去add了一个servlet

查阅源码发现ServletRegistration.Dynamic是一个接口。
  • 1

他的真实对象是通过servletContext对象的一个方法servletContext.addServlet返回来的。这个对象的定义是没有的,因为ServletContext也是一个接口,程序中的servletContxt对象是由tomcat在启动创建的。

这个如果要讨论就要讨论tomat的实现原理了,这个放到以后讨论
  • 1

也就是这个servlet-api.jar把接口写好了供程序员调用,真实的实现都是基于tomcat的。这么理解吧:

假设servlet-api.jar里面有一个UserDao的接口,里面有各种查询方法,add方法啊;但是他只是接口。
真正实现这个UserDao的类是不在jar中,是由容器启动时把这个接口的对象给程序,所以程序有userDao的对象。
  • 1
  • 2

再于是猜想所谓的Servlet Registration 就是这个ServletRegistration.Dynamic接口的对象。 查阅源码,还真发现他有一个方法setMultipartConfig的方法,并且参数类型就是MultipartConfigElemen图41:

这里写图片描述

为了验证这个猜想就在初始化那个方法MyWebApplicationInitializer.onStartup里面里面把这个MultipartConfigElement set一下。图42:

这里写图片描述

最后根据文档的说明,serlvet3.0需要注册的文件转换器叫做StandardServletMulti
partResolver
于是把Appconfig类里面MultipartResolver改成返回StandardServletMultipartResolver。图42:

这里写图片描述

启动tomcat 运行程序 图last:
  • 1

这里写图片描述
至此两种上传文件的方法都完成了,第一种依赖commons-fileUpaload,第二种可以不需要这个jar了。介于篇幅原因本文就到此杀青了。

文的目的不是为了搭建springMVC code-based框架,仅仅是博主感叹一下spring公司编写的性感的开发文档。一下两个都是代码地址
代码:http://download.csdn.net/download/java_lyvee/10162574
代码:http://dl.iteye.com/topics/download/a6e61837-4236-364d-8c22-5eeb848fea2e   
  • 1
  • 2
  • 3

末了打个广告http://lubanedu.ke.qq.com/鲁班学院,每晚八点都有免费的java试听课,都是面向高级开发的课堂内容,非常不错

posted @ 2018-10-13 20:32  后知、后觉  阅读(550)  评论(0编辑  收藏  举报