ホームページ >Java >&#&チュートリアル >SpringBoot 統合インターフェイスの戻り値とグローバル例外を処理する方法

SpringBoot 統合インターフェイスの戻り値とグローバル例外を処理する方法

PHPz
PHPz転載
2023-05-12 16:01:061860ブラウズ

1. SpringBoot は統一された戻り形式を使用しません

デフォルトでは、SpringBoot には次の 3 つの戻り状況があります。

1.1 文字列を使用して返します

@GetMapping("/getUserName")
public String getUserName(){
    return "HuaGe";
}

インターフェイスを呼び出して結果を返します:

HuaGe

1.2 エンティティ クラスを使用して返します

@GetMapping("/getUserName")
public User getUserName(){
    return new User("HuaGe",18,"男");
}

インターフェイスを呼び出します結果を返します:

{
  "name": "HuaGe",
  "age": "18",
  "性别": "男", 
}

1.3 異常な状況での復帰

@GetMapping("/getUserName")
public static String getUserName(){
    HashMap hashMap = Maps.newHashMap();
    return hashMap.get(0).toString();
}

ヌル ポインタ例外をシミュレートします。例外処理を行わずに、SpringBoot:## のデフォルトの戻り結果を確認できます。 #

{
    "timestamp": "2021-08-09T06:56:41.524+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/sysUser/getUserName"
}

上記の状況で、プロジェクト全体が統一された戻り形式を定義しておらず、5 人のバックエンド開発者が 5 つの戻り形式を定義している場合、コードが肥大化するだけでなく、フロントエンドとバックエンドのドッキングが発生します。フロントエンドが例外の詳細を直接表示するなど、特定の状況が発生すると、ユーザーのエクスペリエンスが非常に低下します。

2. 基本的なゲームプレイ

プロジェクトで最も一般的なことは、ツール クラスをカプセル化することです。返される必要があるフィールド情報はクラスで定義され、返される必要があるインターフェイス情報はクラスで定義されます。フロントエンドに返されるデータは、このクラスを通じてカプセル化されます。これにより、一貫性のない戻り形式の問題を解決できます。

2.1 パラメータの説明

  • code: ステータス コード。バックグラウンドではステータス コードの統一セットを維持できます。

  • message: 説明情報、インターフェイス呼び出しの成功/失敗のプロンプト情報;

  • data: データを返します。

  • #2.2 プロセスの説明

    #新しい結果クラス
  • #

    public class Result<T> {
        
        private int code;
        
        private String message;
        
        private T data;
    
        public Result() {}
        public Result(int code, String message) {
            this.code = code;
            this.message = message;
        }
        
        /**
         * 成功
         */
        public static <T> Result<T> success(T data) {
            Result<T> result = new Result<T>();
            result.setCode(ResultMsgEnum.SUCCESS.getCode());
            result.setMessage(ResultMsgEnum.SUCCESS.getMessage());
            result.setData(data);
            return result;
        }
    
        /**
         * 失败
         */
        public static <T> Result<T> error(int code, String message) {
            return new Result(code, message);
        }
    }

    戻りステータス コードを定義します
public enum ResultMsgEnum {
    SUCCESS(0, "成功"),
    FAIL(-1, "失败"),
    AUTH_ERROR(502, "授权失败!"),
    SERVER_BUSY(503, "服务器正忙,请稍后再试!"),
    DATABASE_OPERATION_FAILED(504, "数据库操作失败");
    private int code;
    private String message;

    ResultMsgEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public int getCode() {
        return this.code;
    }
    
    public String getMessage() {
        return this.message;
    }
}

#使用法

  • 上記の 2 つの手順で を定義しますデータ戻り形式

  • ステータス コード
。次に、それをインターフェイスで使用する方法を確認する必要があります。

@GetMapping("/getUserName")
public Result getUserName(){
    return Result.success("huage");
}
呼び出し結果は以下の通りで、Resultで定義したパラメータの型であることがわかります。
{
    "code": 0,
    "message": "成功",
    "data": "huage"
}
この方法で書くことで日々のニーズを満たすことができ、多くの友人がこの方法を使用していると思いますが、多数のインターフェイスがある場合は、各インターフェイスで Result.success## を使用します #返された情報をパッケージ化すると、繰り返されるコードが大量に追加されることになりますが、これは十分にエレガントではなく、見せびらかすには恥ずかしいことさえあります。コードを再度改善して最適な解決策を達成する方法が必要です。

3. 応用的な使い方

基本的な使い方を学んだ後は、主に次の 2 つの知識を使用した究極版を見てみましょう。 、または若い女性を指導することは必要なスキルです。 3.1 クラスの紹介

ResponseBodyAdvice:

このインターフェイスは SpringMVC 4.1 によって提供され、

@ResponseBody
    の実行を可能にします。カスタマイズされた戻りデータは、統一データ形式の戻り値をカプセル化するために使用されます;
  • @RestControllerAdvice: このアノテーションはコントローラーの拡張機能であり、スローされた例外をグローバルにキャプチャできます。

  • #3.2 使用手順

    新しい
  • ResponseAdvice
クラスを作成します。

  • implementation

    ResponseBodyAdvice インターフェイス、supports

  • beforeBodyWrite
  • メソッドを実装します;

    このクラスは、戻り値を均一にカプセル化するために使用されます。コントローラーの結果のインターフェイスの。

    @RestControllerAdvice
    public class ResponseAdvice implements ResponseBodyAdvice<Object> {
        @Autowired
        private ObjectMapper objectMapper;
    
        /**
         * 是否开启功能 true:是 
         */
        @Override
        public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
            return true;
        }
    
        /**
         * 处理返回结果
         */
        @Override
        public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
            //处理字符串类型数据
            if(o instanceof String){
                try {
                    return objectMapper.writeValueAsString(Result.success(o));
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
            }
            return Result.success(o);
        }
    }

  • getUserName
  • インターフェイスを通じてテストできます。

    Result

    を直接使用して返される結果が一貫していることがわかります。
しかし、慎重な友人なら、

ResponseAdvice では、結果の処理に Result.success(o) が使用されており、エラー タイプの結果が「未処理」であることに気づいたはずです。例外が発生したときに返される結果は何でしょうか?上記の HashMap null ポインター例外コードを引き続き使用すると、テスト結果は次のようになります。

{
    "code": 0,
    "message": "成功",
    "data": {
        "timestamp": "2021-08-09T09:33:26.805+00:00",
        "status": 405,
        "error": "Method Not Allowed",
        "path": "/sysUser/getUserName"
    }
}

形式には問題ありませんが、コードおよびデータ フィールド内の特定のデータが不親切であるか、正しくありません。これらの問題をうまく処理できないと、フロントエンドの姉妹の心の中の背の高いイメージに深刻な影響を与えることになり、これは決して許されません。

3.3 グローバル例外ハンドラ過去に例外に遭遇したとき、最初に思い浮かんだのは try..catch..final でしたが、この方法では多くのことが起こります。メンテナンスの困難さやロジックの肥大化などの問題は、私たちが望む結果ではありません。

今日使用するグローバル例外処理方法は、比較的簡単に使用できます。まず、新しいクラスを追加し、

@RestControllerAdvice

アノテーションを追加します。このアノテーションの機能は Hua 兄弟がすでに紹介しているので、詳細は説明しません。

@RestControllerAdvice
public class CustomerExceptionHandler {
    
}

インターセプトしたい例外タイプがある場合は、新しいメソッドを追加し、

@ExceptionHandler

アノテーションを使用して変更します。アノテーション パラメーターはターゲットの例外タイプです。

例: コントローラーのインターフェイスで例外が発生すると、Execption

メソッドを入力してそれをキャプチャし、乱雑な例外情報を指定された形式に変換して、コントローラーに渡します。

ResponseAdviceメソッドは、データを統一形式でカプセル化し、フロントエンド パートナーに返します。

@RestControllerAdvice
@Slf4j
public class CustomerExceptionHandler {

    @ExceptionHandler(AuthException.class)
    public String ErrorHandler(AuthorizationException e) {
        log.error("没有通过权限验证!", e);
        return "没有通过权限验证!";
    }

    @ExceptionHandler(Exception.class)
    public Result Execption(Exception e) {
        log.error("未知异常!", e);
        return Result.error(ResultMsgEnum.SERVER_BUSY.getCode(),ResultMsgEnum.SERVER_BUSY.getMessage());
    }
}

再次调用接口getUserName查看返回结果,会发现还是有一些问题,因为我们在CustomerExceptionHandler中已经将接口返回结果封装成Result类型,而代码执行到统一结果返回类ResponseAdvice时,又会结果再次封装,就出现了如下问题。

{
    "code": 0,
    "message": "成功",
    "data": {
        "code": 503,
        "message": "服务器正忙,请稍后再试!",
        "data": null
    }
}

3.4 统一返回结果处理类最终版

解决上述问题非常简单,只要在beforeBodyWrite中增加一条判断即可。

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 是否开启功能 true:开启
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * 处理返回结果
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //处理字符串类型数据
        if(o instanceof String){
            try {
                return objectMapper.writeValueAsString(Result.success(o));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        //返回类型是否已经封装
        if(o instanceof Result){
            return o;
        }
        return Result.success(o);
    }
}

以上がSpringBoot 統合インターフェイスの戻り値とグローバル例外を処理する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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