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);
    }
使用示例

 

posted @ 2022-11-30 14:16  Rolay  阅读(93)  评论(0编辑  收藏  举报