Spring MVC全局異常後返回JSON異常數據

問題:

        當前項目是做爲手機APP後臺支持,使用spring mvc + mybaits + shiro進行開發。後臺服務與手機端交互是發送JSON數據。若是後臺發生異常,會直接返回異常頁面,顯示異常內容,若是是404請求不到資源或者500這類服務器的問題,可能會致使返回404和500異常頁面,手機端的處理就很是麻煩,爲了解決這個問題,就須要作全局的異常處理。html

解決方案:

(1)自定義或者使用spring自帶的各類異常處理器

       例如spring基於註解的異常解析器AnnotationHandlerMethodExceptionResolver 、spring自帶全局異常處理器SimpleMappingExceptionResolver、自定義實現spring的全局異常解析器HandlerExceptionResolver來處理。
java

       AnnotationHandlerMethodExceptionResolver目前我所知道的是須要在方法上定義異常的類型,若是異常類型多了,寫起代碼太麻煩,因此我認爲很差用。(那位大俠知道不用定義異常類型就處理全部異常,能夠留言告訴我,謝謝!)web

       spring自帶全局異常處理器SimpleMappingExceptionResolver也是比較繁瑣的,須要配置的地方太多了,不喜歡用。spring

       自定義實現spring的全局異常解析器HandlerExceptionResolver來處理我認爲是最方便的,固然,這個是針對我目前的業務場景而言,並非絕對的。json

        因爲Java的異常機制,若是發生大量異常,對jvm的性能會產生很大的影響,輕則性能降低10%,重則致使jvm內存溢出,我我的認爲能不拋異常就最好不拋,因此,我主要使用自定義實現spring的全局異常解析器HandlerExceptionResolver來處理業務問題。
spring-mvc

       

(2)自定義實現spring的全局異常解析器HandlerExceptionResolver

       2.1 只須要在spring-mvc的配置文件中定義一個全局異常處理類 服務器

 

[html]  view plain  copy
 
 print?
  1. <!-- 全局異常處理 -->  
  2. <bean id="exceptionHandler" class="com.aaa.bbb.exception.DefaultExceptionHandler" />  

      2.2  實現HandlerExceptionResolver(第一種實現方式)mvc

             這種方式須要下載溫少寫的fastjson,我用的是1.2.6版本,能夠百度後本身下載。app

 

[java]  view plain  copy
 
 print?
  1. public class DefaultExceptionHandler implements HandlerExceptionResolver {    
  2.     private static Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);  
  3.       
  4.     public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,  Exception ex) {    
  5.             ModelAndView mv = new ModelAndView();  
  6.             /*  使用FastJson提供的FastJsonJsonView視圖返回,不須要捕獲異常   */  
  7.             FastJsonJsonView view = new FastJsonJsonView();  
  8.             Map<String, Object> attributes = new HashMap<String, Object>();  
  9.             attributes.put("code", "1000001");  
  10.             attributes.put("msg", ex.getMessage());  
  11.             view.setAttributesMap(attributes);  
  12.             mv.setView(view);   
  13.             log.debug("異常:" + ex.getMessage(), ex);  
  14.             return mv;  
  15.     }  
  16. }   

       2.2  實現HandlerExceptionResolver(第二種實現方式)jvm

 

 

[java]  view plain  copy
 
 print?
  1. public class DefaultExceptionHandler implements HandlerExceptionResolver {    
  2.     private static Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);  
  3.       
  4.     public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,  Exception ex) {    
  5.             ModelAndView mv = new ModelAndView();             
  6.             /*  使用response返回    */  
  7.             response.setStatus(HttpStatus.OK.value()); //設置狀態碼  
  8.             response.setContentType(MediaType.APPLICATION_JSON_VALUE); //設置ContentType  
  9.             response.setCharacterEncoding("UTF-8"); //避免亂碼  
  10.             response.setHeader("Cache-Control", "no-cache, must-revalidate");  
  11.             try {  
  12.                 response.getWriter().write("{\"success\":false,\"msg\":\"" + ex.getMessage() + "\"}");  
  13.             } catch (IOException e) {  
  14.                log.error("與客戶端通信異常:"+ e.getMessage(), e);  
  15.             }  
  16.   
  17.             log.debug("異常:" + ex.getMessage(), ex);  
  18.             return mv;  
  19.     }  
  20. }  


到此,spring mvc全局異常處理返回json就搞定了,發生異常後,返回的都是json數據,不會再有煩人的異常內容。不過這還不算完整,須要在web.xml中加入異常代碼404或者500的處理才能算完。

 

(1)web頁面異常處理配置

 1.1  <exception-type>java.lang.Throwable</exception-type>表示發生java.lang.Throwable類型的異常,<location>/error_500</location>表示到/error_500地址處理,

    例如用戶請求【http://www.a.com/user/login/getUser】 ,應用名稱是user,若是請求發生java.lang.Throwable,那麼請求會轉到【http://www.a.com/user/error_500】

 

 1.2 <error-code>404</error-code>表示發生404請求失敗,<location>/error_404</location>表示到/error_404處理,

    例如用戶請求【http://www.a.com/user/login/getUser】,應用名稱是user ,若是用戶請求發生404異常,請求資源找不到,那麼請求會轉到【http://www.a.com/user/error_404】

 

[html]  view plain  copy
 
 print?
  1. <!-- web異常頁面處理 -->  
  2. <error-page>  
  3.     <exception-type>java.lang.Throwable</exception-type>  
  4.     <location>/error_500</location>  
  5. </error-page>  
  6. <error-page>  
  7.     <exception-type>java.lang.Exception</exception-type>  
  8.     <location>/error_404</location>  
  9. </error-page>  
  10. <error-page>  
  11.     <error-code>500</error-code>  
  12.     <location>/error_500</location>  
  13. </error-page>  
  14. <error-page>  
  15.     <error-code>501</error-code>  
  16.     <location>/error_500</location>  
  17. </error-page>  
  18. <error-page>  
  19.     <error-code>502</error-code>  
  20.     <location>/error_500</location>  
  21. </error-page>  
  22. <error-page>  
  23.     <error-code>404</error-code>  
  24.     <location>/error_404</location>  
  25. </error-page>  
  26. <error-page>  
  27.     <error-code>403</error-code>  
  28.     <location>/error_404</location>  
  29. </error-page>  
  30. <error-page>  
  31.     <error-code>400</error-code>  
  32.     <location>/error_404</location>  
  33. </error-page>  


(2)後臺處理

 

  若是發生以上異常,請求會轉到【http://www.a.com/user/error_404】,那麼在後臺就須要作相應的處理,處理方式就是在Controller層定義處理異常的方法

 

[java]  view plain  copy
 
 print?
  1. /** 
  2.  * 請求異常 
  3.  * @return 
  4.  * @throws Exception 
  5.  * String 
  6.  */  
  7. @RequestMapping(value = "/error_404", produces = "text/html;charset=UTF-8")  
  8. @ResponseBody  
  9. public String error_404() throws Exception {   
  10.      return "{\"msg\":\"找不到頁面\",\"code\":\"1000001\"}";  
  11. }  
  12. /** 
  13.  * 服務器異常 
  14.  * @return 
  15.  * String 
  16.  */  
  17. @RequestMapping(value ="/error_500", produces = "text/html;charset=UTF-8")  
  18. public String error_500() {     <pre name="code" class="java">                return "{\"msg\":\"服務器處理失敗\",\"code\":\"1000002\"}";  
  19. }  

 

 

最後,基本上全部的異常都能被捕獲,可以出現異常時,友好的提示用戶端,也能避免服務器端拋異常致使的問題。

相關文章
相關標籤/搜索