This is the 25th day of my participation in the August Challenge

In back-end development, different types of data will be obtained and returned in different business scenarios, and the diversity of data formats is a huge disaster for front-end colleagues, which requires the data returned by back-end interfaces to form a unified and standardized result type. Standardization of data interaction is a very important thing in the process of front-end development, which not only reduces the problems in the process of front-end interaction, but also makes the code logic more organized.

SpringBoot returns a unified result

Encapsulate the return result class

Returns the basic characteristics of the result class

For the returned data from the back end, we should consider returning the data in the same format. After developing so many back-end interfaces, we can conclude from our experience that the following indicators need to be paid attention to when requesting an interface:

  • The response status code is the status code returned by the request interface, such as 200, 304, and 500 in the HTTP request
  • Description of response results. If some interface requests succeed or fail, the description must be returned for the front-end display
  • In response to the resulting data, most interfaces return the data retrieved from the back end and present it as a list in the front end page
  • Success or not: When requesting an interface in a practical project, the first concern should be whether the request of the interface is successful or not, and then the successful return data or error code and information will be paid attention to. Therefore, we also add the identification of whether the request is successful in the unified data.
  • Other identifiers: To display more information about interface invocation, the interface invocation time may be added based on actual service requirements.

In addition to the above attributes, the return result class should also be defined as:

  1. Attribute privatization, using get/set methods to manipulate attribute values
  2. The constructor is private, only methods can be called externally, and initialization is done inside the class
  3. Methods are defined as static methods because they need to be called directly from the outside
  4. The result of each method should be the class itself, better using chained programming

Loose customization returns results

The following code shows the return result class information we defined:

@Data
public class Result {
    // Whether the request succeeded
    private Boolean success;
    private Integer code;
    private String desc;
    private Object data;
    // Request time
    //private long timestamp;
    
    // Constructor is private
    private Result(a) {}/** * returns general success *@return Result
     */
    public static Result ok(a){
        Result result = new Result();
        result.setSuccess(true);
        result.setCode("20000");
        result.setDesc("Request successful");
        return result;
    }

    /** * returns general failure, unknown error *@return Result
     */
    public static Result error(a){
        Result result = new Result();
        result.setSuccess(false);
        result.setCode(20001);
        result.setDesc("Request failed");
        returnresult; }... }Copy the code

When the return result class is defined in the code, the return value in each method still needs to be added manually, which increases the risk of data errors and increases the amount of work when the data changes. Therefore, we define all possible returns as enumeration class constants in the return result class using the corresponding enumeration class return to create.

State code enumeration class

The use of enumerated classes further normalizes the value of attributes defined in the return result class.

@Getter
public enum ResultCodeEnum {

    SUCCESS(true.20000."Response successful"),
    UNKNOWN_ERROR(false.20001."Unknown error"),
    PARAM_ERROR(false.20002."Parameter error"),
    NULL_POINT_ERROR(false.20003."Null pointer exception"),
    HTTP_CLIENT_ERROR(false.20003."Abnormal client connection");

    /** * Whether the response was successful */
    private Boolean success;
    
    /** * Response status code */
    private Integer code;

    /** * Response description */
    private String desc;

    ResultCodeEnum(Boolean success, Integer code, String desc){
        this.success = success;
        this.code = code;
        this.desc = desc; }}Copy the code

Enumeration class + custom return result class

@Data
public class Result {
    // Whether the request succeeded
    private Boolean success;
    private Integer code;
    private String desc;
    private Object data;
    // Request time
    //private long timestamp;
    // Constructor is private
    private Result(a) {}/** * returns general success *@return Result
     */
    public static Result ok(a){
        Result result = new Result();
        result.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        result.setCode(ResultCodeEnum.SUCCESS.getCode());
        result.setDesc(ResultCodeEnum.SUCCESS.getDesc());
        return result;
    }

    /** * returns general failure, unknown error *@return Result
     */
    public static Result error(a){
        Result result = new Result();
        result.setSuccess(ResultCodeEnum.UNKNOWN_ERROR.getSuccess());
        result.setCode(ResultCodeEnum.UNKNOWN_ERROR.getCode());
        result.setDesc(ResultCodeEnum.UNKNOWN_ERROR.getDesc());
        return result;
    }

    /** * Returns the result * using enumeration class Settings@param resultCodeEnum
     * @return* /
    public static Result setResult(ResultCodeEnum resultCodeEnum){
        Result result = new Result();
        result.setSuccess(resultCodeEnum.getSuccess());
        result.setCode(resultCodeEnum.getCode());
        result.setDesc(resultCodeEnum.getDesc());
        return result;
    }
    
    /** * returns the result class, using chained programming * custom success identifier *@param 
     * @return* /
     public Result success(Boolen success){
        this.setSuccess(success);
        return this;
    }
    
    /** * returns the result class, using chained programming * custom status code *@param 
     * @return* /
     public Result code(Integer code){
        this.setCode(code);
        return this;
    }
    
    /** * return result class, use chain programming * custom return result description *@param 
     * @return* /
     public Result desc(String desc){
        this.setDesc(desc);
        return this;
    }
    
    /** * returns the result class, using chained programming * custom result data *@param 
     * @return* /
     public Result data(Object data){
        this.setData(data);
        return this; }}Copy the code

Interface request

After defining the return enumeration class and the return result class, we create an interface in the Controller controller and return the uniform result class information, which returns the result in the following format:

  "success"true."code"20000."desc""Query successful"."data": {
    "itms": [{"id""1"."username""admin"."role""ADMIN"}, {"id""2"."username""zhangsan"."role""USER",}]}}Copy the code

In this way, a unified return class is created, and we can use our custom unified return class during the development of the project. We just need to maintain our return result enumeration class.