【重构】新增 yudao-spring-boot-starter-biz-error-code 错误码组件

This commit is contained in:
YunaiV
2022-06-17 22:56:06 +08:00
parent 992e20530d
commit 7a86a61079
21 changed files with 182 additions and 61 deletions

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.system.api.errorcode;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.service.errorcode.ErrorCodeService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* 错误码 Api 实现类
*
* @author 芋道源码
*/
@Service
public class ErrorCodeApiImpl implements ErrorCodeApi {
@Resource
private ErrorCodeService errorCodeService;
@Override
public void autoGenerateErrorCodes(List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs) {
errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs);
}
@Override
public List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, Date minUpdateTime) {
return errorCodeService.getErrorCodeList(applicationName, minUpdateTime);
}
}

View File

@ -1,13 +1,13 @@
package cn.iocoder.yudao.module.system.convert.errorcode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExcelVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

View File

@ -1,37 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.config;
import cn.iocoder.yudao.module.system.framework.errorcode.core.generator.ErrorCodeAutoGenerator;
import cn.iocoder.yudao.module.system.framework.errorcode.core.loader.ErrorCodeLoader;
import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService;
import cn.iocoder.yudao.module.system.framework.errorcode.core.loader.ErrorCodeLoaderImpl;
import cn.iocoder.yudao.module.system.framework.errorcode.core.generator.ErrorCodeAutoGeneratorImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
// TODO 芋艿:貌似放的位置有问题
/**
* 错误码配置类
*/
@Configuration
@EnableConfigurationProperties(ErrorCodeProperties.class)
@EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码
public class ErrorCodeConfiguration {
@Bean
public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName,
ErrorCodeProperties errorCodeProperties,
ErrorCodeFrameworkService errorCodeFrameworkService) {
return new ErrorCodeAutoGeneratorImpl(applicationName, errorCodeProperties.getConstantsClassList(),
errorCodeFrameworkService);
}
@Bean
public ErrorCodeLoader errorCodeLoader(@Value("${spring.application.name}") String applicationName,
ErrorCodeFrameworkService errorCodeFrameworkService) {
return new ErrorCodeLoaderImpl(applicationName, errorCodeFrameworkService);
}
}

View File

@ -1,26 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 错误码的配置属性类
*
* @author dlyan
*/
@ConfigurationProperties("yudao.error-code")
@Data
@Validated
public class ErrorCodeProperties {
/**
* 错误码枚举类
*/
@NotNull(message = "错误码枚举类不能为空")
private List<String> constantsClassList;
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* 错误码自动生成 DTO
*
* @author dylan
*/
@Data
@Accessors(chain = true)
public class ErrorCodeAutoGenerateReqDTO {
/**
* 应用名
*/
@NotNull(message = "应用名不能为空")
private String applicationName;
/**
* 错误码编码
*/
@NotNull(message = "错误码编码不能为空")
private Integer code;
/**
* 错误码错误提示
*/
@NotEmpty(message = "错误码错误提示不能为空")
private String message;
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.dto;
import lombok.Data;
import java.util.Date;
/**
* 错误码的 Response DTO
*
* @author 芋道源码
*/
@Data
public class ErrorCodeRespDTO {
/**
* 错误码编码
*/
private Integer code;
/**
* 错误码错误提示
*/
private String message;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -1,15 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.generator;
/**
* 错误码的自动生成器
*
* @author dylan
*/
public interface ErrorCodeAutoGenerator {
/**
* 将配置类到错误码写入数据库
*/
void execute();
}

View File

@ -1,104 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.generator;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* ErrorCodeAutoGenerator 的实现类
* 目的是,扫描指定的 {@link #constantsClassList} 类,写入到 system 服务中
*
* @author dylan
*/
@RequiredArgsConstructor
@Slf4j
public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator {
/**
* 应用分组
*/
private final String applicationName;
/**
* 错误码枚举类
*/
private final List<String> constantsClassList;
/**
* 错误码 Service
*/
private final ErrorCodeFrameworkService errorCodeService;
@Override
@EventListener(ApplicationReadyEvent.class)
@Async // 异步,保证项目的启动过程,毕竟非关键流程
public void execute() {
// 第一步,解析错误码
List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = parseErrorCode();
log.info("[execute][解析到错误码数量为 ({}) 个]", autoGenerateDTOs.size());
// 第二步,写入到 system 服务
errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs);
log.info("[execute][写入到 system 组件完成]");
}
/**
* 解析 constantsClassList 变量,转换成错误码数组
*
* @return 错误码数组
*/
private List<ErrorCodeAutoGenerateReqDTO> parseErrorCode() {
// 校验 errorCodeConstantsClass 参数
if (CollUtil.isEmpty(constantsClassList)) {
log.info("[execute][未配置 yudao.error-code.constants-class-list 配置项,不进行自动写入到 system 服务中]");
return new ArrayList<>();
}
// 解析错误码
List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>();
constantsClassList.forEach(constantsClass -> {
try {
// 解析错误码枚举类
Class<?> errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass);
// 解析错误码
autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz));
} catch (Exception ex) {
log.warn("[parseErrorCode][constantsClass({}) 加载失败({})]", constantsClass,
ExceptionUtil.getRootCauseMessage(ex));
}
});
return autoGenerateDTOs;
}
/**
* 解析错误码类,获得错误码数组
*
* @return 错误码数组
*/
private List<ErrorCodeAutoGenerateReqDTO> parseErrorCode(Class<?> constantsClass) {
List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>();
Arrays.stream(constantsClass.getFields()).forEach(field -> {
if (field.getType() != ErrorCode.class) {
return;
}
// 转换成 ErrorCodeAutoGenerateReqDTO 对象
ErrorCode errorCode = (ErrorCode) ReflectUtil.getFieldValue(constantsClass, field);
autoGenerateDTOs.add(new ErrorCodeAutoGenerateReqDTO().setApplicationName(applicationName)
.setCode(errorCode.getCode()).setMessage(errorCode.getMsg()));
});
return autoGenerateDTOs;
}
}

View File

@ -1,24 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.loader;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
/**
* 错误码加载器
*
* 注意,错误码最终加载到 {@link ServiceExceptionUtil} 的 MESSAGES 变量中!
*
* @author dlyan
*/
public interface ErrorCodeLoader {
/**
* 添加错误码
*
* @param code 错误码的编号
* @param msg 错误码的提示
*/
default void putErrorCode(Integer code, String msg) {
ServiceExceptionUtil.put(code, msg);
}
}

View File

@ -1,73 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.loader;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Date;
import java.util.List;
/**
* ErrorCodeLoader 的实现类,从 infra 的数据库中,加载错误码。
*
* 考虑到错误码会刷新,所以按照 {@link #REFRESH_ERROR_CODE_PERIOD} 频率,增量加载错误码。
*
* @author dlyan
*/
@RequiredArgsConstructor
@Slf4j
public class ErrorCodeLoaderImpl implements ErrorCodeLoader {
/**
* 刷新错误码的频率,单位:毫秒
*/
private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000;
/**
* 应用分组
*/
private final String applicationName;
/**
* 错误码 Service
*/
private final ErrorCodeFrameworkService errorCodeService;
/**
* 缓存错误码的最大更新时间,用于后续的增量轮询,判断是否有更新
*/
private Date maxUpdateTime;
@EventListener(ApplicationReadyEvent.class)
public void loadErrorCodes() {
this.loadErrorCodes0();
}
@Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD)
public void refreshErrorCodes() {
this.loadErrorCodes0();
}
private void loadErrorCodes0() {
// 加载错误码
List<ErrorCodeRespDTO> errorCodeRespDTOs = errorCodeService.getErrorCodeList(applicationName, maxUpdateTime);
if (CollUtil.isEmpty(errorCodeRespDTOs)) {
return;
}
log.info("[loadErrorCodes0][加载到 ({}) 个错误码]", errorCodeRespDTOs.size());
// 刷新错误码的缓存
errorCodeRespDTOs.forEach(errorCodeRespDTO -> {
// 写入到错误码的缓存
putErrorCode(errorCodeRespDTO.getCode(), errorCodeRespDTO.getMessage());
// 记录下更新时间,方便增量更新
maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeRespDTO.getUpdateTime());
});
}
}

View File

@ -1,35 +0,0 @@
package cn.iocoder.yudao.module.system.framework.errorcode.core.service;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
/**
* 错误码 Framework Service 接口
*
* @author 芋道源码
*/
public interface ErrorCodeFrameworkService {
/**
* 自动创建错误码
*
* @param autoGenerateDTOs 错误码信息
*/
void autoGenerateErrorCodes(@Valid List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs);
/**
* 增量获得错误码数组
*
* 如果 minUpdateTime 为空时,则获取所有错误码
*
* @param applicationName 应用名
* @param minUpdateTime 最小更新时间
* @return 错误码数组
*/
List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, Date minUpdateTime);
}

View File

@ -1,6 +0,0 @@
/**
* 错误码组件
*
* 将错误码缓存在内存中,同时通过定时器每 n 分钟更新
*/
package cn.iocoder.yudao.module.system.framework.errorcode;

View File

@ -1,14 +1,16 @@
package cn.iocoder.yudao.module.system.service.errorcode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
/**
@ -16,7 +18,25 @@ import java.util.List;
*
* @author 芋道源码
*/
public interface ErrorCodeService extends ErrorCodeFrameworkService {
public interface ErrorCodeService {
/**
* 自动创建错误码
*
* @param autoGenerateDTOs 错误码信息
*/
void autoGenerateErrorCodes(@Valid List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs);
/**
* 增量获得错误码数组
*
* 如果 minUpdateTime 为空时,则获取所有错误码
*
* @param applicationName 应用名
* @param minUpdateTime 最小更新时间
* @return 错误码数组
*/
List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, Date minUpdateTime);
/**
* 创建错误码

View File

@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.system.service.errorcode;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO;
import cn.iocoder.yudao.module.system.convert.errorcode.ErrorCodeConvert;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO;
import cn.iocoder.yudao.module.system.convert.errorcode.ErrorCodeConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.yudao.module.system.dal.mysql.errorcode.ErrorCodeMapper;
import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum;
import com.google.common.annotations.VisibleForTesting;
@ -24,9 +24,10 @@ import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_NOT_EXISTS;
/**
* 错误码 Service 实现类

View File

@ -1,17 +1,17 @@
package cn.iocoder.yudao.module.system.service.errorcode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.yudao.module.system.dal.mysql.errorcode.ErrorCodeMapper;
import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
@ -21,12 +21,12 @@ import java.util.List;
import java.util.function.Consumer;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.*;
@Import(ErrorCodeServiceImpl.class)