歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java 異常分類及統一處理

一、異常分類

Java異常分為”檢查”和”非檢查”兩類,”檢查”二字的意思是,代碼編譯時,編譯器會去Check一下有沒有進行異常處理(捕獲或向上拋),對於歸類為需要檢查的異常,若沒處理,編譯就過不去。

初學的時候,常常想為啥異常要這樣分類處理? 後來明白了些,異常不過兩種:主觀和客觀,一個大多數情況下可以避免,一個大多數情況下無法避免。

像NullPointerException這類異常,大多跟程序員素質掛鉤(開發好,測試好, 基本不會在系統運行後蹦出來), 基本是可以避免的,java語法當初把它們對類為‘非檢查異常’,也算給程序員和編譯器省了不少事。

而像IOException這類跟外在環境有關的異常,幾乎是不可避免的(指不定哪一天那一秒網絡就掛了),但是當不期而遇時,程序還是要有所作為,所以編譯器有必要督促一下程序員,Check一下,看看是是否對這些可能不期而至的異常進行了處理。當Exception對象傳遞到某個節點後,程序就可以執行一些措施了,比如:給用戶返回一個提示(”系統繁忙,請重試”),給監控平台推送一個異常消息等等。

二、異常的統一返回處理

1、容器處理

下面列舉Tomcat的處理方式,在web.xml下配置,按http返回碼或Exception類型來處理:

<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下配置

<!-- 將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接口的實現類

/**
 * 自定義異常處理器:支持ajax
 * @author tangqing
 *
 */
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注解

@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、結合

實際項目中,在處理異常的統一返回時,會將一些自定義的異常或者擴展交給框架,將http返回碼的映射交給容器,因為http返回碼更外層,有些到不了框架,有些對於框架來說就不是一個異常(比如404之與Spring MVC)。框架是運行在容器裡的,當框架優先拿到異常並做了返回處理,容器就不會再進行映射。

Copyright © Linux教程網 All Rights Reserved