まず、私たちが知っている必要があり、すべての基本とspringbootのJavaの例外処理がどのようにサポートするために珍しいです。あなたが新人チュートリアルJavaのチュートリアルを参照することができますJavaの例外の基本。
- 例外処理のためのspringbootサポート
springbootでは、我々は唯一の(@ControllerAdvice付き)グローバル例外ハンドラクラスを定義する必要があり、クラスの定義では繰り返さない各コントローラが必要。グローバル例外ハンドラクラスでは、我々はそれぞれのメソッドを指定@ExceptionHandler使用している例外を受信して処理。SLF4Jと@ResponseBodyは、ロギングデータとリターンJSONフォーマットを行う@我々はまた、頻繁に使用します。次のように私は定義されたグローバル例外ハンドラクラス:
- エレガントなグローバル例外処理
上記で定義されたグローバル例外クラスでは、我々は、このようなBizException、ResultDataなどというように奇妙なクラスやメソッドの多くを見ることができます。
これらのクラスは、私自身の定義されている拡張しやすく、グローバルな例外がよりエレガントさせることです、私はエレガントなグローバルな例外を処理する方法を詳細にあなたが表示されます。
合計で2.1
私は、グローバルな例外ハンドラが共通インタフェースCommonException、カスタム例外クラスの列挙ExceptionEnum、一般的な異常なラッパークラスBizException、グローバル例外ハンドラクラスGlobalExceptionHandlerを含んで書きます。
2.2汎用インタフェースCommonException
package com.hy.exception;
/**
* Description:
* 作为一个公共的异常
*
* @author houyi
* @version 1.0
* @date 2020/1/21 16:55
* @since JDK 1.8
*/
public interface CommonException {
public int getExceptionCode();
public String getExceptionMsg();
}
唯一の拡張のための抽象的可能性を達成するために、2つのメソッドを定義(さて、私は戻って読み取りと、私はあなたがゆっくりと理解すると信じて、心配しないで、あなたは理解していない知っています)
2.3カスタム例外列挙クラス
package com.hy.exception;
/**
* Description:
*
* @author houyi
* @version 1.0
* @date 2020/1/21 16:57
* @since JDK 1.8
*/
public enum ExceptionEnum implements CommonException {
/**
* 所有的代码内部错误都抛出该异常
*/
INTERNAL_ERROR(500, "内部服务异常"),
/**
* 如参数校验未通过,参数为空等抛出该异常
*/
PARAMS_ERROR(100, "参数异常"),
/**
* 对爬虫等恶意访问抛出该异常
*/
REQUEST_RATE_LIMIT(300, "请求超过速率"),
/**
* token校验未通过抛出该异常
*/
TOKEN_ERROR(101, "token异常"),
/**
* token过期抛出该异常
*/
TOKEN_EXPIRED(102, "token过期");
private int exCode;
private String exMsg;
ExceptionEnum(int exCode, String exMsg) {
this.exCode = exCode;
this.exMsg = exMsg;
}
@Override
public int getExceptionCode() {
return exCode;
}
@Override
public String getExceptionMsg() {
return exMsg;
}
}
それは異常な列挙クラス定義から分かるようにCommonExceptionインタフェースを達成しながら、二つの属性exCodeとexMsgを含み、getExceptionCode getExceptionMsg二つの方法が実施され、そして戻りexCode exMsg特性。
当社の事業および可能なシナリオに基づいておりExCodeとexMsgが独自のカスタムを完了する必要があります(完全な開発プロジェクトデモ、エラーのチャンス発見の期間の後、我々は、多くの場合、手投げ、あることを言及する価値があります従来の単一または出力エラーコード入力プロンプト重量の代わりに)
这里我们开始了第一个优雅:让枚举类继承CommonException接口。
在这里继承CommonException接口后,原有的功能不多不少,但是却对ExceptionEnum做了抽象处理,在后面的BizException类中定义一个方法要传入ExceptionEnum对象作为参数时,我们对这个参数的类型定义不用ExceptionEnum而用CommonException,这样我们以后如果需要添加行的枚举类,就不用在ExceptionEnum中修改代码,只需要再新建一个类implements CommonException然后定义要添加的异常类型就可以了。
2.4 公共异常封装类BizException
package com.hy.exception;
/**
* Description:
* 公共异常封装类
* 用于在逻辑代码中抛出异常时的封装
*
* @author houyi
* @version 1.0
* @date 2020/1/22 15:44
* @since JDK 1.8
*/
public class BizException extends Exception implements CommonException{
private int exCode;
private String exMsg;
@Override
public int getExceptionCode() {
return exCode;
}
@Override
public String getExceptionMsg() {
return exMsg;
}
/**
* 使用自定义的异常枚举类构造异常
* @param exceptionEnum
*/
public BizException(CommonException exceptionEnum){
this.exCode = exceptionEnum.getExceptionCode();
this.exMsg = exceptionEnum.getExceptionMsg();
}
public BizException(int exCode, String exMsg){
this.exCode = exCode;
this.exMsg = exMsg;
}
public BizException(int exCode){
this.exCode = exCode;
this.exMsg = "未知错误";
}
public BizException(String exMsg){
this.exCode = 10001;
this.exMsg = exMsg;
}
}
我们使用这个类来封装自定义的异常信息再抛出,这样我们在GlobalExceptionHandler类中就可以用一个单独的被@ExceptionHandler(value = BizException.class)注解的方法来处理自定义的异常。
这个类中继承Exception是为了将这个类变为异常类,实现CommonException只是为了复用,少写点代码。
同时,我们应该注意这个类的构造方法:
有一个接收CommonException类型的构造方法可以直接接收一个枚举类型,其他的则是另外零散的自定义异常信息的构造方法。
2.5 全局异常捕获处理类GlobalExceptionHandler
package com.hy.exception;
import com.hy.vo.ResultData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Description:
* 全局异常捕获类
* 所有的异常都会在这个类中处理
*
* @author houyi
* @version 1.0
* @date 2020/1/22 20:50
* @since JDK 1.8
*/
@ControllerAdvice
@Slf4j
@ResponseBody
public class GlobalExceptionHandler {
/**
* 捕获自定义的几种异常
*
* @param ex
* @return 异常码和异常信息封装的ResultData对象
*/
@ExceptionHandler(value = BizException.class)
public ResultData handlerBizException(Exception ex){
// 向下转型使BizException的自定义的不同于父类Exception的方法可以使用
BizException bizException = (BizException)ex;
// 获得异常码和异常信息
int exCode = bizException.getExceptionCode();
String exMsg = bizException.getExceptionMsg();
// 将异常码和异常信息封装成通用数据返回类型
ResultData resultData = ResultData.fail(exCode, exMsg);
// 对异常做日志记录,方便项目正式运行时发生异常后寻找异常发生点
log.error(exCode + ":" +exMsg,bizException);
// 向前端返回数据
return resultData;
}
/**
* 系统抛出的异常
* @param ex
* @return 固定异常码10002 和 异常信息封装的ResultData对象
*/
@ExceptionHandler(value = Exception.class)
public ResultData handlerException(Exception ex){
// 对所以其他异常,统一异常码为10002,并封装
ResultData resultData = ResultData.fail(10002,ex.getMessage());
// 日志记录
log.error(10002 + ":" +ex.getMessage(),ex);
// 返回数据
return resultData;
}
}
一路走来,我们的主角终于要上场了。在全局异常捕获处理类中,我只定义了两个类,一个BizException的捕获处理和除BizException的其他所有异常类的捕获处理。可以看到,不管加多少自定义异常枚举类,我们都只要加自定义异常枚举类。
2.6 测试