如何優雅的處理SpringBoot接口的響應體


我們知道在開發,規范化的開發會節省很多時間,無論是代碼規范還是接口規范,如果你們的開發模式是前后端分離的,那你要和前端開發工程師進行對接,不可能因為每個人的代碼風格不統一來進行更改,統一的規范會讓我們在開發過程事半功倍,下面就看看如何統一處理響應體。

注意】在編寫實體類的時候 為了簡潔 ,我使用了 lombok 用 @Data 、@Setter 、@Getter 取消了get  set 方法,如果你們覺得不習慣,可以自己手動添加。

以下對響應體的處理,不是絕對唯一的,可根據自己的業務需要,自己定義對應的響應方式。

一、定義一個響應實體類

定義了響應的實體類,code 代表響應狀態碼,msg代表響應信息,data  代表響應的具體數據 ,這里使用了泛型,為了可以更好的兼容不同類型的返回數據。

package com.dongl.utils.response;

import lombok.Data;
/**
 * @author D-L
 * @Version 1.0
 * @Description 響應體實體類
 * @Date 2020/8/26
 */

@Data
public class ResultVO<T> {
    /**
     * 狀態碼,比如200代表響應成功
     */
    private int code;
    /**
     * 響應信息,用來說明響應情況
     */
    private String msg;
    /**
     * 響應的具體數據
     */
    private T data;

    public ResultVO(T data) {
        this(ResultCode.SUCCESS, data);
    }

    public ResultVO(ResultCode resultCode, T data) {
        this.code = resultCode.getCode();
        this.msg = resultCode.getMsg();
        this.data = data;
    }
}

 

二、定義一個響應狀態碼枚舉類(統一響應狀態)

這個響應狀態碼可以自己根據具體的業務自行定義:

package com.dongl.utils.response;
import lombok.Getter;
/**
 * @author D-L
 * @Version 1.0
 * @Description   響應狀態碼枚舉類
 * @Date 2020/8/26
 */
@Getter
public enum ResultCode {

    SUCCESS(200, "操作成功"),

    FAILED(1001, "響應失敗"),

    VALIDATE_FAILED(1002, "參數校驗失敗"),

    ERROR(5000, "未知錯誤");

    private int code;
    private String msg;

    ResultCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

 

還記得之前寫過一篇 《如何優雅的處理SpringBoot接口中參數校驗》其中有對異常的全局處理,這里可以對返回的響應數據進一步處理:

package com.dongl.utils.error;

import com.dongl.utils.response.ResultCode;
import com.dongl.utils.response.ResultVO;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author D-L
 * @Classname ExceptionControllerAdvice
 * @Version 1.0
 * @Description   全局處理參數校驗異常返回提示
 * @Date 2020/8/26
 */
@RestControllerAdvice
public class ExceptionControllerAdvice {

    @ExceptionHandler(APIException.class)
    public ResultVO<String> APIExceptionHandler(APIException e) {
        // 注意哦,這里傳遞的響應碼枚舉
        return new ResultVO<>(ResultCode.FAILED, e.getMsg());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVO<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 注意哦,這里傳遞的響應碼枚舉
        return new ResultVO<>(ResultCode.VALIDATE_FAILED, objectError.getDefaultMessage());
    }
}

返回響應體:

{
    "code": 1002,
    "msg": "參數校驗失敗",
    "data": "需要在20和99之間"
}

 

三、全局配置響應體(這里需要加上掃描的包)

這樣定義完了響應體,就需要你在編寫代碼的同時,每一個接口都要添加對應的code msg data ,雖然勉強說的過去,但是總感覺差點意思,當然我們可以統一處理,先創建一個類加上注解使其成為全局處理類。然后繼承ResponseBodyAdvice接口重寫其中的方法,即可對我們的controller進行增強操作。

package com.dongl.utils.response;

import com.dongl.utils.error.APIException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;

/**
 * @author D-L
 * @date 2020-08-27
 * @Description 全局配置 響應體
 * Version 1.0
 */
@RestControllerAdvice(basePackages = {"com.dongl.controller"}) // 注意哦,這里要加上需要掃描的包
public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {
        // 如果接口返回的類型本身就是ResultVO那就沒有必要進行額外的操作,返回false
        return !returnType.getGenericParameterType().equals(ResultVO.class);
    }

    @Override
    public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
        // String類型不能直接包裝,所以要進行些特別的處理
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 將數據包裝在ResultVO里后,再轉換為json字符串響應給前端
                return objectMapper.writeValueAsString(new ResultVO<>(data));
            } catch (JsonProcessingException e) {
                throw new APIException("返回String類型錯誤");
            }
        }
        // 將原本的數據包裝在ResultVO里
        return new ResultVO<>(data);
    }
}

【總結】響應體的定義,以及狀態碼的定義,都可以自己根據自己的需要和業務的需要自行編寫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM