diff --git a/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeAutoConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeAutoConfiguration.java new file mode 100644 index 000000000..1174ffba8 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeAutoConfiguration.java @@ -0,0 +1,25 @@ +package cn.iocoder.dashboard.framework.errorcode.config; + +import cn.iocoder.dashboard.framework.errorcode.core.ErrorCodeRemoteLoader; +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; + +@Configuration +@EnableConfigurationProperties(ErrorCodeProperties.class) +@EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 +public class ErrorCodeAutoConfiguration { + + @Bean + public cn.iocoder.dashboard.framework.errorcode.core.ErrorCodeAutoGenerator errorCodeAutoGenerator(ErrorCodeProperties errorCodeProperties) { + return new cn.iocoder.dashboard.framework.errorcode.core.ErrorCodeAutoGenerator(errorCodeProperties.getGroup()) + .setErrorCodeConstantsClass(errorCodeProperties.getConstantsClass()); + } + + @Bean + public ErrorCodeRemoteLoader errorCodeRemoteLoader(ErrorCodeProperties errorCodeProperties) { + return new ErrorCodeRemoteLoader(errorCodeProperties.getGroup()); + } + +} \ No newline at end of file diff --git a/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java b/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java new file mode 100644 index 000000000..e96370611 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java @@ -0,0 +1,39 @@ +package cn.iocoder.dashboard.framework.errorcode.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@ConfigurationProperties("ruoyi.error-code") +@Validated +public class ErrorCodeProperties { + + /** + * 应用分组 + */ + @NotNull(message = "应用分组不能为空,请设置 ruoyi.error-code.group 配置项,推荐直接使用 spring. application.name 配置项") + private String group; + /** + * 错误码枚举类 + */ + private String constantsClass; + + public String getGroup() { + return group; + } + + public ErrorCodeProperties setGroup(String group) { + this.group = group; + return this; + } + + public String getConstantsClass() { + return constantsClass; + } + + public ErrorCodeProperties setConstantsClass(String constantsClass) { + this.constantsClass = constantsClass; + return this; + } +} \ No newline at end of file diff --git a/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/ErrorCodeAutoGenerator.java b/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/ErrorCodeAutoGenerator.java new file mode 100644 index 000000000..d458578a4 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/ErrorCodeAutoGenerator.java @@ -0,0 +1,85 @@ +package cn.iocoder.dashboard.framework.errorcode.core; + +import cn.iocoder.dashboard.common.exception.ErrorCode; +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeAutoGenerateDTO; +import cn.iocoder.dashboard.modules.system.convert.errorcode.ErrorCodeConvert; +import cn.iocoder.dashboard.modules.system.service.errorcode.ErrorCodeService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ErrorCodeAutoGenerator { + + private Logger logger = LoggerFactory.getLogger(ErrorCodeAutoGenerator.class); + + /** + * 应用分组 + */ + private final String group; + /** + * 错误码枚举类 + */ + private String errorCodeConstantsClass; + + @Resource + private ErrorCodeService errorCodeService; + + public ErrorCodeAutoGenerator(String group) { + this.group = group; + } + + public ErrorCodeAutoGenerator setErrorCodeConstantsClass(String errorCodeConstantsClass) { + this.errorCodeConstantsClass = errorCodeConstantsClass; + return this; + } + + @EventListener(ApplicationReadyEvent.class) + @Async // 异步,保证项目的启动过程,毕竟非关键流程 + public void execute() { + // 校验 errorCodeConstantsClass 参数 + if (!StringUtils.hasText(errorCodeConstantsClass)) { + logger.info("[execute][未配置 ruoyi.error-code.constants-class 配置项,不进行自动写入到 system-service 服务]"); + return; + } + Class errorCodeConstantsClazz; + try { + errorCodeConstantsClazz = Class.forName(errorCodeConstantsClass); + } catch (ClassNotFoundException e) { + logger.error("[execute][配置的 ({}) 找不到对应的类]", errorCodeConstantsClass); + return; + } + // 写入 system-service 服务 + logger.info("[execute][自动将 ({}) 类的错误码,准备写入到 system-service 服务]", errorCodeConstantsClass); + List autoGenerateDTOs = new ArrayList<>(); + Arrays.stream(errorCodeConstantsClazz.getFields()).forEach(field -> { + if (field.getType() != ErrorCode.class) { + return; + } + try { + // TODO 芋艿:校验是否重复了; + ErrorCode errorCode = (ErrorCode) field.get(errorCodeConstantsClazz); + autoGenerateDTOs.add(new ErrorCodeAutoGenerateDTO().setGroup(group) + .setCode(errorCode.getCode()).setMessage(errorCode.getMessage())); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + }); + CommonResult autoGenerateErrorCodesResult = errorCodeService.autoGenerateErrorCodes1(ErrorCodeConvert.INSTANCE.convertList03(autoGenerateDTOs)); + if (autoGenerateErrorCodesResult.isSuccess()) { + logger.info("[execute][自动将 ({}) 类的错误码,成功写入到 system-service 服务]", errorCodeConstantsClass); + } else { + logger.error("[execute][自动将 ({}) 类的错误码,失败写入到 system-service 服务,原因为 ({}/{})]", errorCodeConstantsClass, + autoGenerateErrorCodesResult.getCode(), autoGenerateErrorCodesResult.getMsg()); + } + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/ErrorCodeRemoteLoader.java b/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/ErrorCodeRemoteLoader.java new file mode 100644 index 000000000..41ea7b3bc --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/ErrorCodeRemoteLoader.java @@ -0,0 +1,72 @@ +package cn.iocoder.dashboard.framework.errorcode.core; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.ErrorCodeVO; +import cn.iocoder.dashboard.modules.system.service.errorcode.ErrorCodeService; +import cn.iocoder.dashboard.modules.system.service.errorcode.bo.ErrorCodeBO; +import cn.iocoder.dashboard.util.date.DateUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Scheduled; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +public class ErrorCodeRemoteLoader { + + private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000; + + private Logger logger = LoggerFactory.getLogger(ErrorCodeRemoteLoader.class); + + /** + * 应用分组 + */ + private final String group; + + @Resource + private ErrorCodeService errorCodeService; + + private Date maxUpdateTime; + + public ErrorCodeRemoteLoader(String group) { + this.group = group; + } + + @EventListener(ApplicationReadyEvent.class) + public void loadErrorCodes() { + // 从 ErrorCodeRpc 全量加载 ErrorCode 错误码 + CommonResult> listErrorCodesResult = errorCodeService.listErrorCodes1(group, null); + listErrorCodesResult.checkError(); + logger.info("[loadErrorCodes][从 group({}) 全量加载到 {} 个 ErrorCode 错误码]", group, listErrorCodesResult.getData().size()); + // 写入到 ServiceExceptionUtil 到 + listErrorCodesResult.getData().forEach(errorCodeVO -> { + ServiceExceptionUtil.put(errorCodeVO.getCode(), errorCodeVO.getMessage()); + // 记录下更新时间,方便增量更新 + maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeVO.getUpdateTime()); + }); + } + + @Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD) + public void refreshErrorCodes() { + // 从 ErrorCodeRpc 增量加载 ErrorCode 错误码 + // TODO 优化点:假设删除错误码的配置,会存在问题; + CommonResult> listErrorCodesResult = errorCodeService.listErrorCodes1(group, maxUpdateTime); + listErrorCodesResult.checkError(); + if (CollUtil.isEmpty(listErrorCodesResult.getData())) { + return; + } + logger.info("[refreshErrorCodes][从 group({}) 增量加载到 {} 个 ErrorCode 错误码]", group, listErrorCodesResult.getData().size()); + // 写入到 ServiceExceptionUtil 到 + listErrorCodesResult.getData().forEach(errorCodeVO -> { + ServiceExceptionUtil.put(errorCodeVO.getCode(), errorCodeVO.getMessage()); + // 记录下更新时间,方便增量更新 + maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeVO.getUpdateTime()); + }); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/ErrorCodeController.http b/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/ErrorCodeController.http new file mode 100644 index 000000000..a45e907ad --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/ErrorCodeController.http @@ -0,0 +1,58 @@ +### 请求 /login 接口 => 成功 +POST http://localhost:48080/api/login +Content-Type: application/json + +{ + "username": "admin", + "password": "admin123", + "uuid": "9b2ffbc1-7425-4155-9894-9d5c08541d62", + "code": "1024" +} + +> {% + client.global.set("token", response.body.data.token) + %} + + +### list-group +GET http://localhost:48080/api/system/error-code/list-group +Authorization: Bearer {{token}} +Content-Type: application/x-www-form-urlencoded + +group=test&minUpdateTime=2021-03-14 14:37:47 + + + +### +GET http://localhost:48080/api/system/error-code/query +Authorization: Bearer {{token}} +Content-Type: application/x-www-form-urlencoded + +errorCodeId=350 + +### +POST http://localhost:48080/api/system/error-code/generate +Authorization: Bearer {{token}} + +[ +{ + "code": 202, + "message": "成功1", + "group": "test1" +} +] + +### +POST http://localhost:48080/api/system/error-code/create +Authorization: Bearer {{token}} +Content-Type:application/json + +{ + "code": 200, + "message": "成功", + "group": "test", + "type": 1 +} + + + diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/ErrorCodeVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/ErrorCodeVO.java index 306b18d79..b0b17626b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/ErrorCodeVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/ErrorCodeVO.java @@ -29,5 +29,7 @@ public class ErrorCodeVO { private String memo; @ApiModelProperty(value = "创建时间", required = true) private Date createTime; + @ApiModelProperty(value = "更新时间", required = false) + private Date updateTime; } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/ErrorCodeService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/ErrorCodeService.java index 3f2c81b21..c09e19591 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/ErrorCodeService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/ErrorCodeService.java @@ -2,8 +2,9 @@ package cn.iocoder.dashboard.modules.system.service.errorcode; import cn.hutool.core.collection.CollUtil; import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.dashboard.common.pojo.CommonResult; import cn.iocoder.dashboard.common.pojo.PageResult; -import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodePageDTO; +import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.ErrorCodeVO; import cn.iocoder.dashboard.modules.system.convert.errorcode.ErrorCodeConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.errorcode.ErrorCodeDO; import cn.iocoder.dashboard.modules.system.dal.mysql.errorcode.ErrorCodeMapper; @@ -24,6 +25,7 @@ import java.util.Map; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.ERROR_CODE_DUPLICATE; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.ERROR_CODE_NOT_EXISTS; +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; /** * 错误码 Service @@ -106,6 +108,12 @@ public class ErrorCodeService { }); } + public CommonResult autoGenerateErrorCodes1(@Valid List autoGenerateBOs) { + autoGenerateErrorCodes(autoGenerateBOs); + return success(Boolean.TRUE); + } + + /** * 删除错误码 * @@ -180,5 +188,11 @@ public class ErrorCodeService { return ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs); } + public CommonResult> listErrorCodes1(String group, Date minUpdateTime) { + List errorCodeDOs = errorCodeMapper.selectListByGroup(group, minUpdateTime); + final List errorCodeBOS = ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs); + return success(ErrorCodeConvert.INSTANCE.convertList02(errorCodeBOS)); + } + }