工业互联网平台2.0版本后端代码
houzhongjian
2025-06-05 ca6ad5acfb389b852211355c4a56c71769a018c9
v2.0版本初始化
已修改27个文件
已添加55个文件
4494 ■■■■■ 文件已修改
.gitignore 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.xcodemap/config/xcodemap-class-filter.yaml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/enums/AreaTypeEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/AreaConvert.java 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IailabMybatisAutoConfiguration.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalExceptionHandler.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/ArrayValuable.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/CommonStatusEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DateIntervalEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/TerminalEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/UserTypeEnum.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/template/XMLParserUtils.java 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnum.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumCollectionValidator.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumValidator.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/.gitignore 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/compiler.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/jarRepositories.xml 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/misc.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/sonarlint.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/vcs.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/pom.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatConversationApi.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApi.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatConversationRespDTO.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendReqDTO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendRespDTO.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiModelDO.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/enums/ApiConstants.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/pom.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatConversionApiImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApiImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/package-info.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatConversationServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/resources/application.yaml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-spring-boot-starter-ai/pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/pom.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/logs/log-debug.2024-11-06.log 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/resources/application-prod.yaml 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/logger/ApiAccessLogApi.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/logger/ApiErrorLogApi.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/monitor/MonitorApi.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/monitor/dto/MonitorDiskDTO.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/monitor/dto/MonitorMemDTO.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/util/ServerInfoCollector.java 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/api/monitor/MonitorApiImpl.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/MonitorDiskController.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskPageReqVO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskReqVO.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskRespVO.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskSaveReqVO.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/MonitorMemController.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemPageReqVO.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemReqVO.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemRespVO.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemSaveReqVO.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/dataobject/monitordisk/MonitorDiskDO.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/dataobject/monitormem/MonitorMemDO.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/mysql/monitordisk/MonitorDiskMapper.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/mysql/monitormem/MonitorMemMapper.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/job/monitor/MonitorDiskJob.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/job/monitor/MonitorMemJob.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitordisk/MonitorDiskService.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitordisk/MonitorDiskServiceImpl.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitormem/MonitorMemService.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitormem/MonitorMemServiceImpl.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-dev.yaml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-prod.yaml 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application.yaml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/resources/mapper/monitordisk/MonitorDiskMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-model/iailab-module-model-biz/src/main/resources/application-prod.yaml 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/permission/DataScopeEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/sms/SmsSceneEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/social/SocialTypeEnum.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-biz/proguard.cfg 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/permission/MenuMapper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/job/monitor/MonitorDiskJob.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/job/monitor/MonitorMemJob.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-biz/src/main/resources/application-prod.yaml 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-system/log/system-server.log 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
工业互联网平台鉴权功能.md 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -1,4 +1,3 @@
/iailab-module-ai/
/*/*/target/
/.idea/
/derby.log
@@ -8,4 +7,4 @@
/*/*/.flattened-pom.xml
/*/replay_pid15548.log
/logs/
/*/*/*.iml
/*/*/*.iml
.xcodemap/config/xcodemap-class-filter.yaml
对比新文件
@@ -0,0 +1,26 @@
autoDetectedPackages:
- com.alibaba.nacos
- com.fhs.trans.service
- com.iailab
- com.xxl.job.admin
- com.xxl.job.executorbiz
- iail.mdk.model.common
- org.springframework.messaging.handler.invocation
enableAutoDetect: true
funcDisplayConfig:
  skipConstructors: false
  skipFieldAccess: true
  skipFieldChange: true
  skipGetters: true
  skipNonProjectPackages: true
  skipPrivateMethods: false
  skipSetters: true
ignoreSameClassCall: null
ignoreSamePackageCall: null
includedPackagePrefixes: null
includedParentClasses: null
name: xcodemap-filter
recordMode: smart
sourceDisplayConfig:
  color: blue
startOnDebug: false
iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/enums/AreaTypeEnum.java
@@ -1,6 +1,6 @@
package com.iailab.framework.ip.core.enums;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -13,7 +13,7 @@
 */
@AllArgsConstructor
@Getter
public enum AreaTypeEnum implements IntArrayValuable {
public enum AreaTypeEnum implements ArrayValuable {
    COUNTRY(1, "国家"),
    PROVINCE(2, "省份"),
@@ -21,7 +21,7 @@
    DISTRICT(4, "地区"), // 县、镇、区等
    ;
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AreaTypeEnum::getType).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(AreaTypeEnum::getType).toArray(Integer[]::new);
    /**
     * 类型
@@ -33,7 +33,7 @@
    private final String name;
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
}
iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/AreaConvert.java
@@ -1,46 +1,46 @@
package com.iailab.framework.excel.core.convert;
import cn.hutool.core.convert.Convert;
import com.iailab.framework.ip.core.Area;
import com.iailab.framework.ip.core.utils.AreaUtils;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j;
/**
 * Excel 数据地区转换器
 *
 * @author HUIHUI
 */
@Slf4j
public class AreaConvert implements Converter<Object> {
    @Override
    public Class<?> supportJavaTypeKey() {
        throw new UnsupportedOperationException("暂不支持,也不需要");
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        throw new UnsupportedOperationException("暂不支持,也不需要");
    }
    @Override
    public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty,
                                    GlobalConfiguration globalConfiguration) {
        // 解析地区编号
        String label = readCellData.getStringValue();
        Area area = AreaUtils.parseArea(label);
        if (area == null) {
            log.error("[convertToJavaData][label({}) 解析不掉]", label);
            return null;
        }
        // 将 value 转换成对应的属性
        Class<?> fieldClazz = contentProperty.getField().getType();
        return Convert.convert(fieldClazz, area.getId());
    }
}
//package com.iailab.framework.excel.core.convert;
//
//import cn.hutool.core.convert.Convert;
//import com.iailab.framework.ip.core.Area;
//import com.iailab.framework.ip.core.utils.AreaUtils;
//import com.alibaba.excel.converters.Converter;
//import com.alibaba.excel.enums.CellDataTypeEnum;
//import com.alibaba.excel.metadata.GlobalConfiguration;
//import com.alibaba.excel.metadata.data.ReadCellData;
//import com.alibaba.excel.metadata.property.ExcelContentProperty;
//import lombok.extern.slf4j.Slf4j;
//
///**
// * Excel 数据地区转换器
// *
// * @author HUIHUI
// */
//@Slf4j
//public class AreaConvert implements Converter<Object> {
//
//    @Override
//    public Class<?> supportJavaTypeKey() {
//        throw new UnsupportedOperationException("暂不支持,也不需要");
//    }
//
//    @Override
//    public CellDataTypeEnum supportExcelTypeKey() {
//        throw new UnsupportedOperationException("暂不支持,也不需要");
//    }
//
//    @Override
//    public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty,
//                                    GlobalConfiguration globalConfiguration) {
//        // 解析地区编号
//        String label = readCellData.getStringValue();
//        Area area = AreaUtils.parseArea(label);
//        if (area == null) {
//            log.error("[convertToJavaData][label({}) 解析不掉]", label);
//            return null;
//        }
//        // 将 value 转换成对应的属性
//        Class<?> fieldClazz = contentProperty.getField().getType();
//        return Convert.convert(fieldClazz, area.getId());
//    }
//
//}
iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IailabMybatisAutoConfiguration.java
@@ -1,7 +1,6 @@
package com.iailab.framework.mybatis.config;
import cn.hutool.core.util.StrUtil;
import com.iailab.framework.mybatis.core.enums.SqlConstants;
import com.iailab.framework.mybatis.core.handler.DefaultDBFieldHandler;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalExceptionHandler.java
@@ -304,51 +304,51 @@
        }
        // 1. 数据报表
        if (message.contains("report_")) {
            log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
            log.error("[报表模块 iailab-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
                    "[报表模块 iailab-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
        }
        // 2. 工作流
        if (message.contains("bpm_")) {
            log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
            log.error("[工作流模块 iailab-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
                    "[工作流模块 iailab-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
        }
        // 3. 微信公众号
        if (message.contains("mp_")) {
            log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
            log.error("[微信公众号 iailab-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
                    "[微信公众号 iailab-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
        }
        // 4. 商城系统
        if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) {
            log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
            log.error("[商城系统 iailab-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
                    "[商城系统 iailab-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
        }
        // 5. ERP 系统
        if (message.contains("erp_")) {
            log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
            log.error("[ERP 系统 iailab-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
                    "[ERP 系统 iailab-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
        }
        // 6. CRM 系统
        if (message.contains("crm_")) {
            log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
            log.error("[CRM 系统 iailab-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
                    "[CRM 系统 iailab-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
        }
        // 7. 支付平台
        if (message.contains("pay_")) {
            log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
            log.error("[支付模块 iailab-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
                    "[支付模块 iailab-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
        }
        // 8. AI 大模型
        if (message.contains("ai_")) {
            log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
            log.error("[AI 大模型 iailab-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
                    "[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
                    "[AI 大模型 iailab-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
        }
        return null;
    }
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/ArrayValuable.java
对比新文件
@@ -0,0 +1,15 @@
package com.iailab.framework.common.core;
/**
 * 可生成 T 数组的接口
 *
 * @author HUIHUI
 */
public interface ArrayValuable<T> {
    /**
     * @return 数组
     */
    T[] array();
}
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/CommonStatusEnum.java
@@ -1,7 +1,7 @@
package com.iailab.framework.common.enums;
import cn.hutool.core.util.ObjUtil;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -14,12 +14,12 @@
 */
@Getter
@AllArgsConstructor
public enum CommonStatusEnum implements IntArrayValuable {
public enum CommonStatusEnum implements ArrayValuable {
    ENABLE(0, "开启"),
    DISABLE(1, "关闭");
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(CommonStatusEnum::getStatus).toArray(Integer[]::new);
    /**
     * 状态值
@@ -31,7 +31,7 @@
    private final String name;
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DateIntervalEnum.java
@@ -1,7 +1,7 @@
package com.iailab.framework.common.enums;
import cn.hutool.core.util.ArrayUtil;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -14,7 +14,7 @@
 */
@Getter
@AllArgsConstructor
public enum DateIntervalEnum implements IntArrayValuable {
public enum DateIntervalEnum implements ArrayValuable {
    DAY(1, "天"),
    WEEK(2, "周"),
@@ -23,7 +23,7 @@
    YEAR(5, "年")
    ;
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getInterval).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(DateIntervalEnum::getInterval).toArray(Integer[]::new);
    /**
     * 类型
@@ -35,7 +35,7 @@
    private final String name;
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/TerminalEnum.java
@@ -1,6 +1,6 @@
package com.iailab.framework.common.enums;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -13,7 +13,7 @@
 */
@RequiredArgsConstructor
@Getter
public enum TerminalEnum implements IntArrayValuable {
public enum TerminalEnum implements ArrayValuable {
    UNKNOWN(0, "未知"), // 目的:在无法解析到 terminal 时,使用它
    WECHAT_MINI_PROGRAM(10, "微信小程序"),
@@ -22,7 +22,7 @@
    APP(31, "手机 App"),
    ;
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(TerminalEnum::getTerminal).toArray(Integer[]::new);
    /**
     * 终端
@@ -34,7 +34,7 @@
    private final String name;
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
}
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/UserTypeEnum.java
@@ -1,7 +1,7 @@
package com.iailab.framework.common.enums;
import cn.hutool.core.util.ArrayUtil;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -12,13 +12,12 @@
 */
@AllArgsConstructor
@Getter
public enum UserTypeEnum implements IntArrayValuable {
public enum UserTypeEnum implements ArrayValuable {
    MEMBER(1, "会员"), // 面向 c 端,普通用户
    ADMIN(2, "管理员"); // 面向 b 端,管理后台
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(UserTypeEnum::getValue).toArray(Integer[]::new);
    /**
     * 类型
     */
@@ -33,7 +32,7 @@
    }
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
}
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/template/XMLParserUtils.java
对比新文件
@@ -0,0 +1,296 @@
package com.iailab.framework.common.util.template;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;
public class XMLParserUtils {
    private final Map<String, String> settings;
    private final double[][] inputData;
    public XMLParserUtils(Map<String, String> settings, double[][] inputData) {
        this.settings = settings;
        this.inputData = inputData;
    }
    public String parse(String xml) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
        doc.getDocumentElement().normalize();
        StringBuilder output = new StringBuilder();
        processNode(doc.getDocumentElement(), output, -1);
        return output.toString();
    }
    private void processNode(Node node, StringBuilder output, int index) {
        if (node.getNodeType() == Node.TEXT_NODE) {
            output.append(node.getTextContent().trim());
        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element element = (Element) node;
            switch (element.getTagName()) {
                case "simple-value":
                    processSimpleValue(element, output, index);
                    break;
                case "setting-value":
                    processSettingValue(element, output);
                    break;
                case "input-value":
                    processInputValue(element, output, index);
                    break;
                case "foreach-value":
                    processForeachValue(element, output);
                    break;
                default:
                    processChildren(element, output, index);
            }
        }
    }
    private void processChildren(Element element, StringBuilder output, int index) {
        NodeList children = element.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            processNode(children.item(i), output, index);
        }
    }
    private void processSimpleValue(Element element, StringBuilder output, int index) {
        processChildren(element, output, index);
    }
    private void processSettingValue(Element element, StringBuilder output) {
        String key = element.getAttribute("key");
        output.append(settings.getOrDefault(key, ""));
    }
    private void processInputValue(Element element, StringBuilder output, int index) {
        // 优先使用:port属性(动态计算)
        String portExpr = element.getAttribute(":port");
        if (portExpr.isEmpty()) {
            // 回退到port属性(静态值)
            portExpr = element.getAttribute("port");
        }
        String column = element.getAttribute("column");
        int col = Integer.parseInt(column);
        // 动态计算端口值(考虑当前索引)
        int port = evaluateExpression(portExpr, index);
        if (port >= 0 && port < inputData.length &&
                col >= 0 && col < inputData[port].length) {
            double value = inputData[port][col];
            output.append((int)value);
        } else {
            System.err.printf("Invalid data access: port=%d (max=%d), col=%d (max=%d)%n",
                    port, inputData.length - 1, col,
                    (port >= 0 && port < inputData.length) ? inputData[port].length - 1 : -1);
            // 默认值
            output.append("0");
        }
    }
    private void processForeachValue(Element element, StringBuilder output) {
        String lengthKey = element.getAttribute("length");
        int length = Integer.parseInt(settings.getOrDefault(lengthKey, "0"));
        String separator = element.getAttribute("separator");
        StringBuilder loopResult = new StringBuilder();
        for (int i = 0; i < length; i++) {
            StringBuilder itemOutput = new StringBuilder();
            // 直接处理所有子节点
            NodeList children = element.getChildNodes();
            for (int j = 0; j < children.getLength(); j++) {
                Node child = children.item(j);
                if (child.getNodeType() == Node.TEXT_NODE) {
                    String text = child.getTextContent();
                    // 动态确定转炉状态
                    boolean isBlowing = isFurnaceBlowing(i);
                    // 替换占位符并调整状态描述
                    text = text.replace("{index}", String.valueOf(i + 1))
                            .replace("未吹炼", isBlowing ? "正在吹炼" : "未吹炼")
                            .replace("距离上次吹炼结束时间",
                                    isBlowing ? "吹炼持续时间" : "距离上次吹炼结束时间");
                    itemOutput.append(text);
                } else if (child.getNodeType() == Node.ELEMENT_NODE) {
                    // 传递当前循环索引
                    processNode(child, itemOutput, i);
                }
            }
            loopResult.append(itemOutput);
            if (i < length - 1 && !separator.isEmpty()) {
                loopResult.append(separator);
            }
        }
        output.append(loopResult.toString().replace(" ", "").replace("\n", ""));
    }
    private boolean isFurnaceBlowing(int furnaceIndex) {
        // 实际业务逻辑:根据输入数据判断转炉状态
        // 这里简化处理:第三个转炉(index=2)正在吹炼
        return furnaceIndex == 2;
    }
    // 自定义表达式计算器
    private int evaluateExpression(String expr, int index) {
        if (expr == null || expr.isEmpty()) {
            System.err.println("Empty expression, returning 0");
            return 0;
        }
        // 替换表达式中的{index}占位符
        String processedExpr = expr.replace("{index}", String.valueOf(index));
        // 移除所有空格确保表达式正确解析
        processedExpr = processedExpr.replaceAll("\\s", "");
        // 尝试直接解析为整数(优化常见情况)
        try {
            return Integer.parseInt(processedExpr);
        } catch (NumberFormatException e) {
            // 不是简单整数,继续尝试表达式计算
        }
        // 自定义简单表达式解析器
        try {
            // 处理加法表达式(如 "3+0")
            if (processedExpr.contains("+")) {
                String[] parts = processedExpr.split("\\+");
                int result = 0;
                for (String part : parts) {
                    result += Integer.parseInt(part);
                }
                return result;
            }
            // 处理减法表达式(如 "5-2")
            else if (processedExpr.contains("-")) {
                String[] parts = processedExpr.split("-");
                int result = Integer.parseInt(parts[0]);
                for (int i = 1; i < parts.length; i++) {
                    result -= Integer.parseInt(parts[i]);
                }
                return result;
            }
//            // 处理乘法表达式(如 "2 * 3")
//            else if (processedExpr.contains("*")) {
//                String[] parts = processedExpr.split("\\*");
//                int result = 1;
//                for (String part : parts) {
//                    result *= Integer.parseInt(part);
//                }
//                return result;
//            }
//            // 处理除法表达式(如 "6/2")
//            else if (processedExpr.contains("/")) {
//                String[] parts = processedExpr.split("/");
//                int result = Integer.parseInt(parts[0]);
//                for (int i = 1; i < parts.length; i++) {
//                    int divisor = Integer.parseInt(parts[i]);
//                    if (divisor != 0) {
//                        result /= divisor;
//                    }
//                }
//                return result;
//            }
        } catch (NumberFormatException e) {
            System.err.println("Error parsing expression: " + processedExpr);
        }
        // 无法解析的表达式
        System.err.println("Unsupported expression format: " + processedExpr);
        return 0;
    }
    // test
    public static void main(String[] args) throws Exception {
        String xmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<iquestion>\n" +
                "    <simple-value>根据以下输入,</simple-value>\n" +
                "    <simple-value>\n" +
                "        根据未来<setting-value key=\"predictLength\"/>min的转炉煤气系统运行情况,对煤气调整用户进行调度分配,确保能源产消平衡与系统稳定运行。\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        该系统共包含<setting-value key=\"luShu\"/>座转炉。\n" +
                "    </simple-value>\n" +
                "    <foreach-value length=\"luShu\" index=\"index\" separator=\";\">\n" +
                "        {index}#转炉当前状态未吹炼,\n" +
                "        距离上次吹炼结束时间<input-value :port=\"3 + {index}\" column=\"0\" type=\"double\"/>min,\n" +
                "        前一炉回收间隔<input-value :port=\"3 + {index}\" column=\"2\" type=\"double\"/>min\n" +
                "    </foreach-value>\n" +
                "    <simple-value>\n" +
                "        日计划炉数:<input-value port=\"2\" column=\"0\" type=\"double\"/>,当前已吹炼炉数:<input-value port=\"3\" column=\"0\" type=\"double\"/>;\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        历史60min平均每炉煤气回收量:<input-value port=\"1\" column=\"0\" type=\"double\"/>Km3,\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        当前煤气消耗量<input-value port=\"1\" column=\"1\" type=\"double\"/>km3;\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        当前煤气柜容量<setting-value key=\"guiRongLiang\"/>km3;\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        煤气柜柜位安全区间为<setting-value key=\"anQuanQuJian\"/>km3,期望煤气柜位值在<setting-value key=\"qiWangZhi\"/>km3,\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        当前调度用户为电厂各机组:<setting-value key=\"jiZuMingCheng\"/>,\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        各机组当前使用转炉煤气量 [<input-value port=\"0\" column=\"0\" type=\"double\"/>, <input-value port=\"0\" column=\"1\" type=\"double\"/>, <input-value port=\"0\" column=\"2\" type=\"double\"/>, <input-value port=\"0\" column=\"3\" type=\"double\"/>, <input-value port=\"0\" column=\"4\" type=\"double\"/>, <input-value port=\"0\" column=\"5\" type=\"double\"/>];\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        各机组使用转炉煤气下限量 <setting-value key=\"jiZuXiaXian\"/>。\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        各机组使用转炉煤气上限量 <setting-value key=\"jiZuShangXian\"/>。\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        机组优先级顺序为:<setting-value key=\"jiZuYouXianJi\"/>。\n" +
                "    </simple-value>\n" +
                "    <simple-value>请根据优先级顺序确定调度方案。</simple-value>\n" +
                "</iquestion>";
        // 1. 准备配置数据
        Map<String, String> settings = new HashMap<>();
        settings.put("predictLength", "60");
        settings.put("luShu", "3");
        settings.put("guiRongLiang", "80");
        settings.put("anQuanQuJian", "[30, 110]");
        settings.put("qiWangZhi", "65");
        settings.put("jiZuMingCheng", "1#135, 2#135, 1#BTG, 2#BTG, 3#BTG, 4#BTG");
        settings.put("jiZuXiaXian", "[20, 1, 16, 17, 6, 11]");
        settings.put("jiZuShangXian", "[92, 96, 74, 101, 86, 93]");
        settings.put("jiZuYouXianJi", "1#135, 1#BTG, 3#BTG, 2#135, 2#BTG, 4#BTG");
        // 示例输入数据 - 与期望输出完全匹配
        double[][] inputData = {
                // 机组当前用量
                {39, 39, 32, 56, 38, 48},
                // [0]:历史回收量, [1]:当前消耗量
                {24, 115},
                // [0]:日计划炉数, [1]:已吹炼炉数
                {21, 10},
                // 转炉1: [0]:结束时间, [2]:回收间隔
                {15, 0, 18},
                // 转炉2: [0]:结束时间, [2]:回收间隔
                {9, 0, 24},
                // 转炉3: [0]:吹炼持续时间, [2]:回收间隔
                {7, 0, 25}
        };
        // 3. 创建解析器并执行
        XMLParserUtils parser = new XMLParserUtils(settings, inputData);
        String result = parser.parse(xmlContent); // 替换为你的XML内容
        System.out.println(result);
    }
}
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnum.java
@@ -1,6 +1,6 @@
package com.iailab.framework.common.validation;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import javax.validation.Constraint;
import javax.validation.Payload;
@@ -24,7 +24,7 @@
    /**
     * @return 实现 EnumValuable 接口的
     */
    Class<? extends IntArrayValuable> value();
    Class<? extends ArrayValuable> value();
    String message() default "必须在指定范围 {value}";
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumCollectionValidator.java
@@ -1,7 +1,7 @@
package com.iailab.framework.common.validation;
import cn.hutool.core.collection.CollUtil;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
@@ -9,24 +9,23 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class InEnumCollectionValidator implements ConstraintValidator<InEnum, Collection<Integer>> {
public class InEnumCollectionValidator implements ConstraintValidator<InEnum, Collection<?>> {
    private List<Integer> values;
    private List<?> values;
    @Override
    public void initialize(InEnum annotation) {
        IntArrayValuable[] values = annotation.value().getEnumConstants();
        ArrayValuable<?>[] values = annotation.value().getEnumConstants();
        if (values.length == 0) {
            this.values = Collections.emptyList();
        } else {
            this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
            this.values = Arrays.asList(values[0].array());
        }
    }
    @Override
    public boolean isValid(Collection<Integer> list, ConstraintValidatorContext context) {
    public boolean isValid(Collection<?> list, ConstraintValidatorContext context) {
        // 校验通过
        if (CollUtil.containsAll(values, list)) {
            return true;
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumValidator.java
@@ -1,30 +1,29 @@
package com.iailab.framework.common.validation;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {
public class InEnumValidator implements ConstraintValidator<InEnum, Object> {
    private List<Integer> values;
    private List<?> values;
    @Override
    public void initialize(InEnum annotation) {
        IntArrayValuable[] values = annotation.value().getEnumConstants();
        ArrayValuable<?>[] values = annotation.value().getEnumConstants();
        if (values.length == 0) {
            this.values = Collections.emptyList();
        } else {
            this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
            this.values = Arrays.asList(values[0].array());
        }
    }
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        // 为空时,默认不校验,即认为通过
        if (value == null) {
            return true;
@@ -33,7 +32,7 @@
        if (values.contains(value)) {
            return true;
        }
        // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
        // 校验不通过,自定义提示语句
        context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
        context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
                .replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句
iailab-module-ai/.idea/.gitignore
对比新文件
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
iailab-module-ai/.idea/compiler.xml
对比新文件
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CompilerConfiguration">
    <annotationProcessing>
      <profile default="true" name="Default" enabled="true" />
      <profile name="Maven default annotation processors profile" enabled="true">
        <sourceOutputDir name="target/generated-sources/annotations" />
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
        <outputRelativeToContentRoot value="true" />
        <module name="yudao-module-ai-api" />
      </profile>
      <profile name="Annotation profile for iailab-module-ai" enabled="true">
        <sourceOutputDir name="target/generated-sources/annotations" />
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
        <outputRelativeToContentRoot value="true" />
        <processorPath useClasspath="false">
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/springframework/boot/spring-boot-configuration-processor/3.4.1/spring-boot-configuration-processor-3.4.1.jar" />
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/projectlombok/lombok/1.18.36/lombok-1.18.36.jar" />
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/mapstruct/mapstruct-processor/1.6.3/mapstruct-processor-1.6.3.jar" />
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/mapstruct/mapstruct/1.6.3/mapstruct-1.6.3.jar" />
        </processorPath>
        <module name="iailab-module-ai-api" />
        <module name="iailab-spring-boot-starter-ai" />
        <module name="iailab-module-ai-biz" />
      </profile>
    </annotationProcessing>
  </component>
  <component name="JavacSettings">
    <option name="ADDITIONAL_OPTIONS_OVERRIDE">
      <module name="iailab-module-ai-api" options="-parameters" />
      <module name="iailab-module-ai-biz" options="-parameters" />
      <module name="iailab-spring-boot-starter-ai" options="-parameters" />
    </option>
  </component>
</project>
iailab-module-ai/.idea/jarRepositories.xml
对比新文件
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RemoteRepositoriesConfiguration">
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Central Repository" />
      <option name="url" value="https://repo.maven.apache.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="iailab" />
      <option name="name" value="iailab" />
      <option name="url" value="http://172.16.8.100:8090/repository/iailab/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Maven Central repository" />
      <option name="url" value="https://repo1.maven.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="jboss.community" />
      <option name="name" value="JBoss Community repository" />
      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="iailab" />
      <option name="name" value="iailab" />
      <option name="url" value="http://www.jira.dlindusit.com:30078/repository/iailab/" />
    </remote-repository>
  </component>
</project>
iailab-module-ai/.idea/misc.xml
对比新文件
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ExternalStorageConfigurationManager" enabled="true" />
  <component name="MavenProjectsManager">
    <option name="originalFiles">
      <list>
        <option value="$PROJECT_DIR$/pom.xml" />
        <option value="$PROJECT_DIR$/iailab-module-ai-api/pom.xml" />
        <option value="$PROJECT_DIR$/iailab-spring-boot-starter-ai/pom.xml" />
      </list>
    </option>
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="graalvm-jdk-17" project-jdk-type="JavaSDK" />
</project>
iailab-module-ai/.idea/sonarlint.xml
对比新文件
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="SonarLintProjectSettings">
    <option name="moduleMapping">
      <map>
        <entry key="iailab-module-ai-biz" value="yudao-module-ai-biz" />
        <entry key="iailab-spring-boot-starter-ai" value="yudao-spring-boot-starter-ai" />
      </map>
    </option>
  </component>
</project>
iailab-module-ai/.idea/vcs.xml
对比新文件
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
  </component>
</project>
iailab-module-ai/iailab-module-ai-api/pom.xml
@@ -5,7 +5,7 @@
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-module-ai</artifactId>
        <version>${ai.revision}</version>
        <version>${revision}</version>
    </parent>
    <build>
        <plugins>
@@ -34,11 +34,26 @@
            <artifactId>iailab-common</artifactId>
        </dependency>
        <!-- Web 相关 -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.8.0</version>
            <scope>provided</scope> <!-- 设置为 provided,主要是 PageParam 使用到 -->
        </dependency>
        <!-- 参数校验 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- RPC 远程调用相关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatConversationApi.java
对比新文件
@@ -0,0 +1,20 @@
package com.iailab.module.ai.api.chat;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.module.ai.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 大模型会话")
public interface AiChatConversationApi {
    String PREFIX = ApiConstants.PREFIX + "/conversation";
    @GetMapping(PREFIX + "/energy-conversation")
    @Operation(summary = "会话列表", description = "查询会话列表,只有一条,首次查询先创建再查询")
    Long chatEnergyConversation(@RequestParam("modelName") String modelName);
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApi.java
对比新文件
@@ -0,0 +1,22 @@
package com.iailab.module.ai.api.chat;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendRespDTO;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendReqDTO;
import com.iailab.module.ai.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 大模型消息")
public interface AiChatMessageApi {
    String PREFIX = ApiConstants.PREFIX + "/message";
    @PostMapping(PREFIX + "/send-message")
    @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢")
    AiChatMessageSendRespDTO sendMessage(@Valid @RequestBody AiChatMessageSendReqDTO sendReqDTO);
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatConversationRespDTO.java
对比新文件
@@ -0,0 +1,58 @@
package com.iailab.module.ai.api.chat.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
public class AiChatConversationRespDTO {
    @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    private Long id;
    @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
    private Long userId;
    @Schema(description = "对话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题")
    private String title;
    @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
    private Boolean pinned;
    @Schema(description = "角色编号", example = "1")
    private Long roleId;
    @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long modelId;
    @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922")
    private String model;
    @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
    private String modelName;
    @Schema(description = "角色设定", example = "一个快乐的程序员")
    private String systemMessage;
    @Schema(description = "温度参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8")
    private Double temperature;
    @Schema(description = "单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
    private Integer maxTokens;
    @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
    private Integer maxContexts;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    private LocalDateTime createTime;
    // ========== 关联 role 信息 ==========
    @Schema(description = "角色头像", example = "https://www.Iailab.cn/1.png")
    private String roleAvatar;
    @Schema(description = "角色名字", example = "小黄")
    private String roleName;
    // ========== 仅在【对话管理】时加载 ==========
    @Schema(description = "消息数量", example = "20")
    private Integer messageCount;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendReqDTO.java
对比新文件
@@ -0,0 +1,23 @@
package com.iailab.module.ai.api.chat.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - AI 聊天消息发送 Request VO")
@Data
public class AiChatMessageSendReqDTO {
    @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @NotNull(message = "聊天对话编号不能为空")
    private Long conversationId;
    @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法")
    @NotEmpty(message = "聊天内容不能为空")
    private String content;
    @Schema(description = "是否携带上下文", example = "true")
    private Boolean useContext;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendRespDTO.java
对比新文件
@@ -0,0 +1,34 @@
package com.iailab.module.ai.api.chat.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class AiChatMessageSendRespDTO {
    @Schema(description = "发送消息", requiredMode = Schema.RequiredMode.REQUIRED)
    private Message send;
    @Schema(description = "接收消息", requiredMode = Schema.RequiredMode.REQUIRED)
    private Message receive;
    @Schema(description = "消息")
    @Data
    public static class Message {
        @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
        private Long id;
        @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role")
        private String type; // 参见 MessageType 枚举类
        @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
        private String content;
        @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
        private LocalDateTime createTime;
    }
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiModelDO.java
对比新文件
@@ -0,0 +1,79 @@
package com.iailab.module.ai.api.chat.dto;
import com.iailab.framework.common.enums.CommonStatusEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * AI 模型 DO
 *
 * 默认模型:{@link #status} 为开启,并且 {@link #sort} 排序第一
 *
 * @author houzhongjian
 * @since 2025/6/33 11:39
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AiModelDO {
    /**
     * 编号
     */
    private Long id;
    /**
     * API 秘钥编号
     *
     */
    private Long keyId;
    /**
     * 模型名称
     */
    private String name;
    /**
     * 模型标志
     */
    private String model;
    /**
     * 平台
     *
     */
    private String platform;
    /**
     * 类型
     *
     */
    private Integer type;
    /**
     * 排序值
     */
    private Integer sort;
    /**
     * 状态
     *
     * 枚举 {@link CommonStatusEnum}
     */
    private Integer status;
    // ========== 对话配置 ==========
    /**
     * 温度参数
     *
     * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性
     */
    private Double temperature;
    /**
     * 单条回复的最大 Token 数量
     */
    private Integer maxTokens;
    /**
     * 上下文的最大 Message 数量
     */
    private Integer maxContexts;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/enums/ApiConstants.java
对比新文件
@@ -0,0 +1,23 @@
package com.iailab.module.ai.enums;
import com.iailab.framework.common.enums.RpcConstants;
/**
 * API 相关的枚举
 *
 * @author iailab
 */
public class ApiConstants {
    /**
     * 服务名
     *
     * 注意,需要保证和 spring.application.name 保持一致
     */
    public static final String NAME = "ai-server";
    public static final String PREFIX = RpcConstants.RPC_API_PREFIX +  "/ai";
    public static final String VERSION = "1.0.0";
}
iailab-module-ai/iailab-module-ai-biz/pom.xml
@@ -5,7 +5,7 @@
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-module-ai</artifactId>
        <version>${ai.revision}</version>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>iailab-module-ai-biz</artifactId>
@@ -29,7 +29,7 @@
        <dependency>
            <groupId>com.iailab</groupId>
            <artifactId>iailab-module-ai-api</artifactId>
            <version>${ai.revision}</version>
            <version>${revision}</version>
        </dependency>
        <!-- 业务组件 -->
@@ -114,8 +114,8 @@
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatConversionApiImpl.java
对比新文件
@@ -0,0 +1,34 @@
package com.iailab.module.ai.api.chat;
import com.iailab.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateEnergyReqVO;
import com.iailab.module.ai.dal.dataobject.chat.AiChatConversationDO;
import com.iailab.module.ai.service.chat.AiChatConversationService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class AiChatConversionApiImpl implements AiChatConversationApi {
    @Resource
    private AiChatConversationService chatConversationService;
    @Override
    public Long chatEnergyConversation(String modelName) {
        Long conversationId;
        List<AiChatConversationDO> list = chatConversationService.getChatConversationList(getLoginUserId(), modelName);
        if(list.size() == 0) {
            AiChatConversationCreateEnergyReqVO createReqVO = new AiChatConversationCreateEnergyReqVO();
            createReqVO.setModelName(modelName);
            conversationId = chatConversationService.createChatConversationEnergy(createReqVO);
        } else {
            conversationId = list.get(0).getId();
        }
        return conversationId;
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApiImpl.java
对比新文件
@@ -0,0 +1,27 @@
package com.iailab.module.ai.api.chat;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendRespDTO;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendReqDTO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import com.iailab.module.ai.service.chat.AiChatMessageService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class AiChatMessageApiImpl implements AiChatMessageApi {
    @Resource
    private AiChatMessageService chatMessageService;
    @Override
    public AiChatMessageSendRespDTO sendMessage(AiChatMessageSendReqDTO sendReqDTO) {
        AiChatMessageSendRespVO aiChatMessageSendRespVO = chatMessageService.sendMessage(BeanUtils.toBean(sendReqDTO, AiChatMessageSendReqVO.class), getLoginUserId());
        return BeanUtils.toBean(aiChatMessageSendRespVO, AiChatMessageSendRespDTO.class);
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/package-info.java
对比新文件
@@ -0,0 +1 @@
package com.iailab.module.ai.api;
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatConversationServiceImpl.java
@@ -92,7 +92,7 @@
        AiChatConversationDO conversation = new AiChatConversationDO().setUserId(getLoginUserId()).setPinned(false)
                .setModelId(model.getId()).setModel(model.getModel())
                .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts());
        conversation.setTitle("新对话");
        conversation.setTitle(createReqVO.getModelName());
        chatConversationMapper.insert(conversation);
        return conversation.getId();
    }
iailab-module-ai/iailab-module-ai-biz/src/main/resources/application.yaml
@@ -11,6 +11,7 @@
      username: @nacos.username@
      password: @nacos.password@
      discovery: # 【配置中心】配置项
        ip: @deploy.server@
        namespace: @profiles.active@
        group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
        metadata:
@@ -59,7 +60,7 @@
logging:
  file:
    name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
    name: @log.path@/logs/${spring.application.name}.log # 日志文件名,全路径
--- #################### 接口文档配置 ####################
@@ -111,7 +112,7 @@
  job:
    executor:
      appname: ${spring.application.name} # 执行器 AppName
      logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
      logpath: @log.path@/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
    accessToken: default_token # 执行器通讯TOKEN
--- #################### AI 相关配置 ####################
iailab-module-ai/iailab-spring-boot-starter-ai/pom.xml
@@ -5,7 +5,7 @@
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-module-ai</artifactId>
        <version>${ai.revision}</version>
        <version>${revision}</version>
    </parent>
    <build>
        <plugins>
iailab-module-ai/pom.xml
@@ -10,7 +10,7 @@
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.iailab</groupId>
    <artifactId>iailab-module-ai</artifactId>
    <version>${ai.revision}</version>
    <version>${revision}</version>
    <packaging>pom</packaging>
    <modules>
@@ -44,7 +44,7 @@
        <spring.cloud.version>2024.0.0</spring.cloud.version>
        <spring.cloud.alibaba.version>2023.0.3.2</spring.cloud.alibaba.version>
        <!-- Web 相关 -->
        <springdoc.version>2.7.0</springdoc.version>
        <springdoc.version>2.8.3</springdoc.version>
        <knife4j.version>4.6.0</knife4j.version>
        <!-- 工具类相关 -->
        <bizlog-sdk.version>3.0.6</bizlog-sdk.version>
iailab-module-data/iailab-module-data-biz/logs/log-debug.2024-11-06.log
对比新文件
@@ -0,0 +1,262 @@
[2024-11-06 09:06:36.026] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStarting,line : 55] Starting RabbitMQTest using Java 1.8.0_401 on Thinkpad-E14 with PID 5916 (started by houzh in D:\Work\Yingdashi\Project\iailab-plat\iailab-plat\iailab-module-data\iailab-module-data-biz)
[2024-11-06 09:06:36.028] | [main][DEBUG] | [c.i.m.d.c.RabbitMQTest.logStarting,line : 56] Running with Spring Boot v2.7.18, Spring v5.3.31
[2024-11-06 09:06:36.029] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStartupProfileInfo,line : 638] The following 1 profile is active: "dev"
[2024-11-06 09:06:36.030] | [main][DEBUG] | [o.s.b.SpringApplication.load,line : 665] Loading source class com.iailab.DataWebApplication
[2024-11-06 09:06:36.094] | [main][WARN ] | [c.a.c.n.c.NacosConfigDataLoader.logTo,line : 258] [Nacos Config] config[dataId=data-server-dev.yaml, group=DEFAULT_GROUP] is empty
[2024-11-06 09:06:36.096] | [main][DEBUG] | [o.s.w.c.s.GenericWebApplicationContext.prepareRefresh,line : 637] Refreshing org.springframework.web.context.support.GenericWebApplicationContext@89caf47
[2024-11-06 09:06:41.325] | [main][INFO ] | [o.s.c.c.s.GenericScope.setSerializationId,line : 283] BeanFactory id=3cae36f0-6484-3ade-8207-23df73e70f40
[2024-11-06 09:06:42.336] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration' of type [com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration$$EnhancerBySpringCGLIB$$d78165de] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.361] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration' of type [org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.369] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.373] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'loadBalancerClientsDefaultsMappingsProvider' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration$$Lambda$810/1156038763] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.382] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'defaultsBindHandlerAdvisor' of type [org.springframework.cloud.commons.config.DefaultsBindHandlerAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.391] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'mzt.log.record-com.mzt.logapi.starter.configuration.LogRecordProperties' of type [com.mzt.logapi.starter.configuration.LogRecordProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.418] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'logRecordPerformanceMonitor' of type [com.mzt.logapi.service.impl.DefaultLogRecordPerformanceMonitor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.958] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration' of type [com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:42.984] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'dataPermissionAnnotationAdvisor' of type [com.iailab.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:43.153] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.iailab.framework.tenant.config.IailabTenantAutoConfiguration' of type [com.iailab.framework.tenant.config.IailabTenantAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:43.262] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'dsProcessor' of type [com.iailab.framework.tenant.core.db.dynamic.TenantDsProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:06:44.667] | [main][INFO ] | [c.a.d.p.DruidDataSource.init,line : 1002] {dataSource-1,master} inited
[2024-11-06 09:06:44.668] | [main][INFO ] | [c.b.d.d.DynamicRoutingDataSource.addDataSource,line : 158] dynamic-datasource - add a datasource named [master] success
[2024-11-06 09:06:44.670] | [main][INFO ] | [c.b.d.d.DynamicRoutingDataSource.afterPropertiesSet,line : 241] dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
[2024-11-06 09:06:49.393] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:06:49.568] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:06:51.980] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1220] Using default implementation for ThreadExecutor
[2024-11-06 09:06:52.058] | [main][INFO ] | [o.q.c.SchedulerSignalerImpl.<init>,line : 61] Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[2024-11-06 09:06:52.058] | [main][INFO ] | [o.q.c.QuartzScheduler.<init>,line : 229] Quartz Scheduler v.2.3.2 created.
[2024-11-06 09:06:52.093] | [main][INFO ] | [o.s.s.q.LocalDataSourceJobStore.initialize,line : 672] Using db table-based data access locking (synchronization).
[2024-11-06 09:06:52.099] | [main][INFO ] | [o.s.s.q.LocalDataSourceJobStore.initialize,line : 145] JobStoreCMT initialized.
[2024-11-06 09:06:52.101] | [main][INFO ] | [o.q.c.QuartzScheduler.initialize,line : 294] Scheduler meta-data: Quartz Scheduler (v2.3.2) 'IailabDataScheduler' with instanceId 'Thinkpad-E141730855212013'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 20 threads.
  Using job-store 'org.springframework.scheduling.quartz.LocalDataSourceJobStore' - which supports persistence. and is clustered.
[2024-11-06 09:06:52.101] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1374] Quartz scheduler 'IailabDataScheduler' initialized from an externally provided properties instance.
[2024-11-06 09:06:52.102] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1378] Quartz scheduler version: 2.3.2
[2024-11-06 09:06:52.107] | [main][INFO ] | [o.q.c.QuartzScheduler.setJobFactory,line : 2293] JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@26aecf31
[2024-11-06 09:06:54.172] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:06:54.397] | [main][INFO ] | [o.r.Reflections.scan,line : 219] Reflections took 99 ms to scan 1 urls, producing 38 keys and 321 values
[2024-11-06 09:06:55.214] | [main][DEBUG] | [o.s.b.a.AutoConfigurationPackages.get,line : 196] @EnableAutoConfiguration was declared on a class in the package 'com.iailab'. Automatic @Repository and @Entity scanning is enabled.
[2024-11-06 09:06:55.698] | [main][DEBUG] | [o.s.w.s.m.m.a.RequestMappingHandlerAdapter.initControllerAdviceCache,line : 625] ControllerAdvice beans: 1 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 3 ResponseBodyAdvice
[2024-11-06 09:06:56.060] | [main][DEBUG] | [o.s.w.s.m.m.a.RequestMappingHandlerMapping.handlerMethodsInitialized,line : 367] 149 mappings in 'requestMappingHandlerMapping'
[2024-11-06 09:06:56.340] | [main][DEBUG] | [o.s.w.s.h.SimpleUrlHandlerMapping.logMappings,line : 188] Patterns [/webjars/**, /**, /swagger-ui*/*swagger-initializer.js, /swagger-ui*/**] in 'resourceHandlerMapping'
[2024-11-06 09:06:56.423] | [main][DEBUG] | [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver.initExceptionHandlerAdviceCache,line : 307] ControllerAdvice beans: 2 @ExceptionHandler, 3 ResponseBodyAdvice
[2024-11-06 09:06:56.674] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:06:56.721] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:06:58.761] | [main][INFO ] | [org.redisson.Version.logVersion,line : 41] Redisson 3.18.0
[2024-11-06 09:07:00.360] | [redisson-netty-2-7][INFO ] | [o.r.c.p.MasterPubSubConnectionPool.lambda$createConnection$0,line : 162] 1 connections initialized for 172.16.8.100/172.16.8.100:6379
[2024-11-06 09:07:00.457] | [redisson-netty-2-19][INFO ] | [o.r.c.p.MasterConnectionPool.lambda$createConnection$0,line : 162] 24 connections initialized for 172.16.8.100/172.16.8.100:6379
[2024-11-06 09:07:00.651] | [main][INFO ] | [o.s.b.a.e.w.EndpointLinksResolver.<init>,line : 58] Exposing 1 endpoint(s) beneath base path '/actuator'
[2024-11-06 09:07:00.742] | [main][INFO ] | [o.s.s.w.DefaultSecurityFilterChain.<init>,line : 55] Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@73852c7c, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4b6fc615, org.springframework.security.web.context.SecurityContextPersistenceFilter@47609e3d, org.springframework.security.web.header.HeaderWriterFilter@28f307ca, org.springframework.web.filter.CorsFilter@70661538, org.springframework.security.web.authentication.logout.LogoutFilter@144d064a, com.iailab.framework.security.core.filter.TokenAuthenticationFilter@575b9b92, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@2a7c82e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@22128b73, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@de7abc9, org.springframework.security.web.session.SessionManagementFilter@71103416, org.springframework.security.web.access.ExceptionTranslationFilter@1ab64f66, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3e11cc3a]
[2024-11-06 09:07:04.051] | [main][INFO ] | [c.f.c.s.SpringContextUtil.setApplicationContext,line : 38] ------SpringContextUtil setApplicationContext-------
[2024-11-06 09:07:04.371] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:07:04.462] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:07:04.478] | [main][INFO ] | [c.i.f.d.c.DictFrameworkUtils.init,line : 73] [init][初始化 DictFrameworkUtils 成功]
[2024-11-06 09:07:04.507] | [main][INFO ] | [c.i.f.j.c.IailabJacksonAutoConfiguration.jsonUtils,line : 48] [init][初始化 JsonUtils 成功]
[2024-11-06 09:07:04.649] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:07:05.471] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:07:10.281] | [main][INFO ] | [o.s.s.q.SchedulerFactoryBean.startScheduler,line : 734] Will start Quartz Scheduler [IailabDataScheduler] in 30 seconds
[2024-11-06 09:07:10.301] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStarted,line : 61] Started RabbitMQTest in 42.46 seconds (JVM running for 44.048)
[2024-11-06 09:07:10.311] | [main][DEBUG] | [o.s.b.a.ApplicationAvailabilityBean.onApplicationEvent,line : 77] Application availability state LivenessState changed to CORRECT
[2024-11-06 09:07:10.579] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] ==>  Preparing: SELECT id, bean_name, params, cron_expression, status, remark, updater, update_date, tenant_id, creator, create_date FROM schedule_job
[2024-11-06 09:07:10.612] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] ==> Parameters:
[2024-11-06 09:07:10.643] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] <==      Total: 1
[2024-11-06 09:07:10.836] | [main][INFO ] | [c.a.c.n.r.NacosContextRefresher.registerNacosListener,line : 141] [Nacos Config] Listening config: dataId=data-server-dev.yaml, group=DEFAULT_GROUP
[2024-11-06 09:07:10.976] | [main][DEBUG] | [o.s.b.a.ApplicationAvailabilityBean.onApplicationEvent,line : 77] Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
[2024-11-06 09:07:11.801] | [pool-13-thread-1][INFO ] | [c.i.f.b.c.BannerApplicationRunner.lambda$run$0,line : 22]
----------------------------------------------------------
    项目启动成功!
    ----------------------------------------------------------
[2024-11-06 09:07:11.849] | [main][INFO ] | [o.s.a.r.c.CachingConnectionFactory.connectAddresses,line : 639] Attempting to connect to: [172.16.8.200:15672]
[2024-11-06 09:07:16.914] | [Thread-7][WARN ] | [c.a.n.c.n.NotifyCenter.shutdown,line : 136] [NotifyCenter] Start destroying Publisher
[2024-11-06 09:07:16.915] | [Thread-7][WARN ] | [c.a.n.c.n.NotifyCenter.shutdown,line : 153] [NotifyCenter] Destruction of the end
[2024-11-06 09:07:16.915] | [Thread-2][WARN ] | [c.a.n.c.h.HttpClientBeanHolder.shutdown,line : 102] [HttpClientBeanHolder] Start destroying common HttpClient
[2024-11-06 09:07:16.915] | [SpringApplicationShutdownHook][DEBUG] | [o.s.w.c.s.GenericWebApplicationContext.doClose,line : 1060] Closing org.springframework.web.context.support.GenericWebApplicationContext@89caf47, started on Wed Nov 06 09:06:36 CST 2024
[2024-11-06 09:07:16.916] | [Thread-2][WARN ] | [c.a.n.c.h.HttpClientBeanHolder.shutdown,line : 111] [HttpClientBeanHolder] Destruction of the end
[2024-11-06 09:07:16.966] | [SpringApplicationShutdownHook][INFO ] | [o.s.s.q.SchedulerFactoryBean.destroy,line : 847] Shutting down Quartz Scheduler
[2024-11-06 09:07:16.966] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.shutdown,line : 666] Scheduler IailabDataScheduler_$_Thinkpad-E141730855212013 shutting down.
[2024-11-06 09:07:16.966] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.standby,line : 585] Scheduler IailabDataScheduler_$_Thinkpad-E141730855212013 paused.
[2024-11-06 09:07:16.966] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.shutdown,line : 740] Scheduler IailabDataScheduler_$_Thinkpad-E141730855212013 shutdown complete.
[2024-11-06 09:07:16.971] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.DynamicRoutingDataSource.destroy,line : 215] dynamic-datasource start closing ....
[2024-11-06 09:07:16.974] | [SpringApplicationShutdownHook][INFO ] | [c.a.d.p.DruidDataSource.close,line : 2204] {dataSource-1} closing ...
[2024-11-06 09:07:17.013] | [SpringApplicationShutdownHook][INFO ] | [c.a.d.p.DruidDataSource.close,line : 2277] {dataSource-1} closed
[2024-11-06 09:07:17.013] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.d.DefaultDataSourceDestroyer.destroy,line : 98] dynamic-datasource close the datasource named [master] success,
[2024-11-06 09:07:17.013] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.DynamicRoutingDataSource.destroy,line : 219] dynamic-datasource all closed success,bye
[2024-11-06 09:08:13.680] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStarting,line : 55] Starting RabbitMQTest using Java 1.8.0_401 on Thinkpad-E14 with PID 25204 (started by houzh in D:\Work\Yingdashi\Project\iailab-plat\iailab-plat\iailab-module-data\iailab-module-data-biz)
[2024-11-06 09:08:13.683] | [main][DEBUG] | [c.i.m.d.c.RabbitMQTest.logStarting,line : 56] Running with Spring Boot v2.7.18, Spring v5.3.31
[2024-11-06 09:08:13.684] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStartupProfileInfo,line : 638] The following 1 profile is active: "dev"
[2024-11-06 09:08:13.685] | [main][DEBUG] | [o.s.b.SpringApplication.load,line : 665] Loading source class com.iailab.DataWebApplication
[2024-11-06 09:08:13.805] | [main][WARN ] | [c.a.c.n.c.NacosConfigDataLoader.logTo,line : 258] [Nacos Config] config[dataId=data-server-dev.yaml, group=DEFAULT_GROUP] is empty
[2024-11-06 09:08:13.815] | [main][DEBUG] | [o.s.w.c.s.GenericWebApplicationContext.prepareRefresh,line : 637] Refreshing org.springframework.web.context.support.GenericWebApplicationContext@586495f1
[2024-11-06 09:08:19.665] | [main][INFO ] | [o.s.c.c.s.GenericScope.setSerializationId,line : 283] BeanFactory id=3cae36f0-6484-3ade-8207-23df73e70f40
[2024-11-06 09:08:20.707] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration' of type [com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration$$EnhancerBySpringCGLIB$$30a6dd7c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:20.743] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration' of type [org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:20.752] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:20.759] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'loadBalancerClientsDefaultsMappingsProvider' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration$$Lambda$810/1161998217] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:20.771] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'defaultsBindHandlerAdvisor' of type [org.springframework.cloud.commons.config.DefaultsBindHandlerAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:20.784] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'mzt.log.record-com.mzt.logapi.starter.configuration.LogRecordProperties' of type [com.mzt.logapi.starter.configuration.LogRecordProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:20.826] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'logRecordPerformanceMonitor' of type [com.mzt.logapi.service.impl.DefaultLogRecordPerformanceMonitor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:21.401] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration' of type [com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:21.418] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'dataPermissionAnnotationAdvisor' of type [com.iailab.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:21.561] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.iailab.framework.tenant.config.IailabTenantAutoConfiguration' of type [com.iailab.framework.tenant.config.IailabTenantAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:21.678] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'dsProcessor' of type [com.iailab.framework.tenant.core.db.dynamic.TenantDsProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:08:23.240] | [main][INFO ] | [c.a.d.p.DruidDataSource.init,line : 1002] {dataSource-1,master} inited
[2024-11-06 09:08:23.242] | [main][INFO ] | [c.b.d.d.DynamicRoutingDataSource.addDataSource,line : 158] dynamic-datasource - add a datasource named [master] success
[2024-11-06 09:08:23.244] | [main][INFO ] | [c.b.d.d.DynamicRoutingDataSource.afterPropertiesSet,line : 241] dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
[2024-11-06 09:08:28.721] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:28.928] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:31.564] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1220] Using default implementation for ThreadExecutor
[2024-11-06 09:08:31.595] | [main][INFO ] | [o.q.c.SchedulerSignalerImpl.<init>,line : 61] Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[2024-11-06 09:08:31.596] | [main][INFO ] | [o.q.c.QuartzScheduler.<init>,line : 229] Quartz Scheduler v.2.3.2 created.
[2024-11-06 09:08:31.621] | [main][INFO ] | [o.s.s.q.LocalDataSourceJobStore.initialize,line : 672] Using db table-based data access locking (synchronization).
[2024-11-06 09:08:31.626] | [main][INFO ] | [o.s.s.q.LocalDataSourceJobStore.initialize,line : 145] JobStoreCMT initialized.
[2024-11-06 09:08:31.627] | [main][INFO ] | [o.q.c.QuartzScheduler.initialize,line : 294] Scheduler meta-data: Quartz Scheduler (v2.3.2) 'IailabDataScheduler' with instanceId 'Thinkpad-E141730855311568'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 20 threads.
  Using job-store 'org.springframework.scheduling.quartz.LocalDataSourceJobStore' - which supports persistence. and is clustered.
[2024-11-06 09:08:31.627] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1374] Quartz scheduler 'IailabDataScheduler' initialized from an externally provided properties instance.
[2024-11-06 09:08:31.628] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1378] Quartz scheduler version: 2.3.2
[2024-11-06 09:08:31.631] | [main][INFO ] | [o.q.c.QuartzScheduler.setJobFactory,line : 2293] JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@3c51dec5
[2024-11-06 09:08:33.431] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:33.588] | [main][INFO ] | [o.r.Reflections.scan,line : 219] Reflections took 86 ms to scan 1 urls, producing 38 keys and 321 values
[2024-11-06 09:08:34.350] | [main][DEBUG] | [o.s.b.a.AutoConfigurationPackages.get,line : 196] @EnableAutoConfiguration was declared on a class in the package 'com.iailab'. Automatic @Repository and @Entity scanning is enabled.
[2024-11-06 09:08:34.876] | [main][DEBUG] | [o.s.w.s.m.m.a.RequestMappingHandlerAdapter.initControllerAdviceCache,line : 625] ControllerAdvice beans: 1 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 3 ResponseBodyAdvice
[2024-11-06 09:08:35.264] | [main][DEBUG] | [o.s.w.s.m.m.a.RequestMappingHandlerMapping.handlerMethodsInitialized,line : 367] 149 mappings in 'requestMappingHandlerMapping'
[2024-11-06 09:08:35.523] | [main][DEBUG] | [o.s.w.s.h.SimpleUrlHandlerMapping.logMappings,line : 188] Patterns [/webjars/**, /**, /swagger-ui*/*swagger-initializer.js, /swagger-ui*/**] in 'resourceHandlerMapping'
[2024-11-06 09:08:35.577] | [main][DEBUG] | [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver.initExceptionHandlerAdviceCache,line : 307] ControllerAdvice beans: 2 @ExceptionHandler, 3 ResponseBodyAdvice
[2024-11-06 09:08:35.726] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:35.760] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:37.017] | [main][INFO ] | [org.redisson.Version.logVersion,line : 41] Redisson 3.18.0
[2024-11-06 09:08:38.096] | [redisson-netty-2-7][INFO ] | [o.r.c.p.MasterPubSubConnectionPool.lambda$createConnection$0,line : 162] 1 connections initialized for 172.16.8.100/172.16.8.100:6379
[2024-11-06 09:08:38.188] | [redisson-netty-2-19][INFO ] | [o.r.c.p.MasterConnectionPool.lambda$createConnection$0,line : 162] 24 connections initialized for 172.16.8.100/172.16.8.100:6379
[2024-11-06 09:08:38.394] | [main][INFO ] | [o.s.b.a.e.w.EndpointLinksResolver.<init>,line : 58] Exposing 1 endpoint(s) beneath base path '/actuator'
[2024-11-06 09:08:38.482] | [main][INFO ] | [o.s.s.w.DefaultSecurityFilterChain.<init>,line : 55] Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@650fb50f, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@748321c5, org.springframework.security.web.context.SecurityContextPersistenceFilter@4b7feb38, org.springframework.security.web.header.HeaderWriterFilter@5f967ad3, org.springframework.web.filter.CorsFilter@e0eecbe, org.springframework.security.web.authentication.logout.LogoutFilter@46ae1e6b, com.iailab.framework.security.core.filter.TokenAuthenticationFilter@1fa51751, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@44264fb6, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@90efbba, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@71a7e67, org.springframework.security.web.session.SessionManagementFilter@31829b82, org.springframework.security.web.access.ExceptionTranslationFilter@4bbb00a4, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@721d3a03]
[2024-11-06 09:08:42.301] | [main][INFO ] | [c.f.c.s.SpringContextUtil.setApplicationContext,line : 38] ------SpringContextUtil setApplicationContext-------
[2024-11-06 09:08:42.585] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:42.694] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:42.710] | [main][INFO ] | [c.i.f.d.c.DictFrameworkUtils.init,line : 73] [init][初始化 DictFrameworkUtils 成功]
[2024-11-06 09:08:42.733] | [main][INFO ] | [c.i.f.j.c.IailabJacksonAutoConfiguration.jsonUtils,line : 48] [init][初始化 JsonUtils 成功]
[2024-11-06 09:08:42.811] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:43.238] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:08:45.990] | [main][INFO ] | [o.s.s.q.SchedulerFactoryBean.startScheduler,line : 734] Will start Quartz Scheduler [IailabDataScheduler] in 30 seconds
[2024-11-06 09:08:46.009] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStarted,line : 61] Started RabbitMQTest in 40.921 seconds (JVM running for 43.575)
[2024-11-06 09:08:46.015] | [main][DEBUG] | [o.s.b.a.ApplicationAvailabilityBean.onApplicationEvent,line : 77] Application availability state LivenessState changed to CORRECT
[2024-11-06 09:08:46.200] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] ==>  Preparing: SELECT id, bean_name, params, cron_expression, status, remark, updater, update_date, tenant_id, creator, create_date FROM schedule_job
[2024-11-06 09:08:46.226] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] ==> Parameters:
[2024-11-06 09:08:46.249] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] <==      Total: 1
[2024-11-06 09:08:46.367] | [main][INFO ] | [c.a.c.n.r.NacosContextRefresher.registerNacosListener,line : 141] [Nacos Config] Listening config: dataId=data-server-dev.yaml, group=DEFAULT_GROUP
[2024-11-06 09:08:46.503] | [main][DEBUG] | [o.s.b.a.ApplicationAvailabilityBean.onApplicationEvent,line : 77] Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
[2024-11-06 09:08:47.242] | [main][INFO ] | [o.s.a.r.c.CachingConnectionFactory.connectAddresses,line : 639] Attempting to connect to: [127.0.0.1:15672]
[2024-11-06 09:08:47.343] | [pool-13-thread-1][INFO ] | [c.i.f.b.c.BannerApplicationRunner.lambda$run$0,line : 22]
----------------------------------------------------------
    项目启动成功!
    ----------------------------------------------------------
[2024-11-06 09:08:52.294] | [Thread-7][WARN ] | [c.a.n.c.n.NotifyCenter.shutdown,line : 136] [NotifyCenter] Start destroying Publisher
[2024-11-06 09:08:52.295] | [Thread-2][WARN ] | [c.a.n.c.h.HttpClientBeanHolder.shutdown,line : 102] [HttpClientBeanHolder] Start destroying common HttpClient
[2024-11-06 09:08:52.295] | [Thread-7][WARN ] | [c.a.n.c.n.NotifyCenter.shutdown,line : 153] [NotifyCenter] Destruction of the end
[2024-11-06 09:08:52.296] | [SpringApplicationShutdownHook][DEBUG] | [o.s.w.c.s.GenericWebApplicationContext.doClose,line : 1060] Closing org.springframework.web.context.support.GenericWebApplicationContext@586495f1, started on Wed Nov 06 09:08:13 CST 2024
[2024-11-06 09:08:52.296] | [Thread-2][WARN ] | [c.a.n.c.h.HttpClientBeanHolder.shutdown,line : 111] [HttpClientBeanHolder] Destruction of the end
[2024-11-06 09:08:52.355] | [SpringApplicationShutdownHook][INFO ] | [o.s.s.q.SchedulerFactoryBean.destroy,line : 847] Shutting down Quartz Scheduler
[2024-11-06 09:08:52.355] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.shutdown,line : 666] Scheduler IailabDataScheduler_$_Thinkpad-E141730855311568 shutting down.
[2024-11-06 09:08:52.355] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.standby,line : 585] Scheduler IailabDataScheduler_$_Thinkpad-E141730855311568 paused.
[2024-11-06 09:08:52.355] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.shutdown,line : 740] Scheduler IailabDataScheduler_$_Thinkpad-E141730855311568 shutdown complete.
[2024-11-06 09:08:52.359] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.DynamicRoutingDataSource.destroy,line : 215] dynamic-datasource start closing ....
[2024-11-06 09:08:52.363] | [SpringApplicationShutdownHook][INFO ] | [c.a.d.p.DruidDataSource.close,line : 2204] {dataSource-1} closing ...
[2024-11-06 09:08:52.370] | [SpringApplicationShutdownHook][INFO ] | [c.a.d.p.DruidDataSource.close,line : 2277] {dataSource-1} closed
[2024-11-06 09:08:52.371] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.d.DefaultDataSourceDestroyer.destroy,line : 98] dynamic-datasource close the datasource named [master] success,
[2024-11-06 09:08:52.371] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.DynamicRoutingDataSource.destroy,line : 219] dynamic-datasource all closed success,bye
[2024-11-06 09:11:44.044] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStarting,line : 55] Starting RabbitMQTest using Java 1.8.0_401 on Thinkpad-E14 with PID 19404 (started by houzh in D:\Work\Yingdashi\Project\iailab-plat\iailab-plat\iailab-module-data\iailab-module-data-biz)
[2024-11-06 09:11:44.047] | [main][DEBUG] | [c.i.m.d.c.RabbitMQTest.logStarting,line : 56] Running with Spring Boot v2.7.18, Spring v5.3.31
[2024-11-06 09:11:44.047] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStartupProfileInfo,line : 638] The following 1 profile is active: "dev"
[2024-11-06 09:11:44.048] | [main][DEBUG] | [o.s.b.SpringApplication.load,line : 665] Loading source class com.iailab.DataWebApplication
[2024-11-06 09:11:44.095] | [main][WARN ] | [c.a.c.n.c.NacosConfigDataLoader.logTo,line : 258] [Nacos Config] config[dataId=data-server-dev.yaml, group=DEFAULT_GROUP] is empty
[2024-11-06 09:11:44.099] | [main][DEBUG] | [o.s.w.c.s.GenericWebApplicationContext.prepareRefresh,line : 637] Refreshing org.springframework.web.context.support.GenericWebApplicationContext@5b29ab61
[2024-11-06 09:11:48.038] | [main][INFO ] | [o.s.c.c.s.GenericScope.setSerializationId,line : 283] BeanFactory id=3cae36f0-6484-3ade-8207-23df73e70f40
[2024-11-06 09:11:48.793] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration' of type [com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration$$EnhancerBySpringCGLIB$$a1f2c9f4] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:48.814] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration' of type [org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:48.819] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:48.822] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'loadBalancerClientsDefaultsMappingsProvider' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration$$Lambda$810/1079430578] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:48.830] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'defaultsBindHandlerAdvisor' of type [org.springframework.cloud.commons.config.DefaultsBindHandlerAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:48.838] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'mzt.log.record-com.mzt.logapi.starter.configuration.LogRecordProperties' of type [com.mzt.logapi.starter.configuration.LogRecordProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:48.862] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'logRecordPerformanceMonitor' of type [com.mzt.logapi.service.impl.DefaultLogRecordPerformanceMonitor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:49.304] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration' of type [com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:49.318] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'dataPermissionAnnotationAdvisor' of type [com.iailab.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:49.421] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'com.iailab.framework.tenant.config.IailabTenantAutoConfiguration' of type [com.iailab.framework.tenant.config.IailabTenantAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:49.484] | [main][INFO ] | [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker.postProcessAfterInitialization,line : 376] Bean 'dsProcessor' of type [com.iailab.framework.tenant.core.db.dynamic.TenantDsProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2024-11-06 09:11:50.714] | [main][INFO ] | [c.a.d.p.DruidDataSource.init,line : 1002] {dataSource-1,master} inited
[2024-11-06 09:11:50.715] | [main][INFO ] | [c.b.d.d.DynamicRoutingDataSource.addDataSource,line : 158] dynamic-datasource - add a datasource named [master] success
[2024-11-06 09:11:50.718] | [main][INFO ] | [c.b.d.d.DynamicRoutingDataSource.afterPropertiesSet,line : 241] dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
[2024-11-06 09:11:55.346] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:11:55.551] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:11:57.524] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1220] Using default implementation for ThreadExecutor
[2024-11-06 09:11:57.556] | [main][INFO ] | [o.q.c.SchedulerSignalerImpl.<init>,line : 61] Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[2024-11-06 09:11:57.556] | [main][INFO ] | [o.q.c.QuartzScheduler.<init>,line : 229] Quartz Scheduler v.2.3.2 created.
[2024-11-06 09:11:57.580] | [main][INFO ] | [o.s.s.q.LocalDataSourceJobStore.initialize,line : 672] Using db table-based data access locking (synchronization).
[2024-11-06 09:11:57.584] | [main][INFO ] | [o.s.s.q.LocalDataSourceJobStore.initialize,line : 145] JobStoreCMT initialized.
[2024-11-06 09:11:57.586] | [main][INFO ] | [o.q.c.QuartzScheduler.initialize,line : 294] Scheduler meta-data: Quartz Scheduler (v2.3.2) 'IailabDataScheduler' with instanceId 'Thinkpad-E141730855517527'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 20 threads.
  Using job-store 'org.springframework.scheduling.quartz.LocalDataSourceJobStore' - which supports persistence. and is clustered.
[2024-11-06 09:11:57.586] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1374] Quartz scheduler 'IailabDataScheduler' initialized from an externally provided properties instance.
[2024-11-06 09:11:57.587] | [main][INFO ] | [o.q.i.StdSchedulerFactory.instantiate,line : 1378] Quartz scheduler version: 2.3.2
[2024-11-06 09:11:57.589] | [main][INFO ] | [o.q.c.QuartzScheduler.setJobFactory,line : 2293] JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@6b989889
[2024-11-06 09:11:59.615] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:11:59.767] | [main][INFO ] | [o.r.Reflections.scan,line : 219] Reflections took 86 ms to scan 1 urls, producing 38 keys and 321 values
[2024-11-06 09:12:00.450] | [main][DEBUG] | [o.s.b.a.AutoConfigurationPackages.get,line : 196] @EnableAutoConfiguration was declared on a class in the package 'com.iailab'. Automatic @Repository and @Entity scanning is enabled.
[2024-11-06 09:12:00.848] | [main][DEBUG] | [o.s.w.s.m.m.a.RequestMappingHandlerAdapter.initControllerAdviceCache,line : 625] ControllerAdvice beans: 1 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 3 ResponseBodyAdvice
[2024-11-06 09:12:01.253] | [main][DEBUG] | [o.s.w.s.m.m.a.RequestMappingHandlerMapping.handlerMethodsInitialized,line : 367] 149 mappings in 'requestMappingHandlerMapping'
[2024-11-06 09:12:01.527] | [main][DEBUG] | [o.s.w.s.h.SimpleUrlHandlerMapping.logMappings,line : 188] Patterns [/webjars/**, /**, /swagger-ui*/*swagger-initializer.js, /swagger-ui*/**] in 'resourceHandlerMapping'
[2024-11-06 09:12:01.604] | [main][DEBUG] | [o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver.initExceptionHandlerAdviceCache,line : 307] ControllerAdvice beans: 2 @ExceptionHandler, 3 ResponseBodyAdvice
[2024-11-06 09:12:01.785] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:12:01.812] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:12:03.041] | [main][INFO ] | [org.redisson.Version.logVersion,line : 41] Redisson 3.18.0
[2024-11-06 09:12:04.080] | [redisson-netty-2-7][INFO ] | [o.r.c.p.MasterPubSubConnectionPool.lambda$createConnection$0,line : 162] 1 connections initialized for 172.16.8.100/172.16.8.100:6379
[2024-11-06 09:12:04.196] | [redisson-netty-2-19][INFO ] | [o.r.c.p.MasterConnectionPool.lambda$createConnection$0,line : 162] 24 connections initialized for 172.16.8.100/172.16.8.100:6379
[2024-11-06 09:12:04.452] | [main][INFO ] | [o.s.b.a.e.w.EndpointLinksResolver.<init>,line : 58] Exposing 1 endpoint(s) beneath base path '/actuator'
[2024-11-06 09:12:04.571] | [main][INFO ] | [o.s.s.w.DefaultSecurityFilterChain.<init>,line : 55] Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@503f5382, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5710fca8, org.springframework.security.web.context.SecurityContextPersistenceFilter@50df710a, org.springframework.security.web.header.HeaderWriterFilter@23038621, org.springframework.web.filter.CorsFilter@7e2e1179, org.springframework.security.web.authentication.logout.LogoutFilter@6b4b6cd6, com.iailab.framework.security.core.filter.TokenAuthenticationFilter@19e7aa5b, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@3e64cf62, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7768ffae, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@336e59a6, org.springframework.security.web.session.SessionManagementFilter@71b253b, org.springframework.security.web.access.ExceptionTranslationFilter@1cd25514, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@4d682552]
[2024-11-06 09:12:07.460] | [main][INFO ] | [c.f.c.s.SpringContextUtil.setApplicationContext,line : 38] ------SpringContextUtil setApplicationContext-------
[2024-11-06 09:12:07.753] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:12:07.809] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:12:07.824] | [main][INFO ] | [c.i.f.d.c.DictFrameworkUtils.init,line : 73] [init][初始化 DictFrameworkUtils 成功]
[2024-11-06 09:12:07.859] | [main][INFO ] | [c.i.f.j.c.IailabJacksonAutoConfiguration.jsonUtils,line : 48] [init][初始化 JsonUtils 成功]
[2024-11-06 09:12:07.917] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:12:08.316] | [main][INFO ] | [o.s.c.o.FeignClientFactoryBean.getTarget,line : 418] For 'system-server' URL not provided. Will try picking an instance via load-balancing.
[2024-11-06 09:12:12.183] | [main][INFO ] | [o.s.s.q.SchedulerFactoryBean.startScheduler,line : 734] Will start Quartz Scheduler [IailabDataScheduler] in 30 seconds
[2024-11-06 09:12:12.200] | [main][INFO ] | [c.i.m.d.c.RabbitMQTest.logStarted,line : 61] Started RabbitMQTest in 34.676 seconds (JVM running for 36.159)
[2024-11-06 09:12:12.208] | [main][DEBUG] | [o.s.b.a.ApplicationAvailabilityBean.onApplicationEvent,line : 77] Application availability state LivenessState changed to CORRECT
[2024-11-06 09:12:12.403] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] ==>  Preparing: SELECT id, bean_name, params, cron_expression, status, remark, updater, update_date, tenant_id, creator, create_date FROM schedule_job
[2024-11-06 09:12:12.433] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] ==> Parameters:
[2024-11-06 09:12:12.473] | [main][DEBUG] | [c.i.m.d.j.d.S.selectList.debug,line : 135] <==      Total: 1
[2024-11-06 09:12:12.611] | [main][INFO ] | [c.a.c.n.r.NacosContextRefresher.registerNacosListener,line : 141] [Nacos Config] Listening config: dataId=data-server-dev.yaml, group=DEFAULT_GROUP
[2024-11-06 09:12:12.703] | [main][DEBUG] | [o.s.b.a.ApplicationAvailabilityBean.onApplicationEvent,line : 77] Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
[2024-11-06 09:12:13.427] | [main][INFO ] | [o.s.a.r.c.CachingConnectionFactory.connectAddresses,line : 639] Attempting to connect to: [127.0.0.1:5672]
[2024-11-06 09:12:13.584] | [pool-13-thread-1][INFO ] | [c.i.f.b.c.BannerApplicationRunner.lambda$run$0,line : 22]
----------------------------------------------------------
    项目启动成功!
    ----------------------------------------------------------
[2024-11-06 09:12:13.589] | [main][INFO ] | [o.s.a.r.c.CachingConnectionFactory.createBareConnection,line : 590] Created new connection: rabbitConnectionFactory#3e37c38f:0/SimpleConnection@3023a901 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 60360]
[2024-11-06 09:12:13.767] | [Thread-2][WARN ] | [c.a.n.c.h.HttpClientBeanHolder.shutdown,line : 102] [HttpClientBeanHolder] Start destroying common HttpClient
[2024-11-06 09:12:13.767] | [Thread-7][WARN ] | [c.a.n.c.n.NotifyCenter.shutdown,line : 136] [NotifyCenter] Start destroying Publisher
[2024-11-06 09:12:13.768] | [Thread-7][WARN ] | [c.a.n.c.n.NotifyCenter.shutdown,line : 153] [NotifyCenter] Destruction of the end
[2024-11-06 09:12:13.768] | [SpringApplicationShutdownHook][DEBUG] | [o.s.w.c.s.GenericWebApplicationContext.doClose,line : 1060] Closing org.springframework.web.context.support.GenericWebApplicationContext@5b29ab61, started on Wed Nov 06 09:11:44 CST 2024
[2024-11-06 09:12:13.769] | [Thread-2][WARN ] | [c.a.n.c.h.HttpClientBeanHolder.shutdown,line : 111] [HttpClientBeanHolder] Destruction of the end
[2024-11-06 09:12:13.850] | [SpringApplicationShutdownHook][INFO ] | [o.s.s.q.SchedulerFactoryBean.destroy,line : 847] Shutting down Quartz Scheduler
[2024-11-06 09:12:13.851] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.shutdown,line : 666] Scheduler IailabDataScheduler_$_Thinkpad-E141730855517527 shutting down.
[2024-11-06 09:12:13.851] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.standby,line : 585] Scheduler IailabDataScheduler_$_Thinkpad-E141730855517527 paused.
[2024-11-06 09:12:13.852] | [SpringApplicationShutdownHook][INFO ] | [o.q.c.QuartzScheduler.shutdown,line : 740] Scheduler IailabDataScheduler_$_Thinkpad-E141730855517527 shutdown complete.
[2024-11-06 09:12:13.858] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.DynamicRoutingDataSource.destroy,line : 215] dynamic-datasource start closing ....
[2024-11-06 09:12:13.864] | [SpringApplicationShutdownHook][INFO ] | [c.a.d.p.DruidDataSource.close,line : 2204] {dataSource-1} closing ...
[2024-11-06 09:12:13.876] | [SpringApplicationShutdownHook][INFO ] | [c.a.d.p.DruidDataSource.close,line : 2277] {dataSource-1} closed
[2024-11-06 09:12:13.876] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.d.DefaultDataSourceDestroyer.destroy,line : 98] dynamic-datasource close the datasource named [master] success,
[2024-11-06 09:12:13.876] | [SpringApplicationShutdownHook][INFO ] | [c.b.d.d.DynamicRoutingDataSource.destroy,line : 219] dynamic-datasource all closed success,bye
iailab-module-data/iailab-module-data-biz/src/main/resources/application-prod.yaml
对比新文件
@@ -0,0 +1,127 @@
spring:
  autoconfigure:
    exclude:
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
      - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration
  datasource:
    druid:
      web-stat-filter:
        enabled: true
      stat-view-servlet:
        enabled: true
        allow:
        url-pattern: /druid/*
        login-username:
        login-password:
      filter:
        stat:
          enabled: true
          log-slow-sql: true
          slow-sql-millis: 100
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
    dynamic:
      druid:
        initial-size: 1
        min-idle: 1
        max-active: 20
        max-wait: 600000
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        max-evictable-idle-time-millis: 900000
        validation-query: select version()
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/iailab_expert_master?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
          username: root
          password: 123456
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0
    password: 123456
  rabbitmq:
    host: 172.16.1.221
    port: 5672
    username: admin
    password: admin123
  boot:
    admin:
      client:
        instance:
          service-host-type: IP
rocketmq:
  name-server: 172.16.8.100:9876 # RocketMQ Namesrv
xxl:
  job:
    enabled: true
    admin:
      addresses: http://172.16.8.100:9090/xxl-job-admin
lock4j:
  acquire-timeout: 3000
  expire: 30000
management:
  endpoints:
    web:
      base-path: /actuator
      exposure:
        include: '*'
logging:
  level:
    com.iailab.module.system.dal.mysql: debug
    com.iailab.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO
    com.iailab.module.system.dal.mysql.sms.SmsChannelMapper: INFO
iailab:
  env:
    tag: ${HOSTNAME}
  captcha:
    enable: false
  security:
    mock-enable: true
  xss:
    enable: false
    exclude-urls:
      - ${spring.boot.admin.context-path}/**
      - ${management.endpoints.web.base-path}/**
  access-log:
    enable: false
  demo: false
influx-db:
  org: iailab
  token: _338h4Kbu2KQaes5QwAyOz9pTUueXoSF9XmPi8N9oTS1SrhTZVj4J9JfSraUyWA0PfWMZOlf9QWax-USkJQR_A==
  url: http://172.16.1.221:8086
  username: iailab
  password: iailab2019
iems:
  upload-dir: D:/DLUT/upload/
video:
  capture-dir: D:/iailab
  dahua:
    path:
      capture-path: /Dahua/Capture/
      model-path: /Dahua/Model/
  hikvision:
    path:
      capture-path: /Hikvision/Capture/
      model-path: /Hikvision/Model/
    pic-size: 2 # size of picture 0=CIF, 1=QCIF, 2=D1 3=UXGA(1600x1200), 4=SVGA(800x600), 5=HD720p(1280x720),6=VGA
    pic-quality: 0 # quality of picture 0-best 1-better 2-normal
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/logger/ApiAccessLogApi.java
@@ -6,6 +6,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -21,4 +22,13 @@
    @Operation(summary = "创建 API 访问日志")
    CommonResult<Boolean> createApiAccessLog(@Valid @RequestBody ApiAccessLogCreateReqDTO createDTO);
    /**
     * 【异步】创建 API 访问日志
     *
     * @param createDTO 访问日志 DTO
     */
    @Async
    default void createApiAccessLogAsync(ApiAccessLogCreateReqDTO createDTO) {
        createApiAccessLog(createDTO).checkError();
    }
}
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/logger/ApiErrorLogApi.java
@@ -6,6 +6,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -21,4 +22,14 @@
    @Operation(summary = "创建 API 异常日志")
    CommonResult<Boolean> createApiErrorLog(@Valid @RequestBody ApiErrorLogCreateReqDTO createDTO);
    /**
     * 【异步】创建 API 异常日志
     *
     * @param createDTO 异常日志 DTO
     */
    @Async
    default void createApiErrorLogAsync(ApiErrorLogCreateReqDTO createDTO) {
        createApiErrorLog(createDTO).checkError();
    }
}
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/monitor/MonitorApi.java
对比新文件
@@ -0,0 +1,42 @@
package com.iailab.module.infra.api.monitor;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.module.infra.api.monitor.dto.MonitorDiskDTO;
import com.iailab.module.infra.api.monitor.dto.MonitorMemDTO;
import com.iailab.module.infra.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.util.List;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 服务 - 磁盘监控")
public interface MonitorApi {
    String PREFIX = ApiConstants.PREFIX + "/monitor";
    /**
     * 保存内存信息日志
     *
     * @param reportMemReqDTO 内存日志对象
     * @return 文件路径
     */
    @PostMapping(PREFIX + "/reportMemInfo")
    @Operation(summary = "保存内存日志对象")
    CommonResult<Long> reportMemInfo(@Valid @RequestBody MonitorMemDTO reportMemReqDTO);
    /**
     * 保存磁盘信息日志
     *
     * @param reportMemReqDTOS 磁盘日志对象
     * @return 文件路径
     */
    @PostMapping(PREFIX + "/reportDiskInfo")
    @Operation(summary = "保存磁盘日志对象")
    CommonResult reportDiskInfo(@Valid @RequestBody List<MonitorDiskDTO> reportMemReqDTOS);
}
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/monitor/dto/MonitorDiskDTO.java
对比新文件
@@ -0,0 +1,55 @@
package com.iailab.module.infra.api.monitor.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.math.BigDecimal;
/**
 * 磁盘监控日志 DTO
 *
 * @author 超级管理员
 */
@Schema(description = "RPC 服务 - 服务监控-磁盘监控 Request DTO")
@Data
public class MonitorDiskDTO {
    /**
     * 主机名称
     */
    private String hostName;
    /**
     * 服务器ip
     */
    private String hostIp;
    /**
     * 盘符
     */
    private String disk;
    /**
     * 磁盘名
     */
    private String diskName;
    /**
     * 总空间
     */
    private BigDecimal spaceTotal;
    /**
     * 已用空间
     */
    private BigDecimal spaceUsed;
    /**
     * 可用空间
     */
    private BigDecimal spaceUsable;
    /**
     * 空间使用比例
     */
    private BigDecimal spaceRatio;
    /**
     * 租户Id
     */
    private Integer tenantId;
}
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/api/monitor/dto/MonitorMemDTO.java
对比新文件
@@ -0,0 +1,79 @@
package com.iailab.module.infra.api.monitor.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.math.BigDecimal;
/**
 * 内存监控日志 DO
 *
 * @author 超级管理员
 */
@Schema(description = "RPC 服务 - 服务监控-内存监控 Request DTO")
@Data
public class MonitorMemDTO {
    /**
     * 主机名称
     */
    private String hostName;
    /**
     * 服务器ip
     */
    private String hostIp;
    /**
     * 服务名
     */
    private String serverName;
    /**
     * 总物理内存
     */
    private BigDecimal physicalTotal;
    /**
     * 已用物理内存
     */
    private BigDecimal physicalUsed;
    /**
     * 剩余物理内存
     */
    private BigDecimal physicalFree;
    /**
     * 物理内存使用率
     */
    private BigDecimal physicalUsage;
    /**
     * jvm运行总内存
     */
    private BigDecimal runtimeTotal;
    /**
     * jvm最大内存
     */
    private BigDecimal runtimeMax;
    /**
     * jvm已用内存
     */
    private BigDecimal runtimeUsed;
    /**
     * jvm空闲内存
     */
    private BigDecimal runtimeFree;
    /**
     * jvm内存使用率
     */
    private BigDecimal runtimeUsage;
    /**
     * 系统cpu利用率
     */
    private BigDecimal systemCpuLoad;
    /**
     * 进程cpu利用率
     */
    private BigDecimal processCpuLoad;
    /**
     * 租户Id
     */
    private Integer tenantId;
}
iailab-module-infra/iailab-module-infra-api/src/main/java/com/iailab/module/infra/util/ServerInfoCollector.java
对比新文件
@@ -0,0 +1,198 @@
package com.iailab.module.infra.util;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iailab.module.infra.api.monitor.dto.MonitorDiskDTO;
import com.iailab.module.infra.api.monitor.dto.MonitorMemDTO;
import org.apache.commons.lang3.ObjectUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.FileStore;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.List;
public class ServerInfoCollector {
    private static BigDecimal UNIT = new BigDecimal(1024 * 1024);
    private static BigDecimal PERCENT_UNIT = new BigDecimal(100);
    private static String hostName;
    private static String hostIp;
    public static void initServerInfo() throws UnknownHostException {
        // 获取本地主机对象
        InetAddress localHost = InetAddress.getLocalHost();
        // 获取主机名
        hostName = localHost.getHostName();
//        // 获取IP地址
        hostIp = localHost.getHostAddress();
//        try {
//            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
//            while (interfaces.hasMoreElements()) {
//                NetworkInterface networkInterface = interfaces.nextElement();
//                // 过滤掉loopback接口
//                if (networkInterface.isLoopback() || !networkInterface.isUp()) {
//                    continue;
//                }
//                Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
//                while (addresses.hasMoreElements()) {
//                    InetAddress addr = addresses.nextElement();
//                    // 过滤掉IPv6地址和回环地址
//                    if (!addr.isLoopbackAddress() && addr.getHostAddress().contains(".")) { // 确保是IPv4地址
//                        System.out.println("局域网IP地址: " + addr.getHostAddress());
//                        hostIp = addr.getHostAddress();
//                    }
//                }
//            }
//        } catch (SocketException e) {
//            e.printStackTrace();
//        }
    }
    /**
     * 内存信息处理
     */
    public static MonitorMemDTO collectMonitorMem(String serverName) throws UnknownHostException {
        initServerInfo();
        OperatingSystemMXBean operatingSystemBean = ManagementFactory.getOperatingSystemMXBean();
        JSONObject operatingSystemJson = JSON.parseObject(JSON.toJSONString(operatingSystemBean));
        BigDecimal totalPhysicalMemory = operatingSystemJson.getBigDecimal("totalPhysicalMemorySize");
        BigDecimal freePhysicalMemory = operatingSystemJson.getBigDecimal("freePhysicalMemorySize");
        BigDecimal usedPhysicalMemory = totalPhysicalMemory.subtract(freePhysicalMemory);
        BigDecimal systemCpuLoad = operatingSystemJson.getBigDecimal("systemCpuLoad");
        BigDecimal processCpuLoad = operatingSystemJson.getBigDecimal("processCpuLoad");
        Runtime runtime = Runtime.getRuntime();
        MonitorMemDTO monitorMemDTO = new MonitorMemDTO();
        monitorMemDTO.setHostName(hostName)
                .setHostIp(hostIp)
                .setServerName(serverName)
                .setPhysicalTotal(totalPhysicalMemory.divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setPhysicalUsed(usedPhysicalMemory.divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setPhysicalFree(freePhysicalMemory.divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setPhysicalUsage(NumberUtil.div(usedPhysicalMemory, totalPhysicalMemory).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setRuntimeTotal(new BigDecimal(runtime.totalMemory()).divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setRuntimeFree(new BigDecimal(runtime.freeMemory()).divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setRuntimeMax(new BigDecimal(runtime.maxMemory()).divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setRuntimeUsed(new BigDecimal(runtime.maxMemory() - runtime.totalMemory() + runtime.freeMemory()).divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setRuntimeUsage(new BigDecimal(NumberUtil.div(runtime.totalMemory()/1f - runtime.freeMemory(), runtime.totalMemory())).setScale(2, BigDecimal.ROUND_HALF_UP))
                .setSystemCpuLoad(systemCpuLoad.multiply(PERCENT_UNIT))
                .setProcessCpuLoad(processCpuLoad.multiply(PERCENT_UNIT));
        return monitorMemDTO;
    }
    /**
     * 磁盘信息处理
     */
    public static List<MonitorDiskDTO> collectMonitorDisk() throws IOException {
        List<MonitorDiskDTO> monitorDiskSaveReqVOS = new ArrayList<>();
        String os = System.getProperty("os.name").toLowerCase();
        System.out.println(os);
        if (os.contains("win")) {
            getWindowsDiskUsage(monitorDiskSaveReqVOS);
        } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
            try {
                getLinuxDiskUsage(monitorDiskSaveReqVOS);
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("不支持的服务器系统!");
        }
        return monitorDiskSaveReqVOS;
    }
    private static void getWindowsDiskUsage(List<MonitorDiskDTO> monitorDiskSaveReqVOS) throws IOException {
        initServerInfo();
        // 获取默认文件系统的所有存储设备
        Iterable<FileStore> fileStores = FileSystems.getDefault().getFileStores();
        for (FileStore store : fileStores) {
            MonitorDiskDTO monitorDiskSaveReqVO = new MonitorDiskDTO();
            // 获取磁盘的总空间、已用空间和可用空间
            BigDecimal totalSpace = new BigDecimal(store.getTotalSpace()).divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP); // 总空间
            BigDecimal usableSpace = new BigDecimal(store.getUsableSpace()).divide(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP); // 可用空间
            BigDecimal usedSpace = totalSpace.subtract(usableSpace).setScale(2, BigDecimal.ROUND_HALF_UP); // 计算已用空间
            monitorDiskSaveReqVO.setHostName(hostName)
                    .setHostIp(hostIp)
                    .setDisk(store.toString())
                    .setDiskName(ObjectUtils.isNotEmpty(store.name()) ? store.name(): "/")
                    .setSpaceTotal(totalSpace)
                    .setSpaceUsable(usableSpace)
                    .setSpaceUsed(usedSpace)
                    .setSpaceRatio(usedSpace.divide(totalSpace, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP));
            monitorDiskSaveReqVOS.add(monitorDiskSaveReqVO);
        }
    }
    /**
     * 获取 Linux 系统的磁盘使用情况
     */
    private static void getLinuxDiskUsage(List<MonitorDiskDTO> monitorDiskSaveReqVOS) throws IOException, InterruptedException {
        Process process = Runtime.getRuntime().exec("df -h");
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        boolean isHeader = true;
        while ((line = reader.readLine()) != null) {
            if (isHeader) {
                isHeader = false;
                continue;
            }
            String[] parts = line.trim().split("\\s+");
            System.out.println(parts);
            if (parts.length >= 6) {
                MonitorDiskDTO monitorDiskSaveReqVO = new MonitorDiskDTO();
                String filesystem = parts[0];
                String size = parts[1];
                String used = parts[2];
                String available = parts[3];
                String mountedOn = parts[5];
                BigDecimal totalSpace = formatSize(size);
                BigDecimal usableSpace = formatSize(available);
                BigDecimal usedSpace = formatSize(used);
                monitorDiskSaveReqVO.setHostName(hostName)
                        .setHostIp(hostIp)
                        .setDisk(filesystem + "(" + mountedOn + ")")
                        .setDiskName(mountedOn)
                        .setSpaceTotal(totalSpace)
                        .setSpaceUsable(usableSpace)
                        .setSpaceUsed(usedSpace)
                        .setSpaceRatio(usedSpace.divide(totalSpace, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP));
                monitorDiskSaveReqVOS.add(monitorDiskSaveReqVO);
            }
        }
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            System.err.println("Command execution failed with exit code: " + exitCode);
        }
        reader.close();
    }
    /**
     * 将字节大小转换为可读的格式
     * @param size 字节数
     * @return 人类可读的大小(MB)
     */
    private static BigDecimal formatSize(String size) {
        if(size.contains("T")){
            return new BigDecimal(Float.parseFloat(size.replace("T",""))).multiply(UNIT).setScale(2, BigDecimal.ROUND_HALF_UP);
        } else if (size.contains("G")){
            return new BigDecimal(Float.parseFloat(size.replace("G","")) * 1024).setScale(2, BigDecimal.ROUND_HALF_UP);
        } else if (size.contains("M")){
            return new BigDecimal(Float.parseFloat(size.replace("M",""))).setScale(2, BigDecimal.ROUND_HALF_UP);
        } else if (size.contains("K")){
            return new BigDecimal(Float.parseFloat(size.replace("K","")) / 1024).setScale(2, BigDecimal.ROUND_HALF_UP);
        } else {
            return new BigDecimal(0);
        }
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/api/monitor/MonitorApiImpl.java
对比新文件
@@ -0,0 +1,40 @@
package com.iailab.module.infra.api.monitor;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.infra.api.monitor.dto.MonitorDiskDTO;
import com.iailab.module.infra.api.monitor.dto.MonitorMemDTO;
import com.iailab.module.infra.controller.admin.monitordisk.vo.MonitorDiskSaveReqVO;
import com.iailab.module.infra.controller.admin.monitormem.vo.MonitorMemSaveReqVO;
import com.iailab.module.infra.service.monitordisk.MonitorDiskService;
import com.iailab.module.infra.service.monitormem.MonitorMemService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class MonitorApiImpl implements MonitorApi {
    @Resource
    private MonitorMemService monitorMemService;
    @Resource
    private MonitorDiskService monitorDiskService;
    @Override
    public CommonResult<Long> reportMemInfo(MonitorMemDTO reportMemReqDTO) {
        MonitorMemSaveReqVO bean = BeanUtils.toBean(reportMemReqDTO, MonitorMemSaveReqVO.class);
        return CommonResult.success(monitorMemService.createMonitorMem(bean));
    }
    @Override
    public CommonResult reportDiskInfo(List<MonitorDiskDTO> reportDiskReqDTOS) {
        List<MonitorDiskSaveReqVO> bean = BeanUtils.toBean(reportDiskReqDTOS, MonitorDiskSaveReqVO.class);
        monitorDiskService.createMonitorDiskBatch(bean);
        return CommonResult.success();
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/MonitorDiskController.java
对比新文件
@@ -0,0 +1,126 @@
package com.iailab.module.infra.controller.admin.monitordisk;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.util.object.BeanUtils;
import static com.iailab.framework.common.pojo.CommonResult.success;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.*;
import com.iailab.module.infra.controller.admin.monitordisk.vo.*;
import com.iailab.module.infra.dal.dataobject.monitordisk.MonitorDiskDO;
import com.iailab.module.infra.service.monitordisk.MonitorDiskService;
@Tag(name = "管理后台 - 磁盘监控日志")
@RestController
@RequestMapping("/infra/monitor-disk")
@Validated
public class MonitorDiskController {
    @Resource
    private MonitorDiskService monitorDiskService;
    @PostMapping("/create")
    @Operation(summary = "创建磁盘监控日志")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:create')")
    public CommonResult<Long> createMonitorDisk(@Valid @RequestBody MonitorDiskSaveReqVO createReqVO) {
        return success(monitorDiskService.createMonitorDisk(createReqVO));
    }
    @PutMapping("/update")
    @Operation(summary = "更新磁盘监控日志")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:update')")
    public CommonResult<Boolean> updateMonitorDisk(@Valid @RequestBody MonitorDiskSaveReqVO updateReqVO) {
        monitorDiskService.updateMonitorDisk(updateReqVO);
        return success(true);
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除磁盘监控日志")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:delete')")
    public CommonResult<Boolean> deleteMonitorDisk(@RequestParam("id") Long id) {
        monitorDiskService.deleteMonitorDisk(id);
        return success(true);
    }
    @GetMapping("/get")
    @Operation(summary = "获得磁盘监控日志")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:query')")
    public CommonResult<MonitorDiskRespVO> getMonitorDisk(@RequestParam("id") Long id) {
        MonitorDiskDO monitorDisk = monitorDiskService.getMonitorDisk(id);
        return success(BeanUtils.toBean(monitorDisk, MonitorDiskRespVO.class));
    }
    @GetMapping("/page")
    @Operation(summary = "获得磁盘监控日志分页")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:query')")
    public CommonResult<PageResult<MonitorDiskRespVO>> getMonitorDiskPage(@Valid MonitorDiskPageReqVO pageReqVO) {
        PageResult<MonitorDiskDO> pageResult = monitorDiskService.getMonitorDiskPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, MonitorDiskRespVO.class));
    }
    @GetMapping("/getMonitorDiskList")
    @Operation(summary = "获得磁盘监控日志列表")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:query')")
    public CommonResult<List<Map<String, List<Map<String, Object>>>>> getMonitorMemList(@Valid MonitorDiskReqVO reqVO) {
        List<Map<String, List<Map<String, Object>>>> result = monitorDiskService.getMonitorDiskList(reqVO);
        return success(result);
    }
    @GetMapping("/getAllHost")
    @Operation(summary = "获得内存监控日志统计")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:query')")
    public CommonResult<List<String>> getAllHost() {
        List<String> hosts = monitorDiskService.getAllHost();
        return success(hosts);
    }
    @GetMapping("/getAllIp")
    @Operation(summary = "获得内存监控日志统计")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:query')")
    public CommonResult<List<String>> getAllIp() {
        List<String> ips = monitorDiskService.getAllIp();
        return success(ips);
    }
    @GetMapping("/getMonitorDiskInfo")
    @Operation(summary = "获得磁盘监控日志列表")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:query')")
    public CommonResult<List<Map<String, Object>>> getMonitorDiskInfo(@Valid MonitorDiskReqVO reqVO) {
        List<Map<String, Object>> result = monitorDiskService.getMonitorDiskInfo(reqVO);
        return success(result);
    }
    @GetMapping("/export-excel")
    @Operation(summary = "导出磁盘监控日志 Excel")
    @PreAuthorize("@ss.hasPermission('infra:monitor-disk:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportMonitorDiskExcel(@Valid MonitorDiskPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<MonitorDiskDO> list = monitorDiskService.getMonitorDiskPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "磁盘监控日志.xls", "数据", MonitorDiskRespVO.class,
                        BeanUtils.toBean(list, MonitorDiskRespVO.class));
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskPageReqVO.java
对比新文件
@@ -0,0 +1,47 @@
package com.iailab.module.infra.controller.admin.monitordisk.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import com.iailab.framework.common.pojo.PageParam;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 磁盘监控日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MonitorDiskPageReqVO extends PageParam {
    @Schema(description = "主机名称", example = "iailab")
    private String hostName;
    @Schema(description = "服务器ip")
    private String hostIp;
    @Schema(description = "盘符")
    private String disk;
    @Schema(description = "磁盘名", example = "王五")
    private String diskName;
    @Schema(description = "总空间")
    private BigDecimal spaceTotal;
    @Schema(description = "已用空间")
    private BigDecimal spaceUsed;
    @Schema(description = "可用空间")
    private BigDecimal spaceUsable;
    @Schema(description = "空间使用比例")
    private BigDecimal spaceRatio;
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskReqVO.java
对比新文件
@@ -0,0 +1,49 @@
package com.iailab.module.infra.controller.admin.monitordisk.vo;
import com.iailab.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 磁盘监控日志 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MonitorDiskReqVO extends PageParam {
    @Schema(description = "主机名称", example = "iailab")
    private String hostName;
    @Schema(description = "服务器ip")
    private String hostIp;
    @Schema(description = "盘符")
    private String disk;
    @Schema(description = "磁盘名", example = "王五")
    private String diskName;
    @Schema(description = "总空间")
    private BigDecimal spaceTotal;
    @Schema(description = "已用空间")
    private BigDecimal spaceUsed;
    @Schema(description = "可用空间")
    private BigDecimal spaceUsable;
    @Schema(description = "空间使用比例")
    private BigDecimal spaceRatio;
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskRespVO.java
对比新文件
@@ -0,0 +1,57 @@
package com.iailab.module.infra.controller.admin.monitordisk.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 磁盘监控日志 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MonitorDiskRespVO {
    @Schema(description = "访问ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "528")
    @ExcelProperty("访问ID")
    private Long id;
    @Schema(description = "主机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
    @ExcelProperty("主机名称")
    private String hostName;
    @Schema(description = "服务器ip", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("服务器ip")
    private String hostIp;
    @Schema(description = "盘符")
    @ExcelProperty("盘符")
    private String disk;
    @Schema(description = "磁盘名", example = "王五")
    @ExcelProperty("磁盘名")
    private String diskName;
    @Schema(description = "总空间")
    @ExcelProperty("总空间")
    private BigDecimal spaceTotal;
    @Schema(description = "已用空间")
    @ExcelProperty("已用空间")
    private BigDecimal spaceUsed;
    @Schema(description = "可用空间")
    @ExcelProperty("可用空间")
    private BigDecimal spaceUsable;
    @Schema(description = "空间使用比例")
    @ExcelProperty("空间使用比例")
    private BigDecimal spaceRatio;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitordisk/vo/MonitorDiskSaveReqVO.java
对比新文件
@@ -0,0 +1,41 @@
package com.iailab.module.infra.controller.admin.monitordisk.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 磁盘监控日志新增/修改 Request VO")
@Data
public class MonitorDiskSaveReqVO {
    @Schema(description = "访问ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "528")
    private Long id;
    @Schema(description = "主机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
    @NotEmpty(message = "主机名称不能为空")
    private String hostName;
    @Schema(description = "服务器ip", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotEmpty(message = "服务器ip不能为空")
    private String hostIp;
    @Schema(description = "盘符")
    private String disk;
    @Schema(description = "磁盘名", example = "王五")
    private String diskName;
    @Schema(description = "总空间")
    private BigDecimal spaceTotal;
    @Schema(description = "已用空间")
    private BigDecimal spaceUsed;
    @Schema(description = "可用空间")
    private BigDecimal spaceUsable;
    @Schema(description = "空间使用比例")
    private BigDecimal spaceRatio;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/MonitorMemController.java
对比新文件
@@ -0,0 +1,126 @@
package com.iailab.module.infra.controller.admin.monitormem;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.util.object.BeanUtils;
import static com.iailab.framework.common.pojo.CommonResult.success;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.*;
import com.iailab.module.infra.controller.admin.monitormem.vo.*;
import com.iailab.module.infra.dal.dataobject.monitormem.MonitorMemDO;
import com.iailab.module.infra.service.monitormem.MonitorMemService;
@Tag(name = "管理后台 - 内存监控日志")
@RestController
@RequestMapping("/infra/monitor-mem")
@Validated
public class MonitorMemController {
    @Resource
    private MonitorMemService monitorMemService;
    @PostMapping("/create")
    @Operation(summary = "创建内存监控日志")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:create')")
    public CommonResult<Long> createMonitorMem(@Valid @RequestBody MonitorMemSaveReqVO createReqVO) {
        return success(monitorMemService.createMonitorMem(createReqVO));
    }
    @PutMapping("/update")
    @Operation(summary = "更新内存监控日志")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:update')")
    public CommonResult<Boolean> updateMonitorMem(@Valid @RequestBody MonitorMemSaveReqVO updateReqVO) {
        monitorMemService.updateMonitorMem(updateReqVO);
        return success(true);
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除内存监控日志")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:delete')")
    public CommonResult<Boolean> deleteMonitorMem(@RequestParam("id") Long id) {
        monitorMemService.deleteMonitorMem(id);
        return success(true);
    }
    @GetMapping("/get")
    @Operation(summary = "获得内存监控日志")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:query')")
    public CommonResult<MonitorMemRespVO> getMonitorMem(@RequestParam("id") Long id) {
        MonitorMemDO monitorMem = monitorMemService.getMonitorMem(id);
        return success(BeanUtils.toBean(monitorMem, MonitorMemRespVO.class));
    }
    @GetMapping("/page")
    @Operation(summary = "获得内存监控日志分页")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:query')")
    public CommonResult<PageResult<MonitorMemRespVO>> getMonitorMemPage(@Valid MonitorMemPageReqVO pageReqVO) {
        PageResult<MonitorMemDO> pageResult = monitorMemService.getMonitorMemPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, MonitorMemRespVO.class));
    }
    @GetMapping("/getMonitorMemList")
    @Operation(summary = "获得内存监控日志统计")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:query')")
    public CommonResult<List<MonitorMemDO>> getMonitorMemList(@Valid MonitorMemReqVO reqVO) {
        List<MonitorMemDO> result = monitorMemService.getMonitorMemList(reqVO);
        return success(result);
    }
    @GetMapping("/getAllHost")
    @Operation(summary = "获得内存监控日志统计")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:query')")
    public CommonResult<List<String>> getAllHost() {
        List<String> hosts = monitorMemService.getAllHost();
        return success(hosts);
    }
    @GetMapping("/getAllServer")
    @Operation(summary = "获得内存监控日志统计")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:query')")
    public CommonResult<List<String>> getAllServer() {
        List<String> servers = monitorMemService.getAllServer();
        return success(servers);
    }
    @GetMapping("/getAllIp")
    @Operation(summary = "获得内存监控日志统计")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:query')")
    public CommonResult<List<String>> getAllIp() {
        List<String> ips = monitorMemService.getAllIp();
        return success(ips);
    }
    @GetMapping("/export-excel")
    @Operation(summary = "导出内存监控日志 Excel")
    @PreAuthorize("@ss.hasPermission('infra:monitor-mem:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportMonitorMemExcel(@Valid MonitorMemPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<MonitorMemDO> list = monitorMemService.getMonitorMemPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "内存监控日志.xls", "数据", MonitorMemRespVO.class,
                        BeanUtils.toBean(list, MonitorMemRespVO.class));
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemPageReqVO.java
对比新文件
@@ -0,0 +1,59 @@
package com.iailab.module.infra.controller.admin.monitormem.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import com.iailab.framework.common.pojo.PageParam;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 内存监控日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MonitorMemPageReqVO extends PageParam {
    @Schema(description = "主机名称", example = "张三")
    private String hostName;
    @Schema(description = "服务器ip")
    private String hostIp;
    @Schema(description = "服务名", example = "王五")
    private String serverName;
    @Schema(description = "总物理内存")
    private BigDecimal physicalTotal;
    @Schema(description = "已用物理内存")
    private BigDecimal physicalUsed;
    @Schema(description = "剩余物理内存")
    private BigDecimal physicalFree;
    @Schema(description = "物理内存使用率")
    private BigDecimal physicalUsage;
    @Schema(description = "jvm运行总内存")
    private BigDecimal runtimeTotal;
    @Schema(description = "jvm最大内存")
    private BigDecimal runtimeMax;
    @Schema(description = "jvm已用内存")
    private BigDecimal runtimeUsed;
    @Schema(description = "jvm空闲内存")
    private BigDecimal runtimeFree;
    @Schema(description = "jvm内存使用率")
    private BigDecimal runtimeUsage;
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemReqVO.java
对比新文件
@@ -0,0 +1,58 @@
package com.iailab.module.infra.controller.admin.monitormem.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 查询内存监控日志 Request VO")
@Data
@ToString(callSuper = true)
public class MonitorMemReqVO {
    @Schema(description = "主机名称", example = "张三")
    private String hostName;
    @Schema(description = "服务器ip")
    private String hostIp;
    @Schema(description = "服务名", example = "王五")
    private String serverName;
    @Schema(description = "总物理内存")
    private BigDecimal physicalTotal;
    @Schema(description = "已用物理内存")
    private BigDecimal physicalUsed;
    @Schema(description = "剩余物理内存")
    private BigDecimal physicalFree;
    @Schema(description = "物理内存使用率")
    private BigDecimal physicalUsage;
    @Schema(description = "jvm运行总内存")
    private BigDecimal runtimeTotal;
    @Schema(description = "jvm最大内存")
    private BigDecimal runtimeMax;
    @Schema(description = "jvm已用内存")
    private BigDecimal runtimeUsed;
    @Schema(description = "jvm空闲内存")
    private BigDecimal runtimeFree;
    @Schema(description = "jvm内存使用率")
    private BigDecimal runtimeUsage;
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemRespVO.java
对比新文件
@@ -0,0 +1,81 @@
package com.iailab.module.infra.controller.admin.monitormem.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 内存监控日志 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MonitorMemRespVO {
    @Schema(description = "访问ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "8051")
    @ExcelProperty("访问ID")
    private Long id;
    @Schema(description = "主机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
    @ExcelProperty("主机名称")
    private String hostName;
    @Schema(description = "服务器ip", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("服务器ip")
    private String hostIp;
    @Schema(description = "服务名", example = "王五")
    @ExcelProperty("服务名")
    private String serverName;
    @Schema(description = "总物理内存")
    @ExcelProperty("总物理内存")
    private BigDecimal physicalTotal;
    @Schema(description = "已用物理内存")
    @ExcelProperty("已用物理内存")
    private BigDecimal physicalUsed;
    @Schema(description = "剩余物理内存")
    @ExcelProperty("剩余物理内存")
    private BigDecimal physicalFree;
    @Schema(description = "物理内存使用率")
    @ExcelProperty("物理内存使用率")
    private BigDecimal physicalUsage;
    @Schema(description = "jvm运行总内存")
    @ExcelProperty("jvm运行总内存")
    private BigDecimal runtimeTotal;
    @Schema(description = "jvm最大内存")
    @ExcelProperty("jvm最大内存")
    private BigDecimal runtimeMax;
    @Schema(description = "jvm已用内存")
    @ExcelProperty("jvm已用内存")
    private BigDecimal runtimeUsed;
    @Schema(description = "jvm空闲内存")
    @ExcelProperty("jvm空闲内存")
    private BigDecimal runtimeFree;
    @Schema(description = "jvm内存使用率")
    @ExcelProperty("jvm内存使用率")
    private BigDecimal runtimeUsage;
    @Schema(description = "系统cpu利用率")
    @ExcelProperty("系统cpu利用率")
    private BigDecimal systemCpuLoad;
    @Schema(description = "进程cpu利用率")
    @ExcelProperty("进程cpu利用率")
    private BigDecimal processCpuLoad;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/controller/admin/monitormem/vo/MonitorMemSaveReqVO.java
对比新文件
@@ -0,0 +1,60 @@
package com.iailab.module.infra.controller.admin.monitormem.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 内存监控日志新增/修改 Request VO")
@Data
public class MonitorMemSaveReqVO {
    @Schema(description = "访问ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "8051")
    private Long id;
    @Schema(description = "主机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
    @NotEmpty(message = "主机名称不能为空")
    private String hostName;
    @Schema(description = "服务器ip", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotEmpty(message = "服务器ip不能为空")
    private String hostIp;
    @Schema(description = "服务名", example = "王五")
    private String serverName;
    @Schema(description = "总物理内存")
    private BigDecimal physicalTotal;
    @Schema(description = "已用物理内存")
    private BigDecimal physicalUsed;
    @Schema(description = "剩余物理内存")
    private BigDecimal physicalFree;
    @Schema(description = "物理内存使用率")
    private BigDecimal physicalUsage;
    @Schema(description = "jvm运行总内存")
    private BigDecimal runtimeTotal;
    @Schema(description = "jvm最大内存")
    private BigDecimal runtimeMax;
    @Schema(description = "jvm已用内存")
    private BigDecimal runtimeUsed;
    @Schema(description = "jvm空闲内存")
    private BigDecimal runtimeFree;
    @Schema(description = "jvm内存使用率")
    private BigDecimal runtimeUsage;
    @Schema(description = "系统cpu利用率")
    private BigDecimal systemCpuLoad;
    @Schema(description = "进程cpu利用率")
    private BigDecimal processCpuLoad;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/dataobject/monitordisk/MonitorDiskDO.java
对比新文件
@@ -0,0 +1,72 @@
package com.iailab.module.infra.dal.dataobject.monitordisk;
import lombok.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import com.iailab.framework.mybatis.core.dataobject.BaseDO;
/**
 * 磁盘监控日志 DO
 *
 * @author 超级管理员
 */
@TableName("system_monitor_disk")
@KeySequence("system_monitor_disk_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MonitorDiskDO extends BaseDO {
    /**
     * 访问ID
     */
    @TableId
    private Long id;
    /**
     * 主机名称
     */
    private String hostName;
    /**
     * 服务器ip
     */
    private String hostIp;
    /**
     * 盘符
     */
    private String disk;
    /**
     * 磁盘名
     */
    private String diskName;
    /**
     * 总空间
     */
    private BigDecimal spaceTotal;
    /**
     * 已用空间
     */
    private BigDecimal spaceUsed;
    /**
     * 可用空间
     */
    private BigDecimal spaceUsable;
    /**
     * 空间使用比例
     */
    private BigDecimal spaceRatio;
    /**
     * 租户Id
     */
    private Integer tenantId;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/dataobject/monitormem/MonitorMemDO.java
对比新文件
@@ -0,0 +1,103 @@
package com.iailab.module.infra.dal.dataobject.monitormem;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import com.iailab.framework.mybatis.core.dataobject.BaseDO;
/**
 * 内存监控日志 DO
 *
 * @author 超级管理员
 */
@TableName("system_monitor_mem")
@KeySequence("system_monitor_mem_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MonitorMemDO extends BaseDO {
    /**
     * 访问ID
     */
    @TableId
    private Long id;
    /**
     * 主机名称
     */
    private String hostName;
    /**
     * 服务器ip
     */
    private String hostIp;
    /**
     * 服务名
     */
    private String serverName;
    /**
     * 总物理内存
     */
    private BigDecimal physicalTotal;
    /**
     * 已用物理内存
     */
    private BigDecimal physicalUsed;
    /**
     * 剩余物理内存
     */
    private BigDecimal physicalFree;
    /**
     * 物理内存使用率
     */
    private BigDecimal physicalUsage;
    /**
     * jvm运行总内存
     */
    private BigDecimal runtimeTotal;
    /**
     * jvm最大内存
     */
    private BigDecimal runtimeMax;
    /**
     * jvm已用内存
     */
    private BigDecimal runtimeUsed;
    /**
     * jvm空闲内存
     */
    private BigDecimal runtimeFree;
    /**
     * jvm内存使用率
     */
    private BigDecimal runtimeUsage;
    /**
     * 系统cpu利用率
     */
    private BigDecimal systemCpuLoad;
    /**
     * 进程cpu利用率
     */
    private BigDecimal processCpuLoad;
    /**
     * 租户Id
     */
    private Integer tenantId;
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/mysql/monitordisk/MonitorDiskMapper.java
对比新文件
@@ -0,0 +1,46 @@
package com.iailab.module.infra.dal.mysql.monitordisk;
import java.util.*;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
import com.iailab.module.infra.dal.dataobject.monitordisk.MonitorDiskDO;
import org.apache.ibatis.annotations.Mapper;
import com.iailab.module.infra.controller.admin.monitordisk.vo.*;
import org.apache.ibatis.annotations.Param;
/**
 * 磁盘监控日志 Mapper
 *
 * @author 超级管理员
 */
@Mapper
public interface MonitorDiskMapper extends BaseMapperX<MonitorDiskDO> {
    default PageResult<MonitorDiskDO> selectPage(MonitorDiskPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<MonitorDiskDO>()
                .likeIfPresent(MonitorDiskDO::getHostName, reqVO.getHostName())
                .eqIfPresent(MonitorDiskDO::getHostIp, reqVO.getHostIp())
                .eqIfPresent(MonitorDiskDO::getDisk, reqVO.getDisk())
                .likeIfPresent(MonitorDiskDO::getDiskName, reqVO.getDiskName())
                .eqIfPresent(MonitorDiskDO::getSpaceTotal, reqVO.getSpaceTotal())
                .eqIfPresent(MonitorDiskDO::getSpaceUsed, reqVO.getSpaceUsed())
                .eqIfPresent(MonitorDiskDO::getSpaceUsable, reqVO.getSpaceUsable())
                .eqIfPresent(MonitorDiskDO::getSpaceRatio, reqVO.getSpaceRatio())
                .betweenIfPresent(MonitorDiskDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(MonitorDiskDO::getId));
    }
    default List<MonitorDiskDO> getMonitorDiskList(MonitorDiskReqVO reqVO) {
        return selectList(new LambdaQueryWrapperX<MonitorDiskDO>()
                .likeIfPresent(MonitorDiskDO::getHostName, reqVO.getHostName())
                .eqIfPresent(MonitorDiskDO::getHostIp, reqVO.getHostIp())
                .eqIfPresent(MonitorDiskDO::getDisk, reqVO.getDisk())
                .likeIfPresent(MonitorDiskDO::getDiskName, reqVO.getDiskName())
                .betweenIfPresent(MonitorDiskDO::getCreateTime, reqVO.getCreateTime())
                .orderByAsc(MonitorDiskDO::getCreateTime));
    }
    List<MonitorDiskDO> getMonitorDiskInfo(@Param("params") MonitorDiskReqVO reqVO);
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/dal/mysql/monitormem/MonitorMemMapper.java
对比新文件
@@ -0,0 +1,47 @@
package com.iailab.module.infra.dal.mysql.monitormem;
import java.util.*;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
import com.iailab.module.infra.dal.dataobject.monitormem.MonitorMemDO;
import org.apache.ibatis.annotations.Mapper;
import com.iailab.module.infra.controller.admin.monitormem.vo.*;
/**
 * 内存监控日志 Mapper
 *
 * @author 超级管理员
 */
@Mapper
public interface MonitorMemMapper extends BaseMapperX<MonitorMemDO> {
    default PageResult<MonitorMemDO> selectPage(MonitorMemPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<MonitorMemDO>()
                .likeIfPresent(MonitorMemDO::getHostName, reqVO.getHostName())
                .eqIfPresent(MonitorMemDO::getHostIp, reqVO.getHostIp())
                .likeIfPresent(MonitorMemDO::getServerName, reqVO.getServerName())
                .eqIfPresent(MonitorMemDO::getPhysicalTotal, reqVO.getPhysicalTotal())
                .eqIfPresent(MonitorMemDO::getPhysicalUsed, reqVO.getPhysicalUsed())
                .eqIfPresent(MonitorMemDO::getPhysicalFree, reqVO.getPhysicalFree())
                .eqIfPresent(MonitorMemDO::getPhysicalUsage, reqVO.getPhysicalUsage())
                .eqIfPresent(MonitorMemDO::getRuntimeTotal, reqVO.getRuntimeTotal())
                .eqIfPresent(MonitorMemDO::getRuntimeMax, reqVO.getRuntimeMax())
                .eqIfPresent(MonitorMemDO::getRuntimeUsed, reqVO.getRuntimeUsed())
                .eqIfPresent(MonitorMemDO::getRuntimeFree, reqVO.getRuntimeFree())
                .eqIfPresent(MonitorMemDO::getRuntimeUsage, reqVO.getRuntimeUsage())
                .betweenIfPresent(MonitorMemDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(MonitorMemDO::getId));
    }
    default List<MonitorMemDO> getMonitorMemList(MonitorMemReqVO reqVO) {
        return selectList(new LambdaQueryWrapperX<MonitorMemDO>()
                .likeIfPresent(MonitorMemDO::getHostName, reqVO.getHostName())
                .eqIfPresent(MonitorMemDO::getHostIp, reqVO.getHostIp())
                .likeIfPresent(MonitorMemDO::getServerName, reqVO.getServerName())
                .betweenIfPresent(MonitorMemDO::getCreateTime, reqVO.getCreateTime())
                .orderByAsc(MonitorMemDO::getCreateTime));
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/job/monitor/MonitorDiskJob.java
对比新文件
@@ -0,0 +1,47 @@
//package com.iailab.module.infra.job.monitor;
//
//import com.iailab.framework.tenant.core.aop.TenantIgnore;
//import com.iailab.module.infra.api.monitor.MonitorApi;
//import com.iailab.module.infra.api.monitor.dto.MonitorDiskDTO;
//import com.iailab.module.infra.util.ServerInfoCollector;
//import com.xxl.job.core.handler.annotation.XxlJob;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.io.IOException;
//import java.util.Date;
//import java.util.List;
//import java.util.concurrent.atomic.AtomicInteger;
//
//@Component
//public class MonitorDiskJob {
//
//    private Logger logger = LoggerFactory.getLogger(getClass());
//
//    private final AtomicInteger counts = new AtomicInteger();
//
//    private static final Object lock = new Object();
//
//    private final MonitorApi monitorApi;
//
//
//    public MonitorDiskJob(MonitorApi monitorApi) {
//        this.monitorApi = monitorApi;
//    }
//
//    @XxlJob("monitorDiskJob")
//    @TenantIgnore
//    @Transactional
//    public void execute() throws IOException {
//        synchronized (lock) {
//            logger.info("[execute][定时第 ({}) 次执行]", counts.incrementAndGet());
//            System.out.println(new Date() + ": 我是基础设施-服务器磁盘监控日志存储定时任务");
//            List<MonitorDiskDTO> monitorDiskDTOS = ServerInfoCollector.collectMonitorDisk();
//            monitorApi.reportDiskInfo(monitorDiskDTOS);
//        }
//    }
//
//}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/job/monitor/MonitorMemJob.java
对比新文件
@@ -0,0 +1,50 @@
//package com.iailab.module.infra.job.monitor;
//
//import com.iailab.framework.tenant.core.aop.TenantIgnore;
//import com.iailab.module.infra.api.monitor.MonitorApi;
//import com.iailab.module.infra.api.monitor.dto.MonitorMemDTO;
//import com.iailab.module.infra.util.ServerInfoCollector;
//import com.xxl.job.core.handler.annotation.XxlJob;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.io.IOException;
//import java.util.Date;
//import java.util.concurrent.atomic.AtomicInteger;
//
//@Component
//public class MonitorMemJob {
//
//    private Logger logger = LoggerFactory.getLogger(getClass());
//
//    private final AtomicInteger counts = new AtomicInteger();
//
//    private static final Object lock = new Object();
//
//    private final MonitorApi monitorApi;
//
//    @Value("${spring.application.name}")
//    public String serverName;
//
//    public MonitorMemJob(MonitorApi monitorApi) {
//        this.monitorApi = monitorApi;
//    }
//
//    @XxlJob("monitorMemJob")
//    @TenantIgnore
//    @Transactional
//    public void execute() throws IOException {
//        synchronized (lock) {
//            logger.info("[execute][定时第 ({}) 次执行]", counts.incrementAndGet());
//            System.out.println(new Date() + ": 我是基础设施-服务器内存监控日志存储定时任务");
//            MonitorMemDTO monitorMemDTO = ServerInfoCollector.collectMonitorMem(serverName);
//            monitorApi.reportMemInfo(monitorMemDTO);
//        }
//    }
//
//
//
//}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitordisk/MonitorDiskService.java
对比新文件
@@ -0,0 +1,94 @@
package com.iailab.module.infra.service.monitordisk;
import java.time.LocalDateTime;
import java.util.*;
import javax.validation.*;
import com.iailab.module.infra.controller.admin.monitordisk.vo.*;
import com.iailab.module.infra.dal.dataobject.monitordisk.MonitorDiskDO;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.pojo.PageParam;
/**
 * 磁盘监控日志 Service 接口
 *
 * @author 超级管理员
 */
public interface MonitorDiskService {
    /**
     * 创建磁盘监控日志
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Long createMonitorDisk(@Valid MonitorDiskSaveReqVO createReqVO);
    /**
     * 批量创建磁盘监控日志
     *
     * @param createReqVOS 创建信息
     * @return 编号
     */
    void createMonitorDiskBatch(List<MonitorDiskSaveReqVO> createReqVOS);
    /**
     * 更新磁盘监控日志
     *
     * @param updateReqVO 更新信息
     */
    void updateMonitorDisk(@Valid MonitorDiskSaveReqVO updateReqVO);
    /**
     * 删除磁盘监控日志
     *
     * @param id 编号
     */
    void deleteMonitorDisk(Long id);
    /**
     * 获得磁盘监控日志
     *
     * @param id 编号
     * @return 磁盘监控日志
     */
    MonitorDiskDO getMonitorDisk(Long id);
    /**
     * 获得磁盘监控日志分页
     *
     * @param pageReqVO 分页查询
     * @return 磁盘监控日志分页
     */
    PageResult<MonitorDiskDO> getMonitorDiskPage(MonitorDiskPageReqVO pageReqVO);
    /**
     * 获得磁盘监控日志列表
     *
     * @param reqVO 查询
     * @return 磁盘监控日志列表
     */
    List<Map<String, List<Map<String, Object>>>> getMonitorDiskList(MonitorDiskReqVO reqVO);
    /**
     * 获得磁盘监控日志信息
     *
     * @param reqVO 查询
     * @return 磁盘监控日志信息
     */
    List<Map<String, Object>> getMonitorDiskInfo(MonitorDiskReqVO reqVO);
    /**
     * 获取所有主机
     *
     * @return 获取所有主机
     */
    List<String> getAllHost();
    /**
     * 获取所有ip
     *
     * @return 获取所有ip
     */
    List<String> getAllIp();
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitordisk/MonitorDiskServiceImpl.java
对比新文件
@@ -0,0 +1,180 @@
package com.iailab.module.infra.service.monitordisk;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iailab.framework.tenant.core.aop.TenantIgnore;
import com.iailab.module.infra.dal.dataobject.monitormem.MonitorMemDO;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import com.iailab.module.infra.controller.admin.monitordisk.vo.*;
import com.iailab.module.infra.dal.dataobject.monitordisk.MonitorDiskDO;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.infra.dal.mysql.monitordisk.MonitorDiskMapper;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.infra.enums.ErrorCodeConstants.*;
/**
 * 磁盘监控日志 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class MonitorDiskServiceImpl implements MonitorDiskService {
    @Resource
    private MonitorDiskMapper monitorDiskMapper;
    @Override
    public Long createMonitorDisk(MonitorDiskSaveReqVO createReqVO) {
        // 插入
        MonitorDiskDO monitorDisk = BeanUtils.toBean(createReqVO, MonitorDiskDO.class);
        monitorDiskMapper.insert(monitorDisk);
        // 返回
        return monitorDisk.getId();
    }
    @Override
    public void createMonitorDiskBatch(List<MonitorDiskSaveReqVO> createReqVOS) {
        // 插入
        List<MonitorDiskDO> monitorDiskDOS = BeanUtils.toBean(createReqVOS, MonitorDiskDO.class);
        monitorDiskDOS.stream().forEach(monitorDiskDO -> {
            monitorDiskDO.setTenantId(1);
            monitorDiskDO.setCreator("iailab");
        });
        monitorDiskMapper.insertBatch(monitorDiskDOS);
    }
    @Override
    public void updateMonitorDisk(MonitorDiskSaveReqVO updateReqVO) {
        // 校验存在
        validateMonitorDiskExists(updateReqVO.getId());
        // 更新
        MonitorDiskDO updateObj = BeanUtils.toBean(updateReqVO, MonitorDiskDO.class);
        monitorDiskMapper.updateById(updateObj);
    }
    @Override
    public void deleteMonitorDisk(Long id) {
        // 校验存在
        validateMonitorDiskExists(id);
        // 删除
        monitorDiskMapper.deleteById(id);
    }
    private void validateMonitorDiskExists(Long id) {
        if (monitorDiskMapper.selectById(id) == null) {
            throw exception(MONITOR_DISK_NOT_EXISTS);
        }
    }
    @Override
    public MonitorDiskDO getMonitorDisk(Long id) {
        return monitorDiskMapper.selectById(id);
    }
    @Override
    public PageResult<MonitorDiskDO> getMonitorDiskPage(MonitorDiskPageReqVO pageReqVO) {
        return monitorDiskMapper.selectPage(pageReqVO);
    }
    /**
     * 折线图展示
     * @param reqVO 查询
     * @return
     */
    @Override
    public List<Map<String, List<Map<String, Object>>>> getMonitorDiskList(MonitorDiskReqVO reqVO) {
        List<MonitorDiskDO> monitorDiskList = monitorDiskMapper.getMonitorDiskList(reqVO);
        if(ObjectUtils.isNotEmpty(monitorDiskList)) {
            // 根据 hostName 字段进行分组
            Map<String, List<MonitorDiskDO>> hostNameCollect = monitorDiskList.stream()
                    .collect(Collectors.groupingBy(MonitorDiskDO::getHostName));
            List<Map<String, List<Map<String, Object>>>> host = hostNameCollect.entrySet().stream().map(hostEntry -> {
                List<MonitorDiskDO> hostValue = hostEntry.getValue();
                String key = hostEntry.getKey();
                Map<String, List<Map<String, Object>>> hostItem = new HashMap<>();
                // 根据 createTime 字段进行分组
                Map<LocalDateTime, List<MonitorDiskDO>> createTimeCollect = hostValue.stream()
                        .collect(Collectors.groupingBy(MonitorDiskDO::getCreateTime));
                List<Map<String, Object>> collect = createTimeCollect.entrySet().stream().map(entry -> {
                    List<MonitorDiskDO> value = entry.getValue();
                    Map<String, Object> item = new HashMap<>();
                    value.stream().forEach(monitorDiskDO -> {
                        item.put("createTime", monitorDiskDO.getCreateTime());
                        item.put(monitorDiskDO.getDisk(), monitorDiskDO.getSpaceRatio().multiply(new BigDecimal(100)));
                    });
                    return item;
                }).collect(Collectors.toList());
                hostItem.put(key, collect);
                return hostItem;
            }).collect(Collectors.toList());
            return host;
        }
        return null;
    }
    /**
     * 饼图展示
     * @param reqVO 查询
     * @return
     */
    @Override
    @TenantIgnore
    public List<Map<String, Object>> getMonitorDiskInfo(MonitorDiskReqVO reqVO) {
        List<MonitorDiskDO> monitorDiskInfo = monitorDiskMapper.getMonitorDiskInfo(reqVO);
        if(ObjectUtils.isNotEmpty(monitorDiskInfo)) {
            // 根据 hostName 字段进行分组
            Map<String, List<MonitorDiskDO>> hostNameCollect = monitorDiskInfo.stream()
                    .collect(Collectors.groupingBy(MonitorDiskDO::getHostName));
            List<Map<String, Object>> collect = hostNameCollect.entrySet().stream().map(entry -> {
                List<MonitorDiskDO> value = entry.getValue();
                Map<String, Object> item = new HashMap<>();
                List<Map<String, Object>> disks = new ArrayList<>();
                value.stream().forEach(monitorDiskDO -> {
                    Map<String, Object> diskMap = new HashMap<>();
                    item.put("name", monitorDiskDO.getHostName());
                    item.put("ip", monitorDiskDO.getHostIp());
                    diskMap.put("disk", monitorDiskDO.getDisk());
                    diskMap.put("total", monitorDiskDO.getSpaceTotal().divide(new BigDecimal(1024)).setScale(3, BigDecimal.ROUND_HALF_UP).toString());
                    diskMap.put("used", monitorDiskDO.getSpaceUsed().divide(new BigDecimal(1024)).setScale(2, BigDecimal.ROUND_HALF_UP));
                    disks.add(diskMap);
                });
                item.put("disks", disks);
                return item;
            }).collect(Collectors.toList());
            return collect;
        }
        return null;
    }
    @Override
    public List<String> getAllHost() {
        QueryWrapper<MonitorDiskDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT host_name"); // 添加 DISTINCT 修饰
        List<String> hosts = monitorDiskMapper.selectObjs(queryWrapper);
        return hosts;
    }
    @Override
    public List<String> getAllIp() {
        QueryWrapper<MonitorDiskDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT host_ip"); // 添加 DISTINCT 修饰
        List<String> ips = monitorDiskMapper.selectObjs(queryWrapper);
        return ips;
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitormem/MonitorMemService.java
对比新文件
@@ -0,0 +1,83 @@
package com.iailab.module.infra.service.monitormem;
import java.util.*;
import javax.validation.*;
import com.iailab.module.infra.controller.admin.monitormem.vo.*;
import com.iailab.module.infra.dal.dataobject.monitormem.MonitorMemDO;
import com.iailab.framework.common.pojo.PageResult;
/**
 * 内存监控日志 Service 接口
 *
 * @author 超级管理员
 */
public interface MonitorMemService {
    /**
     * 创建内存监控日志
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Long createMonitorMem(@Valid MonitorMemSaveReqVO createReqVO);
    /**
     * 更新内存监控日志
     *
     * @param updateReqVO 更新信息
     */
    void updateMonitorMem(@Valid MonitorMemSaveReqVO updateReqVO);
    /**
     * 删除内存监控日志
     *
     * @param id 编号
     */
    void deleteMonitorMem(Long id);
    /**
     * 获得内存监控日志
     *
     * @param id 编号
     * @return 内存监控日志
     */
    MonitorMemDO getMonitorMem(Long id);
    /**
     * 获得内存监控日志分页
     *
     * @param pageReqVO 分页查询
     * @return 内存监控日志分页
     */
    PageResult<MonitorMemDO> getMonitorMemPage(MonitorMemPageReqVO pageReqVO);
    /**
     * 获得内存监控日志
     *
     * @param pageReqVO 查询
     * @return 内存监控日志
     */
    List<MonitorMemDO> getMonitorMemList(MonitorMemReqVO pageReqVO);
    /**
     * 获取所有主机
     *
     * @return 获取所有主机
     */
    List<String> getAllHost();
    /**
     * 获取所有服务
     *
     * @return 获取所有服务
     */
    List<String> getAllServer();
    /**
     * 获取所有ip
     *
     * @return 获取所有ip
     */
    List<String> getAllIp();
}
iailab-module-infra/iailab-module-infra-biz/src/main/java/com/iailab/module/infra/service/monitormem/MonitorMemServiceImpl.java
对比新文件
@@ -0,0 +1,108 @@
package com.iailab.module.infra.service.monitormem;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import com.iailab.module.infra.controller.admin.monitormem.vo.*;
import com.iailab.module.infra.dal.dataobject.monitormem.MonitorMemDO;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.infra.dal.mysql.monitormem.MonitorMemMapper;
import java.util.Collections;
import java.util.List;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.infra.enums.ErrorCodeConstants.*;
/**
 * 内存监控日志 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class MonitorMemServiceImpl implements MonitorMemService {
    @Resource
    private MonitorMemMapper monitorMemMapper;
    @Override
    public Long createMonitorMem(MonitorMemSaveReqVO createReqVO) {
        // 插入
        MonitorMemDO monitorMem = BeanUtils.toBean(createReqVO, MonitorMemDO.class);
        monitorMem.setCreator("iailab");
        monitorMem.setTenantId(1);
        monitorMemMapper.insert(monitorMem);
        // 返回
        return monitorMem.getId();
    }
    @Override
    public void updateMonitorMem(MonitorMemSaveReqVO updateReqVO) {
        // 校验存在
        validateMonitorMemExists(updateReqVO.getId());
        // 更新
        MonitorMemDO updateObj = BeanUtils.toBean(updateReqVO, MonitorMemDO.class);
        updateObj.setUpdater("iailab");
        monitorMemMapper.updateById(updateObj);
    }
    @Override
    public void deleteMonitorMem(Long id) {
        // 校验存在
        validateMonitorMemExists(id);
        // 删除
        monitorMemMapper.deleteById(id);
    }
    private void validateMonitorMemExists(Long id) {
        if (monitorMemMapper.selectById(id) == null) {
            throw exception(MONITOR_MEM_NOT_EXISTS);
        }
    }
    @Override
    public MonitorMemDO getMonitorMem(Long id) {
        return monitorMemMapper.selectById(id);
    }
    @Override
    public PageResult<MonitorMemDO> getMonitorMemPage(MonitorMemPageReqVO pageReqVO) {
        return monitorMemMapper.selectPage(pageReqVO);
    }
    @Override
    public List<MonitorMemDO> getMonitorMemList(MonitorMemReqVO reqVO) {
        return monitorMemMapper.getMonitorMemList(reqVO);
    }
    @Override
    public List<String> getAllHost() {
        QueryWrapper<MonitorMemDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT host_name"); // 添加 DISTINCT 修饰
        List<String> hosts = monitorMemMapper.selectObjs(queryWrapper);
        return hosts;
    }
    @Override
    public List<String> getAllServer() {
        QueryWrapper<MonitorMemDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT server_name"); // 添加 DISTINCT 修饰
        List<String> servers = monitorMemMapper.selectObjs(queryWrapper);
        return servers;
    }
    @Override
    public List<String> getAllIp() {
        QueryWrapper<MonitorMemDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT host_ip"); // 添加 DISTINCT 修饰
        List<String> ips = monitorMemMapper.selectObjs(queryWrapper);
        return ips;
    }
}
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-dev.yaml
@@ -64,7 +64,7 @@
  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  redis:
    host: 172.16.8.100 # 地址
    host: 127.0.0.1 # 地址
    port: 6379 # 端口
    database: 0 # 数据库索引
    password: 123456 # 密码,建议生产环境开启
@@ -78,7 +78,7 @@
spring:
  # RabbitMQ 配置项,对应 RabbitProperties 配置类
  rabbitmq:
    host: 172.16.8.200 # RabbitMQ 服务的地址
    host: 172.16.1.221 # RabbitMQ 服务的地址
    port: 5672 # RabbitMQ 服务的端口
    username: admin # RabbitMQ 服务的账号
    password: admin123 # RabbitMQ 服务的密码
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-prod.yaml
对比新文件
@@ -0,0 +1,150 @@
--- #################### 数据库相关配置 ####################
spring:
  # 数据源配置项
  autoconfigure:
    exclude:
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
  #      - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
  #      - de.codecentric.boot.admin.server.cloud.config.AdminServerDiscoveryAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
  #      - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
  #      - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
  datasource:
    druid: # Druid 【监控】相关的全局配置
      web-stat-filter:
        enabled: true
      stat-view-servlet:
        enabled: true
        allow: # 设置白名单,不填则允许所有访问
        url-pattern: /druid/*
        login-username: # 控制台管理用户名和密码
        login-password:
      filter:
        stat:
          enabled: true
          log-slow-sql: true # 慢 SQL 记录
          slow-sql-millis: 100
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
    dynamic: # 多数据源配置
      druid: # Druid 【连接池】相关的全局配置
        initial-size: 1 # 初始连接数
        min-idle: 1 # 最小连接池数量
        max-active: 20 # 最大连接池数量
        max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
        time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
        min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
        max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
        validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://172.16.8.100:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
          #          url: jdbc:mysql://127.0.0.1:3306/iailab-plat?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例
          #          url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
          #          url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
          #          url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro # SQLServer 连接的示例
          #          url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例
          username: root
          password: 123456
        #          username: sa # SQL Server 连接的示例
        #          password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # SQL Server 连接的示例
        #          username: SYSDBA # DM 连接的示例
        #          password: SYSDBA # DM 连接的示例
        slave: # 模拟从库,可根据自己需要修改
          lazy: true # 开启懒加载,保证启动速度
          url: jdbc:mysql://127.0.0.1:3306/iailab-plat?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
          username: root
          password: 123456
  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  redis:
    host: 172.16.8.100 # 地址
    port: 6379 # 端口
    database: 0 # 数据库索引
    password: 123456 # 密码,建议生产环境开启
--- #################### MQ 消息队列相关配置 ####################
# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
  name-server: 172.16.8.100:9876 # RocketMQ Namesrv
spring:
  # RabbitMQ 配置项,对应 RabbitProperties 配置类
  rabbitmq:
    host: 172.16.1.221 # RabbitMQ 服务的地址
    port: 5672 # RabbitMQ 服务的端口
    username: admin # RabbitMQ 服务的账号
    password: admin123 # RabbitMQ 服务的密码
  # Kafka 配置项,对应 KafkaProperties 配置类
  kafka:
    bootstrap-servers: 172.16.8.100:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
--- #################### 定时任务相关配置 ####################
xxl:
  job:
    enabled: true # 是否开启调度中心,默认为 true 开启
    admin:
      addresses: http://172.16.216.133:9090/xxl-job-admin # 调度中心部署跟地址
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项
lock4j:
  acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
  expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
  endpoints:
    web:
      base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
      exposure:
        include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
# Spring Boot Admin 配置项
spring:
  boot:
    admin:
      # Spring Boot Admin Client 客户端的相关配置
      client:
        instance:
          service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
      # Spring Boot Admin Server 服务端的相关配置
      context-path: /admin # 配置 Spring
# 日志文件配置
logging:
  level:
    # 配置自己写的 MyBatis Mapper 打印日志
    com.iailab.module.infra.dal.mysql: debug
    com.iailab.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印
    com.iailab.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info
--- #################### 定时任务相关配置 ####################
xxl:
  job:
    executor:
      appname: ${spring.application.name} # 执行器 AppName
      logpath: D:/DLUT/IailabPlat/webapp/infra/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
    accessToken: default_token # 执行器通讯TOKEN
--- #################### 平台相关配置 ####################
# 平台配置项,设置当前项目所有自定义的配置
iailab:
  env: # 多环境的配置项
    tag: ${HOSTNAME}
  security:
    mock-enable: true
  access-log: # 访问日志的配置项
    enable: true
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application.yaml
@@ -81,8 +81,8 @@
    map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
  global-config:
    db-config:
      id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
      #      id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库
      #id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
      id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库
      #      id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库
      #      id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
iailab-module-infra/iailab-module-infra-biz/src/main/resources/mapper/monitordisk/MonitorDiskMapper.xml
对比新文件
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.iailab.module.infra.dal.mysql.monitordisk.MonitorDiskMapper">
    <select id="getMonitorDiskInfo" resultType="com.iailab.module.infra.dal.dataobject.monitordisk.MonitorDiskDO">
        WITH RankedData AS (
            SELECT
                host_name,
                host_ip,
                disk,
                disk_name,
                space_total,
                space_used,
                create_time,
                ROW_NUMBER() OVER (PARTITION BY host_name, disk, disk_name ORDER BY create_time DESC) AS rn
            FROM
                system_monitor_disk
        )
        SELECT
            host_name,
            host_ip,
            disk,
            disk_name,
            space_total,
            space_used
        FROM
            RankedData
        WHERE
            rn = 1
        <if test="params.hostName != null and params.hostName != ''">
            and host_name = #{params.hostName}
        </if>
        <if test="params.hostIp != null and params.hostIp != ''">
            and host_ip = #{params.hostIp}
        </if>
        <if test="params.createTime != null and params.createTime != ''">
            and create_time between #{params.createTime[0]} and #{params.createTime[1]}
        </if>
    </select>
</mapper>
iailab-module-model/iailab-module-model-biz/src/main/resources/application-prod.yaml
对比新文件
@@ -0,0 +1,106 @@
--- #################### db configuration ####################
spring:
  autoconfigure:
    exclude:
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
      - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration
  boot:
    admin:
      client:
        instance:
          service-host-type: IP
  datasource:
    druid:
      web-stat-filter:
        enabled: true
      stat-view-servlet:
        enabled: true
        allow:
        url-pattern: /druid/*
        login-username:
        login-password:
      filter:
        stat:
          enabled: true
          log-slow-sql: true
          slow-sql-millis: 100
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
    dynamic:
      druid:
        initial-size: 1
        min-idle: 1
        max-active: 20
        max-wait: 600000
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        max-evictable-idle-time-millis: 900000
        validation-query: SELECT 1 FROM DUAL
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://172.16.8.100:3306/iailab_expert_master?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
          username: root
          password: 123456
  redis:
    host: 172.16.8.100
    port: 6379
    database: 0
    password: 123456
xxl:
  job:
    enabled: true
    admin:
      addresses: http://172.16.8.100:9090/xxl-job-admin
lock4j:
  acquire-timeout: 3000
  expire: 30000
management:
  endpoints:
    web:
      base-path: /actuator
      exposure:
        include: '*'
logging:
  level:
    com.iailab.module.system.dal.mysql: debug
    com.iailab.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO
    com.iailab.module.system.dal.mysql.sms.SmsChannelMapper: INFO
iailab:
  env:
    tag: ${HOSTNAME}
  captcha:
    enable: false
  security:
    mock-enable: true
  xss:
    enable: false
    exclude-urls:
      - ${spring.boot.admin.context-path}/**
      - ${management.endpoints.web.base-path}/**
  access-log:
    enable: false
  demo: false
influx-db:
  org: iailab
  token: _338h4Kbu2KQaes5QwAyOz9pTUueXoSF9XmPi8N9oTS1SrhTZVj4J9JfSraUyWA0PfWMZOlf9QWax-USkJQR_A==
  url: http://172.16.1.221:8086
  username: iailab
  password: iailab2019
iems:
  upload-dir: D:/DLUT/upload/
mpk:
  bak-file-path: D:\DLUT\mpkBakFile
  bak-resources: D:\DLUT\mpkResources
  model-file-path: D:\DLUT\MDK\Model\miail\
`mablab:
  bak-file-path: D:\DLUT\matlabBakFile`
iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/permission/DataScopeEnum.java
@@ -1,6 +1,6 @@
package com.iailab.module.system.enums.permission;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -15,7 +15,7 @@
 */
@Getter
@AllArgsConstructor
public enum DataScopeEnum implements IntArrayValuable {
public enum DataScopeEnum implements ArrayValuable {
    ALL(1), // 全部数据权限
@@ -30,10 +30,10 @@
     */
    private final Integer scope;
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DataScopeEnum::getScope).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(DataScopeEnum::getScope).toArray(Integer[]::new);
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/sms/SmsSceneEnum.java
@@ -1,7 +1,7 @@
package com.iailab.module.system.enums.sms;
import cn.hutool.core.util.ArrayUtil;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -14,7 +14,7 @@
 */
@Getter
@AllArgsConstructor
public enum SmsSceneEnum implements IntArrayValuable {
public enum SmsSceneEnum implements ArrayValuable {
    MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"),
    MEMBER_UPDATE_MOBILE(2, "user-update-mobile", "会员用户 - 修改手机"),
@@ -23,7 +23,7 @@
    ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录");
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(SmsSceneEnum::getScene).toArray(Integer[]::new);
    /**
     * 验证场景的编号
@@ -39,7 +39,7 @@
    private final String description;
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/enums/social/SocialTypeEnum.java
@@ -1,7 +1,7 @@
package com.iailab.module.system.enums.social;
import cn.hutool.core.util.ArrayUtil;
import com.iailab.framework.common.core.IntArrayValuable;
import com.iailab.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -14,7 +14,7 @@
 */
@Getter
@AllArgsConstructor
public enum SocialTypeEnum implements IntArrayValuable {
public enum SocialTypeEnum implements ArrayValuable {
    /**
     * Gitee
@@ -55,7 +55,7 @@
    WECHAT_MINI_APP(34, "WECHAT_MINI_APP"),
    ;
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SocialTypeEnum::getType).toArray();
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(SocialTypeEnum::getType).toArray(Integer[]::new);
    /**
     * 类型
@@ -67,7 +67,7 @@
    private final String source;
    @Override
    public int[] array() {
    public Integer[] array() {
        return ARRAYS;
    }
iailab-module-system/iailab-module-system-biz/proguard.cfg
对比新文件
@@ -0,0 +1,132 @@
#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-dontshrink
#是否关闭字节码级别的优化,如果不开启则设置如下配置
-dontoptimize
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
#混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings
-verbose
-printmapping proguard-mapping.txt  # 生成混淆映射表(用于调试)
#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# 此选项将保存接口中的所有原始名称(不混淆)-->
-keepnames interface ** { *; }
# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {
                        @org.springframework.context.annotation.Bean *;
                        @org.springframework.beans.factory.annotation.Autowired *;
                        @org.springframework.beans.factory.annotation.Value *;
                        @org.springframework.stereotype.Service *;
                        @org.springframework.stereotype.Component *;
                        }
#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
-keep public class com.iailab.module.system.SystemServerApplication {
        public static void main(java.lang.String[]);
    }
 # 保留Feign客户端接口
 -keep @org.springframework.cloud.openfeign.FeignClient class * {
     *;
 }
 # 业务包保留
 -keep class com.iailab.module.system.api.** { *; }
 # 日志与反射
 -keepclassmembers class * {
     org.slf4j.Logger *;
 }
 -keepattributes RuntimeVisibleAnnotations, Signature
# 保留common模块的公共类
-keep class com.iailab.framework.** { *; }
# 保留mybatis-plus相关类
-keep class com.baomidou.mybatisplus.** { *; }
-keep @com.baomidou.mybatisplus.annotation.TableName class * { *; }
# 保留数据权限注解
-keep @com.iailab.framework.datapermission.core.** class *
 # 保留Spring Cloud配置类
 -keep class org.springframework.cloud.** { *; }
 # 保留domain实体类
 -keep class com.iailab.module.*.dal.dataobject.** { *; }
 # 保留DTO和VO
 -keep class com.iailab.module.*.controller.**.vo.** { *; }
 -keep class com.iailab.module.*.service.**.dto.** { *; }
 # 保留JSON注解
 -keep @com.fasterxml.jackson.annotation.JsonInclude class *
 -keepclassmembers class * {
     @com.fasterxml.jackson.annotation.JsonIgnore *;
     @com.fasterxml.jackson.annotation.JsonProperty *;
 }
 -keep @io.swagger.v3.oas.annotations.Operation class *
 # 保留路由断言工厂类
 -keep class org.springframework.cloud.gateway.handler.predicate.** { *; }
 # 保留若依自定义过滤器
 -keep class com.iailab.gateway.filters.** { *; }
 # 保留所有Spring组件类的原始名称
 -keepnames @org.springframework.stereotype.Component class *
 -keepnames @org.springframework.stereotype.Service class *
 -keepnames @org.springframework.stereotype.Repository class *
 # 保留@Bean方法的名称
 -keepclassmembernames class * {
     @org.springframework.context.annotation.Bean *;
 }
 # 保留所有 Spring 注解及组件
 -keep @org.springframework.stereotype.Component class * { *; }
 -keep @org.springframework.context.annotation.Configuration class * { *; }
 # 保留配置类及字段
 -keep @org.springframework.boot.context.properties.ConfigurationProperties class * { *; }
 -keepclassmembers @org.springframework.boot.context.properties.ConfigurationProperties class * { *; }
 # 保留关键业务模块
 -keep class com.iailab.module.system.framework.sms.** { *; }
 -keepclassmembers class com.iailab.module.system.framework.sms.** { *; }
 -keep class com.iailab.module.system.convert.**.** { *; }
  -keepclassmembers class com.iailab.module.system.convert.**.** { *; }
 # 保留 Setter 和资源文件
 -keepclassmembers class * { void set*(***); }
 # ========== SPI 相关保留 ==========
 -keep interface com.xingyuv.captcha.service.** { *; }
 -keep class * implements com.xingyuv.captcha.service.** { *; }
 # ========== Spring 自动配置类 ==========
 -keep @org.springframework.boot.autoconfigure.AutoConfiguration class * { *; }
 -keep class com.xingyuv.captcha.config.** { *; }
 # ========== 明确保留报错类 ==========
 -keep class com.iailab.module.system.framework.captcha.core.RedisCaptchaServiceImpl {
     public <init>();
     public *;
 }
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/permission/MenuMapper.java
@@ -22,6 +22,7 @@
    default List<MenuDO> selectList(MenuListReqVO reqVO) {
        return selectList(new LambdaQueryWrapperX<MenuDO>()
                .eq(MenuDO::getStatus, reqVO.getStatus())
                .likeIfPresent(MenuDO::getName, reqVO.getName()));
    }
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/job/monitor/MonitorDiskJob.java
对比新文件
@@ -0,0 +1,49 @@
//package com.iailab.module.system.job.monitor;
//
//import com.iailab.framework.tenant.core.aop.TenantIgnore;
//import com.iailab.module.infra.api.monitor.MonitorApi;
//import com.iailab.module.infra.api.monitor.dto.MonitorDiskDTO;
//import com.iailab.module.infra.util.ServerInfoCollector;
//import com.xxl.job.core.handler.annotation.XxlJob;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.io.IOException;
//import java.util.Date;
//import java.util.List;
//import java.util.concurrent.atomic.AtomicInteger;
//
//@Component
//public class MonitorDiskJob {
//
//    private Logger logger = LoggerFactory.getLogger(getClass());
//
//    private final AtomicInteger counts = new AtomicInteger();
//
//    private static final Object lock = new Object();
//
//    private final MonitorApi monitorApi;
//
//    @Value("${spring.application.name}")
//    public String serverName;
//
//    public MonitorDiskJob(MonitorApi monitorApi) {
//        this.monitorApi = monitorApi;
//    }
//
//    @XxlJob("monitorDiskJob")
//    @TenantIgnore
//    @Transactional
//    public void execute() throws IOException {
//        synchronized (lock) {
//            logger.info("[execute][定时第 ({}) 次执行]", counts.incrementAndGet());
//            System.out.println(new Date() + ": 我是系统服务system-server-服务器磁盘监控日志存储定时任务");
//            List<MonitorDiskDTO> monitorDiskDTOS = ServerInfoCollector.collectMonitorDisk();
//            monitorApi.reportDiskInfo(monitorDiskDTOS);
//        }
//    }
//
//}
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/job/monitor/MonitorMemJob.java
对比新文件
@@ -0,0 +1,48 @@
//package com.iailab.module.system.job.monitor;
//
//import com.iailab.framework.tenant.core.aop.TenantIgnore;
//import com.iailab.module.infra.api.monitor.MonitorApi;
//import com.iailab.module.infra.api.monitor.dto.MonitorMemDTO;
//import com.iailab.module.infra.util.ServerInfoCollector;
//import com.xxl.job.core.handler.annotation.XxlJob;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.io.IOException;
//import java.util.Date;
//import java.util.concurrent.atomic.AtomicInteger;
//
//@Component
//public class MonitorMemJob {
//
//    private Logger logger = LoggerFactory.getLogger(getClass());
//
//    private final AtomicInteger counts = new AtomicInteger();
//
//    private static final Object lock = new Object();
//
//    private final MonitorApi monitorApi;
//
//    @Value("${spring.application.name}")
//    public String serverName;
//
//    public MonitorMemJob(MonitorApi monitorApi) {
//        this.monitorApi = monitorApi;
//    }
//
//    @XxlJob("monitorMemJob")
//    @TenantIgnore
//    @Transactional
//    public void execute() throws IOException {
//        synchronized (lock) {
//            logger.info("[execute][定时第 ({}) 次执行]", counts.incrementAndGet());
//            System.out.println(new Date() + ": 我是系统服务system-server-服务器内存监控日志存储定时任务");
//            MonitorMemDTO monitorMemDTO = ServerInfoCollector.collectMonitorMem(serverName);
//            monitorApi.reportMemInfo(monitorMemDTO);
//        }
//    }
//
//}
iailab-module-system/iailab-module-system-biz/src/main/resources/application-prod.yaml
对比新文件
@@ -0,0 +1,116 @@
--- #################### 数据库相关配置 ####################
spring:
  # 数据源配置项
  autoconfigure:
    exclude:
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
  datasource:
    druid: # Druid 【监控】相关的全局配置
      web-stat-filter:
        enabled: true
      stat-view-servlet:
        enabled: true
        allow: # 设置白名单,不填则允许所有访问
        url-pattern: /druid/*
        login-username: # 控制台管理用户名和密码
        login-password:
      filter:
        stat:
          enabled: true
          log-slow-sql: true # 慢 SQL 记录
          slow-sql-millis: 100
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
    dynamic: # 多数据源配置
      druid: # Druid 【连接池】相关的全局配置
        initial-size: 5 # 初始连接数
        min-idle: 10 # 最小连接池数量
        max-active: 20 # 最大连接池数量
        max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
        time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
        min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
        max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
        validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://172.16.8.100:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
          username: root
          password: 123456
        slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
          lazy: true # 开启懒加载,保证启动速度
          url: jdbc:mysql://127.0.0.1:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
          username: root
          password: 123456
  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  redis:
    host: 127.0.0.1 # 地址
    port: 6379 # 端口
    database: 1 # 数据库索引
    password: 123456 # 密码,建议生产环境开启
--- #################### MQ 消息队列相关配置 ####################
# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
  name-server: 127.0.0.1:9876 # RocketMQ Namesrv
spring:
  # RabbitMQ 配置项,对应 RabbitProperties 配置类
  rabbitmq:
    host: 172.16.1.221 # RabbitMQ 服务的地址
    port: 5672 # RabbitMQ 服务的端口
    username: admin # RabbitMQ 服务的账号
    password: admin123 # RabbitMQ 服务的密码
  # Kafka 配置项,对应 KafkaProperties 配置类
  kafka:
    bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
--- #################### 定时任务相关配置 ####################
xxl:
  job:
    enabled: true # 是否开启调度中心,默认为 true 开启
    admin:
      addresses: http://172.16.216.133:9090/xxl-job-admin # 调度中心部署跟地址
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项
lock4j:
  acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
  expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
  endpoints:
    web:
      base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
      exposure:
        include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
--- #################### 平台相关配置 ####################
# 平台配置项,设置当前项目所有自定义的配置
iailab:
  env: # 多环境的配置项
    tag: ${HOSTNAME}
  security:
    mock-enable: true
  access-log: # 访问日志的配置项
    enable: false
  xss:
    enable: false
    exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系
      - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
      - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
  demo: false # 开启演示模式
  captcha:
    enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试
iailab-system/log/system-server.log
对比新文件
@@ -0,0 +1,188 @@
2025-06-05 15:13:24.253 |  INFO 51220 | main [TID: N/A] c.i.m.system.SystemServerApplication     | Starting SystemServerApplication using Java 17.0.11 on Thinkpad-E14 with PID 51220 (D:\Work\Yingdashi\Project\iailab-plat\iailab-plat\iailab-module-system\iailab-module-system-biz\target\classes started by houzh in D:\Work\Yingdashi\Project\iailab-plat\iailab-plat)
2025-06-05 15:13:24.258 |  INFO 51220 | main [TID: N/A] c.i.m.system.SystemServerApplication     | The following 1 profile is active: "test"
2025-06-05 15:13:26.733 |  INFO 51220 | main [TID: N/A] c.a.c.n.c.NacosConfigDataLoader          | [Nacos Config] Load config[dataId=system-server-test.yaml, group=DEFAULT_GROUP] success
2025-06-05 15:13:42.105 |  INFO 51220 | main [TID: N/A] o.s.cloud.context.scope.GenericScope     | BeanFactory id=c0d8b71f-8806-3bf3-ab6e-9e72d53a8b49
2025-06-05 15:13:43.819 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration' of type [com.mzt.logapi.starter.configuration.LogRecordProxyAutoConfiguration$$EnhancerBySpringCGLIB$$e92f3e7e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:43.910 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration' of type [org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:43.932 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:43.944 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'loadBalancerClientsDefaultsMappingsProvider' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration$$Lambda$658/0x000002ad116ff088] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:43.983 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'defaultsBindHandlerAdvisor' of type [org.springframework.cloud.commons.config.DefaultsBindHandlerAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:44.025 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'mzt.log.record-com.mzt.logapi.starter.configuration.LogRecordProperties' of type [com.mzt.logapi.starter.configuration.LogRecordProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:44.092 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'logRecordPerformanceMonitor' of type [com.mzt.logapi.service.impl.DefaultLogRecordPerformanceMonitor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:45.717 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration' of type [com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:45.774 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'dataPermissionAnnotationAdvisor' of type [com.iailab.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:45.996 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'com.iailab.framework.tenant.config.IailabTenantAutoConfiguration' of type [com.iailab.framework.tenant.config.IailabTenantAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:46.156 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'dsProcessor' of type [com.iailab.framework.tenant.core.db.dynamic.TenantDsProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:46.382 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'org.apache.rocketmq.spring.autoconfigure.ListenerContainerConfiguration' of type [org.apache.rocketmq.spring.autoconfigure.ListenerContainerConfiguration$$EnhancerBySpringCGLIB$$408f94c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:46.397 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'org.apache.rocketmq.spring.autoconfigure.MessageConverterConfiguration' of type [org.apache.rocketmq.spring.autoconfigure.MessageConverterConfiguration$$EnhancerBySpringCGLIB$$accf02b0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:46.686 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'createRocketMQMessageConverter' of type [org.apache.rocketmq.spring.support.RocketMQMessageConverter] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:46.725 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'rocketmq-org.apache.rocketmq.spring.autoconfigure.RocketMQProperties' of type [org.apache.rocketmq.spring.autoconfigure.RocketMQProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:46.756 |  INFO 51220 | main [TID: N/A] trationDelegate$BeanPostProcessorChecker | Bean 'rocketMQMessageListenerContainerRegistrar' of type [org.apache.rocketmq.spring.support.RocketMQMessageListenerContainerRegistrar] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2025-06-05 15:13:49.329 |  INFO 51220 | main [TID: N/A] o.s.b.w.embedded.tomcat.TomcatWebServer  | Tomcat initialized with port(s): 48081 (http)
2025-06-05 15:13:49.334 |  INFO 51220 | main [TID: N/A] o.a.catalina.core.AprLifecycleListener   | Loaded Apache Tomcat Native library [1.3.0] using APR version [1.7.4].
2025-06-05 15:13:49.337 |  INFO 51220 | main [TID: N/A] o.a.catalina.core.AprLifecycleListener   | APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
2025-06-05 15:13:49.338 |  INFO 51220 | main [TID: N/A] o.a.catalina.core.AprLifecycleListener   | APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2025-06-05 15:13:49.425 |  INFO 51220 | main [TID: N/A] o.a.catalina.core.AprLifecycleListener   | OpenSSL successfully initialized [OpenSSL 3.0.13 30 Jan 2024]
2025-06-05 15:13:49.523 |  INFO 51220 | main [TID: N/A] o.apache.catalina.core.StandardService   | Starting service [Tomcat]
2025-06-05 15:13:49.523 |  INFO 51220 | main [TID: N/A] org.apache.catalina.core.StandardEngine  | Starting Servlet engine: [Apache Tomcat/9.0.83]
2025-06-05 15:13:50.780 |  INFO 51220 | main [TID: N/A] o.a.c.c.C.[Tomcat].[localhost].[/]       | Initializing Spring embedded WebApplicationContext
2025-06-05 15:13:50.781 |  INFO 51220 | main [TID: N/A] w.s.c.ServletWebServerApplicationContext | Root WebApplicationContext: initialization completed in 24017 ms
2025-06-05 15:13:52.077 |  INFO 51220 | main [TID: N/A] o.s.c.openfeign.FeignClientFactoryBean   | For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
2025-06-05 15:13:52.546 |  INFO 51220 | main [TID: N/A] o.s.c.openfeign.FeignClientFactoryBean   | For 'system-server' URL not provided. Will try picking an instance via load-balancing.
2025-06-05 15:13:55.197 |  WARN 51220 | Thread-6 [TID: N/A] c.a.nacos.common.notify.NotifyCenter     | [NotifyCenter] Start destroying Publisher
2025-06-05 15:13:55.200 |  WARN 51220 | Thread-6 [TID: N/A] c.a.nacos.common.notify.NotifyCenter     | [NotifyCenter] Destruction of the end
2025-06-05 15:13:55.196 |  WARN 51220 | Thread-1 [TID: N/A] c.a.n.common.http.HttpClientBeanHolder   | [HttpClientBeanHolder] Start destroying common HttpClient
2025-06-05 15:13:55.212 |  WARN 51220 | Thread-1 [TID: N/A] c.a.n.common.http.HttpClientBeanHolder   | [HttpClientBeanHolder] Destruction of the end
2025-06-05 15:13:56.095 |  INFO 51220 | main [TID: N/A] com.alibaba.druid.pool.DruidDataSource   | {dataSource-1,master} inited
2025-06-05 15:13:56.123 |  INFO 51220 | main [TID: N/A] c.b.d.d.DynamicRoutingDataSource         | dynamic-datasource - add a datasource named [slave] success
2025-06-05 15:13:56.133 |  INFO 51220 | main [TID: N/A] c.b.d.d.DynamicRoutingDataSource         | dynamic-datasource - add a datasource named [master] success
2025-06-05 15:13:56.134 |  INFO 51220 | main [TID: N/A] c.b.d.d.DynamicRoutingDataSource         | dynamic-datasource initial loaded [2] datasource,primary datasource named [master]
2025-06-05 15:13:57.222 |  INFO 51220 | main [TID: N/A] o.s.c.openfeign.FeignClientFactoryBean   | For 'system-server' URL not provided. Will try picking an instance via load-balancing.
2025-06-05 15:14:02.825 |  INFO 51220 | main [TID: N/A] o.s.c.openfeign.FeignClientFactoryBean   | For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
2025-06-05 15:14:02.836 |  INFO 51220 | main [TID: N/A] o.s.c.openfeign.FeignClientFactoryBean   | For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
2025-06-05 15:14:05.089 |  INFO 51220 | main [TID: N/A] org.redisson.Version                     | Redisson 3.18.0
2025-06-05 15:14:06.237 |  INFO 51220 | redisson-netty-2-9 [TID: N/A] o.r.c.pool.MasterPubSubConnectionPool    | 1 connections initialized for 172.16.8.100/172.16.8.100:6379
2025-06-05 15:14:06.391 |  INFO 51220 | redisson-netty-2-19 [TID: N/A] o.r.c.pool.MasterConnectionPool          | 24 connections initialized for 172.16.8.100/172.16.8.100:6379
2025-06-05 15:14:06.967 |  INFO 51220 | main [TID: N/A] o.s.c.openfeign.FeignClientFactoryBean   | For 'infra-server' URL not provided. Will try picking an instance via load-balancing.
2025-06-05 15:14:07.268 |  INFO 51220 | main [TID: N/A] c.x.c.s.i.BlockPuzzleCaptchaServiceImpl  | --->>>xingyuv captcha-plus 初始化验证码底图<<<---blockPuzzle
2025-06-05 15:14:07.595 | ERROR 51220 | main [TID: N/A] c.x.c.s.i.BlockPuzzleCaptchaServiceImpl  | load font error:{}
java.io.IOException: Problem reading font data.
    at java.desktop/java.awt.Font.createFont0(Font.java:1208) ~[na:na]
    at java.desktop/java.awt.Font.createFont(Font.java:1076) ~[na:na]
    at com.xingyuv.captcha.service.impl.AbstractCaptchaService.loadWaterMarkFont(AbstractCaptchaService.java:210) ~[captcha-plus-1.0.8.jar:na]
    at com.xingyuv.captcha.service.impl.AbstractCaptchaService.init(AbstractCaptchaService.java:100) ~[captcha-plus-1.0.8.jar:na]
    at com.xingyuv.captcha.service.impl.BlockPuzzleCaptchaServiceImpl.init(BlockPuzzleCaptchaServiceImpl.java:34) ~[captcha-plus-1.0.8.jar:na]
    at com.xingyuv.captcha.service.impl.CaptchaServiceFactory.getInstance(CaptchaServiceFactory.java:36) ~[captcha-plus-1.0.8.jar:na]
    at com.xingyuv.captcha.config.AjCaptchaServiceAutoConfiguration.captchaService(AjCaptchaServiceAutoConfiguration.java:63) ~[spring-boot-starter-captcha-plus-1.0.8.jar:1.0.8]
    at com.xingyuv.captcha.config.AjCaptchaServiceAutoConfiguration$$EnhancerBySpringCGLIB$$efe47e61.CGLIB$captchaService$0(<generated>) ~[spring-boot-starter-captcha-plus-1.0.8.jar:1.0.8]
    at com.xingyuv.captcha.config.AjCaptchaServiceAutoConfiguration$$EnhancerBySpringCGLIB$$efe47e61$$FastClassBySpringCGLIB$$2b9e829c.invoke(<generated>) ~[spring-boot-starter-captcha-plus-1.0.8.jar:1.0.8]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.39.jar:5.3.39]
    at com.xingyuv.captcha.config.AjCaptchaServiceAutoConfiguration$$EnhancerBySpringCGLIB$$efe47e61.captchaService(<generated>) ~[spring-boot-starter-captcha-plus-1.0.8.jar:1.0.8]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:641) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:626) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:214) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:479) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:554) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:524) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:677) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:228) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:329) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:209) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:548) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:524) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:677) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:228) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:329) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:209) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) ~[spring-boot-2.7.18.jar:2.7.18]
    at com.iailab.module.system.SystemServerApplication.main(SystemServerApplication.java:17) ~[classes/:na]
2025-06-05 15:14:07.604 |  WARN 51220 | main [TID: N/A] ConfigServletWebServerApplicationContext | Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminAuthServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'captchaService' defined in class path resource [com/xingyuv/captcha/config/AjCaptchaServiceAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.xingyuv.captcha.service.CaptchaService]: Factory method 'captchaService' threw exception; nested exception is java.lang.IllegalStateException: Shutdown in progress
2025-06-05 15:14:07.657 |  INFO 51220 | main [TID: N/A] c.b.d.d.DynamicRoutingDataSource         | dynamic-datasource start closing ....
2025-06-05 15:14:07.663 |  INFO 51220 | main [TID: N/A] com.alibaba.druid.pool.DruidDataSource   | {dataSource-0} closing ...
2025-06-05 15:14:07.663 |  INFO 51220 | main [TID: N/A] c.b.d.d.d.DefaultDataSourceDestroyer     | dynamic-datasource close the datasource named [slave] success,
2025-06-05 15:14:07.663 |  INFO 51220 | main [TID: N/A] com.alibaba.druid.pool.DruidDataSource   | {dataSource-1} closing ...
2025-06-05 15:14:07.674 |  INFO 51220 | main [TID: N/A] com.alibaba.druid.pool.DruidDataSource   | {dataSource-1} closed
2025-06-05 15:14:07.675 |  INFO 51220 | main [TID: N/A] c.b.d.d.d.DefaultDataSourceDestroyer     | dynamic-datasource close the datasource named [master] success,
2025-06-05 15:14:07.675 |  INFO 51220 | main [TID: N/A] c.b.d.d.DynamicRoutingDataSource         | dynamic-datasource all closed success,bye
2025-06-05 15:14:07.677 |  WARN 51220 | main [TID: N/A] s.c.a.AnnotationConfigApplicationContext | Exception thrown from ApplicationListener handling ContextClosedEvent
org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'rabbitConnectionFactory': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:214) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.event.AbstractApplicationEventMulticaster.retrieveApplicationListeners(AbstractApplicationEventMulticaster.java:264) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:221) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:140) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:430) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:436) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:387) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1072) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1035) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.cloud.context.named.NamedContextFactory.destroy(NamedContextFactory.java:99) ~[spring-cloud-context-3.1.8.jar:3.1.8]
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:213) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:587) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:559) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1163) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:520) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1156) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1123) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:604) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) ~[spring-boot-2.7.18.jar:2.7.18]
    at com.iailab.module.system.SystemServerApplication.main(SystemServerApplication.java:17) ~[classes/:na]
2025-06-05 15:14:07.679 |  WARN 51220 | main [TID: N/A] s.c.a.AnnotationConfigApplicationContext | Exception thrown from ApplicationListener handling ContextClosedEvent
org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'rabbitConnectionFactory': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:214) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.event.AbstractApplicationEventMulticaster.retrieveApplicationListeners(AbstractApplicationEventMulticaster.java:264) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:221) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:140) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:430) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:436) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:387) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1072) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1035) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.cloud.context.named.NamedContextFactory.destroy(NamedContextFactory.java:99) ~[spring-cloud-context-3.1.8.jar:3.1.8]
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:213) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:587) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:559) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1163) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:520) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1156) ~[spring-beans-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1123) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:604) ~[spring-context-5.3.39.jar:5.3.39]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.7.18.jar:2.7.18]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) ~[spring-boot-2.7.18.jar:2.7.18]
    at com.iailab.module.system.SystemServerApplication.main(SystemServerApplication.java:17) ~[classes/:na]
pom.xml
@@ -23,7 +23,7 @@
    <name>${project.artifactId}</name>
    <description>平台项目基础脚手架</description>
    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
    <url>http://172.16.8.100:8888/summary/iailab-plat-v2.0.git</url>
    <properties>
        <revision>1.0.0</revision>
工业互联网平台鉴权功能.md
对比新文件
@@ -0,0 +1,269 @@
## 工业互联网平台鉴权功能 ##
1. 登录功能
   登录接口: http://0.0.0.0/admin-api/system/auth/login
① 参数说明
      {
      "tenantName": "tenant1", //租户名称(必传),需事先在平台配置
      "username": "admin",     //用户名(必传),平台事先维护好用户
      "password": "123",       //密码(必传)
      "captchaVerification": "PfcH6mgr==" //验证码(非必传),若开启的话需要前后台同时开启
      }
其中租户名称在登录逻辑中用不到,用到的是租户对应的ID,接口请求的时候需要将Tenant-Id封装到请求头中,登录逻辑会从请求头中获取并使用,如下截图
特别注意:平台其它接口也都需要封装此租户ID
② 主要代码
1、控制层接口
      `@PostMapping("/login")
      @PermitAll
      @Operation(summary = "使用账号密码登录")
      public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
      return success(authService.login(reqVO));
      }`
2、参数对象 AuthLoginReqVO
@Schema(description = "管理后台 - 账号密码登录 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginReqVO {
    @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailabyuanma")
    @NotEmpty(message = "登录账号不能为空")
    @Length(min = 4, max = 16, message = "账号长度为 4-16 位")
    @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
    private String username;
    @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
    @NotEmpty(message = "密码不能为空")
    @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
    private String password;
    // ========== 图片验证码相关 ==========
    @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
            example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
    @NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
    private String captchaVerification;
}
3、登录实现类
    @Override
    public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
        // 校验验证码
        validateCaptcha(reqVO);
        // 使用账号密码,进行登录
        AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
        // 创建 Token 令牌,记录登录日志
        return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
    }
4、验证用户名密码
    @Override
    public AdminUserDO authenticate(String username, String password) {
        final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
        // 校验账号是否存在
        AdminUserDO user = userService.getUserByUsername(username);
        if (user == null) {
            createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }
        if (!userService.isPasswordMatch(password, user.getPassword())) {
            createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }
        // 校验是否禁用
        if (CommonStatusEnum.isDisable(user.getStatus())) {
            createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
            throw exception(AUTH_LOGIN_USER_DISABLED);
        }
        return user;
    }
用户名密码校验不通过常量如下图
5、创建令牌
    private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
        // 插入登陆日志
        createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
        // 创建访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(),
                OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);
        // 构建返回结果
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }
其中“OAuth2ClientConstants.CLIENT_ID_DEFAULT”是在平台配置好的默认客户端,主要包括授权类型、刷新token有效期、访问token有效期等
6、创建访问令牌和刷新令牌
    @Override
    @Transactional
    public OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String clientId, List<String> scopes) {
        OAuth2ClientDO clientDO = oauth2ClientService.validOAuthClientFromCache(clientId);
        // 创建刷新令牌
        OAuth2RefreshTokenDO refreshTokenDO = createOAuth2RefreshToken(userId, userType, clientDO, scopes);
        // 创建访问令牌
        return createOAuth2AccessToken(refreshTokenDO, clientDO);
    }
    private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2RefreshTokenDO refreshTokenDO, OAuth2ClientDO clientDO) {
        OAuth2AccessTokenDO accessTokenDO = new OAuth2AccessTokenDO().setAccessToken(generateAccessToken())
                .setUserId(refreshTokenDO.getUserId()).setUserType(refreshTokenDO.getUserType())
                .setUserInfo(buildUserInfo(refreshTokenDO.getUserId(), refreshTokenDO.getUserType()))
                .setClientId(clientDO.getClientId()).setScopes(refreshTokenDO.getScopes())
                .setRefreshToken(refreshTokenDO.getRefreshToken())
                .setExpiresTime(LocalDateTime.now().plusSeconds(clientDO.getAccessTokenValiditySeconds()));
        accessTokenDO.setTenantId(TenantContextHolder.getTenantId()); // 手动设置租户编号,避免缓存到 Redis 的时候,无对应的租户编号
        oauth2AccessTokenMapper.insert(accessTokenDO);
        // 记录到 Redis 中
        oauth2AccessTokenRedisDAO.set(accessTokenDO);
        return accessTokenDO;
    }
    private OAuth2RefreshTokenDO createOAuth2RefreshToken(Long userId, Integer userType, OAuth2ClientDO clientDO, List<String> scopes) {
        OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO().setRefreshToken(generateRefreshToken())
                .setUserId(userId).setUserType(userType)
                .setClientId(clientDO.getClientId()).setScopes(scopes)
                .setExpiresTime(LocalDateTime.now().plusSeconds(clientDO.getRefreshTokenValiditySeconds()));
        oauth2RefreshTokenMapper.insert(refreshToken);
        return refreshToken;
    }
注意:访问令牌是请求后端接口的通行证,所有需要鉴权的后端api都需要携带访问令牌,访问令牌过期后会请求刷新令牌接口,重新获取访问令牌。 当刷新令牌过期后,就需要重新登录获取授权了!
7、刷新令牌
    @PostMapping("/refresh-token")
    @PermitAll
    @Operation(summary = "刷新令牌")
    @Parameter(name = "refreshToken", description = "刷新令牌", required = true)
    public CommonResult<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
        return success(authService.refreshToken(refreshToken));
    }
    @Override
    public AuthLoginRespVO refreshToken(String refreshToken) {
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }
    @Override
    public OAuth2AccessTokenDO refreshAccessToken(String refreshToken, String clientId) {
        // 查询访问令牌
        OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectByRefreshToken(refreshToken);
        if (refreshTokenDO == null) {
            throw exception0(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), "无效的刷新令牌");
        }
        // 校验 Client 匹配
        OAuth2ClientDO clientDO = oauth2ClientService.validOAuthClientFromCache(clientId);
        if (ObjectUtil.notEqual(clientId, refreshTokenDO.getClientId())) {
            throw exception0(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), "刷新令牌的客户端编号不正确");
        }
        // 移除相关的访问令牌
        List<OAuth2AccessTokenDO> accessTokenDOs = oauth2AccessTokenMapper.selectListByRefreshToken(refreshToken);
        if (CollUtil.isNotEmpty(accessTokenDOs)) {
            oauth2AccessTokenMapper.deleteBatchIds(convertSet(accessTokenDOs, OAuth2AccessTokenDO::getId));
            oauth2AccessTokenRedisDAO.deleteList(convertSet(accessTokenDOs, OAuth2AccessTokenDO::getAccessToken));
        }
        // 已过期的情况下,删除刷新令牌
        if (DateUtils.isExpired(refreshTokenDO.getExpiresTime())) {
            oauth2RefreshTokenMapper.deleteById(refreshTokenDO.getId());
            throw exception0(GlobalErrorCodeConstants.UNAUTHORIZED.getCode(), "刷新令牌已过期");
        }
        // 创建访问令牌
        return createOAuth2AccessToken(refreshTokenDO, clientDO);
    }
8、前端封装token和租户ID代码参考
      // request拦截器
      service.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
      // 是否需要设置 token
      let isToken = (config!.headers || {}).isToken === false
      whiteList.some((v) => {
      if (config.url && config.url.indexOf(v) > -1) {
      return (isToken = false)
      }
      })
      if (getAccessToken() && !isToken) {
      config.headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token
      }
      // 设置租户
      if (tenantEnable && tenantEnable === 'true') {
      const tenantId = getTenantId()
      if (tenantId) config.headers['tenant-id'] = tenantId
      }
      const method = config.method?.toUpperCase()
      // 防止 GET 请求缓存
      if (method === 'GET') {
      config.headers['Cache-Control'] = 'no-cache'
      config.headers['Pragma'] = 'no-cache'
      }
      // 自定义参数序列化函数
      else if (method === 'POST') {
      const contentType = config.headers['Content-Type'] || config.headers['content-type']
      if (contentType === 'application/x-www-form-urlencoded') {
      if (config.data && typeof config.data !== 'string') {
      config.data = qs.stringify(config.data)
      }
      }
      }
      return config
      },
      (error: AxiosError) => {
      // Do something with request error
      console.log(error) // for debug
      return Promise.reject(error)
      }
      )
2. 退出登录功能
   登出接口: http://0.0.0.0/admin-api/system/auth/logout
核心代码如下
    @PostMapping("/logout")
    @PermitAll
    @Operation(summary = "登出系统")
    public CommonResult<Boolean> logout(HttpServletRequest request) {
        String token = SecurityFrameworkUtils.obtainAuthorization(request,
                securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
        if (StrUtil.isNotBlank(token)) {
            authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
        }
        return success(true);
    }
    @Override
    public void logout(String token, Integer logType) {
        // 删除访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(token);
        if (accessTokenDO == null) {
            return;
        }
        // 删除成功,则记录登出日志
        createLogoutLog(accessTokenDO.getUserId(), accessTokenDO.getUserType(), logType);
    }
    @Override
    public OAuth2AccessTokenDO removeAccessToken(String accessToken) {
        // 删除访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(accessToken);
        if (accessTokenDO == null) {
            return null;
        }
        oauth2AccessTokenMapper.deleteById(accessTokenDO.getId());
        oauth2AccessTokenRedisDAO.delete(accessToken);
        // 删除刷新令牌
        oauth2RefreshTokenMapper.deleteByRefreshToken(accessTokenDO.getRefreshToken());
        return accessTokenDO;
    }