项目经验_之_常用规范类
前言
Github:https://github.com/HealerJean
一、常用类
1、枚举
1)CodeEnum
package com.healerjean.proj.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * CodeEnum
 *
 * @author zhangyujin
 * @date 2023/6/12  10:41.
 */
public interface CodeEnum {
    @Getter
    @AllArgsConstructor
    enum ErrorCodeEnum implements CodeEnum {
        ERROR_CODE_SUCCESS("00000", "成功"),
        ERROR_CODE_PARAMS_ERROR("10000", "参数错误"),
        ERROR_CODE_BUSINESS_ERROR("20000", "业务处理失败"),
        ERROR_CODE_PRC_ERROR("30000", "RPC处理失败"),
        ERROR_CODE_RUNTIME_ERROR("40000", "运行时失败"),
        ERROR_CODE_FAIL("99999", "系统太火爆了,请稍后重试!"),
        ;
        private final String code;
        private final String msg;
    }
    @Getter
    @AllArgsConstructor
    enum BusinessErrorEnum implements CodeEnum {
        ERROR_CODE_20000("20000", "业务处理失败", "系统太火爆了,请稍后重试!"),
        ERROR_CODE_20001("20001", "订单创建失败", "您有一个订单正在创建,请稍后查看"),
        ERROR_CODE_20002("20002", "付款失败,存在创建中的订单", "您的订单付款失败,请稍后查看"),
        ERROR_CODE_20003("20003", "付款失败,存在未支付的订单", "您的订单付款失败,请稍后查看"),
        ;
        private final String code;
        private final String msg;
        private final String showMsg;
    }
    @Getter
    @AllArgsConstructor
    enum ParamsErrorEnum implements CodeEnum {
        ERROR_CODE_10000("10000", "参数错误"),
        ERROR_CODE_10001("10001", "不支持的请求方式"),
        ERROR_CODE_10002("10002", "参数格式异常"),
        ;
        private final String code;
        private final String msg;
    }
    @Getter
    @AllArgsConstructor
    enum RpcErrorEnum implements CodeEnum {
        /**
         * 系统_失败分类(请求0、返回1)_业务_方法_调用方CODE码(代码补齐)
         */
        ERROR_CODE_USER_0_30001_0001("USER_0_30001_0001", "RPC异常-USER-用户信息-查询单个用户信息-接口调用失败"),
        ERROR_CODE_USER_1_30001_0001("USER_1_30001_0001", "RPC异常-USER-用户信息-查询单个用户信息-接口返回失败"),
        ERROR_CODE_USER_1_30001_0002("USER_1_30001_0002", "RPC异常-USER-用户信息-分页查询用户信息-接口返回失败"),
        ;
        private final String code;
        private final String msg;
    }
    @Getter
    @AllArgsConstructor
    enum PlatformErrorEnum implements CodeEnum {
        ERROR_CODE_40000("40000", "运行时失败"),
        ERROR_CODE_40001("40001", "路由消息处理失败"),
        ;
        private final String code;
        private final String msg;
    }
}
2、实体
1)入参 PageReq
package com.healerjean.proj.common.data.req;
import com.healerjean.proj.common.data.dto.PageQueryDTO;
import lombok.Data;
import java.io.Serializable;
/**
 * PageReq
 *
 * @author zhangyujin
 * @date 2023/6/14  14:24
 */
@Data
public class PageReq<T> implements Serializable {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 467204528695545241L;
    /**
     * 条件对象
     */
    private T data;
    /**
     * pageQuery
     */
    private PageQueryDTO pageQuery;
}
package com.healerjean.proj.common.data.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
 * @author zhangyujin
 * @date 2023/6/14  14:26.
 */
@Accessors(chain = true)
@Data
public class PageQueryDTO implements Serializable {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = -6352246288500328255L;
    /**
     * 当前页数
     */
    private Long currPage;
    /**
     * 分页
     */
    private Long pageSize;
    /**
     * 默认分页参数
     */
    public PageQueryDTO() {
        this.currPage = 1L;
        this.pageSize = 10L;
    }
}
2)出参 BaseRes
package com.healerjean.proj.common.data.bo;
import com.healerjean.proj.common.enums.CodeEnum;
import lombok.Data;
import lombok.experimental.Accessors;
/**
 * 返回对象
 */
@Accessors(chain = true)
@Data
public class BaseRes<T> {
    public BaseRes() {
    }
    /**
     * 是否成功
     */
    private Boolean success;
    /**
     * 返回结果
     */
    private T data;
    /**
     * msg
     */
    private String msg = "";
    /**
     * Code
     */
    private String code;
    /**
     * buildSuccess
     *
     * @param <T> <T>
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildSuccess() {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(true);
        baseRes.setCode(CodeEnum.ErrorCodeEnum.ERROR_CODE_SUCCESS.getCode());
        return baseRes;
    }
    /**
     * buildSuccess
     *
     * @param data data
     * @param <T>  <T>
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildSuccess(T data) {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(true);
        baseRes.setCode(CodeEnum.ErrorCodeEnum.ERROR_CODE_SUCCESS.getCode());
        baseRes.setData(data);
        return baseRes;
    }
    /**
     * buildSuccess
     *
     * @param <T> <T>
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildSuccess(T data, String msg) {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(true);
        baseRes.setData(data);
        baseRes.setCode(CodeEnum.ErrorCodeEnum.ERROR_CODE_SUCCESS.getCode());
        baseRes.setMsg(msg);
        return baseRes;
    }
    /**
     * buildFailure
     *
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildFailure() {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(false);
        baseRes.setCode(CodeEnum.ErrorCodeEnum.ERROR_CODE_FAIL.getCode());
        return baseRes;
    }
    /**
     * parameterErrorEnum
     *
     * @param msg msg
     * @param <T> <T>
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildParamsFailure(String msg) {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(false);
        baseRes.setCode(CodeEnum.ErrorCodeEnum.ERROR_CODE_PARAMS_ERROR.getCode());
        baseRes.setMsg(msg);
        return baseRes;
    }
    /**
     * parameterErrorEnum
     *
     * @param codeEnum codeEnum
     * @param <T>      <T>
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildFailure(CodeEnum codeEnum) {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(false);
        if (codeEnum instanceof CodeEnum.ErrorCodeEnum) {
            CodeEnum.ErrorCodeEnum errorEnum = (CodeEnum.ErrorCodeEnum) codeEnum;
            baseRes.setCode(errorEnum.getCode());
            baseRes.setMsg(errorEnum.getMsg());
            return baseRes;
        }
        if (codeEnum instanceof CodeEnum.BusinessErrorEnum) {
            CodeEnum.BusinessErrorEnum errorEnum = (CodeEnum.BusinessErrorEnum) codeEnum;
            baseRes.setCode(errorEnum.getCode());
            baseRes.setMsg(errorEnum.getMsg());
            return baseRes;
        }
        return baseRes;
    }
    /**
     * @param code code
     * @param msg  msg
     * @param <T>  <T>
     * @return ResponseBean
     */
    public static <T> BaseRes<T> buildFailure(String code, String msg) {
        BaseRes<T> baseRes = new BaseRes<>();
        baseRes.setSuccess(false);
        baseRes.setCode(code);
        baseRes.setMsg(msg);
        return baseRes;
    }
}
3)出参分页返回 PageVO
package com.healerjean.proj.common.data.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
* PageBO
*
* @author zhangyujin
* @date 2023/6/14  11:54.
*/
@Data
public class PageVO<T> implements Serializable {
  /**
   * serialVersionUID
   */
  private static final long serialVersionUID = 1817973891205894329L;
  /**
   * 总记录数
   */
  private Long totalCount;
  /**
   * 每页记录数
   */
  private Long pageSize;
  /**
   * 总页数
   */
  private Long totalPage;
  /**
   * 当前页数
   */
  private Long currPage;
  /**
   * 列表数据
   */
  private List<T> list;
  /**
   * 默认
   */
  private PageVO() {
  }
  /**
   * 构造器
   *
   * @param totalCount 条数
   * @param pageSize   size
   * @param totalPage  current
   * @param currPage   cur
   * @param list       list
   */
  public PageVO(Long totalCount, Long pageSize, Long totalPage, Long currPage, List<T> list) {
      this.totalCount = totalCount;
      this.pageSize = pageSize;
      this.totalPage = totalPage;
      this.currPage = currPage;
      this.list = list;
  }
  /**
   * 无数据
   */
  public static <T> PageVO<T> none(Long pageSize, Long currenPage) {
      return new PageVO<>(0L, pageSize, 0L, currenPage, Collections.emptyList());
  }
}
4) 业务分页返回 PageBO
package com.healerjean.proj.common.data.bo;
import lombok.Data;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
 * PageBO
 *
 * @author zhangyujin
 * @date 2023/6/14  11:54.
 */
@Data
public class PageBO<T> implements Serializable {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1411218404349777400L;
    /**
     * 总记录数
     */
    private Long totalCount;
    /**
     * 每页记录数
     */
    private Long pageSize;
    /**
     * 总页数
     */
    private Long totalPage;
    /**
     * 当前页数
     */
    private Long currPage;
    /**
     * 列表数据
     */
    private List<T> list;
    /**
     * 默认
     */
    private PageBO() {
    }
    /**
     * 构造器
     *
     * @param totalCount 条数
     * @param pageSize   size
     * @param totalPage  current
     * @param currPage   cur
     * @param list       list
     */
    public PageBO(Long totalCount, Long pageSize, Long totalPage, Long currPage, List<T> list) {
        this.totalCount = totalCount;
        this.pageSize = pageSize;
        this.totalPage = totalPage;
        this.currPage = currPage;
        this.list = list;
    }
    /**
     * 无数据
     */
    public static <T> PageBO<T> none(Long pageSize, Long currenPage) {
        return new PageBO<>(0L, pageSize, 0L, currenPage, Collections.emptyList());
    }
}
5)业务分页查询 PageQueryBO
package com.healerjean.proj.common.data.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
 * @author zhangyujin
 * @date 2023/6/14  14:14.
 */
@Accessors(chain = true)
@Data
public class PageQueryBO<T> implements Serializable {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 3015419757742187536L;
    /**
     * 当前页数
     */
    private Long currPage;
    /**
     * 分页
     */
    private Long pageSize;
    /**
     * 是否进行 count 查询
     * 默认不需要
     */
    private Boolean searchCountFlag;
    /**
     * 查询数据
     */
    private T data;
    /**
     * 默认分页参数
     */
    public PageQueryBO() {
        this.currPage = 1L;
        this.pageSize = 10L;
        this.searchCountFlag = true;
    }
}
6)业务排序 OrderByBO
package com.healerjean.proj.common.data.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
 * OrderByBO
 *
 * @author zhangyujin
 * @date 2023/6/14  17:40.
 */
@Accessors(chain = true)
@Data
public class OrderByBO implements Serializable {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 160148478613404512L;
    /**
     * 排序属性
     */
    private String property;
    /**
     * 排序方向
     */
    private String direction;
}
7)对象转化 PageConverter
package com.healerjean.proj.common.data.convert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.healerjean.proj.common.data.bo.OrderByBO;
import com.healerjean.proj.common.data.bo.PageBO;
import com.healerjean.proj.common.data.bo.PageQueryBO;
import com.healerjean.proj.common.data.dto.OrderByDTO;
import com.healerjean.proj.common.data.dto.PageQueryDTO;
import com.healerjean.proj.common.data.vo.PageVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author zhangyujin
* @date 2023/6/14  13:56.
*/
@Mapper
public interface PageConverter {
  /**
   * 实例
   */
  PageConverter INSTANCE = Mappers.getMapper(PageConverter.class);
  /**
   * covertPageBoToVo
   *
   * @param pageBo pageBo
   * @param <T>    <T>
   * @return PageVO
   */
  default <T> PageVO<T> covertPageBoToVo(PageBO<?> pageBo, List<T> list) {
      return new PageVO<>(pageBo.getTotalCount(), pageBo.getPageSize(), pageBo.getTotalPage(), pageBo.getCurrPage(), list);
  }
  /**
   * covertPageBoToVo
   *
   * @param iPage iPage
   * @param list  list
   * @param <T>   <T>
   * @return PageVO
   */
  default <T> PageBO<T> covertPageBoToBo(Page<?> iPage, List<T> list) {
      return new PageBO<>(iPage.getTotal(), iPage.getSize(), iPage.getPages(), iPage.getCurrent(), list);
  }
  /**
   * pageQueryDtoToBo
   *
   * @param pageQuery pageQuery
   * @return PageQueryBO
   */
  default <T> PageQueryBO<T> pageQueryDtoToBo(PageQueryDTO pageQuery) {
      if (Objects.isNull(pageQuery)) {
          pageQuery = new PageQueryDTO();
      }
      PageQueryBO<T> result = new PageQueryBO<>();
      if (Objects.nonNull(pageQuery.getCurrPage())) {
          result.setCurrPage(pageQuery.getCurrPage());
      }
      if (Objects.nonNull(pageQuery.getPageSize())) {
          result.setPageSize(pageQuery.getPageSize());
      }
      return result;
  }
  /**
   * coverOrderByDtoToBo
   *
   * @param orderByBo orderByBo
   * @return PageQueryBO.OrderByBO
   */
  default OrderByBO coverOrderByDtoToBo(OrderByDTO orderByBo) {
      OrderByBO orderByBO = new OrderByBO();
      orderByBO.setProperty(orderByBo.getProperty());
      orderByBO.setDirection(orderByBo.getDirection());
      return orderByBO;
  }
  /**
   * coverOrderByDtoToBoList
   *
   * @param orderByBos orderByBos
   * @return List<PageQueryBO.OrderByBO>
   */
  default List<OrderByBO> coverOrderByDtoToBoList(List<OrderByDTO> orderByBos) {
      if (CollectionUtils.isEmpty(orderByBos)) {
          return Collections.emptyList();
      }
      return orderByBos.stream().map(this::coverOrderByDtoToBo).collect(Collectors.toList());
  }
}
3、Exception
1)业务异常 BusinessException
@Getter
public class BusinessException extends RuntimeException {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 799633539625676004L;
    /**
     * 返回错误码
     */
    private final String code;
    /**
     * 展示信息
     */
    private final String showMsg;
    /**
     * BusinessException
     *
     * @param businessErrorEnum businessErrorEnum
     */
    public BusinessException(CodeEnum.BusinessErrorEnum businessErrorEnum) {
        super(businessErrorEnum.getMsg());
        this.code = businessErrorEnum.getCode();
        this.showMsg = businessErrorEnum.getShowMsg();
    }
    /**
     * BusinessException
     *
     * @param message message
     */
    public BusinessException(String message) {
        super(message);
        this.code = CodeEnum.ErrorCodeEnum.ERROR_CODE_BUSINESS_ERROR.getCode();
        this.showMsg = message;
    }
}
2)参数异常类:ParameterException
@Getter
public class ParameterException extends RuntimeException {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = -6114625076221233075L;
    /**
     * 返回错误码
     */
    private final String code;
    /**
     * BusinessException
     *
     * @param paramErrorEnum paramErrorEnum
     */
    public ParameterException(CodeEnum.ParamsErrorEnum paramErrorEnum) {
        super(paramErrorEnum.getMsg());
        this.code = paramErrorEnum.getCode();
    }
    /**
     * ParameterErrorException
     *
     * @param message message
     */
    public ParameterException(String message) {
        super(message);
        this.code = CodeEnum.ErrorCodeEnum.ERROR_CODE_PARAMS_ERROR.getCode();
    }
}
3)接口异常类 RpcException
@Getter
public class RpcException extends RuntimeException {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 799633539625676004L;
    /**
     * 返回错误码
     */
    private final String code;
    /**
     * 展示信息
     */
    private final String showMsg;
    /**
     * RpcException-处理未知的异常
     *
     *
     * @param rpcErrorEnum rpcErrorEnum
     */
    public RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum) {
        super(rpcErrorEnum.getMsg());
        this.code = rpcErrorEnum.getCode();
        this.showMsg = CodeEnum.ErrorCodeEnum.ERROR_CODE_FAIL.getMsg();
    }
    /**
     * RpcException 处理已知的异常
     *
     * @param rpcErrorEnum rpcErrorEnum
     * @param code         code
     * @param showMsg      showMsg
     */
    public RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String showMsg) {
        super(rpcErrorEnum.getMsg());
        this.code = rpcErrorEnum.getCode() + "_" + code;
        this.showMsg = showMsg;
    }
    /**
     * RpcException 处理已知的异常
     *
     * @param rpcErrorEnum rpcErrorEnum
     * @param code         code
     * @param showMsg      showMsg
     */
    public RpcException(CodeEnum.RpcErrorEnum rpcErrorEnum, String code, String msg, String showMsg) {
        super(msg);
        this.code = rpcErrorEnum.getCode() + "_" + code;
        this.showMsg = showMsg;
    }
}
4、运行异常类:PlatformException
package com.healerjean.proj.exceptions;
import com.healerjean.proj.common.enums.CodeEnum;
import lombok.Getter;
/**
 * PlatformException
 *
 * @author zhangyujin
 * @date 2024/1/3
 */
@Getter
public class PlatformException extends RuntimeException {
    private static final long serialVersionUID = 5535821215702463243L;
    /**
     * 返回错误码
     */
    private final String code;
    /**
     * 展示信息
     */
    private final String showMsg;
    /**
     * PlatformException
     *
     * @param platformErrorEnum platformErrorEnum
     */
    public PlatformException(CodeEnum.PlatformErrorEnum platformErrorEnum) {
        super(platformErrorEnum.getMsg());
        this.code = platformErrorEnum.getCode();
        this.showMsg = CodeEnum.ErrorCodeEnum.ERROR_CODE_FAIL.getMsg();
    }
}
4、控制层
1)ControllerHandleConfig
package com.healerjean.proj.controller;
import com.healerjean.proj.common.data.bo.BaseRes;
import com.healerjean.proj.common.enums.CodeEnum;
import com.healerjean.proj.exceptions.BusinessException;
import com.healerjean.proj.exceptions.ParameterException;
import com.healerjean.proj.exceptions.PlatformException;
import com.healerjean.proj.exceptions.RpcException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.servlet.http.HttpServletResponse;
import javax.validation.UnexpectedTypeException;
/**
 * ControllerHandleConfig
 *
 * @author zhangyujin
 * @date 2023/6/15  10:55.
 */
@Slf4j
@ControllerAdvice
public class ControllerHandleConfig {
    /**
     * 不支持的请求方始
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(value = HttpStatus.METHOD_NOT_ALLOWED)
    public BaseRes<?> methodNotSupportExceptionHandler(HttpRequestMethodNotSupportedException e) {
        log.error("不支持的请求方式", e);
        return BaseRes.buildFailure(CodeEnum.ParamsErrorEnum.ERROR_CODE_10001.getCode(), e.getMessage());
    }
    /**
     * 参数类型错误
     * 1、(BindException : 比如 Integer 传入String  )
     * Field error in object 'demoDTO' on field 'age': rejected value [fasdf]; codes [typeMismatch.demoDTO.age,typeMismatch.age,typeMismatch.java.lang.Integer,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [demoDTO.age,age]; arguments []; default message [age]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'age'; nested exception is java.lang.NumberFormatException: For input string: "fasdf"]
     */
    @ExceptionHandler(value = {BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRes<?> bindExceptionHandler(BindException e) {
        log.error("====参数类型错误===", e);
        return BaseRes.buildFailure(CodeEnum.ParamsErrorEnum.ERROR_CODE_10000);
    }
    /**
     * 参数格式问题
     */
    @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, HttpMessageConversionException.class, UnexpectedTypeException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRes<?> httpMessageConversionExceptionHandler(Exception e) {
        log.error("====参数格式异常===", e);
        return BaseRes.buildFailure(CodeEnum.ParamsErrorEnum.ERROR_CODE_10002);
    }
    /**
     * 参数错误
     */
    @ExceptionHandler(value = ParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRes<?> parameterErrorExceptionHandler(ParameterException e) {
        log.error("====参数异常:code:{},msg:{}", e.getCode(), e.getMessage(), e);
        return BaseRes.buildFailure(e.getCode(), e.getMessage());
    }
    /**
     * 业务异常,给前台返回异常数据
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRes<?> businessExceptionHandler(BusinessException e) {
        log.error("====业务异常:code:{},msg:{},showMsg:{}", e.getCode(), e.getMessage(), e.getShowMsg(), e);
        return BaseRes.buildFailure(e.getCode(), e.getShowMsg());
    }
    /**
     * RPC,给前台返回异常数据
     */
    @ExceptionHandler(value = RpcException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRes<?> rpcExceptionHandler(RpcException e) {
        log.error("====RPC异常:code:{},msg:{},showMsg:{}", e.getCode(), e.getMessage(), e.getShowMsg(), e);
        return BaseRes.buildFailure(e.getCode(), e.getShowMsg());
    }
    /**
     * 运行异常,给前台返回异常数据
     */
    @ExceptionHandler(value = PlatformException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRes<?> rpcExceptionHandler(PlatformException e) {
        log.error("====运行异常:code:{},msg:{},showMsg:{}", e.getCode(), e.getMessage(), e.getShowMsg(), e);
        return BaseRes.buildFailure(e.getCode(), e.getShowMsg());
    }
    /**
     * 所有异常报错
     */
    @ExceptionHandler
    @ResponseBody
    public HttpEntity<BaseRes<?>> allExceptionHandler(HttpServletResponse response, Exception e) {
        log.error("====系统错误===", e);
        response.setStatus(500);
        return returnMessage(BaseRes.buildFailure(CodeEnum.ErrorCodeEnum.ERROR_CODE_FAIL));
    }
    /**
     * returnMessage
     *
     * @param baseRes baseRes
     * @return HttpEntity<BaseRes < ?>>
     */
    private HttpEntity<BaseRes<?>> returnMessage(BaseRes<?> baseRes) {
        HttpHeaders header = new HttpHeaders();
        header.add("Content-Type", "application/json");
        header.add("Charset", "UTF-8");
        return new HttpEntity<>(baseRes, header);
    }
    /**
     * 参数非法
     * 1、(BindException : 比如 Integer 传入abc  )
     */
    // @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, HttpRequestMethodNotSupportedException.class, HttpMessageConversionException.class, BindException.class, UnexpectedTypeException.class})
    // @ResponseBody
    // public HttpEntity<ResponseBean> httpMessageConversionExceptionHandler(HttpServletResponse response, Exception e) {
    //     log.error("====参数格式异常===", e);
    //     // 等同于 @ResponseStatus(HttpStatus.BAD_REQUEST)
    //     // 但是setStatus 不能比随便设置,最好一般情况下不要和HttpStatus 有重复的,这样有可能会造成没有输出Response body
    //     response.setStatus(ResponseEnum.参数格式异常.code);
    //     return returnMessage(ResponseBean.buildFailure(ResponseEnum.参数格式异常));
    // }
    // @ExceptionHandler(value ={HttpMessageConversionException.class, BindException.class} )
    // @ResponseBody
    // public HttpEntity<ResponseBean> httpMessageConversionExceptionHandler(Exception e) {
    //     log.error("====参数格式异常===", e);
    //     return new ResponseEntity<>(ResponseBean.buildFailure(ResponseEnum.参数格式异常),HttpStatus.BAD_REQUEST);
    // }
}
2)验证
package com.healerjean.proj.controller;
import com.healerjean.proj.common.anno.LogIndex;
import com.healerjean.proj.common.data.bo.BaseRes;
import com.healerjean.proj.common.enums.CodeEnum;
import com.healerjean.proj.data.vo.UserDemoVO;
import com.healerjean.proj.exceptions.BusinessException;
import com.healerjean.proj.exceptions.ParameterException;
import com.healerjean.proj.exceptions.PlatformException;
import com.healerjean.proj.exceptions.RpcException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * ExceltionController
 *
 * @author zhangyujin
 * @date 2024/1/3
 */
@RestController
@RequestMapping("hlj/exception")
@Api(tags = "Exception-控制器")
@Slf4j
public class ExceptionController {
    @ApiOperation("parameterExceptionEnum")
    @LogIndex
    @GetMapping("parameterExceptionEnum")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> parameterExceptionEnum() {
        throw new ParameterException(CodeEnum.ParamsErrorEnum.ERROR_CODE_10002);
    }
    @ApiOperation("parameterExceptionMsg")
    @LogIndex
    @GetMapping("parameterExceptionMsg")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> parameterExceptionMsg() {
        throw new ParameterException("用户Id不能为空");
    }
    @ApiOperation("businessExceptionEnum")
    @LogIndex
    @GetMapping("businessExceptionEnum")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> businessExceptionEnum() {
        throw new BusinessException(CodeEnum.BusinessErrorEnum.ERROR_CODE_20001);
    }
    @ApiOperation("businessExceptionMsg")
    @LogIndex
    @GetMapping("businessExceptionMsg")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> businessExceptionMsg() {
        throw new BusinessException("用户创建失败");
    }
    @ApiOperation("rpcExceptionDefaultEnum")
    @LogIndex
    @GetMapping("rpcExceptionDefaultEnum")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> rpcExceptionDefaultEnum() {
        throw new RpcException(CodeEnum.RpcErrorEnum.ERROR_CODE_USER_0_30001_0001);
    }
    @ApiOperation("rpcExceptionEnumShowMsg")
    @LogIndex
    @GetMapping("rpcExceptionEnumShowMsg")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> rpcExceptionEnumShowMsg() {
        throw new RpcException(CodeEnum.RpcErrorEnum.ERROR_CODE_USER_1_30001_0001, "1000", "用户不存在");
    }
    @ApiOperation("rpcExceptionEnumMsg")
    @LogIndex
    @GetMapping("rpcExceptionEnumMsg")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> rpcExceptionEnumMsg() {
        throw new RpcException(CodeEnum.RpcErrorEnum.ERROR_CODE_USER_1_30001_0001, "1000", "底层结构异常", "用户不存在");
    }
    @ApiOperation("platformException")
    @LogIndex
    @GetMapping("platformException")
    @ResponseBody
    public BaseRes<List<UserDemoVO>> platformException() {
        throw new PlatformException(CodeEnum.PlatformErrorEnum.ERROR_CODE_40001);
    }
}
二、常见规范
1、注释规范
/**
     * 根据合同模板生成合同初始pdf文件,讲合同状态设置为待确认状态
     * 1、数据校验
     *  1.1、基本数据校验
     *  1.2、校验合同模板是否存在
     *  1.3、校验签署人是否完整
     *  1.4、校验签署方是否真实有效
     * 2、把合同签署各方的信息和模板取出,将变量更替,生成word和pdf
     * 4、保存签署人信息
     * 5、合同初始化日志保存
     * 6、删除临时文件
     */
void createContractByTeamplate(ContractDTO contractDTO) ;
2、POJO( DTO、VO、BO、PO、DO)、Query
POJO的定义是无规则简单的对象,在日常的代码分层中pojo会被分为VO、BO、PO、DTO
1)VO( View Object)显示层对象
VO(ViewObject):显示层对象,通常是Web向模板渲染引擎层传输的对象。1、前端展示的数据,在接口数据返回给前端的时候需要转成
VO2、个人理解使用场景,接口层服务中,将
DTO转成VO,返回给前台
public List<UserVO> getUserVOs(UserQuery userQuery){
    
   //DTO转VO
    BeanUils.dtoToUserVO(userservice.getUserDTOs());
}
2)BO( Business Object)业务层对象
业务对象。 由
Service层输出的封装业务逻辑的对象。1、主要在服务内部使用的业务对象
2、可以包含多个对象,可以用于对象的聚合操作
3、个人理解使用场景,在服务层服务中,由
DTO转成BO然后进行业务处理后,转成DTO返回到接口层
Service内部的私有代码 
List<UserBO> getUserBOs(UserQuery userQuery){
   //DO转BO
    BeanUils.doToUserBO(userdao.getUserDOs());
}
3)DTO (Data Transfer Object)数据传输对象
数据传输对象,
Service或Manager向外传输的对象。1、在服务间的调用中,传输的数据对象
2、个人理解,
DTO是可以存在于各层服务中(接口、服务、数据库等等)服务间的交互使用DTO来解耦
 List<UserDTO> getUserDTOs(UserQuery userQuery){
     
      //BO转DTO,也可能DO转DTO
    BeanUils.boToUserDTO(userservice.getUserBOs());
 }
4)PO(persistent object)持久对象
1、出现位置为数据库数据,用来存储数据库提取的数据
2、只存储数据,不包含数据操作
3、个人理解使用场景,在数据库层中,获取的数据库数据存储到PO中,然后转为DTO返回到服务层中
List<UserDO> getUsers(UserQuery userQuery);
5)DO ( Data Object)领域实体对象
DO(DataObject)这个等同于上面的PO
List<UserDO> getUsers(UserQuery userQuery);
3、RPC 命名
1)提供者 ` DemoProvider`
2)消费者
3)接入层 RpcProxy
直接包装外部接口,无业务数据
package com.healerjean.proj.rpc.consumer.proxy.impl;
import com.healerjean.proj.common.anno.LogIndex;
import com.healerjean.proj.rpc.provider.DemoPrcResource;
import com.healerjean.proj.rpc.consumer.proxy.DemoRpcProxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
 * DemoRpcProxy
 *
 * @author zhangyujin
 * @date 2023/6/15  21:23.
 */
@Slf4j
@Service("demoRpcProxy")
public class DemoRpcProxyImpl implements DemoRpcProxy {
    @Resource
    private DemoPrcResource demoPrcResource;
    /**
     * Rpc调用
     *
     * @param reqString reqString
     * @return String
     */
    @LogIndex
    @Override
    public String rpcInvoke(String reqString) {
        return demoPrcResource.rpcInvoke(reqString);
    }
}
4)适配层 RpcAdapter
适配消费者,用于适配外部数据和聚合同类型的接口
/**
 * DemoAdapterImpl
 *
 * @author zhangyujin
 * @date 2023/7/14
 */
@Slf4j
@Service
public class DemoRpcAdapterImpl implements DemoRpcAdapter {
    @Resource
    private DemoRpcProxy demoRpcProxy;
    /**
     * Rpc调用
     *
     * @param msg msg
     * @return String String
     */
    String rpcInvoke(String msg) {
        try {
            return demoRpcProxy.rpcInvoke(msg);
        } catch (Exception e) {
            log.info("[DemoAdapter#rpcInvoke] msg", msg, e);
            return null;
        }
    }
}
4、返回码规范
以 HTTP 状态码为例,为了更加清晰的表述和区分状态码的含义,HTTP 状态做了分段。

参考 HTTP 状态码的思路,我们对错误码进行分段,如上 CodeEnum

5、接口文档
1)角色列表查询
说明
- 测试调用地址:/api/roles
- 调用方式:GET
请求参数
| 参数名称 | 参数类型 | 参数长度 | 是否必需 | 说明 | 备注 | 
|---|---|---|---|---|---|
| pageSize | 整数 | 否 | 每页显示数量 | 默认10 | |
| pageNo | 整数 | 否 | 当前查看页码 | 默认1 | |
| roleName | 字符串 | 64 | 否 | 角色名称 | |
| systemCode | 字符串 | 32 | 否 | 系统CODE | |
| isPage | 布尔 | 4 | 否 | 是否分页 | true/false | 
请求报文样例
{
    "pageSize": 1,
    "pageNo": 1,
    "roleName": "",
    "systemCode": "scf-manager",
    "isPage": true
}
响应参数
| 参数名称 | 参数类型 | 参数长度 | 是否必需 | 说明 | 备注 | 
|---|---|---|---|---|---|
| msg | 字符串 | 255 | 是 | 返回结果 | |
| total | 数字 | 否 | 总数 | ||
| pageNo | 数字 | 否 | 页数 | ||
| totalPage | 数字 | 否 | 总页数 | ||
| pageSize | 数字 | 否 | 每页数量 | ||
| datas | Role数组 | 否 | 返回的数据信息 | 
Role 数据结构
| 参数名称 | 参数类型 | 参数长度 | 是否必需 | 说明 | 备注 | 
|---|---|---|---|---|---|
| id | 数字 | 16 | 是 | id | |
| roleName | 字符串 | 64 | 是 | 角色名称 | |
| systemCode | 字符串 | 64 | 是 | 系统CODE | |
| status | 字符串 | 8 | 是 | 状态 | |
| desc | 字符串 | 255 | 否 | 描述 | 
响应报文样例
{
    "msg": "角色列表查询成功",
    "total": 2,
    "pageNo": 1,
    "totalPage": 1,
    "datas": [
        {
            "id": 1,
            "roleName": "后台管理员",
            "systemCode": "scf-manager",
            "status": "10"
        },
        {
            "id": 4,
            "roleName": "测试角色哦",
            "systemCode": "scf-manager",
            "status": "10",
            "desc": "真的是测试"
        }
    ],
    "pageSize": 10
}
返回码解析
| 返回码 | 含义 | 备注 | 
|---|---|---|
| 200 | 成功 | 

  
  

