新增 yudao-spring-boot-starter-biz-error-code 错误码组件

This commit is contained in:
YunaiV
2022-06-18 00:11:46 +08:00
parent ca28d791aa
commit 2bd40cfb3b
114 changed files with 118 additions and 6114 deletions

View File

@@ -22,7 +22,7 @@ import java.util.List;
@Api(tags = "RPC 服务 - 错误码")
public interface ErrorCodeApi {
String PREFIX = ApiConstants.PREFIX + "/oauth2/token";
String PREFIX = ApiConstants.PREFIX + "/error-code";
@PostMapping(PREFIX + "/auto-generate")
@ApiOperation("自动创建错误码")

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,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

@@ -78,6 +78,7 @@ yudao:
- /admin-api/system/captcha/get-image # 获取图片验证码,和租户无关
- /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
- /rpc-api/system/tenant/valid # 防止递归。避免调用 /rpc-api/system/tenant/valid 接口时,又去触发 /rpc-api/system/tenant/valid 去校验
- /rpc-api/system/error-code/* # 错误码的自动创建与下载的接口,无法带上租户编号
ignore-tables:
- system_tenant
- system_tenant_package