SpringBoot + Vue フロントエンドとバックエンドの個別開発: グローバル例外処理と統一された結果のカプセル化

SpringBoot + Vue フロントエンドとバックエンドの個別開発: グローバル例外処理と統一された結果のカプセル化

フロントエンドとバックエンドの分離開発における例外処理

  フロントエンドとバックエンドの分離プロジェクトでは、バックエンド サービスがエラーを報告して例外をスローすることが避けられない場合があります。グローバル例外処理メカニズムが構成されていない場合、tomcat または nginx の 5XX ページが返されます。一般ユーザーの場合は必要ありません フレンドリーすぎるため、ユーザーは何が起こっているのか理解できません。現時点では、プログラマーは、フレンドリーでシンプルな形式を設計してフロントエンドに返す必要があります。そうすれば、フロントエンドは、ユーザーに Java 例外をスローするのではなく、ユーザーが理解できるエラー メッセージを返します。
  バックエンドはフロントエンドにエラー メッセージを返します。フロントエンドはこのエラー メッセージを受信して​​ユーザーに通知できる必要があります。つまり、フロントエンドも例外を処理する必要があります。Vue プロジェクトでは、フロントエンドは axios を使用してリクエストを送信します。バックエンドに送信し、フロントエンドはグローバル axios インターセプターを構成する必要があります。これは、バックエンドから返された http 応答をインターセプトしてリクエストが成功したかどうかを判断し、失敗した場合は対応するエラー メッセージを返します
  。合意された結果が正常であるか、例外が発生したかによって異なります。そうしないと、バックエンドから返されるデータが変化し、フロントエンドはリクエストが成功したかどうかを判断できなくなります。

統合された結果のカプセル化

  統合された結果のパッケージ化は、フロントエンドとバックエンドのネゴシエーションによって決定され、パッケージ化のタイプはプロジェクトごとに異なる場合があります。
  ここでは、シンプルな統合結果カプセル化クラスを使用して、フロントエンドとバックエンドの対話の重要なリンクを示します。一般に、統合結果カプセル化クラスにはいくつかの要素が必要です。

  • リクエストが成功したかどうかはコードで示すことができます (たとえば、200 は成功を意味し、400 は例外を意味します)
  • リクエスト結果メッセージメッセージ
  • リクエスト結果データ データ

  ここでは、Result クラスを使用して統合結果カプセル化クラスを表すため、Result クラスには次の 3 つの属性が必要です。
ここに画像の説明を挿入
  Result にはどのようなメソッドが必要ですか? リクエストには成功と失敗の 2 つのケースしかありません。Result オブジェクトを生成してフロントエンドに返すには、Result に静的メソッドを定義する必要があります。パラメータは Result オブジェクトの 3 つの属性です。したがって、次の 2 つを定義しますメソッド
ここに画像の説明を挿入
  : これら 2 つのメソッドは特に使いやすいわけではないため、十分ではありません。ほとんどの成功したリクエストのコードは 200 です。成功したメッセージは重要ではなく、データがフロントエンドに必要なものです。つまり、ほとんどの成功したリクエストでは、データをフロントエンドに渡すだけで済みます。 Result を作成するメソッドでは、パラメーターは 1 つだけ、つまりデータです。コードは直接 200 で、操作が成功したことを示すメッセージが表示されます。そこで、 succ オーバーロード メソッドを定義します。これにより、結果パッケージをより便利に使用できるようになります。同じことが、
ここに画像の説明を挿入
  ほとんどのリクエストの失敗にも当てはまります。一般に、リクエストが失敗した場合、バックエンドはフロントエンドにデータを返しません。リクエストが失敗した場合、エラー メッセージ メッセージはフロントエンドが必要とするものであり、400 は http で不正なリクエスト、つまりリクエストの失敗を表すため、コードを直接 400 として定義することもできます。そこで、fail のオーバーロード メソッドを定義します。
ここに画像の説明を挿入
  この時点で、統合された結果のカプセル化クラスが定義されており、その完全なコードは次のとおりです。

@Data
public class Result implements Serializable {
    
    

    private int code;
    private String msg;
    private Object data;

    public static Result succ(Object data) {
    
    
        return succ(200, "操作成功", data);
    }

    public static Result fail(String msg) {
    
    
        return fail(400, msg, null);
    }

    public static Result succ (int code, String msg, Object data) {
    
    
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    public static Result fail (int code, String msg, Object data) {
    
    
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }
}

  なお、Resultクラスはシリアル化用のSerializableインターフェースを実装しており、ネットワーク送信用にJSONなどに変換してフロントエンドに送信することができます。

バックエンドのグローバル例外のキャプチャと処理

  GlobalExceptionHandler というクラスを定義して、グローバル例外をキャプチャして処理できます。このクラスには @RestControllerAdvice
  @RestControllerAdvice のアノテーションを付ける必要があり、これを使用して @ExceptionHandler、@InitBinder、@ModelAttribute を定義し、すべての @RequestMapping に適用できます。@RestControllerAdvice は、クラスパス スキャンによってその実装クラスを自動的に検出できるようにするコンポーネント アノテーションです。@RestControllerAdvice アノテーションは主に @ExceptionHandler と組み合わせて使用​​され、例外を均一に処理します。

  つまり、 @RestControllerAdvice アノテーションはグローバル コントローラー例外処理を定義します。

  このクラスでは、例外をキャプチャして処理するために複数のオーバーロードされたハンドラー メソッドを定義できます。ハンドラーのメソッド パラメーターはさまざまな例外です。ハンドラー メソッドには @ExceptionHandler のアノテーションを付ける必要があります。アノテーションの要素値は、キャプチャされた例外の種類を指定できます。例外は、@ExceptionHandler(value = RuntimeException.class)実行時例外のキャッチなどです。@ExceptionHandler アノテーションでマークされたこの例外の処理はグローバルであり、値 value と同じタイプのすべての例外は処理のためにこの場所に送られます。

  ハンドラー メソッドでは @ResponseStatus アノテーションを使用する必要もあります。これを @ResponseStatus アノテーションおよびカスタム例外と組み合わせて使用​​すると、カスタム応答ステータス コードとカスタム エラー メッセージをクライアントに返すことができます。つまり、@ResponseStatus アノテーションは @ExceptionHandler アノテーションと組み合わせて使用​​されます。ここでは主に、さまざまな例外に対応する http ステータス コードを設定するためにそれを使用する必要があります。@ResponseStatus アノテーションには 2 つのパラメーターがあり、value 属性は例外のステータス コードを設定し、easeon は例外の説明です。

  GlobalExceptionHandler グローバル例外処理クラスの完全なコード例は次のとおりです。

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = RuntimeException.class)
    public Result handler(RuntimeException e) {
    
    
        log.error("运行时异常:----------------{}", e.getMessage());
        return Result.fail(e.getMessage());
    }

    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(value = AccessDeniedException.class)
    public Result handler(AccessDeniedException e) {
    
    
        log.info("security权限不足:----------------{}", e.getMessage());
        return Result.fail("权限不足");
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handler(MethodArgumentNotValidException e) {
    
    
        log.info("实体校验异常:----------------{}", e.getMessage());
        BindingResult bindingResult = e.getBindingResult();
        ObjectError objectError = bindingResult.getAllErrors().stream().findFirst().get();
        return Result.fail(objectError.getDefaultMessage());
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result handler(IllegalArgumentException e) {
    
    
        log.error("Assert异常:----------------{}", e.getMessage());
        return Result.fail(e.getMessage());
    }


}

  プロジェクトにはさまざまな例外が多数あるため、例外クラスをカスタマイズし、GlobalExceptionHandler にカスタム例外のキャプチャを追加することもできます。たとえば、ログイン検証コードの例外をカスタマイズできます。

public class CaptchaException extends AuthenticationException {
    
    

    public CaptchaException(String msg) {
    
    
        super(msg);
    }
}

  次に、カスタム例外処理をグローバル例外処理に追加します。

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = CaptchaException.class)
    public Result handler(CaptchaException e) {
    
    
        log.error("登录验证码异常:----------------{}", e.getMessage());
        return Result.fail(e.getMessage());
    }

  Java の例外はすべて Throwable のサブクラスであり、例外の特定の情報を返す getMessage() メソッドが Throwable で定義されていることに注意してください: この例の MethodArgumentNotValidException は、Spring エンティティ検証で定義された BindException を継承します
ここに画像の説明を挿入
  。 BindingResult 属性。BindingResult は、結果バインディングを返すためにエンティティ クラス検証情報で使用されます。BindingResult クラスは、Spring 検証の Errors クラスを継承します。Errors クラスは、特定のオブジェクトのデータ バインディングおよび検証エラーに関する情報を格納および公開するために使用されます。bindingResult.hasErrors() は検証がパスしたかどうかを判断できます。Errors クラスには getAllErrors() メソッドがあり、グローバル フィールドとフィールド フィールドのすべてのエラーを取得するために使用されます。ObjectError クラスは、オブジェクト エラーをカプセル化するために使用されます。

フロントエンド axios ポストインターセプター

  Vue の src ディレクトリに axios.js ファイルを作成して axios を設定します。フロントエンドは axios ポストインターセプターを使用して http 応答をインターセプトし、バックエンドから返された情報を取得します。

  axios.js の完全なコード例は次のとおりです。

import axios from "axios";
import router from "./router";
import Element from "element-ui"

axios.defaults.baseURL = "http://localhost:8082"

const request = axios.create({
    
    
    timeout: 5000,
    headers: {
    
    
        'Content-Type': "application/json; charset=utf-8"
    }
})

// 后置拦截
request.interceptors.response.use(response => {
    
    
        console.log("response ->" + response)
        // 这里是response的拦截
        let res = response.data
        if (res.code === 200) {
    
    
            return response
        } else {
    
    
            Element.Message.error(!res.msg ? '系统异常' : res.msg)
            // 拒绝流程继续往下走
            return Promise.reject(response.data.msg)
        }
    },
    // 如果业务中出现异常
    error => {
    
    
        // 先看后端返没返报错信息,返了就用后端的
        if (error.response.data) {
    
    
            error.message = error.response.data.msg
        }

        // 401没权限
        if (error.response.status === 401) {
    
    
            router.push("/login")
        }

        Element.Message.error(error.message, {
    
    duration:3000})

        return Promise.reject(error)

    }
)

export default request

  ポストインターセプタの中にあるresponse => {...}と はerror => {...}、それぞれレスポンスデータとエラーリクエストの処理を表しており、レスポンスデータの場合、コードが200であればリクエストが成功したことを意味し、レスポンスが返されます。それ以外の場合は、例外処理を入力します。ここでは element-UI を使用してエラー メッセージをポップアップします。応答データのメッセージが空の場合、エラー メッセージはシステム例外です。それ以外の場合、エラー メッセージは応答データ内の例外メッセージです。呼び出します。 Promise.reject は、フォローアッププロセスを拒否します。不正なリクエストの処理も同様です

おすすめ

転載: blog.csdn.net/qq_44709990/article/details/123048867