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试听课,都是面向高级开发的课堂内容,非常不错

转载于:https://www.cnblogs.com/xuxinstyle/p/9784040.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

powershell 入门_使用PowerShell入门的5个Cmdlet

powershell 入门PowerShell is quickly becoming the preferred scripting language and CLI of Power Users as well as IT Pros. It’s well worth learning a few commands to get you started, so we’ve got 5 useful cmdlets for you to learn today. PowerShellSwift成为…

Part 3: Services

介绍 在第3部分中&#xff0c;我们将扩展应用程序并启用负载平衡。为此&#xff0c;我们必须在分布式应用程序的层次结构中提升一个级别:服务。 StackServices (你在这里)Container (涵盖在第2部分中)关于服务 在分布式应用程序中&#xff0c;应用程序的不同部分被称为“服务”…

diy感应usb摄像头拍照_DIY无线感应充电器

diy感应usb摄像头拍照Courtesy of Instructables user Inducktion shares a very detailed tutorial on how to build a wireless power charger. He explains the impetus behind the project: 由Instructables用户提供Inducktion分享了有关如何构建无线电源充电器的非常详细…

常用模块之 time,datetime,random,os,sys

time与datetime模块 先认识几个python中关于时间的名词&#xff1a; 时间戳(timestamp)&#xff1a;通常来说&#xff0c;时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”&#xff0c;返回的是float类型。1970年之前的日期无法以此表…

使用aSpotCat控制您的Android应用权限

Viewing the permissions of each installed Android app requires digging through the Manage Applications screen and examining each app one by one — or does it? aSpotCat takes an inventory of the apps on your system and the permissions they require. 要查看每…

xtrabackup备份mysql“ib_logfile0 is of different”错误分析

今天用xtrabackup工具完整备份mysql数据库的时候出现“./ib_logfile0 is of different”错误&#xff0c;具体的日志信息如下: 我第一时间查询了百度和谷歌都没有找见相对应的答案。决定从错误日志入手&#xff0c;上面的日志提示说&#xff1a;mysql数据库inondb的日志文件的大…

如何使自己的不和谐机器人

Discord has an excellent API for writing custom bots, and a very active bot community. Today we’ll take a look at how to get started making your own. Discord具有出色的用于编写自定义机器人的API&#xff0c;以及非常活跃的机器人社区。 今天&#xff0c;我们将探…

​css3属性选择器总结

css3属性选择器总结 &#xff08;1&#xff09;E[attr]只使用属性名&#xff0c;但没有确定任何属性值 <p miaov"a1">111111</p> <p miaov"a2">111111</p> p[miaov]{background: red;} /*所有属性为miaov的元素都会被背景变红&a…

程序代码初学者_初学者:如何使用热键在Windows中启动任何程序

程序代码初学者Assigning shortcut keys to launch programs in Windows is probably one of the oldest geek tricks in the book, but in true geek fashion we are going to show you how to do it in Windows 8. 分配快捷键以在Windows中启动程序可能是本书中最古老的怪胎技…

stevedore——启用方式

2019独角兽企业重金招聘Python工程师标准>>> setuptools维护的入口点注册表列出了可用的插件&#xff0c;但是并没有为最终用户提供使用或启用的方法。 下面将描述用于管理要使用的扩展集的公共模式。 通过安装方式启用 对于许多应用程序&#xff0c;仅仅安装一个扩…

C# -- 文件的压缩与解压(GZipStream)

文件的压缩与解压 需引入 System.IO.Compression; 1.C#代码&#xff08;入门案例&#xff09; 1 Console.WriteLine("压缩文件...............");2 using (FileStream fr File.OpenRead("d:\\test.txt"))3 {4 …

win7屏保文件.scr_如何将屏保添加到Ubuntu 12.04

win7屏保文件.scrUbuntu 12.04 doesn’t ship with any screen savers, just a black screen that appears when your system is idle. If you’d rather have screensavers, you can swap gnome-screensaver for XScreenSaver. Ubuntu 12.04没有附带任何屏幕保护程序&#xff…

简单读写XML文件

IPAddress.xml 文件如下&#xff1a; <?xml version"1.0" encoding"utf-8"?><IP><IPAddress>192.168.0.120</IPAddress></IP> 在 Form 窗体(读取XML配置.Designer.cs)中有如下控件&#xff1a; 代码 privateSystem.Wind…

如何与Ubuntu One同步配置文件

Ubuntu One lets you easily synchronize files and folders, but it isn’t clear how to sync configuration files. Using Ubuntu One’s folder synchronization options or some symbolic links, you can synchronize configuration files across all your computers. Ubu…

智能家居设备_您的智能家居设备正在监视您吗?

智能家居设备In a world where we’re all paranoid about devices spying on us (and rightfully so), perhaps no other devices receive more scrutiny than smarthome products. But is that scrutiny warranted? 在一个我们都对监视设备的人都抱有偏执的世界(理应如此)&a…

Jenkins忘记admin密码处理方法

1、先找到enkins/config.xml文件&#xff0c;并备份。 此文件位于Jenkins系统设置的主目录&#xff0c;根据自己的配置情况而定。我的位置如下 /data/temp/jenkins/config.xml2、然后编辑config.xml删除<useSecurity>true</useSecurity>至</securityRealm>&a…

科研绘图工具软件_如何在Windows 10 Mail中使用绘图工具

科研绘图工具软件Microsoft recently released a new feature for the Windows 10 Mail app that lets you convey messages with drawings right inside the body of an email. This is a great way to quickly sketch things like graphs or tables to get your point across…

子元素相对于父元素垂直居中对齐

记个笔记 1. 元素相对于浏览器居中 <style>.window-center {/* 将position设置为fixed&#xff0c;使元素相对于浏览器窗口定位 */position: fixed;/* 将margin设置为auto&#xff0c;使浏览器自动推算元素外边距 */margin: auto;/* 将上下左右边距&#xff08;相对于浏览…

网站运行java_定制化Azure站点Java运行环境(5)

Java 8下PermGen及参数设置在上一章节中&#xff0c;我们定制化使用了Java 8环境&#xff0c;使用我们的测试页面打印出了JVM基本参数&#xff0c;但如果我们自己观察&#xff0c;会发现在MXBeans中&#xff0c;没有出现PermGen的使用数据&#xff0c;初始大小等信息&#xff0…

三阶魔方魔方公式_观看此魔方的自我解决

三阶魔方魔方公式Finally: a Rubik’s cube that can solve itself. A maker named Human Controller built it in Japan, and you can see it in action right now. 最后&#xff1a;一个可以解决自身问题的魔方。 一家名为Human Controller的制造商在日本制造了它&#xff0…