一.文件上傳
1.文件上傳
- SpringMVC為文件上傳提供了直接的支持吼鳞,這種類型是通過即插即用的MultipartResolver技術(shù)的奄抽。Spring用Jakarta Commons FileUpload技術(shù)實(shí)現(xiàn)了一個(gè)MultipartResolver實(shí)現(xiàn)類:CommonsMultipartResolver.
- SpringMVC上下文中默認(rèn)沒有裝配MultipartResolver蔼两,因此默認(rèn)情況下不能處理文件的上傳工作,如果想使用Spring的文件上傳功能逞度,需現(xiàn)在上下文中配置MultipartResolver额划。
2. 配置MultipartResolver
- defaultEncoding:必須和用戶JSP的pageEncoing屬性一致,以便正確解析表單的內(nèi)容档泽。
- 為了讓CommonsMulitpartResolver正確工作俊戳,必須先將Jakarta Commons FileUpload及Jakarta Commons io的類包添加到類路徑下。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<propert name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="524880"></property>
</bean>
二.攔截器
1.自定義攔截器
SpringMVC也可以使用攔截器對(duì)請(qǐng)求進(jìn)行攔截處理馆匿,用戶可以自定義攔截器來實(shí)現(xiàn)特定的功能抑胎,自定義的攔截器必須實(shí)現(xiàn)HandlerInterceptor接口。接口中有三個(gè)方法:
preHandle():這個(gè)方法在業(yè)務(wù)處理器請(qǐng)求之前被調(diào)用渐北,在該方法中對(duì)用戶請(qǐng)求request進(jìn)行處理阿逃。如果你決定該攔截器對(duì)請(qǐng)求進(jìn)行攔截處理好還要調(diào)用其他的攔截器,或者是業(yè)務(wù)處理器去進(jìn)行處理赃蛛,則返回true恃锉;如果程序員決定不需要再調(diào)用其他的組件去處理請(qǐng)求,則返回false呕臂。
postHandle():這個(gè)方法在業(yè)務(wù)處理器處理完請(qǐng)求后淡喜,但是DispatcherServlet向客戶端返回響應(yīng)前被調(diào)用,在該方法中對(duì)用戶請(qǐng)求request()進(jìn)行處理诵闭。
afterCompletion():這個(gè)方法在DispatcherServlet完全處理完請(qǐng)求后被調(diào)用,可以在該方法中進(jìn)行一些資源清理的操作。
2.攔截器方法執(zhí)行順序
3.配置自定義攔截器
<mvc:interceptors>
<!-- 攔截所有資源 -->
<bean class="com.desperado.interceptors.FirstInterceptor"></bean>
<!--攔截指定資源-->
<mvc:interceptor>
<mvc:mapping path="/emps"/>
<bean class="com.desperado.interceptors.SecondInterceptor"></bean>
</mvc:interceptor>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
4.多個(gè)攔截器的執(zhí)行順序
5.攔截器preHandle()方法返回false時(shí)候的執(zhí)行順序
6.一道經(jīng)典面試題
攔截器和過濾器有什么區(qū)別:
- 攔截器是基于java的反射機(jī)制的疏尿,而過濾器是基于函數(shù)回調(diào)的瘟芝。
- 攔截器不依賴于Servlet容器,而過濾器依賴與Servlet容器褥琐。
- 攔截器只能對(duì)action請(qǐng)求起作用锌俱,而過濾器則可以對(duì)幾乎所有的請(qǐng)求其作用。
- 攔截器可以訪問action的上下文敌呈、值棧里面的對(duì)象贸宏,而過濾器不能訪問。
- 在action的聲明周期中磕洪,攔截器可以多次被調(diào)用吭练,而過濾器只能在容器初始化時(shí)被調(diào)用一次、(這里的調(diào)用一次析显,是對(duì)于構(gòu)造函數(shù)而言的鲫咽,而doFilter會(huì)對(duì)匹配的請(qǐng)求做持續(xù)的處理。)
- 攔截器可以獲取IOC容器中的Bean谷异,而過濾器不行分尸。
執(zhí)行順序
三.異常處理
1.異常處理
- Spring MVC通過HandlerExceptionResolver處理程序的異常把曼,包括Handler映射卡儒、數(shù)據(jù)綁定以及目標(biāo)方法執(zhí)行時(shí)發(fā)生的異常吧兔。
- SpringMVC提供的HandlerExceptionResolver的實(shí)現(xiàn)類
- AbstractHandlerExceptionResolver
- AbstractHandlerMethodExceptionResolver
- ExceptionHandlerExceptionResolver
- AnnotationMethodHandlerExceptionResolver
- DefaultHandlerExceptionResolver
- ResponseStatusExceptionResolver
- SimpleMappingExceptionResolver
- HandlerExceptionResolverComposite
2.HandlerExceptionResolver
- DispatcherServlet默認(rèn)裝配的HandlerExceptionResolver:
沒有使用<mvc:annotation-driver />
-AnnotationMethodHandlerExceptionResolver
-DefaultHandlerExceptionResolver
-ResponseStatusExceptionResolver使用了<mvc:annotation-driver />
-ExceptionHandlerExceptionResolver
-DefaultHandlerExceptionResolver
-ResponseStatusExceptionResolver
3.ExceptionHandlerExceptionResolver
- 主要處理Handler中用@ExceptionHandler注解定義的方法肴楷。
- @ExceptionHandler注解定義的優(yōu)先級(jí)問題:如果發(fā)生的是NullPointerException胧砰,但是聲明的異常有RuntimeException和Exception瞬沦,此時(shí)會(huì)根據(jù)異常的最近繼承關(guān)系找到繼承深度最淺的那個(gè)@ExceptionHandler注解方法臊泌,即標(biāo)記了RuntimException的方法猫妙。
- ExceptionHandlerMethodResolver內(nèi)部若找不到@ExceptionHandler注解的話尖昏,會(huì)找@ControllerAdvice中的@ExceptionHandler注解方法
4.ResponseStatusExceptionResolver
- 在異常及異常父類中找到@ResponseStatus注解仰税,然后使用這個(gè)注解的屬性進(jìn)行處理。
- 定義一個(gè)@ResponseStatus注解修飾的異常類抽诉。
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class UnAuthorizedException extends RuntimeException{}
- 若在處理器方法中拋出了上面定義的異常:
由于觸發(fā)的異常帶有@ResponseStatus注解陨簇,因此會(huì)被ResponseStatusExceptionResolver解析到。最后響應(yīng)HttpStatus.UNAUTHORIZED代碼給客戶端迹淌。
5.DefaultHandlerExceptionResolver
對(duì)一些特殊的異常進(jìn)行處理河绽,比如:
NoSuchRequestHandlingMethodException
HttpRequestMethodNotSupportedException
HttpMediaTypeNotSupportedException
HttpMediaTypeNotAcceptableException
等。
6.SimpleMappingExceptionResolver
如果希望對(duì)所有異常進(jìn)行統(tǒng)一處理唉窃,可以使用該解析器耙饰,它將異常類名映射為視圖名,即發(fā)生異常是使用對(duì)應(yīng)的視圖報(bào)告異常
四.Spring的運(yùn)行流程
- 請(qǐng)求到達(dá)Spring DispatcherServlet的url-pattern纹份。
- 判斷SpringMVC中是否存在對(duì)應(yīng)的映射
- 如果不存在判斷是否配置了<mvc:default-servlet-handler />
- 如果配置了就去找目標(biāo)資源苟跪,如果沒有配置廷痘,返回404頁(yè)面。
- 如果存在則從HandlerMapping獲取handlerExecutionChain對(duì)象件已。
- 獲取HandlerAdapter對(duì)象笋额。
- 調(diào)用攔截器的preHandle方法。
- 調(diào)用目標(biāo)Handler的目標(biāo)方法得到ModelAndView對(duì)象篷扩。
- 調(diào)用攔截器的postHandle方法兄猩。
- 判斷是否存在異常
- 存在異常,由HandlerExceptionResolver組件處理異常得到新的ModelAndView對(duì)象鉴未。
- 不存在異常枢冤,由ViewResolver組件根據(jù)ModelAndView對(duì)象得到實(shí)際的View
- 渲染視圖
- 調(diào)用攔截器的afterCompletion方法。
五.在Spring的環(huán)境下使用SpringMVC
1.Bean被創(chuàng)建兩次?
Spring的IOC容器不應(yīng)該掃描SpringMVC中的Bean铜秆,對(duì)應(yīng)的SpringMVC的IOC容器不應(yīng)該掃描Spring中的Bean淹真。
2.在SpringMVC配置文件中引用業(yè)務(wù)層的Bean
- 多個(gè)SpringIOC容器之間可以設(shè)置為父子關(guān)系,以實(shí)現(xiàn)良好的解耦羽峰。
- SpringMVC WEB層容器可作為"業(yè)務(wù)層"Spring容器的子容器趟咆,即WEB層容器可以引用業(yè)務(wù)層容器的Bean,而業(yè)務(wù)層容器卻訪問不到WEB層容器的Bean梅屉。
六值纱、Spring和Struts2對(duì)比
- SpringMVC的入口是Servlet,而Struts2是Filter.
- SpringMVC會(huì)比Struts2快點(diǎn)坯汤,SpringMVC是基于方法設(shè)計(jì)的虐唠,而Struts2是基于類,每次發(fā)一個(gè)請(qǐng)求都會(huì)實(shí)實(shí)例一個(gè)Action
- SpringMVC使用更加簡(jiǎn)潔惰聂,開發(fā)效率高疆偿。
- Struts2的OGNL表達(dá)式使頁(yè)面開發(fā)效率相比SpringMVC要高一點(diǎn)。