一、異常分類
java異常分為"檢查"和"非檢查"兩類,"檢查"二字的意思是,代碼編譯時,編譯器會去Check一下有沒有進行異常處理(捕獲或向上拋),對于歸類為需要檢查的異常,若沒處理,編譯就過不去。
初學的時候,常常想為啥異常要這樣分類處理? 后來明白了些,異常不過兩種:主觀和客觀,一個大多數情況下可以避免,一個大多數情況下無法避免。
像NullPointerException這類異常,大多跟程序員素質掛鉤(開發好,測試好, 基本不會在系統運行后蹦出來), 基本是可以避免的,java語法當初把它們對類為‘非檢查異常',也算給程序員和編譯器省了不少事;
而像IOException這類跟外在環境有關的異常,幾乎是不可避免的(指不定哪一天那一秒網絡就掛了),但是當不期而遇時,程序還是要有所作為,所以編譯器有必要督促一下程序員,Check一下,看看是是否對這些可能不期而至的異常進行了處理。當Exception對象傳遞到某個節點后,程序就可以執行一些措施了,比如:給用戶返回一個提示("系統繁忙,請重試"),給監控平臺推送一個異常消息等等。
二、異常的統一返回處理
1、容器處理
下面列舉Tomcat的處理方式,在web.xml下配置,按http返回碼或Exception類型來處理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<error-page> <error-code> 404 </error-code> <location>/WEB-INF/views/error/ 404 .jsp</location> </error-page> <error-page> <error-code> 500 </error-code> <location>/WEB-INF/views/error/ 500 .jsp</location> </error-page> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/WEB-INF/views/error/throwable.jsp</location> </error-page> |
缺點:無法處理不需要返回html的請求,比如ajax;
2、框架處理
下面列舉Spring MVC的處理方式
(1)使用Spring MVC自帶的簡單異常處理器SimpleMappingExceptionResolver;
(2)實現接口HandlerExceptionResolver 自定義異常處理器; (建議使用,可支持ajax等擴展)
(3)使用@ExceptionHandler注解實現異常處理;
第(1)種,在spring-mvc.xml下配置
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- 將Controller拋出的異常轉到特定視圖 --> <bean class = "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" > <property name= "exceptionMappings" > <props> <!-- 不同異常分開跳轉--> <!-- 可以自定義不同的異常--> <prop key= "com.test.MyException1" >/error/e1</prop> <prop key= "com.test.MyException2" >/error/e2</prop> <!-- 如果不想自定義異常,只配置下面的即可--> <prop key= "java.lang.Throwable" >/error/ 500 </prop> </props> </property> </bean> |
缺點:無法處理不需要返回html的請求;
第(2)種,自定義HandlerExceptionResolver接口的實現類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
/** * 自定義異常處理器:支持ajax * @author wangxu * */ public class MyExceptionHandler implements HandlerExceptionResolver { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { /* 區分ajax */ boolean isAjax = request.getHeader( "X-Requested-With" ) != null && "XMLHttpRequest" .equals(request .getHeader( "X-Requested-With" ).toString()); if (!isAjax) { if (ex instanceof com.test.MyException1) { return new ModelAndView( "/error/e1" ); } else if (ex instanceof com.test.MyException1) { return new ModelAndView( "/error/e2" ); } else { return new ModelAndView( "/error/500" ); } } String jsonRes = "{\"message\":\"" + "系統異常" + "\"}" ; // 自定義結構和前臺對接 PrintWriter out = null ; try { out = response.getWriter(); request.setCharacterEncoding( "utf-8" ); response.setContentType( "text/plain;charset=utf-8" ); out.print(jsonRes); out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { out.close(); } return null ; } } |
并在spring-mvc.xml下注冊處理器
<bean id="exceptionHandler" class="com.test.MyExceptionHandler"/>
優點:可以處理ajax請求,也方便編碼實現功能擴展,比如異常的監控等。
第(3)種,@ExceptionHandler注解
1
2
3
4
5
6
7
8
9
10
11
12
|
@Controller public class TestExceptionHandlerController { @ExceptionHandler ({ MyException1. class }) public String exception(MyException1 e) { return "/error/e1" ; } @RequestMapping ( "/marry" ) public void test() { throw new MyException1( "沒錢!" ); } } |
缺點:@ExceptionHandler的方法,必須和可能拋異常的方法在一同個Controller下。(不建議使用)
3、結合
實際項目中,在處理異常的統一返回時,會將一些自定義的異?;蛘邤U展交給框架,將http返回碼的映射交給容器,因為http返回碼更外層,有些到不了框架,有些對于框架來說就不是一個異常(比如404之與Spring MVC)??蚣苁沁\行在容器里的,當框架優先拿到異常并做了返回處理,容器就不會再進行映射。
以上就是本文的全部內容,希望對大家的學習有所幫助。