Java 异常分类及统一处理_java统一异常处理_酷酷的糖先森的博客-程序员秘密

技术标签: java  编译器  异常处理  J2EE  异常  class  

一、异常分类

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)。框架是运行在容器里的,当框架优先拿到异常并做了返回处理,容器就不会再进行映射。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014723529/article/details/53080974

智能推荐

HttpClient向HTTPS地址发送POST请求_bestlove13141516的博客-程序员秘密

HttpClient向HTTPS地址发送POST请求package com.jadyer.util;  import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.KeyManagementException; import java.securi

ngx-echarts遇到的坑_pg_li的博客-程序员秘密

1、ngx-echarts版本问题导致的问题2、高度传值传不进去 解决方式:&amp;lt;div echarts [loading]=&quot;loading&quot; [loadingOpts]=&quot;getLoadingOpts()&quot; [options]= &quot;option&quot; [initOpts]= &quot;opts&quot; [merge]=&quot;updateOptions&quot; ..

java微信公共帐号支付(JS支付)_xb12369的博客-程序员秘密

最近公司需要开发微信商城,然后各种作微信的东西啊,各种看API,头大,这里先记录下来以免后面忘记了~首先是微信提供的api地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6效果图:还是那句话,第三方的东西做一遍跟做一百遍效果是一样的,直接上代码咯~==========

TTGO T-Watch-2020 编程系列(三) Hello World,添加日期在主屏幕_lv_align_in_top_mid_coolwaterld的博客-程序员秘密

本文深度依赖 TTGO T-Watch-2020 编程系列(二) 开发环境的搭建Windows, 没看过的请先看https://blog.csdn.net/coolwaterld/article/details/109067854 不知道什么是TTGO T-Watch-2020的请参看TTGO T-Watch-2020 编程系列(一)基于ESP32可编程手表简介,https://blog.csdn.net/coolwaterld/article/details/109065963 决定是否需要看本文 本

hadoop错误DataXceiver error processing WRITE_BLOCK operation_dengdun2029的博客-程序员秘密

错误: DataXceiver error processing WRITE_BLOCK operation原因: 文件操作超租期,实际上就是data stream操作过程中文件被删掉了。解决办法: 修改hdfs-site.xml (针对2.x版本,1.x版本属性名应该是:dfs.datanode.max.xcievers): &lt;pr...

SCRUM敏捷软件模型开发过程_bug_Cat的博客-程序员秘密

第15讲:SCRUM敏捷软件模型开发过程重点:(1)回顾和思考CMMI模型的核心思想是什么?这一模型有什么特点?适合什么样的企业和项目?(2)了解学界所说的“重”过程的“重”是什么意思? 与之相对应的“轻”过程的轻又是什么意思?(3)了解敏捷软件开发过程的指导思想,了解SCRUM的基本框架。(4)理解SCRUM敏捷开发模型的”三个角色“、”三个工件“、”四个会议“的内容和方法。一...

随便推点

Linux平台下Oracle数据泵备份(expdp)SHELL脚本_expdp [email protected]的博客-程序员秘密

原 Linux 平台下 Oracle 数据泵备份(expdp) SHELL 脚本https://blog.csdn.net/tianlesoftware/article/details/5719646版权声明: https://blog.csdn.net/tianlesoftware/article/details/5719646数据泵是Oracle 10g的新特性,10g以后的版本才有。 关于...

VUE 跳转至某一页面后 再跳转至其他页面出现空白 刷新后正常显示的问题解决_吴迪大光头的博客-程序员秘密

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档VUE 跳转至某一页面后 再跳转至其他页面出现空白的问题解决今天测试项目的时候出现了这个问题,搞了我好几个小时,原来一直以为是路由出了问题,看了半天也没解决,结果最后发现问题很简单,唉!检查一下template最外层的div是不是被误删了,如果误删了或者没加上,加上即可,示例如下:改前:改后希望可以帮遇到相同问题的童鞋们节约时间吧!...

android 11.0 12.0SystemUI状态栏高度设置为0时微信头部异常问题的解决_安卓兼职framework应用工程师的博客-程序员秘密

在11.0 12.0定制化开发中,由于产品需要全屏功能,所以不需要SystemUI的状态栏所以就把状态栏高度设置为0,这样虽然SystemUI的状态栏是隐藏不见了,但是又会有新的问题出现,比如安装微信,qq等 首页的头像好像被挡住了一部分,经过思考影响头部的只可能是Status.java了,所以需要分析状态栏的问题。

kotlin入门系列-第一个kotlin的android demo_BlackSmith-2617的博客-程序员秘密

google I/O后浏览新闻知道了kotlin已经是Android开发第一语言,很想试试这个新的语言开发有什么不同。  在Ubuntu上我的Android studio是2.3版本的,因此,先配置kotlin的环境是第一步,在“file”--“setting”搜索plugin然后在里面搜索kotlin插件,就能够找到对应的了,然后下载,如下图所示:  幸好不越墙也是可以下载的,不过公

Java 6 中自带的 Java DB(derby) 数据库_boren31的博客-程序员秘密

新安装了 JDK 6 的程序员们也许会发现,除了传统的 bin、jre 等目录,JDK 6 新增了一个名为 db 的目录。这便是 Java 6 的新成员:Java DB。这是一个纯 Java 实现、开源的数据库管理系统(DBMS),源于 Apache 软件基金会(ASF)名下的项目 Derby。它只有 2MB 大小,对比动辄上 G 的数据库来说可谓袖珍。但这并不妨碍 Derby 功能齐备,支持几乎

推荐文章

热门文章

相关标签