Java代码中异常处理机制,如何自定义异常类以及如何构建全局异常处理;try{}catch(){}finally{}捕获并处理异常,throw和throws的区别,catch和throw两者结合使用

发布于:2022-11-28 ⋅ 阅读:(334) ⋅ 点赞:(0)

目录

一、Java异常详细介绍

1. 常见的三种类型异常

2. 常见的Java内置异常类

3.Throwable异常方法

二、Java异常处理机制:

三、Java异常处理的方式:

1.try-catch-finally

2.异常抛出:throws +异常类型

3.throws和throw的区别:

4.catch和throw同时使用:

5.Java 7 增强的throw语法:

四、如何声明自定义异常:

五、如何实现全局异常处理:

1.自定义业务异常类

2.创建统一的返回体

3.枚举 创建统一异常码

4.自定义全局异常类


一、Java异常详细介绍

        在Java中,异常就是Java在编译或运行或者运行过程中出现的错误。 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;如果你用 System.out.println(11/0),那么你是因为你用 0 做了除数,会抛出 java.lang.ArithmeticException 的异常

        异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的,异常发生的原因有很多,通常包含以下几大类:

  • 用户输入了非法数据。

  • 要打开的文件不存在。

  • 网络通信时连接中断,或者 JVM 内存溢出

1. 常见的三种类型异常

  • 非运行时异常:非运行异常时Non_RuntimeException类及其子类的实例,又称为可检测异常;是指 RuntimeException 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOException、ClassNotFoundException 等以及用户自定义的 Exception 异常,一般情况下不自定义检查异常。

  • 运行时异常: 与可检测异常相反,运行时异常可以在编译时被忽略。程序中可以选择捕获处理,也可以不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生。

  • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

异常层次结构:

-Throwable所有异常的父类

-Error 是在严重故障的情况下发生的异常情况,Java程序不处理这些情况。 生成错误以指示运行时环境生成的错误。例如:JVM内存不足。 通常,程序无法从错误中恢复

-Exception类是Throwable类的子类,所有异常类都是java.lang.Exception类的子类型分为运行时异常和非运行时异常,Exception类有两个主要的子类:RuntimeException运行时类和IOException类;

2. 常见的Java内置异常类

可检测异常:

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

不可检测异常类(运行时异常):

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

3.Throwable异常方法

可以用来捕获异常后获取想要的异常信息:

序号 方法及说明
1 public String getMessage()
返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。
2 public Throwable getCause()
返回一个Throwable 对象代表异常原因。
3 public String toString()
使用getMessage()的结果返回类的串级名字。
4 public void printStackTrace()
打印toString()结果和栈层次到System.err,即错误输出流。
5 public StackTraceElement [] getStackTrace()
返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。
6

public Throwable fillInStackTrace()
用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。

二、Java异常处理机制:

Java异常处理的抓抛:
过程一:抛出异常

        Java程序的执行过程中如出现异常, 会生成一个异常类对象,该异常对象将被提交给Java运行时系统, 这个过程称为抛出(throw)异常。
过程二:抓,可以理解为异常的处理方式

        如果一个方法内抛出异常, 该异常对象会被抛给调用者方法中处理。如果异常没有在调用者方法中处理, 它继续抛给这个调用方法的上层方法。这个过程将一直继续下去, 直到异常被处理。这一过程称为捕获(catch)异常。
        如果一个异常回到main()方法, 并且main()也不处理, 则程序运行终止。程序员通常只能处理Exception, 而对Error无能为力。

三、Java异常处理的方式:

一般有两种:方式一 try-catch-finally ;方式二 throws + 异常类型;

1.try-catch-finally

        使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。

//声明有两个元素的一个数组,当代码试图访问数组的第三个元素的时候就会抛出一个异常
import java.io.*;
public class ExcepTest{

   public static void main(String args[]){
      try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}

 运行输出结果:

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

补充:

一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获,多重捕获块的语法如下所示:

try{
    // 程序代码
 }catch(异常类型1 异常的变量名1){
    // 程序代码
 }catch(异常类型2 异常的变量名2){
    // 程序代码
 }catch(异常类型2 异常的变量名2){
    // 程序代码
 }
  • 如果保护代码中发生异常,异常被抛给第一个 catch 块。
  • 如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
  • 如果不匹配,它会被传递给第二个 catch 块。
  • 如此,直到异常被捕获或者通过所有的 catch 块。

try关键字:

        捕获异常的第一步是用try{…}语句块选定捕获异常的范围, 将可能出现异常的代码放在try语句块中。在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常处理,一旦处理完成就跳出当前的try-catch结构(在没有写finally的情况下)。继续执行其后的代码。在try结构中声明的变量,出了try结构之后,就不能被调用。

catch关键字:

        在catch语句块中是对异常对象进行处理的代码。 每个try语句块可以伴随一个或多个catch语句, 用于处理可能产生的不同类型的异常对象。catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓,如果异常类型满足子父类的关系,则要求子类一定要声明在父类的上面,否则报错。

        如果明确知道产生的是何种异常, 可以用该异常类作为catch的参数;也可以用其父类作为catch的参数。比 如 : 可 以 用 ArithmeticException 类 作 为 参 数 的 地 方 , 就 可 以 用RuntimeException类作为参数, 或者用所有异常的父类Exception类作为参数。但不能是与ArithmeticException类无关的异常, 如NullPointerException(catch中的语句将不会执行) 。使用try-cathch-finally处理编译时异常,使得程序在编译时不在报错,但在运行时,仍有可能报错。相当我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。

 finally 关键字:

        finally 关键字用来创建在 try 代码块后面执行的代码块。无论是否发生异常,finally 代码块中的代码总会被执行。在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。

        当使用流,连接等任何资源时,java7之前要使用finally块显式关闭它们,Java7以后使用try-with-resources来处理资源对象;finally 代码块出现在 catch 代码块最后,语法如下:

 try{
    // 程序代码
 }catch(异常类型1 异常的变量名1){
    // 程序代码
 }catch(异常类型2 异常的变量名2){
    // 程序代码
 }finally{
    // 程序代码
 }

         前面使用的异常都是RuntimeException类或是它的子类,这些类的异常的特点是:即使没有使用try和catch捕获, Java自己也能捕获,并且编译通过( 但运行时会发生异常使得程序运行终止 )。如果抛出的异常是IOException等类型的非运行时异常,则必须捕获,否则编译错误。也就是说,我们必须处理编译时异常,将异常进行捕捉,转化为运行时异常,就用到了我们下面要讲的throws。 

2.异常抛出:throws +异常类型

        声明抛出异常是Java中处理异常的第二种方式throws +异常类型,异常类型写在方法的声明处, 此方法执行时可能会抛出的异常类型。
        如果一个方法(中的语句执行时)可能生成某种异常, 但是并不能确定如何处理这种异常, 则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。在方法声明中用throws语句可以声明抛出异常的列表, throws后面的异常类型可以是方法中产生的异常类型, 也可以是它的父类。

        一旦方法体执行时出现异常仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时就会被抛出。异常代码后续的代码,就不在执行。throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉。

        如果一个方法没有捕获一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。一个方法可以声明抛出多个异常,多个异常之间用逗号隔开;

import java.io.*;
public class className
{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException
   {
       // Method implementation
   }
   //Remainder of class definition
}

在多态的情况下,对methodA()方法的调用-异常的捕获按父类声明的异常处理分析如下:

        执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的,我们建议这几个方法使用throws的方式进行处理。而方法a的执行处可以考虑使用try-catch;

public class A {
public void methodA() throws IOException {
……
} }
public class B1 extends A {
public void methodA() throws FileNotFoundException {
……
} }
public class B2 extends A {
public void methodA() throws Exception { //报错
……
} }

如何选择try-catch和throws:
        如果父类中被重写的方法中没有throws方式处理异常,则子类重写的方法中也不能使用throws,意味如果子类重写的方法中有异常,必须使用try-catch。 

注意:重写方法不能抛出比被重写方法范围更大的异常类型是重写方法声明抛出异常的原则; 

3.throws和throw的区别:

1)throws用于方法头,而throw用于方法内部;

2)throws表示的只是异常的申明,而throw抛出的是异常对象;

3)throws抛出异常时,它的上级(调用者)也要申明抛出异常或者捕获,不然编译报错。而throw的话,可以不申明或不捕获(这是非常不负责任的方式)但编译器不会报错;

4)throw,如果执行了,那么一定是抛出了某种异常了,安生throws表示可能出现,但不一定;

4.catch和throw同时使用:

前面出现的异常处理方式有如下两种:

1)出现在异常方法内捕获并处理异常,该方法的调用者将不能再次捕获该异常

2)该方法签名中声明抛出该异常,将该异常完全交给方法调用者处理

        实际应用中往往需要更复杂的处理方式,当一个异常出现时单靠某个方法无法完全处理该异常,必须由几个方法协作才可以处理该异常。也就是说我们在异常出现的方法中捕获该异常并对异常进行部分处理,然后再抛出异常由方法调用者捕获并处理该异常。这就用到了catch和throw同时使用,代码如下:

//声明有两个元素的一个数组,当代码试图访问数组的第三个元素的时候就会抛出一个异常
import java.io.*;
public class ExcepTest{

   public static void main(String args[]){
     try{
        test();
     }catch(ArrayIndexOutOfBoundsException e){
        System.out.println(e.getMessage());
     }
   }
   public void test() throws ArrayIndexOutOfBoundsException {
     try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
         throw new ArrayIndexOutOfBoundsException("........");
      }
      System.out.println("Out of the block");
   }
}

        上边代码的test方法中catch块捕获到异常后对异常信息进行了控制台的输出,相当于是在出现异常的方法中对异常的第一次处理,接着抛出一个ArrayIndexOutOfBoundsException异常实例对象,并在方法的声明处通过throws抛出异常交给它的调用者处理该异常,也就是test的方法调用者会再次捕获ArrayIndexOutOfBoundsException异常并对异常进行处理;

        这种catch和throw结合使用的情况在实际开发中非常常用,企业级应用对异常的处理通常分成两个部分:1.应用后台需要通过日志来记录异常发生的详细情况;2.应用还需要根据异常向应用使用者传达某种提示;这种情况下所有异常都需要两个方法共同来完成,也就必须将catch和throw结合使用。

5.Java 7 增强的throw语法:

try
{
    new Fileoutputstream ("a.txt"】;)
catch (Exception ex){
    ex.printstackTrace();
    throw ex ;
}

        上面代码片段中再次抛出了捕获到的异常,但这个ex对象的情况比较特殊:程序捕获该异常时,声明该异常的类型为Exception;但实际上 try 块中可能只调用了FileOutputStream构造器,这个构造器声明只是抛出了FileNotFoundException异常。
        在Java 7以前,Java 编译器的处理“简单而粗暴”——由于在捕获该异常时声明ex 的类型是Exception,因此Java编译器认为这段代码可能抛出Exception异常,所以包含这段代码的方法通常需要声明抛出 Exception异常。例如如下方法。

public class ThrowTest2{
 public static void main (String[] args) throws Exception{
//Java6认为代码可能抛出Exception异常,所以此处声明抛出Exception异常
    try{
        new Fileoutputstream ("a.txt");
    }
    catch (Exception ex){
        ex.printStackTrace();
        throw ex;
    }
  }
}

        从Java 7开始,Java编译器会执行更细致的检查,Java编译器会检查throw语句抛出异常的实际类型,这样编译器知道代码实际上只可能排除FileNotFoundException异常,因此在方法签名中只要声明抛出FileNotFoundException异常即可。即可以将代码改为如下形式:

public class ThrowTest2
{
  public static void main(String[] args) throws FileNotFoundException(){
    // Java 7会检查代码处可能抛出异常的实际类型
    //因此此处只需声明抛出FileNotFoundException异常即可
    try{
        new FileoutputStream ( "a.txt");
    }
    catch (Exception ex){
        ex.printStackTrace();
        throw ex;
    }
  }
}

四、如何声明自定义异常:

        java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出, 也可根据需要使用人工创建并抛出。首先要生成异常类对象, 然后通过throw语句实现抛出操作(提交给Java运行环境)。可以抛出的异常必须是Throwable或其子类的实例。

编写异常类时需要注意下面几点:

  • 所有异常都必须是 Throwable 的子类。
  • 如果希望写一个检查性异常类,则需要继承 Exception 类。
  • 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
  • 一般地,用户自定义异常类都是RuntimeException的子类。
  • 自定义异常类通常需要编写几个重载的构造器。
  • 自定义的异常通过throw抛出。
  • 自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。
  • 用户自己的异常类必须继承现有的异常类。

        只继承 Exception 类来创建的异常类是检查性异常类。下面的 InsufficientFundsException 类是用户定义的异常类,它继承自 Exception。一个异常类和其它任何类一样,包含有变量和方法。

自定义异常类:

// 文件名InsufficientFundsException.java
import java.io.*;

public class InsufficientFundsException extends Exception
{
   private double amount;
   public InsufficientFundsException(double amount)
   {
      this.amount = amount;
   } 
   public double getAmount()
   {
      return amount;
   }
}

抛出(throw)异常:抛出一个 InsufficientFundsException 自定义异常

import java.io.*;

public class CheckingAccount
{
   private double balance;
   private int number;
   public CheckingAccount(int number)
   {
      this.number = number;
   }
   public void deposit(double amount)
   {
      balance += amount;
   }
   public void withdraw(double amount) throws
                              InsufficientFundsException
   {
      if(amount <= balance)
       {
          balance -= amount;
       }
       else
       {
          double needs = amount - balance;
          throw new InsufficientFundsException(needs);
       }
    }
    public double getBalance()
    {
       return balance;
    }
    public int getNumber()
    {
       return number;
    }
 }

捕获异常:调用 CheckingAccount 类的 deposit() 和 withdraw() 方法

public class BankDemo
{
   public static void main(String [] args)
   {
      CheckingAccount c = new CheckingAccount(101);
      System.out.println("Depositing $500...");
      c.deposit(500.00);
      try
      {
         System.out.println("\nWithdrawing $100...");
         c.withdraw(100.00);
         System.out.println("\nWithdrawing $600...");
         c.withdraw(600.00);
      }catch(InsufficientFundsException e)
      {
         System.out.println("Sorry, but you are short $"
                                  + e.getAmount());
         e.printStackTrace();
      }
    }
}

运行输出结果:

Depositing $500...

Withdrawing $100...

Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
        at CheckingAccount.withdraw(CheckingAccount.java:25)
        at BankDemo.main(BankDemo.java:13)

五、如何实现全局异常处理:

        SpringBoot中,@ControllerAdvice 即可开启全局异常处理,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。

1.自定义业务异常类

/**
 * 自定义service层异常类 RuntimeException 可以不捕获也没事
 */
public class ServiceException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	private ResultCode resultCode;

	public ServiceException(ResultCode resultCode) {
		this(resultCode.message());
		this.resultCode = resultCode;
	}

	private ServiceException(String message) {
		super(message);
	}

	public ResultCode getResultCode() {
		return resultCode;
	}

	public void setResultCode(ResultCode resultCode) {
		this.resultCode = resultCode;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}
}

2.创建统一的返回体

package cn.com.wind.sprtes.exception;

import java.io.Serializable;

/**
 * 统一Controller中RESTFul风格接口返回的结果
 */
public class Result implements Serializable {

	private static final long serialVersionUID = 1L;

	// 状态码
	private Integer code;
	// 错误信息
	private String msg;
	// 响应回去的数据
	private Object data;

	private Result() {
	}

	private Result(Integer code, String msg) {
		this.code = code;
		this.msg = msg;
	}

	private void setResultCode(ResultCode code) {
		this.code = code.code();
		this.msg = code.message();
	}

	/**
	 * 操作失败,自定义code和msg
	 */
	public static Result failure(Integer code, String msg) {
		Result result = new Result(code, msg);
		return result;
	}

	/**
	 * 操作成功,没有返回的数据
	 */
	public static Result success() {
		Result result = new Result();
		result.setResultCode(ResultCode.SUCCESS);
		return result;
	}

	/**
	 * 操作成功,有返回的数据
	 */
	public static Result success(Object data) {
		Result result = new Result();
		result.setResultCode(ResultCode.SUCCESS);
		result.setData(data);
		return result;
	}

	/**
	 * 操作失败,没有返回的数据
	 */
	public static Result failure(ResultCode resultCode) {
		Result result = new Result();
		result.setResultCode(resultCode);
		return result;
	}

	/**
	 * 操作失败,有返回的数据
	 */
	public static Result failure(ResultCode resultCode, Object data) {
		Result result = new Result();
		result.setResultCode(resultCode);
		result.setData(data);
		return result;
	}

	public Integer getCode() {
		return code;
	}

	public void setCode(Integer code) {
		this.code = code;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

}

3.枚举 创建统一异常码

/**
 * 统一并自定义返回状态码,如有需求可以另外增加
 */
public enum ResultCode {

	/* 成功状态码 */
	SUCCESS(200, "操作成功"),

	/* 默认失败状态码 */
	ERROR(-1, "操作失败,未知制定错误信息"),

	/* 参数错误:10001-19999 */
	PARAM_IS_INVALID(10001, "参数无效"), 
	PARAM_IS_BLANK(10002, "参数为空"), 
	PARAM_TYPE_BIND_ERROR(10003, "参数类型错误"),
	PARAM_NOT_COMPLETE(10004, "参数缺失"),

	/* 用户错误:20001-29999 */
	USER_NOT_LOGIN(20001, "用户未登录"), 
	USER_LOGIN_ERROR(20002, "账号不存在或密码错误"), 
	USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
	USER_NOT_EXIST(20004, "用户不存在"), 
	USER_HAS_EXISTED(20005, "用户已存在"), 
	USER_NOT_EMPTY(20006, "用户名不能为空"),
	USER_MUST_BE_IS_NUMBER_AND_LETTER(20007, "密码只能为数字或者字母"), 
	USER_BACTH_DELETE_ERROR(20008, "批量删除报错"),

	/* 业务错误:30001-39999 */
	SPECIFIED_QUESTIONED_USER_NOT_EXIST(30001, "业务逻辑出现问题"),

	/* 系统错误:40001-49999 */
	SYSTEM_INNER_ERROR(40001, "系统内部错误,请稍后重试"),

	/* 数据错误:50001-599999 */
	DATA_NONE(50001, "数据未找到"), 
	DATA_WRONG(50002, "数据错误"), 
	DATA_EXISTED(50003, "数据已存在"),

	/* 接口错误:60001-69999 */
	INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"), 
	INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),
	INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"), 
	INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
	INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),

	/* 权限错误:70001-79999 */
	PERMISSION_NO_ACCESS(70001, "无访问权限"),

	/* 角色部分错误:80001-89999 */
	ROLE_IS_EXIST(80001, "角色不存在"), 
	ROLE_MSG_NOT_AGREEMENT(80002, "角色信息不一致");

	private Integer code;

	private String message;

	ResultCode(Integer code, String message) {
		this.code = code;
		this.message = message;
	}

	public Integer code() {
		return this.code;
	}

	public String message() {
		return this.message;
	}
}

4.自定义全局异常类

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器 把异常到controller层 这里会获取看看异常对不对,全都交给全局异常处理 和swagger没关系
 * 
 * 异常得到期望的返回格式,这里就需要用到了@ControllerAdvice 或者RestControllerAdvice(如果全部异常处理返回json,
 * 那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,
 * 这样在方法上就可以不需要添加 @ResponseBodyServiceException
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

	//可以放入自定义异常类 , 不一定是要Exception ,可以是继承了运行时异常的类
	@ResponseBody
	@ExceptionHandler(Exception.class)
	public Object handleException(Exception e) {
		//异常具体位置
		StackTraceElement[] stackTrace = e.getStackTrace();
		Result result = null;
		if (e instanceof ServiceException) {
			result = Result.failure(((ServiceException) e).getResultCode());
		} else {
			result = Result.failure(500, "服务器意外错误:" + e.getMessage());
		}
		return result;
	}

}

        自定义全局异常处理除了可以处理上述的数据格式之外,也可以处理页面的跳转,只需在新增的异常方法的返回处理上填写该跳转的路径并不使用ResponseBody 注解即可。 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到