Pārlūkot izejas kodu

支持程序启动时加载错误码

dylan 4 gadi atpakaļ
vecāks
revīzija
8fb01d0cec

+ 25 - 0
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());
+    }
+
+}

+ 39 - 0
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;
+    }
+}

+ 85 - 0
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<ErrorCodeAutoGenerateDTO> 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<Boolean> 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());
+        }
+    }
+
+}

+ 72 - 0
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<List<ErrorCodeVO>> 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<List<ErrorCodeVO>> 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());
+        });
+    }
+
+}

+ 58 - 0
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
+}
+
+
+

+ 2 - 0
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;
 
 }

+ 15 - 1
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<Boolean> autoGenerateErrorCodes1(@Valid List<ErrorCodeAutoGenerateBO> autoGenerateBOs) {
+        autoGenerateErrorCodes(autoGenerateBOs);
+        return success(Boolean.TRUE);
+    }
+
+
     /**
      * 删除错误码
      *
@@ -180,5 +188,11 @@ public class ErrorCodeService {
         return ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs);
     }
 
+    public CommonResult<List<ErrorCodeVO>> listErrorCodes1(String group, Date minUpdateTime) {
+        List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectListByGroup(group, minUpdateTime);
+        final List<ErrorCodeBO> errorCodeBOS = ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs);
+        return success(ErrorCodeConvert.INSTANCE.convertList02(errorCodeBOS));
+    }
+
 }