spring boot api 統一處理消息返回體

日常工作中經常會和前端對接,提供統一的接口返回格式,但是我們每個接口關注的業務都不一樣,按以往的寫法,每次返回的時候都要去構造一個統一的返回類型,很麻煩。可以使用 ResponseBodyAdvice 來統一處理。上代碼。

 

/**
 * @author pengbenlei
 * @Description
 * @create 2022-11-16 15:00
 */
public enum ReturnCode {

    RC100(100, "操作成功"),
    RC404(404, "找不到資源"),
    RC500(500, "系統異常,請稍後重試"),
    RC1002(1002, "登錄已過期,請重新登錄");

    /**
     * 自定義狀態碼
     **/
    private final int code;
    /**
     * 自定義描述
     **/
    private final String message;

    ReturnCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}
統一狀態枚舉
import com.leenleda.data.synchronism.common.enums.ReturnCode;
import lombok.Data;

/**
 * @author pengbenlei
 * @Description
 * @create 2022-11-16 15:00
 */
@Data
public class ResultData<T> {

    private int status;
    private String message;
    private T data;
    private long timestamp ;

    public ResultData (){
        this.timestamp = System.currentTimeMillis();
    }

    public static <T> ResultData<T> success(T data) {
        ResultData<T> resultData = new ResultData<>();
        resultData.setStatus(ReturnCode.RC100.getCode());
        resultData.setMessage(ReturnCode.RC100.getMessage());
        resultData.setData(data);
        return resultData;
    }
    public static <T> ResultData<T> success() {
        ResultData<T> resultData = new ResultData<>();
        resultData.setStatus(ReturnCode.RC100.getCode());
        resultData.setMessage(ReturnCode.RC100.getMessage());
        return resultData;
    }

    public static <t> ResultData<t> fail(int code, String message) {
        ResultData<t> resultData = new ResultData<>();
        resultData.setStatus(code);
        resultData.setMessage(message);
        return resultData;
    }

}
統一返回消息
import com.fasterxml.jackson.databind.ObjectMapper;
import com.leenleda.data.synchronism.common.enums.ReturnCode;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Map;

/**
 * @author pengbenlei
 * @Description
 * @create 2022-11-16 15:03
 */
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        if (o == null) {
            // 返回void
            return ResultData.success();
        }
        if (o instanceof String) {
            return objectMapper.writeValueAsString(ResultData.success(o));
        }
        if (o instanceof ResultData) {
            return o;
        }
        if (o instanceof Map) {
            if (((Map<?, ?>) o).get("status").equals(ReturnCode.RC404.getCode())) {
                return ResultData.fail(ReturnCode.RC404.getCode(), ReturnCode.RC404.getMessage());
            }else  if (((Map<?, ?>) o).get("status").equals(ReturnCode.RC500.getCode())) {
                return ResultData.fail(ReturnCode.RC500.getCode(), ReturnCode.RC500.getMessage());
            }
        }
        return ResultData.success(o);
    }
}
統一返回處理

以上基本就能滿足功能了,但是如果有異常的話,還是不能統一到咋們這個裏面來,所以還需要加個,全局的異常攔截。

import lombok.Data;

/**
 * @author pengbenlei
 * @Description
 * @create 2022-11-16 15:02
 */
@Data
public class BusinessException extends RuntimeException {
    private int code = 100;
    private String message;

    public BusinessException(int code, String msg) {
        this.code = code;
        this.message = msg;
    }

}
自定義業務異常
import com.leenleda.data.synchronism.admin.dto.response.ResultData;
import com.leenleda.data.synchronism.common.enums.ReturnCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.List;

/**
 * @author pengbenlei
 * @Description
 * @create 2022-11-16 15:01
 */
@Slf4j
@RestControllerAdvice
public class RestExceptionHandler {


    /**
     * 默認全局異常處理。
     *
     * @param exception the exception
     * @return ResultData
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultData<String> validException(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        String message = "";
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            if (errors != null) {
                if (errors.size() > 0) {
                    FieldError fieldError = (FieldError) errors.get(0);
                    message = fieldError.getDefaultMessage();
                }
            }
        }
        log.error("接口入參驗證異常捕獲 ex={}", message, exception);
        return ResultData.fail(ReturnCode.RC500.getCode(), message);
    }

    /**
     * 404 異常
     *
     * @param e the e
     * @return ResultData
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultData<String> notFoundException(NoHandlerFoundException e) {
        log.error("全局404異常信息 ex={}", e.getMessage(), e);
        return ResultData.fail(ReturnCode.RC404.getCode(), e.getMessage());
    }

    /**
     * 默認全局異常處理。
     *
     * @param e the e
     * @return ResultData
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultData<String> exception(Exception e) {
        log.error("全局異常信息 ex={}", e.getMessage(), e);
        return ResultData.fail(ReturnCode.RC500.getCode(), e.getMessage());
    }


    /**
     * 業務異常處理。
     *
     * @param e the e
     * @return ResultData
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultData<String> businessException(BusinessException e) {
        log.error("業務異常信息 ex={}", e.getMessage(), e);
        return ResultData.fail(e.getCode(), e.getMessage());
    }
}
全局異常攔截處理

自此,就弄完了,在平時使用時,只需要關注方法本身的返回值,例如:

/***
     * 數據源列表
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @GetMapping("/list")
    public PageVo getList(@RequestParam("page-index") int pageIndex, @RequestParam("page-size") int pageSize) {
        return datasourceInfoService.list(pageIndex, pageSize);
    }
使用示例

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章