前言:經久不衰的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?
為什么是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。
<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相關的一些技術點總結以及經驗之談,敬請關注。
“風蕭蕭兮易水寒 壯士一去兮不復還”