天天看點

個人部落格開發之blog-api項目統一結果集api封裝

前言

由于傳回

json api

格式接口,是以我們需要通過java bean封裝一個統一資料傳回格式,便于和前端約定互動,

狀态碼枚舉ResultCode

package cn.soboys.core.ret;


import lombok.Getter;

/**
 * @author kenx
 * @version 1.0
 * @date 2021/6/17 15:35
 * 響應碼枚舉,對應HTTP狀态碼
 */
@Getter
public enum ResultCode {

    SUCCESS(200, "成功"),//成功
    //FAIL(400, "失敗"),//失敗
    BAD_REQUEST(400, "Bad Request"),
    UNAUTHORIZED(401, "認證失敗"),//未認證
    NOT_FOUND(404, "接口不存在"),//接口不存在
    INTERNAL_SERVER_ERROR(500, "系統繁忙"),//伺服器内部錯誤
    METHOD_NOT_ALLOWED(405,"方法不被允許"),

    /*參數錯誤:1001-1999*/
    PARAMS_IS_INVALID(1001, "參數無效"),
    PARAMS_IS_BLANK(1002, "參數為空");
    /*使用者錯誤2001-2999*/


    private Integer code;
    private String message;

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

           

結果體Result

package cn.soboys.core.ret;

import lombok.Data;

import java.io.Serializable;

/**
 * @author kenx
 * @version 1.0
 * @date 2021/6/17 15:47
 * 統一API響應結果格式封裝
 */
@Data
public class Result<T> implements Serializable {

    private static final long serialVersionUID = 6308315887056661996L;
    private Integer code;
    private String message;
    private T data;


    public Result setResult(ResultCode resultCode) {
        this.code = resultCode.getCode();
        this.message = resultCode.getMessage();
        return this;
    }

    public Result setResult(ResultCode resultCode, T data) {
        this.code = resultCode.getCode();
        this.message = resultCode.getMessage();
        this.setData(data);
        return this;
    }


}

           

響應結果方法工具類

package cn.soboys.core.ret;

/**
 * @author kenx
 * @version 1.0
 * @date 2021/6/17 16:30
 * 響應結果傳回封裝
 */
public class ResultResponse {
    private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";

    // 隻傳回狀态
    public static Result success() {
        return new Result()
                .setResult(ResultCode.SUCCESS);
    }

    // 成功傳回資料
    public static Result success(Object data) {
        return new Result()
                .setResult(ResultCode.SUCCESS, data);


    }

    // 失敗
    public static Result failure(ResultCode resultCode) {
        return new Result()
                .setResult(resultCode);
    }

    // 失敗
    public static Result failure(ResultCode resultCode, Object data) {
        return new Result()
                .setResult(resultCode, data);
    }



}

           

自定義解析controller攔截

注解@ResponseResult

package cn.soboys.core.ret;

import java.lang.annotation.*;

/**
 * @author kenx
 * @version 1.0
 * @date 2021/6/17 16:43
 * 統一包裝接口傳回的值 Result
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseResult {
}

           

請求攔截ResponseResultInterceptor

package cn.soboys.core.ret;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author kenx
 * @version 1.0
 * @date 2021/6/17 17:10
 * 請求攔截
 */
public class ResponseResultInterceptor implements HandlerInterceptor {

    //标記名稱
    public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //請求方法
        if (handler instanceof HandlerMethod) {
            final HandlerMethod handlerMethod = (HandlerMethod) handler;
            final Class<?> clazz = handlerMethod.getBeanType();
            final Method method = handlerMethod.getMethod();
            //判斷是否在對象上加了注解
            if (clazz.isAnnotationPresent(ResponseResult.class)) {
                //設定此請求傳回體需要包裝,往下傳遞,在ResponseBodyAdvice接口進行判斷
                request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
                //方法體上是否有注解
            } else if (method.isAnnotationPresent(ResponseResult.class)) {
                //設定此請求傳回體需要包裝,往下傳遞,在ResponseBodyAdvice接口進行判斷
                request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class));
            }
        }
        return true;
    }
}


           

請求全局解析ResponseResultHandler

package cn.soboys.core.ret;

import cn.soboys.core.utils.HttpContextUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @author kenx
 * @version 1.0
 * @date 2021/6/17 16:47
 * 全局統一響應傳回體處理
 */
@Slf4j
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {

    public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";

    /**
     * @param methodParameter
     * @param aClass
     * @return 此處如果傳回false , 則不執行目前Advice的業務
     * 是否請求包含了包裝注解 标記,沒有直接傳回不需要重寫傳回體,
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        HttpServletRequest request = HttpContextUtil.getRequest();
        //判斷請求是否有包裝标志
        ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
        return responseResultAnn == null ? false : true;
    }

    /**
     * @param body
     * @param methodParameter
     * @param mediaType
     * @param aClass
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @return 處理響應的具體業務方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (body instanceof Result) {
            return body;
        } else if (body instanceof String) {
            return JSON.toJSONString(ResultResponse.success(body));
        } else {
            return ResultResponse.success(body);
        }
    }
}
           

具體詳細内容請參考我這篇文章Spring Boot 無侵入式 實作RESTful API接口統一JSON格式傳回

關注公衆号猿小叔擷取更多幹貨分享