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
提供了很多視圖技術,比如圖中的Freemarker
、tiles
、jsp
等等。
目前只需要配置對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技術來處理JSON
和XML
。圖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
還對xml
和bihernate
做了處理,故而代碼有點復雜(這個文檔上有說明的,我想不到為什么還要對hibernate
做處理,講道理hibernate
現在已經不怎么用了),本例中只需對JSON
進行處理,代碼相對就簡單的多。圖25
誠然fastJson
也有也有很多配置,比如對于key是否加雙引號啊等等配置,不在本文討論的,可以查閱fastJson
的文檔。上圖的代碼注釋里面就有一些fastJson
的基本配置,其實這個轉換器的默認配置已經可以滿足基本開發需求了,比如字符集的處理,查閱源碼可以看到他有默認的字符集設置UTF-8。圖26
:
有小插曲,博主在查閱fastJson的源碼過程當中發覺一個特別有趣的事,附圖:N4
- 1
天地良心,這是阿里巴巴的程注釋
- 1
至此code-baseds
的springmvc
項目對 fastjson
支持已經配置好,可以啟動tomcat
檢查一下是否能夠正常處理json
圖27:
在index.jsp
頁面用jQuery
去發了一個ajax
請求,可以看到在IndexController
中json.xhtml
是一個加了@ResponseBody
的方法,并且返回了一個map
。
注意map當中是有中文的
- 1
最后在客戶端的JavaScript
的success
方法中打印了服務器響應的消息。講道理會正常返回JSON
數據給瀏覽器。圖28:
可以看到中文也是可以正常顯示的,至此我們通過code-based
的方式完成了對jsp
和json
的處理。當然一般項目里面還會涉及到上傳,由于篇幅原因,本文接下來只會對上傳進行介紹,還有他的比如類型轉換,驗證等等下一篇博客再來介紹。關于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
和一個正常加了@Controller
的controller
沒很大區別,無非就是這個處理文件上傳的controller需要使用MultipartHttpServletRequest
或MultipartFile
作為方法參數而已。
是把文件當成一個普通參數,繼而加上指定的注解便可以了。同時也體現了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
于是把
partResolverAppconfig
類里面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試聽課,都是面向高級開發的課堂內容,非常不錯