Spring Boot グローバル例外処理ソリューション

1. カスタムの戻り結果クラス

異なるプロジェクト間の違いを考慮すると、バックエンドの戻り結果の要件が若干異なる可能性があるため、戻り結果クラスを設計するときにカスタマイズできる必要があり、HashMap にはまさにこの機能があります。さまざまなプロジェクト要件に合わせて柔軟にフィールドを追加できます。

package com.example.jiakao.pojo.response;

import com.example.jiakao.common.enhance.Jsonable;

import java.util.HashMap;

public class R extends HashMap<String,Object> implements Jsonable {
    private static final String K_CODE = "code";
    private static final String K_MSG = "msg";
    private static final String K_DATA = "data";
    private static final int CODE_SUCCESS = 200;
    private static final int CODE_ERROR_DEFAULT = 400;
    public R setSuccess(){
        return setCode(CODE_SUCCESS);
    }
    public R setError(){
        return setCode(CODE_ERROR_DEFAULT);
    }
    public R setCode(int code){
        put(K_CODE, code);
        return this;
    }
    public R setMsg(String msg){
        put(K_MSG,msg);
        return this;
    }
    public R setData(Object data){
        put(K_DATA,data);
        return this;
    }

}

Jsonable インターフェースは一般的なシリアル化メソッドを提供します

package com.example.jiakao.common.enhance;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public interface Jsonable {
    default String json() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(this);
    }
}

プロジェクトの戻り結果クラスをカスタマイズします。プロジェクトの戻り結果は、Rs の静的メソッドを通じて構築されます。ここで、さまざまなプロジェクトに必要なフィールドをカスタマイズして追加できます。ここでは、例外インターフェイスにメソッド フィールドを追加して、インターフェイス パスを記録します。

package com.example.jiakao.common.util;

import com.example.jiakao.pojo.response.R;

public class Rs {
    private static final String DEFAULT_SUCCESS_MSG = "操作成功";
    private static final String DEFAULT_ERROR_MSG = "操作失败";
    private static final String K_METHOD = "method";

    public static R error(String method){
        R r = new R();
        r.put(K_METHOD, method);
        return r.setError().setMsg(DEFAULT_ERROR_MSG);
    }
    public static R error(String msg,String method){
        R r = new R();
        r.put(K_METHOD, method);
        return r.setError().setMsg(msg);
    }
    public static R error(int code, String msg,String method){
        R r = new R();
        r.put(K_METHOD, method);
        return r.setCode(code).setMsg(msg);
    }

    public static R ok(){
        return new R().setSuccess().setMsg(DEFAULT_SUCCESS_MSG);
    }
    public static R ok(String msg){
        return new R().setSuccess().setMsg(msg);
    }
    public static R ok(String msg, Object data){
        return new R().setSuccess().setMsg(msg).setData(data);
    }
    public static R ok(Object data){
        return new R().setSuccess().setMsg(DEFAULT_SUCCESS_MSG).setData(data);
    }
}

2. HttpException をカプセル化して例外のキャプチャを容易にする

package com.example.jiakao.Exception.http;

import lombok.Data;

@Data
public class HttpException extends RuntimeException {
    protected Integer code;
//    服务器内部错误
    protected Integer httpStatusCode = 500;
    public HttpException(int code) {
        this.code = code;
    }
}

一般的に使用される 400、401、403、および 404 はすべて、HttpException 設定に対応するステータス コードから継承されます。

package com.example.jiakao.Exception.http;

public class ArgumentsException extends HttpException {
    public ArgumentsException(int code) {
        super(code);
//        参数错误、请求出错
        this.httpStatusCode = 400;
    }
}
package com.example.jiakao.Exception.http;

public class UnauthorizedException extends HttpException{
    public UnauthorizedException(int code) {
        super(code);
//        未授权
        this.httpStatusCode = 403;
    }
}
package com.example.jiakao.Exception.http;

public class ForbiddenException extends HttpException{
    public ForbiddenException(int code) {
        super(code);
//        禁止访问
        this.httpStatusCode = 403;
    }
}
package com.example.jiakao.Exception.http;

public class NotFoundException extends HttpException{
    public NotFoundException(int code) {
        super(code);
//        资源不存在
        this.httpStatusCode = 404;
    }
}

3.一元管理に便利な中国語メッセージに対応した異常コードのプロパティファイルを記述する

# 通用异常状态码
exception.codes[400] = 请求出错
exception.codes[401] = 未授权
exception.codes[403] = 禁止访问
exception.codes[404] = 资源不存在
exception.codes[500] = 服务器内部错误

# 自定义异常码
exception.codes[40000] = 参数错误
exception.codes[40001] = 用户已存在

4. 例外コードメッセージ読み込みインジェクションクラス

これはカスタム例外メッセージを読み取るために使用されるため、例外がスローされたときにコードを渡すだけで対応する例外メッセージを取得できます。

package com.example.jiakao.Exception.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

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

@ConfigurationProperties(prefix = "exception")
@PropertySource(value = "classpath:config/exception-code.properties")
@Component
@Data
public class ExceptionCodeConfiguration {
    private Map<Integer,String> codes = new HashMap<>();

    public String getMessage(int code) {
        String message = codes.get(code);
        if(message == null){
            message = "未定义错误";
        }
        return message;
    }
}

5. グローバル例外キャプチャ

ここでは、カスタム HttpException は個別にキャプチャされ、handleHttpException によって処理されます。HttpException 以外の例外については、handleException メソッドが統合処理に使用されます。

package com.example.jiakao.Exception;

import com.example.jiakao.Exception.config.ExceptionCodeConfiguration;
import com.example.jiakao.Exception.http.HttpException;
import com.example.jiakao.common.util.Rs;
import com.example.jiakao.pojo.response.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class GlobalExceptionAdvice {
    @Autowired
    private ExceptionCodeConfiguration codeConfiguration;

    @ExceptionHandler(value=Exception.class)
    @ResponseBody
    @ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
    public R handleException(HttpServletRequest req, Exception e) {
        e.printStackTrace();
        String reqUrl = req.getRequestURI();
        String method = req.getMethod();
        return Rs.error(9999,"未知异常",method + " " + reqUrl);
    }

    @ExceptionHandler(HttpException.class)
    public ResponseEntity<R> handleHttpException(HttpServletRequest req, HttpException e){
        String reqUrl = req.getRequestURI();
        String method = req.getMethod();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
        ResponseEntity<R> r = new ResponseEntity<>(Rs.error(e.getCode(), codeConfiguration.getMessage(e.getCode()),method + " " + reqUrl), headers,httpStatus);
        return r;
    }
}

おすすめ

転載: blog.csdn.net/qq_33235279/article/details/129790624