SpringMVC實現文件上傳與下載、攔截器、異常處理器等功能
文件下載
使用ResponseEntity實現下載文件的功能
index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http:www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>首頁</title> </head> <body> <a th:href="@{/testDown}" rel="external nofollow" >點擊下載</a> </body> </html>
控制器
@RequestMapping("/testDown") public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException { //獲取ServletContext對象 ServletContext servletContext = session.getServletContext(); //獲取服務器中文件的真實路徑 String realPath = servletContext.getRealPath("/static/img/1.jpg"); //創建輸入流 InputStream is = new FileInputStream(realPath); //創建字節數組 byte[] bytes = new byte[is.available()]; //將流讀到字節數組中 is.read(bytes); //創建HttpHeaders對象設置響應頭信息 MultiValueMap<String, String> headers = new HttpHeaders(); //設置要下載方式以及下載文件的名字 headers.add("Content-Disposition", "attachment;filename=1.jpg"); //設置響應狀態碼 HttpStatus statusCode = HttpStatus.OK; //創建ResponseEntity對象 ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode); //關閉輸入流 is.close(); return responseEntity; }
註意:如果報500錯誤,可能是項目中無法找到靜態資源文件,需要對項目重新打包。
文件上傳
文件上傳要求form表單的請求方式必須為post,並且添加屬性enctype=”multipart/form-data”以二進制方式上傳
SpringMVC中將上傳的文件封裝到MultipartFile對象中,通過此對象可以獲取文件相關信息
上傳步驟:
添加依賴
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
在SpringMVC的配置文件springMVC.xml中添加配置
<!--必須通過文件解析器的解析才能將文件轉換為MultipartFile對象--> <!--必須設置id屬性,springMVC是根據id獲取,且id必須設置為multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
index.html
<form method="post" th:action="@{/testUp}" enctype="multipart/form-data"> <input type="file" name="photo"> <input type="submit" value="上傳"> </form>
控制器
@RequestMapping("/testUp") //MultipartFile的形參名必須與index.html中的file標簽的name一致 public String testUp(MultipartFile photo, HttpSession session) throws IOException { //獲取上傳的文件的文件名 String fileName = photo.getOriginalFilename(); //處理文件重名問題 String hzName = fileName.substring(fileName.lastIndexOf(".")); fileName = UUID.randomUUID().toString() + hzName; //獲取服務器中photo目錄的路徑 ServletContext servletContext = session.getServletContext(); String photoPath = servletContext.getRealPath("photo"); File file = new File(photoPath); if(!file.exists()){ file.mkdir(); } String finalPath = photoPath + File.separator + fileName; //實現上傳功能 photo.transferTo(new File(finalPath)); return "success"; }
攔截器
攔截器的配置
SpringMVC中的攔截器用於攔截控制器方法的執行
SpringMVC中的攔截器需要實現HandlerInterceptor接口
HandlerInterceptor源碼
public interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }
HandlerInterceptor接口有三個默認方法
- preHandle:控制器方法執行之前執行preHandle(),其boolean類型的返回值表示是否攔截或放行,返回true為放行,即調用控制器方法;返回false表示攔截,即不調用控制器方法
- postHandle:控制器方法執行之後執行postHandle()
- afterCompletion:處理完視圖和模型數據,渲染視圖完畢之後執行afterCompletion()
控制器
FirstInterceptor.java
public class FirstInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor-->preHandle"); return false; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor-->postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor-->afterCompletion"); } }
SpringMVC的攔截器必須在SpringMVC的配置文件中進行配置:
方式一
<mvc:interceptors> <bean class="com.gonghr.springmvc.interceptors.FirstInterceptor"></bean> </mvc:interceptors>
輸出:
FirstInterceptor–>preHandle
方式二
<mvc:interceptors> <ref bean="firstInterceptor"></ref> </mvc:interceptors>
註意提前開啟註解掃描,並把攔截器放入Ioc容器
輸出:
FirstInterceptor–>preHandle
註意:以上兩種配置方式都是對DispatcherServlet所處理的所有的請求進行攔截。
方式三
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <!--攔截所有請求--> <mvc:exclude-mapping path="/"/> <!--不攔截主頁--> <ref bean="firstInterceptor"></ref> </mvc:interceptor> </mvc:interceptors>
可以進入首頁
發送任意請求都會被攔截
輸出:
FirstInterceptor–>preHandle
以上配置方式可以通過ref或bean標簽設置攔截器,通過mvc:mapping設置需要攔截的請求,通過mvc:exclude-mapping設置需要排除的請求,即不需要攔截的請求
/**:攔截所有請求
/*:攔截一級目錄的請求
多個攔截器的執行順序
第一個攔截器
@Component public class FirstInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor-->preHandle"); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor-->postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor-->afterCompletion"); } }
第二個攔截器
@Component public class SecondInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("SecondInterceptor-->preHandle"); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("SecondInterceptor-->postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("SecondInterceptor-->afterCompletion"); } }
兩個攔截器都設置為對任意請求放行。
輸出:
FirstInterceptor–>preHandle
SecondInterceptor–>preHandle
SecondInterceptor–>postHandle
FirstInterceptor–>postHandle
SecondInterceptor–>afterCompletion
FirstInterceptor–>afterCompletion
- 若每個攔截器的preHandle()都返回true
此時多個攔截器的執行順序和攔截器在SpringMVC的配置文件的配置順序有關:
preHandle()會按照配置的順序執行,而postHandle()和afterCompletion()會按照配置的反序執行
如果設置第一個攔截器對所有請求放行,第二個攔截器對所有請求攔截。
第一個攔截器
@Component public class FirstInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor-->preHandle"); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor-->postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor-->afterCompletion"); } }
第二個攔截器
@Component public class SecondInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("SecondInterceptor-->preHandle"); return false; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("SecondInterceptor-->postHandle"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("SecondInterceptor-->afterCompletion"); } }
輸出:
FirstInterceptor–>preHandle
SecondInterceptor–>preHandle
FirstInterceptor–>afterCompletion
- 若某個攔截器的preHandle()返回瞭false
preHandle()返回false和它之前的攔截器的preHandle()都會執行,postHandle()都不執行,返回false的攔截器之前的攔截器的afterCompletion()會執行
異常處理器
基於配置的異常處理
SpringMVC提供瞭一個處理控制器方法執行過程中所出現的異常的接口:HandlerExceptionResolver
HandlerExceptionResolver接口的實現類有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver
SpringMVC提供瞭自定義的異常處理器SimpleMappingExceptionResolver,使用方式:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- properties的鍵表示處理器方法執行過程中出現的異常 properties的值表示若出現指定異常時,設置一個新的視圖名稱,跳轉到指定頁面 --> <prop key="java.lang.ArithmeticException">error</prop> </props> </property> <!-- exceptionAttribute屬性設置一個屬性名,將出現的異常信息在請求域中進行共享 --> <property name="exceptionAttribute" value="ex"></property> </bean>
error.html
出現錯誤 <p th:text="${ex}"></p>
index.html
<a th:href="@{/testException}">測試異常處理</a>
基於註解的異常處理
//@ControllerAdvice將當前類標識為異常處理的組件 @ControllerAdvice public class ExceptionController { //@ExceptionHandler用於設置所標識方法處理的異常 @ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class}) //ex表示當前請求處理中出現的異常對象 public String handleArithmeticException(Exception ex, Model model){ model.addAttribute("ex", ex); return "error"; } }
總結
到此這篇關於SpringMVC實現文件上傳與下載、攔截器、異常處理器等功能的文章就介紹到這瞭,更多相關SpringMVC文件上傳與下載、攔截器、異常處理器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- SpringMVC攔截器創建配置及執行順序
- 詳解SpringMVC的攔截器鏈實現及攔截器鏈配置
- 詳解Spring MVC的攔截器與異常處理機制
- springboot過濾器和攔截器的實例代碼
- 詳解SpringMVC HandlerInterceptor攔截器的使用與參數