文件上傳
Spring MVC 為文件上傳提供了直接的支持,這種支持是通過即插即用的 MultipartResolver 實現的。Spring 用 Jakarta Commons FileUpload 技術實現了一個MultipartResolver 實現類:CommonsMultipartResovler
Spring MVC 上下文中默認沒有裝配 MultipartResovler,因此默認情況下不能處理文件的上傳工作,如果想使用 Spring 的文件上傳功能,需現在上下文中配置 MultipartResolver
defaultEncoding: 必須和用戶 JSP 的 pageEncoding 屬性一致,以便正確解析表單的內容
為了讓 CommonsMultipartResovler 正確工作,必須先將 Jakarta Commons FileUpload 及 Jakarta Commons io的類包添加到類路徑下。
<!-- 配置 MultipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="1024000"></property> </bean>
例子:
<form action="testFileUpload" method="POST" enctype="multipart/form-data"> File: <input type="file" name="file"/> Desc: <input type="text" name="desc"/> <input type="submit" value="Submit"/> </form> @RequestMapping("/testFileUpload") public String testFileUpload(@RequestParam("desc") String desc, @RequestParam("file") MultipartFile file) throws IOException{ System.out.println("desc: " + desc); System.out.println("OriginalFilename: " + file.getOriginalFilename()); System.out.println("InputStream: " + file.getInputStream()); return "success"; }
使用攔截器
自定義攔截器
Spring MVC 也可以使用攔截器對請求進行攔截處理,用戶可以自定義攔截器來實現特定的功能,自定義的攔截器必須實現HandlerInterceptor接口
preHandle():這個方法在業務處理器處理請求之前被調用,在該方法中對用戶請求 request 進行處理。如果程序員決定該攔截器對請求進行攔截處理后還要調用其他的攔截器,或者是業務處理器去進行處理,則返回true;如果程序員決定不需要再調用其他的組件去處理請求,則返回false。可以考慮做權限. 日志, 事務等.
postHandle():這個方法在業務處理器處理完請求后,但是DispatcherServlet 向客戶端返回響應前被調用,在該方法中對用戶請求request進行處理。可以對請求域中的屬性或視圖做出修改.
afterCompletion():這個方法在 DispatcherServlet 完全處理完請求后被調用,可以在該方法中進行一些資源清理的操作。
配置自定義攔截器
<mvc:interceptors> <!-- 配置自定義的攔截器 --> <bean class="com.atguigu.springmvc.interceptors.FirstInterceptor"></bean> <!-- 配置攔截器(不)作用的路徑 --> <mvc:interceptor> <mvc:mapping path="/emps"/> <bean class="com.atguigu.springmvc.interceptors.SecondInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
攔截器方法執行順序
preHandle() 按順序執行, postHandle(), afterCompletion() 按反敘事執行。
異常處理
Spring MVC 通過 HandlerExceptionResolver 處理程序的異常,包括 Handler 映射、數據綁定以及目標方法執行時發生的異常。
SpringMVC 提供的 HandlerExceptionResolver 的實現類
HandlerExceptionResolver
DispatcherServlet 默認裝配的 HandlerExceptionResolver:
使用了 <mvc:annotation-driven/> 配置 :
ExceptionHandlerExceptionResolver
/** * 1. 在 @ExceptionHandler 方法的入參中可以加入 Exception 類型的參數, 該參數即對應發生的異常對象 * 2. @ExceptionHandler 方法的入參中不能傳入 Map. 若希望把異常信息傳導頁面上, 需要使用 ModelAndView 作為返回值 * 3. @ExceptionHandler 方法標記的異常有優先級的問題. * 4. @ControllerAdvice: 如果在當前 Handler 中找不到 @ExceptionHandler 方法來出來當前方法出現的異常, * 則將去 @ControllerAdvice 標記的類中查找 @ExceptionHandler 標記的方法來處理異常. */ @ExceptionHandler({ArithmeticException.class}) public ModelAndView handleArithmeticException(Exception ex){ System.out.println("出異常了: " + ex); ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex); return mv; }
ResponseStatusExceptionResolver
@ResponseStatus(reason="測試",value=HttpStatus.NOT_FOUND) @RequestMapping("/testResponseStatusExceptionResolver") public String testResponseStatusExceptionResolver(@RequestParam("i") int i){ if(i == 13){ throw new UserNameNotMatchPasswordException(); } System.out.println("testResponseStatusExceptionResolver..."); return "success"; }
DefaultHandlerExceptionResolver
對一些特殊的異常進行處理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST) public String testDefaultHandlerExceptionResolver(){ System.out.println("testDefaultHandlerExceptionResolver..."); return "success"; }
SimpleMappingExceptionResolver
如果希望對所有異常進行統一處理,可以使用 SimpleMappingExceptionResolver,它將異常類名映射為視圖名,即發生異常時使用對應的視圖報告異常
<!-- 配置使用 SimpleMappingExceptionResolver 來映射異常 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionAttribute" value="ex"></property> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean>
在 Spring 的環境下使用 SpringMVC
需要進行 Spring 整合 SpringMVC 嗎 ?
需要: 通常情況下, 類似於數據源, 事務, 整合其他框架都是放在 Spring 的配置文件中(而不是放在 SpringMVC 的配置文件中).
實際上放入 Spring 配置文件對應的 IOC 容器中的還有 Service 和 Dao.
問題: 若 Spring 的 IOC 容器和 SpringMVC 的 IOC 容器掃描的包有重合的部分, 就會導致有的 bean 會被創建 2 次.
解決:
1. 使 Spring 的 IOC 容器掃描的包和 SpringMVC 的 IOC 容器掃描的包沒有重合的部分.
2. 使用 exclude-filter 和 include-filter 子節點來規定只能掃描的注解
<context:component-scan base-package="com.atguigu.springmvc" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>
<context:component-scan base-package="com.atguigu.springmvc"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>
SpringMVC 的 IOC 容器中的 bean 可以來引用 Spring IOC 容器中的 bean.
反之則不行. Spring IOC 容器中的 bean 卻不能來引用 SpringMVC IOC 容器中的 bean!
SpringMVC 對比 Struts2
①. Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
②. Spring MVC 會稍微比 Struts2 快些. Spring MVC 是基於方法設計, 而 Sturts2 是基於類, 每次發一次請求都會實例一個 Action.
③. Spring MVC 使用更加簡潔, 開發效率Spring MVC確實 比 struts2 高: 支持 JSR303, 處理 ajax 的請求更方便
④. Struts2 的 • OGNL 表達式使頁面的開發效率相比Spring MVC 更高些.