Java异常分类及统一处理详解_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 wangxu
 *
 */
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)。框架是运行在容器里的,当框架优先拿到异常并做了返回处理,容器就不会再进行映射。

以上就是本文的全部内容,希望对大家的学习有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索Java异常分类
Java统一处理
java统一异常处理、java异常详解、java项目异常统一处理、java web统一异常处理、javaweb统一异常管理,以便于您获取更多的相关知识。

时间: 2024-10-26 05:47:04

Java异常分类及统一处理详解_java的相关文章

Java Web请求与响应实例详解_java

Servlet最主要作用就是处理客户端请求并作出回应,为此,针对每次请求,Web容器在调用service()之前都会创建两个对象,分别是HttpServletRequest和HttpServletResponse.其中HttpServletRequest封装HTTP请求消息,HttpServletResponse封装HTTP响应消息.需要注意的是,Web服务器运行过程中,每个Servlet都会只创建一个实例对象,不过每次请求都会调用Servlet实例的service(ServletRequest

多用多学之Java中的Set,List,Map详解_java

很长时间以来一直代码中用的比较多的数据列表主要是List,而且都是ArrayList,感觉有这个玩意就够了.ArrayList是用于实现动态数组的包装工具类,这样写代码的时候就可以拉进拉出,迭代遍历,蛮方便的. 也不知道从什么时候开始慢慢的代码中就经常会出现HashMap和HashSet之类的工具类.应该说HashMap比较多一些,而且还是面试经典题,平时也会多看看.开始用的时候简单理解就是个键值对应表,使用键来找数据比较方便.随后深入了解后发现 这玩意还有点小奥秘,特别是新版本的JDK对Has

java 装饰模式(Decorator Pattern)详解_java

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 我们通过下面的实例来演示装饰器模式的使用.其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类. 实现 我们将创建一个 Shape 接口和实现了 Shape 接口的实体类.然后我们创建一个实现了 Shape 接口的抽象装饰类Sha

Java并发编程总结——慎用CAS详解_java

一.CAS和synchronized适用场景 1.对于资源竞争较少的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源:而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少,因此可以获得更高的性能. 2.对于资源竞争严重的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized.以java.util.concurrent.atomic包中AtomicInteger类为例,其getAn

Java编程之文件读写实例详解_java

本文实例讲述了Java编程中文件读写的方法.分享给大家供大家参考,具体如下: Java中文件读写操作的作用是什么? 回答这个问题时应该先想到的是Java只是一门语言,我们的一种使用工具而已,这样答案就明晰了,就是将外来的各种数据写入到某一个文件中去,用以保存下来:或者从文件中将其数据读取出来,供我们使用.就如下电影过程,从网络资源中下载一部电影保存于你电脑中(写文件),当你想看的时候就用播放器打开(读文件). Java中如何对文件进行读写操作? 先理一理,Java中的流分两种,字节流和字符流,其

关于java中构造函数的一些知识详解_java

java的构造函数是一个非常重要的作用,首先java里的构造函数是可以重载的,而且因为也是可以继承在父类的构造函数,所以在子类里,首先必然是调用父类的构造函数.可以看下面的两个例子来对比: public class Test { public static void main(String args[]) { B b = new B(100); } } class A { public A() { System.out.println("A without any parameter"

Java连接操作Oracle数据库代码详解_java

废话不多说了,直接给大家贴关键代码了,具体代码如下所示: package com.sp.test; import java.sql.*; import java.util.*; public class Text_lianxi extends Thread { public void run() { try { yunxing(); Thread.sleep(10000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.pr

java中queue接口的使用详解_java

Queue接口与List.Set同一级别,都是继承了Collection接口.LinkedList实现了Queue接口.Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用.BlockingQueue 继承了Queue接口.  队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素就

JAVA获取CLASSPATH路径的方法详解_java

ClassLoader 提供了两个方法用于从装载的类路径中取得资源: public URL getResource (String name); public InputStream getResourceAsStream (String name);        这里name是资源的类路径,它是相对与"/"根路径下的位置.getResource得到的是一个URL对象来定位资源,而getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据.