UDN-企业互联网技术人气社区

板块导航

浏览  : 1000
回复  : 0

[讨论交流] Java 异常分类及统一处理

[复制链接]
小辫儿的头像 楼主
发表于 2016-12-31 15:02:48 | 显示全部楼层 |阅读模式
  一、异常分类

  Java异常分为”检查”和”非检查”两类,”检查”二字的意思是,代码编译时,编译器会去Check一下有没有进行异常处理(捕获或向上抛),对于归类为需要检查的异常,若没处理,编译就过不去。

  初学的时候,常常想为啥异常要这样分类处理? 后来明白了些,异常不过两种:主观和客观,一个大多数情况下可以避免,一个大多数情况下无法避免。

  像NullPointerException这类异常,大多跟程序员素质挂钩(开发好,测试好, 基本不会在系统运行后蹦出来), 基本是可以避免的,java语法当初把它们对类为‘非检查异常’,也算给程序员和编译器省了不少事。

  而像IOException这类跟外在环境有关的异常,几乎是不可避免的(指不定哪一天那一秒网络就挂了),但是当不期而遇时,程序还是要有所作为,所以编译器有必要督促一下程序员,Check一下,看看是是否对这些可能不期而至的异常进行了处理。当Exception对象传递到某个节点后,程序就可以执行一些措施了,比如:给用户返回一个提示(”系统繁忙,请重试”),给监控平台推送一个异常消息等等。

  二、异常的统一返回处理

  1、容器处理

  下面列举Tomcat的处理方式,在web.xml下配置,按http返回码或Exception类型来处理:
  1. <error-page>
  2.      <error-code>404</error-code>
  3.      <location>/WEB-INF/views/error/404.jsp</location>
  4. </error-page>

  5. <error-page>
  6.      <error-code>500</error-code>
  7.      <location>/WEB-INF/views/error/500.jsp</location>
  8. </error-page>

  9. <error-page>
  10.      <exception-type>java.lang.Throwable</exception-type>
  11.      <location>/WEB-INF/views/error/throwable.jsp</location>
  12. </error-page>
复制代码

  缺点:无法处理不需要返回html的请求,比如ajax;

  2、框架处理

  下面列举Spring MVC的处理方式

  • 使用Spring MVC自带的简单异常处理器 SimpleMappingExceptionResolver
  • 实现接口 HandlerExceptionResolver 自定义异常处理器; (建议使用,可支持ajax等扩展)
  • 使用 @ExceptionHandler 注解实现异常处理

  第(1)种,在 spring-mvc.xml 下配置
  1. <!-- 将Controller抛出的异常转到特定视图 -->
  2. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  3. <property name="exceptionMappings">
  4.   <props>
  5.    <!-- 不同异常分开跳转-->
  6.    <!-- 可以自定义不同的异常-->   
  7.    <prop key="com.test.MyException1">/error/e1</prop>
  8.    <prop key="com.test.MyException2">/error/e2</prop>
  9.    <!-- 如果不想自定义异常,只配置下面的即可-->
  10.    <prop key="java.lang.Throwable">/error/500</prop>
  11.   </props>
  12. </property>
  13. </bean>
复制代码

  缺点:无法处理不需要返回html的请求

  第(2)种,自定义 HandlerExceptionResolver 接口的实现类
  1. /**
  2. * 自定义异常处理器:支持ajax
  3. * @author tangqing
  4. *
  5. */
  6. public class MyExceptionHandler implements HandlerExceptionResolver {

  7.     public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

  8.         /* 区分ajax */
  9.         boolean isAjax = request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString());
  10.         if (!isAjax) {
  11.             if (ex instanceof com.test.MyException1) {
  12.                 return new ModelAndView("/error/e1");
  13.             } else if (ex instanceof com.test.MyException1) {
  14.                 return new ModelAndView("/error/e2");
  15.             } else {
  16.                 return new ModelAndView("/error/500");
  17.             }
  18.         }
  19.         String jsonRes = "{\"message\":\"" + "系统异常" + "\"}"; // 自定义结构和前台对接
  20.         PrintWriter out = null;
  21.         try {
  22.             out = response.getWriter();
  23.             request.setCharacterEncoding("utf-8");
  24.             response.setContentType("text/plain;charset=utf-8");
  25.             out.print(jsonRes);
  26.             out.flush();
  27.         } catch(IOException e) {
  28.             e.printStackTrace();
  29.         } finally {
  30.             out.close();
  31.         }
  32.         return null;
  33.     }
  34. }
复制代码

  并在 spring-mvc.xml 下注册处理器
  1. <bean id="exceptionHandler" class="com.test.MyExceptionHandler"/>
复制代码

  优点:可以处理ajax请求,也方便编码实现功能扩展,比如异常的监控等。

  第(3)种, @ExceptionHandler 注解
  1. @Controller public class TestExceptionHandlerController {

  2.     @ExceptionHandler({
  3.         MyException1.class
  4.     }) public String exception(MyException1 e) {
  5.         return "/error/e1";
  6.     }@RequestMapping("/marry") public void test() {
  7.         throw new MyException1("没钱!");
  8.     }
  9. }
复制代码

  缺点: @ExceptionHandler 的方法,必须和可能抛异常的方法在一同个Controller下。(不建议使用)

  3、结合

  实际项目中,在处理异常的统一返回时,会将一些自定义的异常或者扩展交给框架,将http返回码的映射交给容器,因为http返回码更外层,有些到不了框架,有些对于框架来说就不是一个异常(比如404之与Spring MVC)。框架是运行在容器里的,当框架优先拿到异常并做了返回处理,容器就不会再进行映射。

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部