ホームページ  >  記事  >  Java  >  SpringBootのグローバル例外問題を解決する方法

SpringBootのグローバル例外問題を解決する方法

王林
王林転載
2023-05-16 10:49:121587ブラウズ

SpringBoot は、Spring アプリケーションの作成、実行、デバッグ、デプロイメントなどの一連の問題を簡素化するために生まれた製品です。自動アセンブリの機能により、外部の XML ではなくビジネス自体に集中できるようになります。仕様に従い、関連する依存関係を導入するだけで、簡単に WEB プロジェクトを構築できます。

実際のプロジェクト開発では、特にサーバーとしてのプログラムでさまざまな異常事態が頻繁に発生します。開発者の皆さん、私たちは常にフロントエンドの呼び出しに提供するインターフェイスを作成しています。分業と協力の場合、例外は避けられません。間違った情報がユーザーに直接さらされた場合、そのエクスペリエンスは想像できますし、実際にそうなるでしょう。ハッカーにとって、詳細な例外情報は多くの場合非常に役立ちます...

try-catch メソッドを採用して例外情報を手動で取得し、対応する結果セットを返します。同様のコードを見たことがあります (例: Result オブジェクトにカプセル化されています); このメソッドはエラーの危険性の問題を間接的に解決しますが、コードの量が増加するという同じ欠点も明らかです。例外が多すぎると、対応するキャッチがこれらのビジネス例外とエラー コードの一致を管理するのは難しいため、シンプルな構成で全体的な状況を制御するのが最善の方法です...

を見てみましょう。 Spring Boot によって提供されるソリューション

1 依存関係をインポートする

pom.xml に spring-boot-starter-web 依存関係を追加する

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

例外をカスタマイズする
アプリケーション開発プロセス中, ただし、システム自体の例外に加えて、さまざまなビジネス シナリオで使用される例外も異なります。「グローバル例外を簡単に取得する」のタイトルにもっと関連するように、独自の例外を定義し、キャプチャする方法を確認してください...

package com.battcn.exception;

/**
 * 自定义异常
 *
 * @author Levin
 * @since
public class CustomException extends RuntimeException

    private static final long serialVersionUID = 4564124491192825748L;

    private int code;

    public CustomException() {
        super();
    }

    public CustomException(int code, String message) {
        super(message);
        this.setCode(code);
    }

    public int getCode() {
        return code;
    }

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

2 例外情報テンプレート

例外情報のスタイルがより統一されるように、返される例外情報の形式を定義します

package com.battcn.exception;

/**
 * @author Levin
 * @since
public class ErrorResponseEntity

    private int code;
    private String message;
    // 省略 get set

3 制御層

通常書いたコードと同じかどうかよく見てください。何が違うのでしょうか。心配しないで読み続けてください...

package com.battcn.controller;

import com.battcn.exception.CustomException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常演示
 *
 * @author Levin
 * @since
@RestController
public class ExceptionController

    @GetMapping("/test3")
    public String test3(Integer num) {
        // TODO 演示需要,实际上参数是否为空通过 @RequestParam(required = true)  就可以控制
        if (num == null) {
            throw new CustomException(400, "num不能为空");
        }
        int i = 10 / num;
        return "result:"

4 例外処理 (キー)

アノテーションの概要:

  • @ControllerAdviceController 層がスローした例外をキャッチする @ResponseBody を付加すると、返される情報は JSON 形式になります。

  • @RestControllerAdvice@ControllerAdvice と @ResponseBody の組み合わせと同等です。

  • @ExceptionHandlerコードの重複と複雑さを軽減するために、1 種類の例外を統一的に処理します。

GlobalExceptionHandler クラスを作成し、 @RestControllerAdvice アノテーションを追加して例外通知クラスを定義し、定義されたメソッドに @ExceptionHandler を追加して例外キャプチャを実現します...

package com.battcn.config;

import com.battcn.exception.CustomException;
import com.battcn.exception.ErrorResponseEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 全局异常处理
 *
 * @author Levin
 * @since
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler


    /**
     * 定义要捕获的异常 可以多个 @ExceptionHandler({})
     *
     * @param request  request
     * @param e        exception
     * @param response response
     * @return
    @ExceptionHandler(CustomException.class)
    public ErrorResponseEntity customExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        CustomException exception = (CustomException) e;
        return new ErrorResponseEntity(exception.getCode(), exception.getMessage());
    }

    /**
     * 捕获  RuntimeException 异常
     * TODO  如果你觉得在一个 exceptionHandler 通过  if (e instanceof xxxException) 太麻烦
     * TODO  那么你还可以自己写多个不同的 exceptionHandler 处理不同异常
     *
     * @param request  request
     * @param e        exception
     * @param response response
     * @return
    @ExceptionHandler(RuntimeException.class)
    public ErrorResponseEntity runtimeExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        RuntimeException exception = (RuntimeException) e;
        return new ErrorResponseEntity(400, exception.getMessage());
    }

    /**
     * 通用的接口映射异常处理方
     */
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
                                                             HttpStatus status, WebRequest request) {
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
        }
        if (ex instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
            logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName() + ",参数:" + exception.getName()
                    + ",信息:" + exception.getLocalizedMessage());
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
        }
        return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
    }
}

テスト

準備が完了したら、Chapter17Applicationを起動してください。以下のテスト結果を見ると、非常に簡単で、コードもすっきりし、スケーラビリティも向上していることがわかります...

http://localhost:8080/test3にアクセスします

{"code":400,"message":"num不能为空"}

http://localhost:8080/test3?num=0

{"code":400,"message":"/ by zero"}

にアクセスしますhttp://localhost:8080 /test3?num=5

result:2

以上がSpringBootのグローバル例外問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。