Struts2、Spring MVC4 框架下的ajax統一異常處理


本文算是struts2 異常處理3板斧spring mvc4:異常處理 后續篇章,普通頁面出錯后可以跳到統一的錯誤處理頁面,但是ajax就不行了,ajax的本意就是不讓當前頁面發生跳轉,僅局部刷新,從而改善用戶體驗,基本思路是:把異常轉換成json數據返回,這樣ajax的回調函數,就能解析出錯誤原因。

 

一、如何區分ajax請求與普通請求

打開firefox的調試工具觀察一下:

普通的頁面請求

jquery發起的ajax請求

對比一下,可以發現jquery發生的ajax請求,Request Headers里多出了x-requested-with,用它就可以判斷是否ajax請求。

 

二、struts2框架

a) 先定義一個ajax通用異常

 1 package com.cnblogs.yjmyzz.exception;
 2 
 3 public class AjaxException extends Exception {    
 4 
 5     private static final long serialVersionUID = -8503861588580421151L;
 6 
 7     public AjaxException(String message) {
 8         super(message);
 9     }
10 
11 }
View Code

b) 然后修改異常攔截器

 1 package com.cnblogs.yjmyzz.interceptor;
 2 import javax.servlet.http.HttpServletRequest;
 3 
 4 import org.apache.logging.log4j.*;
 5 import org.apache.struts2.ServletActionContext;
 6 import org.springframework.util.StringUtils;
 7 import com.cnblogs.yjmyzz.exception.AjaxException;
 8 import com.opensymphony.xwork2.*;
 9 import com.opensymphony.xwork2.interceptor.*;
10 
11 public class ExceptionInterceptor extends AbstractInterceptor {
12 
13     private static final long serialVersionUID = -6358803554282730952L;
14     Logger logger = LogManager.getLogger();
15 
16     @Override
17     public String intercept(ActionInvocation ai) throws Exception {
18         String result = null;
19         try {
20             result = ai.invoke();
21         } catch (Exception e) {
22             logger.error(ai.toString(), e);
23             ai.getStack().push(new ExceptionHolder(e));
24             result = "error";
25 
26             HttpServletRequest request = ServletActionContext.getRequest();
27             String xRequestedWith = request.getHeader("X-Requested-With");
28             if (!StringUtils.isEmpty(xRequestedWith)) {
29                 // ajax請求
30                 // 轉換成ajax異常,並放入stack中
31                 ai.getStack().push(
32                         new ExceptionHolder(new AjaxException(e.getMessage())));
33                 result = "ajax-error";
34             }
35         }
36         return result;
37     }
38 
39 }
View Code

c) 修改struts.xml文件

 1     <package name="base-default" extends="struts-default">
 2         <global-results>
 3             <result name="ajax-error">/WEB-INF/common/ajax-error.jsp</result>
 4             <result name="error">/WEB-INF/common/error.jsp</result>
 5         </global-results>
 6         <global-exception-mappings>
 7             <exception-mapping exception="com.cnblogs.yjmyzz.exception.AjaxException"
 8                 result="ajax-error" />
 9             <exception-mapping exception="java.lang.Exception"
10                 result="error" />
11         </global-exception-mappings>
12     </package>
View Code

即:返回ajax-error,異常類型為AjaxException,則交給/WEB-INF/common/ajax-error.jsp處理

d) ajax-error.jsp頁面

1 <%@ page contentType="application/json;charset=UTF-8" language="java"%><%@ taglib prefix="s" uri="/struts-tags"%>{"error":"<s:property value="exception" />"}
View Code

即:如果出錯,最終返回的是json串,類似:{"error":"com.cnblogs.yjmyzz.exception.AjaxException: / by zero"}

e) 然后調用ajax的地方

 1             $.ajax({
 2                 type:"GET",
 3                 url:"${pageContext.request.contextPath}/rest/orders/x",               
 4                 success: function(data, textStatus, jqXHR){
 5                     if (data.error!=undefined){
 6                         alert("錯誤:" + data.error);
 7                         return false;
 8                     }
 9                     //正常處理
10                     alert("ajax請求成功!");
11                 },
12                 error: function(jqXHR, textStatus, errorThrown){
13                     alert('error: ' + textStatus);
14                 }
15             });
View Code

如果服務端出異常,則ajax調用完成后,會彈出異常信息,否則按正常流程處理

 

三、Spring MVC4

a) 先修改Controller基類里的異常處理方法

 1     @ExceptionHandler
 2     public String exp(HttpServletRequest request, Exception ex) {
 3         String resultViewName = "errors/error";
 4 
 5         // 記錄日志
 6         logger.error(ex.getMessage(), ex);
 7 
 8         // 根據不同錯誤轉向不同頁面
 9         if (ex instanceof BusinessException) {
10             resultViewName = "errors/biz-error";
11         } else {
12             // 異常轉換
13             ex = new Exception("系統太累了,需要休息!");
14         }
15         request.setAttribute("ex", ex);
16 
17         String xRequestedWith = request.getHeader("X-Requested-With");
18         if (!StringUtils.isEmpty(xRequestedWith)) {
19             // ajax請求
20             resultViewName = "errors/ajax-error";
21 
22         }
23 
24         return resultViewName;
25     }
View Code

大致意思是,如果發現是ajax請求,則有異常,則交給"errors/ajax-error"視圖處理

b) ajax-error.jsp頁面

1 <%@ page contentType="application/json;charset=UTF-8" language="java"%><%Exception e = (Exception) request.getAttribute("ex");%>{"error":"<%=e.getClass().getSimpleName()%>","detail":"<%=e.getMessage()%>"}
View Code

c) 調用ajax的頁面

 1             $.ajax({
 2                 type:"GET",
 3                 url:"${pageContext.request.contextPath}/common-exception",               
 4                 success: function(d, textStatus, jqXHR){
 5                     if (d.error!=undefined){
 6                         alert("錯誤:" + d.detail);
 7                         return false;
 8                     }
 9                     //其它正常處理
10                     alert("ajax請求成功!");
11                 },
12                 error: function(jqXHR, textStatus, errorThrown){
13                     alert('error: ' + textStatus);
14                 }
15             });
View Code

如果服務端返回異常,ajax得到的反饋內容大概是:{"error":"Exception","detail":"系統太累了,需要休息!"}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM