1. 程式人生 > >springMVC整理04--文件上傳 & 攔截器 & 異常處理

springMVC整理04--文件上傳 & 攔截器 & 異常處理

1.2 cli 啟用 錯誤頁 ini val con 捕獲 錯誤頁面

1. 文件上傳

SpringMVC 的文件上傳非常簡便,首先導入文件上傳依賴的 jar:

1 <!-- 文件上傳所依賴的 jar 包 -->
2 <dependency>
3 <groupId>commons-fileupload</groupId>
4 <artifactId>commons-fileupload</artifactId>
5 <version>1.3.1</version>
6 </dependency>

在 springMVC-servlet.xml 配置文件中配置文件解析器:

1 <!--1*1024*1024 即 1M resolveLazily 屬性啟用是為了推遲文件解析,以便捕獲文件大小異常
2 -->
3 <!--文件上傳解析器-->
4 <bean id="multipartResolver"
5 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
6 <property name="maxUploadSize" value="1048576"/>
7 <property name="defaultEncoding"
value="UTF-8"/> 8 <property name="resolveLazily" value="true"/> 9 </bean>

註意解析器的 id 必須等於 multipartResolver,否則上傳會出現異常:

1.1 單個文件上傳

 1 @Controller
 2 public class FileController {
 3 /**
 4 * 上傳單個文件操作
 5 * MultipartFile file 就是上傳的文件
 6 * @return
 7 */
 8 @RequestMapping(value = "/upload1.html")
9 public String fileUpload1(@RequestParam("file") MultipartFile file) { 10 try { 11 //將上傳的文件存在 E:/upload/下 12 FileUtils.copyInputStreamToFile(file.getInputStream(), 13 new File("E:/upload/", 14 file.getOriginalFilename())); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 } 18 //上傳成功返回原來頁面 19 return "/file.jsp"; 20 } 21 }上傳文件時,Controller 的方法中參數類型是 MultipartFile 即可將文件映射到參數上。

頁面file.jsp:

1 <form method="post" action="/upload1.html" enctype="multipart/form-data">
2 <input type="file" name="file"/>
3 <button type="submit" >提交</button>
4 </form>

另外上傳的文件還可以映射成 CommonsMultipartFile,它是 MultipartFile 的子類:

 1 /**
 2 * CommonsMultipartFile 是 MultipartFile 的子類
 3 * @return
 4 */
 5 @RequestMapping("/upload2.html")
 6 public String fileUpload2(@RequestParam("file") CommonsMultipartFile file) {
 7 try {
 8 System. out .println("fileName:" + file.getOriginalFilename());
 9 String path = "E:/upload/" + file.getOriginalFilename();
10 File newFile = new File(path);
11 //通過 CommonsMultipartFile 的方法直接寫文件
12 file.transferTo(newFile);
13 } catch (Exception e) {
14 e.printStackTrace();
15 }
16 return "/file.jsp";
17 }

頁面:

1 <form method="post" action="/upload2.html" enctype="multipart/form-data">
2 <input type="file" name="file"/>
3 <button type="submit" >提交</button>
4 </form>

1.2 批量上傳

 1 /**
 2 * 批量上傳的時候參數是數組
 3 * @return
 4 */
 5 @RequestMapping("/upload3.html")
 6 public String fileUpload3(@RequestParam("file") CommonsMultipartFile[] file) {
 7 try {
 8 //批量上傳時遍歷文件數組
 9 for (CommonsMultipartFile f : file) {
10 System. out .println("fileName:" + f.getOriginalFilename());
11 String path = "E:/upload/" + f.getOriginalFilename();
12 File newFile = new File(path);
13 f.transferTo(newFile);
14 }
15 } catch (Exception e) {
16 e.printStackTrace();
17 }
18 return "/file.jsp";
19 }

頁面:

1 <form method="post" action="/upload3.html" enctype="multipart/form-data">
2 <!--註意 name 都是 file,與 Controller 中方法的參數名對應-->
3 <input type="file" name="file"/>
4 <input type="file" name="file"/>
5 <input type="file" name="file"/>
6 <button type="submit" >提交</button>
7 </form>

2. 使用攔截器

模擬登陸攔截器:

 1 public class  LoginInterceptor  extends HandlerInterceptorAdapter { {
 2 @Override
 3 public bo olean preHandle(HttpServletRequest  request, HttpServletResponse  response,
 4 Object  handler)  throws  Exception { {
 5 System. out .println(" " 開始攔截" ");
 6 //  其他情況判斷 n session  中是否有  key ,有的話繼續用戶的操作
 7 if ( request. getSession(). getAttribute( "user")  !=  null) { {
 8 return true;
 9 } }
10 //  最後的情況就是進入登錄頁面
11 response. sendRedirect( request. getContextPath()  +  "/login.jsp");
12 return false;
13 } }
14 @Override
15 public void postHandle(HttpServletRequest  request, HttpServletResponse  response,
16 Object  handler,  ModelAndView  modelAndView)  throws  Exception { {
17 System. out .println(" " 視圖解析前  postHandle");
18 } }
19 @Override
20 public void afterConcurrentHandlingStarted(HttpServletRequest  request,
21 HttpServletResponse  response,  Object  handler)  throws  Exception { {
22 System. out .println(" " 處理異步請求" ");
23 } }
24 } }

配置攔截器:

1 <mvc:interceptors>
2 <mvc:interceptor><!--配置局部攔截器,需要滿足下列路徑條件-->
3 <mvc:mapping path="/**"/>
4 <mvc:exclude-mapping path="/login.html" />
5 <bean class="interceptor.LoginInterceptor"/><!--自定義攔截器註冊-->
6 </mvc:interceptor>
7 </mvc:interceptors>

登陸的 Controller

1 @Controller
2 public class  LoginController { {
3 @RequestMapping( "login.html")
4 public  String login( String  username, HttpServletRequest  request){ {
5 // 模擬登陸
6 request. getSession(). setAttribute( "user", username);
7 return  "redirect:index.html";
8 } }
9 } }

登陸頁面:

1 <form action="/login.html">
2 <input name="username"/><input type="submit">
3 </form>

3. 異常處理

3.1 集成異常處理

對 於 一 些 通用 的 ,不 需 要特 殊 處 理的 異 常,可 以 使 用統 一 的 異常 處 理器 , 在springMVC-servlet.xml 中加入配置:

 1 <!--集成異常處理-->
 2 <bean
 3 class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
 4 <!-- 定義默認的異常處理頁面-->
 5 <property name="defaultErrorView" value="error.jsp"></property>
 6 <!-- 定義異常處理頁面用來獲取異常信息的變量名,默認名為 exception -->
 7 <property name="exceptionAttribute" value="ex"></property>
 8 <!-- 定義需要特殊處理的異常,用類名或完全路徑名作為 key,異常也頁名作為值 -->
 9 <property name="exceptionMappings">
10 <props>
11 <prop key="java.lang.NullPointerException">error.jsp</prop>
12 <prop key="java.lang.ClassCastException">error.jsp</prop>
13 <prop key="java.lang.IndexOutOfBoundsException">error.jsp</prop>
14 <!-- 這裏還可以繼續擴展對不同異常類型的處理 -->
15 </props>
16 </property>
17 </bean>

我們寫一個 controller 專門拋出異常,用來模擬程序中可能出現的異常信息:

 1 @Controller
 2 public class ExceptionController {
 3 @RequestMapping("/ex.html")
 4 public String exceptionTest(Integer type) throws Exception {
 5 //手動拋出幾個異常,模擬程序中可能出現的異常
 6 switch (type) {
 7 case 1:
 8 throw new NullPointerException("測試空指針異常");
 9 case 2:
10 throw new ClassCastException("測試類型轉換異常");
11 case 3:
12 throw new IndexOutOfBoundsException("測試越界異常");
13 }
14 return "index.jsp";
15 }
16 }

測試頁面:

1 <body>
2 <a href="/ex.html?type=1">空指針</a><br/>
3 <a href="/ex.html?type=2">類型轉換</a><br/>
4 <a href="/ex.html?type=3">越界</a><br/>
5 ${ex}<!--就是 spring 異常處理器中配置的 exceptionAttribute-->
6 </body>

運行結果:

技術分享圖片

點擊不同的鏈接可以看大不同的提示信息。

3.2 自定義異常處理

對於需要特殊處理的異常,可以自定義異常處理器自定義異常處理的類需要繼承 HandlerExceptionResolver

1 public class  MyExceptionHandler  implements HandlerExceptionResolver { {
2 @Override
3 public  ModelAndView resolveException(HttpServletRequest  httpServletRequest,
4 HttpServletResponse  httpServletResponse,  Object o o,  Exception e e) { {
5 String  msg  = e e.getMessage();
6 httpServletRequest. setAttribute( "ex",  msg);
7 return new ModelAndView( "/error.jsp");
8 } }
9 } }

在 spring 配置文件中定義 bean:

1 <!--自定義異常處理-->
2 <bean id="exceptionHandler" class="exception.MyExceptionHandler"/>

註:自定義異常處理和前面的集成異常處理不能一起使用,需要將 前面例子的 bean 註釋掉。如果需要處理 ajax 發送的請求,出現異常時返回 json 數據,可以增加處理 json 的代碼。
修改 MyExceptionHandler 中的代碼:

 1 public class MyExceptionHandler implements HandlerExceptionResolver {
 2 @Override
 3 public ModelAndView resolveException(HttpServletRequest httpServletRequest,
 4 HttpServletResponse httpServletResponse, Object o, Exception e) {
 5 String msg = e.getMessage();
 6 if (httpServletResponse.isCommitted()) {
 7 return null;
 8 }
 9 //如果是 ajax 請求就返回 json 數據
10 if (isAjax(httpServletRequest)) {
11 Map<String, String> result = new HashMap<>();
12 result.put("ex", msg);
13 MappingJackson2JsonView view = new MappingJackson2JsonView();
14 return new ModelAndView(view, "result", result);
15 } else {//不是 ajax 就返回錯誤頁面
16 httpServletRequest.setAttribute("ex", msg);
17 return new ModelAndView("/error.jsp");
18 }
19 }
20 public static boolean isAjax(HttpServletRequest request) {
21 return
22 "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With")) ||
23 request.getParameter("ajax") != null;
24 }
25 }

測試頁面:

 1 <script type="text/javascript" src="jquery-1.10.1.min.js"></script>
 2 <input type="button" onclick=" testEx ()" value="測試自定義異常"/>
 3 <script type="text/javascript">
 4 function  testEx (){
 5 $.ajax({
 6 type: "POST",
 7 url: "/ex.html?type=1",
 8 success: function(data){
 9 alert(data.result.ex);//讀取 json 數據
10 }
11 });
12 }
13 </script>

測試結果:

技術分享圖片

springMVC整理04--文件上傳 & 攔截器 & 異常處理