SpringMVC提供了一個MultipartResolver接口用來實現文件上傳,並使用Commons FileUpload技術實現了一個該接口的實現類CommonsMultipartResolver。如果要在SpringMVC中實現文件上傳功能,就可以在springmvc.xml中配置MultipartResolver接口的實現類。
以下是使用SpringMVC實現文件上傳的具體步驟:
①導入JAR包:
使用SpringMVC實現文件上傳,需要額外導入以下2個JAR包:
| commons-fileupload-1.2.1.jar | commons-io-2.0.jar |
②在SpringMVC配置文件中,配置MultipartResolver接口的實現類
springmvc.xml
…<bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="defaultEncoding" value="UTF-8"></property><property name="maxUploadSize" value="1024000"></property></bean>
需要注意,這個bean的id值必須是multipartResolver。DispatcherServlet在Web服務啟動時,會自動查找id=”multipartResolver”的Bean,並對其進行解析。如果id值不是multipartResolver, DispatcherServlet就會忽略對此Bean的解析,也就無法加入SpringMVC對文件上傳的支持。
CommonsMultipartResolver中屬性的介紹如下:
| 屬性 | 簡介 |
| defaultEncoding | 指定解析request請求的編碼格式。 |
| uploadTempDir | 指定上傳文件時的臨時目錄,默認是Servlet容器的臨時目錄。文件上傳完畢時,臨時目錄中的臨時文件會被自動清除。 |
| maxUploadSize | 設置上傳文件的最大值,單位是字節。默認是-1,表示無限制。 |
| maxInMemorySize | 設置在文件上傳時,允許寫到內存中的最大值,單位是字節,默認是10240字節。 |
③編寫請求處理方法,實現文件上傳
請求處理類:SecondSpringDemo.java
@Controller@RequestMapping(value = "/SecondSpringDemo")public class SecondSpringDemo{@RequestMapping("/testFileUpload")public String testFileUpload(@RequestParam("desc") String desc, @RequestParam("file") MultipartFile file)throws IOException{String fileName = file.getOriginalFilename();System.out.println("desc: " + desc);System.out.println("OriginalFilename: " + fileName);System.out.println("InputStream: "+ file.getInputStream());InputStream input = file.getInputStream();System.out.println("D:"+File.separator+fileName);OutputStream out= new FileOutputStream("D:"+File.separator+fileName);byte[] b = new byte[1024];while ((input.read(b)) != -1){out.write(b);}input.close();out.close();return "success";}}
通過參數@RequestParam("file") MultipartFile file獲取到前端傳來的File對象,並通過file.getInputStream()得到File對象的輸入流,之后再通過輸出流將文件寫入到D盤,即實現文件上傳功能。
④測試
index.jsp
<form action="SecondSpringDemo/testFileUpload"method="POST" enctype="multipart/form-data">文件: <input type="file" name="file"/>描述: <input type="text" name="desc"/><input type="submit" value="Submit"/></form>
在JSP頁面中使用文件上傳時,除了文件的字段要使用type="file"外,還需要注意設置表單的提交方式以及編碼類型,即method="POST" enctype="multipart/form-data"。
32.2 攔截器
32.2.1 攔截器簡介
攔截器的實現原理和過濾器相似,都可以對用戶發出的請求或者對服務器做出的響應進行攔截。SpringMVC也提供了一個用於支持攔截器的HandlerInterceptor接口,此接口的實現類就是一個攔截器。
HandlerInterceptor接口包含了以下方法:
| 方法 | 簡介 |
| boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception | 用於攔截客戶端發出的請求。此方法會在request請求到達服務器之前被調用,如果攔截處理后,需要將請求放行,則返回true;如果攔截處理后,需要結束請求(即讓請求不再向服務器傳遞),則返回false。 |
| void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception | 用於攔截服務器發出的響應。此方法會在請求處理方法執行處理完request請求之后、服務器發出的response響應到達DispatcherServlet的渲染方法之前被調用,參見下圖。 |
| void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception | 此方法會在DispatcherServlet將response響應的視圖渲染完畢之后被調用,參見下圖。 |
攔截器的執行流程如下:

圖32-01
32.2.2 攔截器使用步驟
以下是在SpringMVC中創建並使用攔截器的具體步驟:
①創建自定義攔截器
創建一個類,並實現HandlerInterceptor接口,如下:
FirstInterceptor.java
//import…public class FirstInterceptor implements HandlerInterceptor{// 攔截客戶端發出的請求@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{System.out.println("第一個攔截器的preHandle()方法...");return true;// 將請求放行}// 用於攔截服務器發出的響應@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception{System.out.println("第一個攔截器的postHandle()方法...");}// 視圖渲染完畢之后被調用@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception{System.out.println("第一個攔截器的afterCompletion()方法...");}}
②配置攔截器
將寫好的攔截器配置到SpringMVC配置文件之中:
springmvc.xml
…<mvc:interceptors><!-- 配置自定義的攔截器 --><bean class="org.lanqiao.interceptor.FirstInterceptor"></bean></mvc:interceptors>
③測試
默認的攔截器會攔截所有向服務器發送的請求,如下:
請求處理類:SecondSpringDemo.java
…@Controller@RequestMapping(value = "/SecondSpringDemo")public class SecondSpringDemo{…@RequestMapping("/testInterceptor")public String testInterceptor(){System.out.println("請求處理方法...");return "success";}}
index.jsp
<a href="SecondSpringDemo/testInterceptor">testInterceptor</a>
執行index.jsp中的超鏈接,控制台的運行結果:

圖32-02
32.2.3 攔截器的攔截配置
以上方法實現的攔截器會攔截所有請求,此外我們還可以通過配置,使得攔截器只攔截或不攔截某些特定請求。為此,只需要將SpringMVC中對攔截器的配置修改如下:
springmvc.xml
…<mvc:interceptors><mvc:interceptor><!-- 攔截的請求路徑 --><mvc:mapping path="/**"/><!-- 不攔截的請求路徑 --><mvc:exclude-mappingpath="/SecondSpringDemo/testFileUpload"/><bean lass=" org.lanqiao.interceptor.FirstInterceptor "></bean></mvc:interceptor></mvc:interceptors>
<mvc:interceptor>子元素的簡介如下:
| 元素 | 簡介 |
| <mvc:mapping path=""/> | 配置會被攔截器攔截的請求路徑。 |
| <mvc:exclude-mapping path=""/> | 配置不會被攔截器攔截的請求路徑。 |
最終攔截的請求路徑是mapping與exclude-mapping的交集。例如,上述springmvc.xml中配置的FirstInterceptor攔截器:會攔截除了請求路徑是/SecondSpringDemo/testFileUpload以外的所有請求。
本例中只涉及到了一個攔截器,如果配置了多個攔截器,則多個攔截器攔截請求/響應的順序與使用多個過濾器攔截請求/響應的順序是完全相同的,讀者可以參見“過濾器與監聽器”一節。
