关于异常以及如何统一处理异常

前言:

最近公司新来的实习生,在写代码时,代码中出现代码中就会出现大量的try {…} catch {…} finally {…} 代码块,这种情况会产生大量的冗余代码,而且还影响代码的可读性。所以就异常处理这一块说收统一处理。

1.异常定义:

阻止当前方法或作用域继续执行的问题。虽然java中有异常处理机制,但是要明确一点,绝不应该用"正常"的态度来看待异常。绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败。之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意。

2.异常体系

在这里插入图片描述

2.1 各种异常的介绍

Throwable
Throwable 是 Java 语言中所有错误(Error)和异常(Exception)的超类。
Throwable 包含了其线程创建时线程执行堆栈的快照,它提供了 printStackTrace() 等接口用于获取堆栈跟踪数据等信息。
主要方法:

fillInStackTrace - 用当前的调用栈层次填充 Throwable 对象栈层次,添加到栈层次任何先前信息中。
getMessage - 返回关于发生的异常的详细信息。这个消息在 Throwable 类的构造函数中初始化了。
getCause - 返回一个 Throwable 对象代表异常原因。
getStackTrace - 返回一个包含堆栈层次的数组。下标为 0 的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。
printStackTrace - 打印 toString() 结果和栈层次到 System.err,即错误输出流。
toString - 使用 getMessage 的结果返回代表 Throwable 对象的字符串。

Error
Error 是 Throwable 的一个子类。 Error 表示合理的应用程序不应该尝试捕获的严重问题。大多数此类错误都是异常情况。编译器不会检查 Error。
常见 Error:

AssertionError - 断言错误。
VirtualMachineError - 虚拟机错误。
UnsupportedClassVersionError - Java 类版本错  误。
StackOverflowError - 栈溢出错误。
OutOfMemoryError - 内存溢出错误。

Exception

Exception 是 Throwable 的一个子类。Exception 表示合理的应用程序可能想要捕获的条件。

编译器会检查 Exception 异常。此类异常,要么通过 throws 进行声明抛出,要么通过 try catch 进行捕获处理,否则不能通过编译。

常见 Exception:

ClassNotFoundException - 应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException - 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException - 拒绝访问一个类的时候,抛出该异常。
InstantiationException - 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
InterruptedException - 一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException - 请求的变量不存在。
NoSuchMethodException - 请求的方法不存在。

RuntimeException

RuntimeException 是 Exception 的一个子类。RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。
编译器不会检查 RuntimeException 异常。当程序中可能出现这类异常时,倘若既没有通过 throws 声明抛出它,也没有用 try catch 语句捕获它,程序还是会编译通过。

常见 RuntimeException:

ArrayIndexOutOfBoundsException - 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException - 试图将错误类型的对象存储到一个对象数组时抛出的异常。
ClassCastException - 当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException - 抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException - 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
IllegalStateException - 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。
IllegalThreadStateException - 线程没有处于请求操作所要求的适当状态时抛出的异常。
IndexOutOfBoundsException - 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException - 如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException - 当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException - 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException - 由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException - 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException - 当不支持请求的操作时,抛出该异常。

3 .异常的统一处理

异常的处理一般是处理RuntimeException

3.1 何时throw抛异常:

1 dao层异常上抛-->service层上抛(只对RunTimeException异常期作用)-->controller层统一处理	    (@ControllerAdvice)
2  默认我们需要service层的异常需要抛出
3  servcie层被Spring管理,默认Spring的事务回滚只对RunTimeException起作用,所以我们要把service层的编译器异常转换为运行时异常抛出

3.2 何时try/cash捕捉异常:

1  只有这种异常不需要影响业务,或者通过这种异常可以执行其他业务,我们才需要try

2 否则统一抛出throw

3.3 异常的统一处理

1、可以自定义异常切面处理,统一拦截controller层的RunTimeException,进行统一处理
代码如下:

@ControllerAdvice
public class BaseExceptionAdvice {
    
    
    
    @ExceptionHandler(LyException.class)
   	 public ResponseEntity<ExceptionResult> handlerCusException (CusException e) {
    
    
        	return ResponseEntity.(e.getErrorCode()).body(new ExceptionResult(e));
   			 }
}

注解:

@ControllerAdvice

作用:拦截所有的以@Controller为注解的类,以及他们的子类

@ExceptionHandler

作用:配合@ControllerAdivce使用

2、自定义异常类,继承RuntimeException,可以自己录入状态码和异常信息:

public class CusException  extends RuntimeException {
    
    
   		private int errorCode;
    	public CusException (ExceptionEnum e){
    
    
        		super(e.getErrorInfo());
        		this.errorCode=e.getErrorCode();
    	}

3、自定义异常返回结果类:

public class ExceptionResult {
    
    
    private int errorCode;
   	private String errorInfo;
   	private String timestamp;
    
   	public ExceptionResult(LyException e) {
    
    
       		this.errorCode= e.errorCode();
        	this.errorInfo= e.errorInfo();
        	//记录错误发生的时间
        	this.timestamp = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
   		}
}

4、上面消息的异常最好配合下枚举,将状态码和对应信息做好一一对应,实例代码如下:

public enum ExceptionEnum {
    
    
    PROD_INFO_NOT_FOUND(400,"商品信息未找到"),
   	PRICE_CANNOT_BE_NULL(400,"商品价格不能为空"),
	//成员变量
    private int errorCode;
    private String errorInfo;
    //构造函数
    ExceptionEnum(int errorCode, String errorInfo) {
    
    
        this.errorCode= errorCode;
        this.errorInfo= errorInfo;
   			}
}

写在最后

异常的统一处理可以大大减少代码的冗余以及异常的统一管理

猜你喜欢

转载自blog.csdn.net/damokelisijian866/article/details/107829009