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
{
// 攔截客戶端發出的請求
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
System.out.println("第一個攔截器的preHandle()方法...");
return true;// 將請求放行
}
// 用於攔截服務器發出的響應
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception
{
System.out.println("第一個攔截器的postHandle()方法...");
}
// 視圖渲染完畢之后被調用
@Override
public 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-mapping
path="/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
以外的所有請求。
本例中只涉及到了一個攔截器,如果配置了多個攔截器,則多個攔截器攔截請求/響應的順序與使用多個過濾器攔截請求/響應的順序是完全相同的,讀者可以參見“過濾器與監聽器”一節。