业务项目自定义响应包装类和请求类

序言

现公司的很多东西,都是一团糟,所以很多东西,都需要重新去规范

对响应结果的统一包装

import com.xingren.common.exceptions.ApiCallException;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.Optional;

/**
 * API调用结果类
 */
@Data
@ApiModel(value="API调用结果")
public class JsonResult<T> {

    /**
     * 是否成功
     */
    @ApiModelProperty(name = "是否成功")
    private boolean success;

    /**
     * 响应结果
     */
    @ApiModelProperty(name = "响应结果")
    private Optional<T> data = Optional.empty();

    /**
     * 错误码
     */
    @ApiModelProperty(name = "错误码")
    private Optional<Integer> errCode = Optional.empty();

    /**
     * 错误消息
     */
    @ApiModelProperty(name = "错误消息")
    private Optional<String> errMessage = Optional.empty();

    /**
     * 检查传入的调用结果,如果成功并且响应结果不为空,则返回响应结果,否则抛出{@code ApiCallException}。
     *
     * @param result
     * @param <T>
     * @return
     */
    public static <T> T checkAndExtract(@NotNull JsonResult<T> result) {
        if (result.isSuccess() && result.getData().isPresent()) {
            return result.getData().get();
        }
        throw new ApiCallException(result);
    }

    /**
     * 检查传入的调用结果,如果成功,则返回响应结果,否则抛出{@code ApiCallException}。
     *
     * @param result
     * @param <T>
     * @return
     */
    public static <T> Optional<T> checkAndExtractOptional(@NotNull JsonResult<T> result) {
        if (result.isSuccess()) {
            return result.getData();
        }
        throw new ApiCallException(result);
    }

    /**
     * 生成服务调用成功响应
     *
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> ok() {
        JsonResult<T> result = new JsonResult<>();
        result.setSuccess(true);
        return result;
    }

    /**
     * 生成服务调用成功响应
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> ok(@NotNull T data) {
        JsonResult<T> result = new JsonResult<>();
        result.setSuccess(true);
        result.setData(Optional.of(data));
        return result;
    }

    /**
     * 生成服务调用成功响应--Optional
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> ok(@NotNull Optional<T> data) {
        JsonResult<T> result = new JsonResult<>();
        result.setSuccess(true);
        result.setData(data);
        return result;
    }

    /**
     * 生成服务调用错误响应
     *
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> error() {
        return error(Errors.SERVER_ERROR);
    }

    /**
     * 生成服务调用错误响应
     *
     * @param errorMessage
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> error(String errorMessage) {
        return error(Errors.SERVER_ERROR.getCode(), errorMessage);
    }

    /**
     * 生成服务调用错误响应
     *
     * @param error
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> error(Error error) {
        return error(error.getCode(), error.getMessage());
    }

    /**
     * 生成服务调用错误响应
     *
     * @param errorCode
     * @param errorMessage
     * @param <T>
     * @return
     */
    public static <T> JsonResult<T> error(Integer errorCode, String errorMessage) {
        JsonResult<T> result = new JsonResult<>();
        result.setErrCode(Optional.of(errorCode));
        result.setErrMessage(Optional.ofNullable(errorMessage));
        return result;
    }
}

分页情况的包装类

import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collector;
import java.util.stream.Stream;

/**
 * 分页查询结果,同时提供Lambda风格的接口。
 * <pre>
 *     Pagination<String> dest = src.stream().map(String::valueOf).collect(Pagination.toPagination(src.getPage(), src.getSize(), src.getTotal()));
 * </pre>
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pagination<T> {

    /**
     * 查询记录集
     */
    private List<T> content = Lists.newArrayList();

    /**
     * 当前页索引
     */
    private Integer page;

    /**
     * 当前页容量
     */
    private Integer size;

    /**
     * 总记录数
     *
     * @deprecated 如非必要,否则尽量不要赋值,也即业务无需显示精确页数
     */
    @Deprecated
    private Optional<Integer> total = Optional.empty();

    /**
     * 是否可以查询下一页
     * <p>
     * 实现逻辑:hasNext = content.size() == size,从而避免因查询数据量大导致count慢查询
     * 含义:只有当值为true时,才表示当前页"有可能"不是最后一页(缺点:如果最后一页数据的size刚好等于页的size时,会多一次无用的分页查询)
     */
    private Optional<Boolean> hasNext = Optional.empty();

    /**
     * 隐藏构造函数,使用工厂方法。
     */
    private Pagination(List<T> content, Integer page, Integer size) {
        this.content = content;
        this.page = page;
        this.size = size;
    }

    /**
     * 构造单页结果(content, 0, content.size())
     */
    public static <E> Pagination<E> of(List<E> content) {
        return new Pagination<E>(content, 0, content.size());
    }

    /**
     * 构造分页结果(content, page, content.size())
     */
    public static <E> Pagination<E> of(List<E> content, Integer page) {
        return new Pagination<E>(content, page, content.size());
    }

    public Stream<T> stream() {
        return content.stream();
    }

    public Stream<T> parallelStream() {
        return content.parallelStream();
    }

    /**
     * 实现 Stream -> Pagination 的{@code Collector}。
     */
    public static <T> Collector<T, ?, Pagination<T>> toPagination(Integer page, Integer size, Optional<Integer> total) {
        return Collector.of(() -> {
                    Pagination<T> pagination = new Pagination<>();
                    pagination.setPage(page);
                    pagination.setSize(size);
                    pagination.setTotal(total);
                    return pagination;
                }, (pagination, elm) -> pagination.getContent().add(elm),
                (left, right) -> {
                    left.getContent().addAll(right.getContent());
                    return left;
                });
    }

    /**
     * 实现 Stream -> Pagination 的{@code Collector}。
     */
    public static <T> Collector<T, ?, Pagination<T>> toPagination(Integer page, Integer size,
                                                                  Optional<Integer> total, Optional<Boolean> hasNext) {
        return Collector.of(() -> {
                    Pagination<T> pagination = new Pagination<>();
                    pagination.setPage(page);
                    pagination.setSize(size);
                    pagination.setTotal(total);
                    pagination.setHasNext(hasNext);
                    return pagination;
                }, (pagination, elm) -> pagination.getContent().add(elm),
                (left, right) -> {
                    left.getContent().addAll(right.getContent());
                    return left;
                });
    }
}

请求包装类

这一块,如果Controller使用的是springMVC那一套的东西,可以使用Spring Data JPA包中的Pageable类。

用法:

public JsonResult<Pagination<StockCheckVO>> queryCheckList(@Valid StockCheckQuery query,
                                                           @PageableDefault(sort = {"created"},
                                                                     direction = Sort.Direction.DESC)
                                                                     Pageable pageable) {

}

但是如果Controller层,公司重写了一套,比如我司,就不好使用Pageable了。这时就得自定义:

import lombok.Data;

@Data
public class Pageable {

    /**
     * 页号
     */
    private int pageNum;

    /**
     * 一页条数
     */
    private int pageSize;

    /**
     * 总页数
     */
    private int pages;

    /**
     * 总记录数
     */
    private int total;

}

个人总结,仅供参考,山鬼谣me;

上一篇:《关系营销2.0——社交网络时代的营销之道》一第1章 克服恐惧,开始关系营销


下一篇:spring-cloud微服务之【服务降级】【Hystrix】--持续更新