项目经验_之_常用规范类
前言
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
(View
Objec
t):显示层对象,通常是Web
向模板渲染引擎层传输的对象。1、前端展示的数据,在接口数据返回给前端的时候需要转成
VO
2、个人理解使用场景,接口层服务中,将
DT
O转成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
(Data
Object
)这个等同于上面的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 | 成功 |