解读MyabtisPlus中的R类(通用响应包装类)

2024-01-09 16:11:44

前言

大部分R类可以自已手写一个适配的,但MybatisPlus中有专门的R类,于是就使用封装好的类即可

1. 概念

通用R类是一种用于处理API响应的通用响应包装类。

概念含义作用示例用途
1.R类是一个泛型类,可以用于封装任意类型的API响应数据。

2.通过对响应进行包装,提供了一种一致的方式来表示成功、失败或异常情况。
1.R类的名称可能表示"Response",代表着它是用于处理响应的类。

2.通过包含业务错误码、结果集和描述信息等属性,提供了对API响应的全面描述。
1.封装响应: 提供了一种封装API响应的结构,包括成功和失败的情况。

2.统一格式: 定义了统一的响应格式,使得在不同的API请求中都能够使用相同的响应结构。

3.易于处理: 通过提供静态工厂方法和实用方法,简化了对响应的处理和判断。

4.异常处理: 通过serviceData方法,可以方便地处理服务间调用时的异常情况。

5.清晰的代码流: 使用ok方法使得代码中对成功响应的判断更加清晰,提高了代码的可读性。
1.在服务层封装的方法中,使用R类来包装成功或失败的响应,使得调用方能够清晰地了解操作的结果。

2.在Controller层中,根据R类的响应进行不同的处理,例如成功时显示数据,失败时返回错误信息。

总体而言,通用R类的设计旨在提供一种简单、灵活、一致且易于处理的方式来处理不同类型的API响应,使得代码更加清晰和可维护。

2. 源码解读

里头具体的一些方法类如下:

IErrorCode 类的接口

public interface IErrorCode {

    /**
     * 错误编码 -1、失败 0、成功
     */
    long getCode();

    /**
     * 错误描述
     */
    String getMsg();
}

ApiErrorCode实现类 (主要是code以及msg的属性类)

public enum ApiErrorCode implements IErrorCode {
    /**
     * 失败
     */
    FAILED(-1, "操作失败"),
    /**
     * 成功
     */
    SUCCESS(0, "执行成功");

    private final long code;
    private final String msg;

    ApiErrorCode(final long code, final String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static ApiErrorCode fromCode(long code) {
        ApiErrorCode[] ecs = ApiErrorCode.values();
        for (ApiErrorCode ec : ecs) {
            if (ec.getCode() == code) {
                return ec;
            }
        }
        return SUCCESS;
    }

    @Override
    public long getCode() {
        return code;
    }

    @Override
    public String getMsg() {
        return msg;
    }

    @Override
    public String toString() {
        return String.format(" ErrorCode:{code=%s, msg=%s} ", code, msg);
    }
}

再查看其源码:

package com.baomidou.mybatisplus.extension.api;

import java.io.Serializable;
import java.util.Optional;

import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;

import lombok.Data;
import lombok.experimental.Accessors;

/**
 * REST API 返回结果
 *
 * @author hubin
 * @since 2018-06-05
 */
@Data
@Accessors(chain = true)
public class R<T> implements Serializable {

    /**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 1L;
	
	/**
     * 业务错误码
     */
    private long code;
    /**
     * 结果集
     */
    private T data;
    /**
     * 描述
     */
    private String msg;

    public R() {
        // to do nothing
    }

    public R(IErrorCode errorCode) {
        errorCode = Optional.ofNullable(errorCode).orElse(ApiErrorCode.FAILED);
        this.code = errorCode.getCode();
        this.msg = errorCode.getMsg();
    }

    public static <T> R<T> ok(T data) {
        ApiErrorCode aec = ApiErrorCode.SUCCESS;
        if (data instanceof Boolean && Boolean.FALSE.equals(data)) {
            aec = ApiErrorCode.FAILED;
        }
        return restResult(data, aec);
    }

    public static <T> R<T> failed(String msg) {
        return restResult(null, ApiErrorCode.FAILED.getCode(), msg);
    }

    public static <T> R<T> failed(IErrorCode errorCode) {
        return restResult(null, errorCode);
    }

    public static <T> R<T> restResult(T data, IErrorCode errorCode) {
        return restResult(data, errorCode.getCode(), errorCode.getMsg());
    }

    private static <T> R<T> restResult(T data, long code, String msg) {
        R<T> apiResult = new R<>();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }

    public boolean ok() {
        return ApiErrorCode.SUCCESS.getCode() == code;
    }

    /**
     * 服务间调用非业务正常,异常直接释放
     */
    public T serviceData() {
        if (!ok()) {
            throw new ApiException(this.msg);
        }
        return data;
    }
}

对应该源码的相关完整知识点可看我如下文章:

  1. spring中@Data注解详细解析
  2. java之序列化与反序列化的详细解析(全)
  3. 详解Java中@Accessors注解(全)

简易的解释如下:

  • @Data:Lombok注解,用于自动生成样板代码,如getter、setter、toString和equals。
  • @Accessors(chain = true):Lombok注解,用于启用流畅的setter方法(支持方法链)。

属性如下:

  • code:表示业务错误码的属性。
  • data:表示结果集的属性。
  • msg:表示描述信息的属性。
  1. 静态工厂方法:

提供了一些静态工厂方法用于创建R对象,例如ok和failed。

public static <T> R<T> ok(T data) {
    // 创建成功响应的工厂方法
}

public static <T> R<T> failed(String msg) {
    // 创建失败响应的工厂方法
}
  1. 其他方法:
  • restResult方法用于创建R对象的实例。
  • ok方法用于判断响应是否成功。
  • serviceData方法用于在服务间调用时,处理非业务正常的情况。
public static <T> R<T> restResult(T data, IErrorCode errorCode) {
    // 创建R对象实例的方法
}

public boolean ok() {
    // 判断响应是否成功的方法
}

public T serviceData() {
    // 处理服务间调用时的方法
}

这个类的设计旨在提供一种简单而灵活的方式来处理不同类型的API响应,包括成功、失败和异常情况。

上述的源码比较简单,不做过多的解读= - =
请看下方demo辅助理解!

3. Demo

类似的Demo如下:

假设有一个用户服务,包含了一个方法用于获取用户信息:

public class UserService {

    public R<User> getUserById(Long userId) {
        // 模拟从数据库或其他服务中获取用户信息
        User user = userRepository.findById(userId);

        if (user != null) {
            // 用户存在,返回成功响应
            return R.ok(user);
        } else {
            // 用户不存在,返回失败响应
            return R.failed("User not found");
        }
    }
}

在这个例子中,UserService类中的getUserById方法使用了R类来封装API响应。如果用户存在,它会创建一个成功的R对象,否则创建一个失败的R对象。

然后,在调用这个服务的地方,可以这样处理响应:

public class UserController {

    private UserService userService;

    public void handleUserRequest(Long userId) {
        try {
            // 调用用户服务获取用户信息
            R<User> userResponse = userService.getUserById(userId);

            if (userResponse.ok()) {
                // 处理成功响应
                User user = userResponse.getData();
                System.out.println("User details: " + user);
            } else {
                // 处理失败响应
                System.out.println("Failed to get user: " + userResponse.getMsg());
            }
        } catch (ApiException e) {
            // 处理异常情况
            System.out.println("Error: " + e.getMessage());
        }
    }
}

在这个例子中,UserController类中的handleUserRequest方法处理了从UserService中获取用户信息的响应。

它检查响应是否成功,并根据情况执行相应的操作。异常情况也被捕获和处理,确保在服务调用中发生异常时能够进行适当的处理。这样的设计使得API响应的处理更加清晰和可控。

文章来源:https://blog.csdn.net/weixin_47872288/article/details/135446929
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。