Spring MVC全局异常后返回JSON异常数据

Posted 再见理想

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring MVC全局异常后返回JSON异常数据相关的知识,希望对你有一定的参考价值。

问题:

        当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发。后台服务与手机端交互是发送JSON数据。如果后台发生异常,会直接返回异常页面,显示异常内容,如果是404请求不到资源或者500这类服务器的问题,可能会导致返回404和500异常页面,手机端的处理就非常麻烦,为了解决这个问题,就需要做全局的异常处理。

解决方案:

(1)自定义或者使用spring自带的各种异常处理器

       例如spring基于注解的异常解析器AnnotationHandlerMethodExceptionResolver 、spring自带全局异常处理器SimpleMappingExceptionResolver、自定义实现spring的全局异常解析器HandlerExceptionResolver来处理。

       AnnotationHandlerMethodExceptionResolver目前我所知道的是需要在方法上定义异常的类型,如果异常类型多了,写起代码太麻烦,所以我认为不好用。(那位大侠知道不用定义异常类型就处理所有异常,可以留言告诉我,谢谢!)

       spring自带全局异常处理器SimpleMappingExceptionResolver也是比较繁琐的,需要配置的地方太多了,不喜欢用。

       自定义实现spring的全局异常解析器HandlerExceptionResolver来处理我认为是最方便的,当然,这个是针对我目前的业务场景而言,并不是绝对的。

        由于Java的异常机制,如果发生大量异常,对jvm的性能会产生很大的影响,轻则性能下降10%,重则导致jvm内存溢出,我个人认为能不抛异常就最好不抛,所以,我主要使用自定义实现spring的全局异常解析器HandlerExceptionResolver来处理业务问题。

       

(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(第一种实现方式)

             这种方式需要下载温少写的fastjson,我用的是1.2.6版本,可以百度后自己下载。

 

[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(第二种实现方式)

 

 

[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. }  

 



最后,基本上所有的异常都能被捕获,能够出现异常时,友好的提示用户端,也能避免服务器端抛异常导致的问题。

以上是关于Spring MVC全局异常后返回JSON异常数据的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 返回 JSONS 和异常处理

Spring Mvc使用Jackson进行json转对象时,遇到的字符串转日期的异常处理(JSON parse error: Can not deserialize value of type jav

Spring MVC 中的全局异常定义不起作用

MVC抛出自定义异常,并易Json方式返回

spring boot 2 全局统一返回RESTful风格数据统一异常处理

如何在 Spring MVC 中针对 HTML 和 JSON 请求以不同方式处理异常