zoukankan      html  css  js  c++  java
  • 如何优雅的处理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);
        }
    }

    【总结】响应体的定义,以及状态码的定义,都可以自己根据自己的需要和业务的需要自行编写。

  • 相关阅读:
    [leetcode]Largest Number
    [leetcode]Second Highest Salary
    [leetcode]Combine Two Tables
    [leetode]Binary Search Tree Iterator
    [leetcode]Excel Sheet Column Number
    [leetcode]Two Sum III
    [leetcode]Majority Element
    Mysql5.7.26解压版(免安装版)简单快速配置步骤,5分钟搞定(win10-64位系统)
    APP移动端自动化测试工具选型“兵器谱”一览(主流开源工具)
    Jmeter+jenkins如何快速搭建接口和性能测试持续集成解决方案-[基于windows篇]
  • 原文地址:https://www.cnblogs.com/dongl961230/p/13569977.html
Copyright © 2011-2022 走看看