From cf4eeab3954991885d1b8f01e438b0e5f24d1a81 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 2 May 2021 15:41:38 +0800 Subject: [PATCH] 项目结构调整 x 16 : 将 monitor、sms、dict 等组件拆分出去 --- pom.xml | 5 +++++ yudao-admin-server/pom.xml | 32 +++++++++++++++----------------- yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java | 9 +++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java | 4 ++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md | 1 + yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java | 9 +++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java | 4 ++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md | 1 + yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/package-info.java | 6 ++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/redis/RedisConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/message/config/InfConfigRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/producer/config/InfConfigProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/post/SysPostExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRolePageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserImportExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dept/SysDeptRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dict/SysDictDataRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysMenuRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dept/SysDeptProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dict/SysDictDataProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysPermissionProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysRoleProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodegenController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java | 10 +++++----- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java | 2 +- yudao-admin-server/src/main/resources/1logback-spring.xml | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-admin-server/src/main/resources/logback-spring.xml | 76 ---------------------------------------------------------------------------- yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseDbAndRedisIntegrationTest.java | 2 +- yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java | 2 +- yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeServiceTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeServiceImplTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java | 8 ++++---- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java | 8 ++++---- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java | 8 ++++---- yudao-dependencies/pom.xml | 42 +++++++++++++++++++++++++++++++++++++++++- yudao-framework/pom.xml | 20 ++++++++++++++++++-- yudao-framework/yudao-common/pom.xml | 7 +++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java | 33 +++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/MapUtils.java | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java | 18 ++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java | 30 ++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java | 32 ++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/package-info.java | 7 +++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringAopUtils.java | 46 ++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringExpressionUtils.java | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java | 35 +++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/package-info.java | 4 ++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/ArrayUtils.java | 33 --------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/CollectionUtils.java | 150 ------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/MapUtils.java | 66 ------------------------------------------------------------------ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/SetUtils.java | 18 ------------------ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/date/DateUtils.java | 77 ----------------------------------------------------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/json/JsonUtils.java | 82 ---------------------------------------------------------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java | 30 ------------------------------ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/object/ObjectUtils.java | 32 -------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/package-info.java | 7 ------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/servlet/ServletUtils.java | 95 ----------------------------------------------------------------------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringAopUtils.java | 46 ---------------------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringExpressionUtils.java | 82 ---------------------------------------------------------------------------------- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/string/StrUtils.java | 37 ------------------------------------- yudao-framework/yudao-common/《芋道 Spring Boot 参数校验 Validation 入门》.md | 1 + yudao-framework/yudao-framework-all/pom.xml | 149 ----------------------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java | 20 -------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java | 32 -------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java | 183 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java | 75 --------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java | 33 --------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java | 13 ------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java | 32 -------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java | 63 --------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java | 9 --------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/config/DictConfiguration.java | 18 ------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/dto/DictDataRespDTO.java | 33 --------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/service/DictDataFrameworkService.java | 35 ----------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/util/DictUtils.java | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/package-info.java | 6 ------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/annotations/DictFormat.java | 22 ---------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java | 73 ------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/JsonConvert.java | 39 --------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/util/ExcelUtils.java | 48 ------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/config/IdempotentConfiguration.java | 42 ------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/annotation/Idempotent.java | 46 ---------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/aop/IdempotentAspect.java | 56 -------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java | 22 ---------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java | 25 ------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java | 63 --------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/redis/IdempotentRedisDAO.java | 34 ---------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/package-info.java | 12 ------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/config/Lock4jConfiguration.java | 23 ----------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/DefaultLockFailureStrategy.java | 20 -------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/Lock4jRedisKeyConstants.java | 19 ------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java | 9 --------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/package-info.java | 10 ---------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java | 18 ------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java | 14 -------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java | 19 ------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java | 113 ----------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java | 130 ---------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java | 44 -------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java | 54 ------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java | 5 ----- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/《芋道 Spring Boot 定时任务入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java | 119 ----------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java | 101 ----------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java | 71 ----------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java | 20 -------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java | 88 ---------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java | 20 -------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java | 40 ---------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/《芋道 Spring Boot Redis 入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/package-info.java | 9 --------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java | 21 --------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java | 54 ------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java | 36 ------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java | 17 ----------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java | 68 -------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java | 48 ------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java | 18 ------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java | 33 --------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java | 122 -------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java | 90 ------------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java | 212 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java | 43 ------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java | 23 ----------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java | 96 ------------------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java | 204 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java | 45 --------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java | 37 ------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java | 47 ----------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java | 21 --------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java | 52 ---------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/package-info.java | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java | 97 ------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java | 100 ---------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java | 56 -------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerProperties.java | 14 -------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/annotation/BizTrace.java | 42 ------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/aop/BizTraceAspect.java | 70 ---------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java | 33 --------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/package-info.java | 6 ------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnum.java | 35 ----------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnumValidator.java | 44 -------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/《芋道 Spring Boot 参数校验 Validation 入门》.md | 1 - yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/BaseMockitoUnitTest.java | 13 ------------- yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java | 224 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java | 43 ------------------------------------------- yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/package-info.java | 1 - yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java | 202 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java | 43 ------------------------------------------- yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/package-info.java | 1 - yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/package-info.java | 1 - yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/package-info.java | 1 - yudao-framework/yudao-spring-boot-starter-biz-dict/pom.xml | 30 ++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/DictConfiguration.java | 18 ++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/dto/DictDataRespDTO.java | 33 +++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/service/DictDataFrameworkService.java | 35 +++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictUtils.java | 28 ++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/package-info.java | 6 ++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java | 15 +++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java | 1 + yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java | 17 +++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java | 21 +++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java | 6 ++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java | 21 +++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java | 17 +++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java | 18 ++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java | 33 +++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java | 23 +++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java | 21 +++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/pom.xml | 32 ++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java | 20 ++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java | 32 ++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java | 33 +++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java | 13 +++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java | 32 ++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-excel/pom.xml | 33 +++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/annotations/DictFormat.java | 22 ++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java | 39 +++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java | 4 ++++ yudao-framework/yudao-spring-boot-starter-job/pom.xml | 26 ++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java | 18 ++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java | 14 ++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java | 19 +++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java | 5 +++++ yudao-framework/yudao-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md | 1 + yudao-framework/yudao-spring-boot-starter-monitor/pom.xml | 45 +++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerAutoConfiguration.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerProperties.java | 14 ++++++++++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/annotation/BizTrace.java | 42 ++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/aop/BizTraceAspect.java | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java | 33 +++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/package-info.java | 6 ++++++ yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md | 1 + yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml | 3 +-- yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/JsonLongSetTypeHandler.java | 2 +- yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml | 44 -------------------------------------------- yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java | 15 --------------- yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java | 57 --------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java | 354 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java | 84 ------------------------------------------------------------------------------------ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java | 55 ------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java | 1 - yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java | 17 ----------------- yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java | 21 --------------------- yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java | 6 ------ yudao-framework/yudao-spring-boot-starter-protection/pom.xml | 20 ++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/IdempotentConfiguration.java | 42 ++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/annotation/Idempotent.java | 46 ++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/aop/IdempotentAspect.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java | 22 ++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java | 25 +++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/redis/IdempotentRedisDAO.java | 34 ++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/package-info.java | 12 ++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/Lock4jConfiguration.java | 23 +++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java | 20 ++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/Lock4jRedisKeyConstants.java | 19 +++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/package-info.java | 4 ++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/package-info.java | 9 +++++++++ yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md | 1 + yudao-framework/yudao-spring-boot-starter-redis/pom.xml | 31 +++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/RedisConfig.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyDefine.java | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyRegistry.java | 28 ++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/AbstractChannelMessageListener.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/ChannelMessage.java | 20 ++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/AbstractStreamMessageListener.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/StreamMessage.java | 20 ++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/util/RedisMessageUtils.java | 40 ++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/package-info.java | 4 ++++ yudao-framework/yudao-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md | 1 + yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java | 2 +- yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java | 2 +- yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java | 2 +- yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java | 2 +- yudao-framework/yudao-spring-boot-starter-test/pom.xml | 41 +++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/BaseMockitoUnitTest.java | 13 +++++++++++++ yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/package-info.java | 4 ++++ yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java | 4 ++++ yudao-framework/yudao-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md | 1 + yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java | 8 ++++---- yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java | 2 +- yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java | 2 +- yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java | 2 +- yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java | 2 +- yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java | 6 +++--- 424 files changed, 6516 insertions(+), 6276 deletions(-) create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/package-info.java create mode 100644 yudao-admin-server/src/main/resources/1logback-spring.xml delete mode 100644 yudao-admin-server/src/main/resources/logback-spring.xml create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/MapUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/package-info.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringAopUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringExpressionUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/package-info.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/ArrayUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/CollectionUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/MapUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/SetUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/date/DateUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/json/JsonUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/object/ObjectUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/package-info.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/servlet/ServletUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringAopUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringExpressionUtils.java delete mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/string/StrUtils.java create mode 100644 yudao-framework/yudao-common/《芋道 Spring Boot 参数校验 Validation 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/pom.xml delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/config/DictConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/dto/DictDataRespDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/service/DictDataFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/util/DictUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/annotations/DictFormat.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/JsonConvert.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/util/ExcelUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/config/IdempotentConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/annotation/Idempotent.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/aop/IdempotentAspect.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/redis/IdempotentRedisDAO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/config/Lock4jConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/DefaultLockFailureStrategy.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/Lock4jRedisKeyConstants.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/《芋道 Spring Boot 定时任务入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/《芋道 Spring Boot Redis 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/annotation/BizTrace.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/aop/BizTraceAspect.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnumValidator.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/《芋道 Spring Boot 参数校验 Validation 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/BaseMockitoUnitTest.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-dict/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/DictConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/dto/DictDataRespDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/service/DictDataFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java create mode 100644 yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/annotations/DictFormat.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerProperties.java create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/annotation/BizTrace.java create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/aop/BizTraceAspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/IdempotentConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/annotation/Idempotent.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/aop/IdempotentAspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/redis/IdempotentRedisDAO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/Lock4jConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/Lock4jRedisKeyConstants.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/RedisConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyDefine.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyRegistry.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/AbstractChannelMessageListener.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/ChannelMessage.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/AbstractStreamMessageListener.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/StreamMessage.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/util/RedisMessageUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md create mode 100644 yudao-framework/yudao-spring-boot-starter-test/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/BaseMockitoUnitTest.java create mode 100644 yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md diff --git a/pom.xml b/pom.xml index eec6216..e132d63 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,11 @@ yudao-dependencies yudao-framework yudao-admin-server + yudao-spring-boot-starter-job + yudao-spring-boot-starter-config + yudao-spring-boot-starter-test + yudao-spring-boot-starter-biz-sms + yudao-spring-boot-starter-excel ${artifactId} diff --git a/yudao-admin-server/pom.xml b/yudao-admin-server/pom.xml index d0b7670..71e0667 100644 --- a/yudao-admin-server/pom.xml +++ b/yudao-admin-server/pom.xml @@ -17,10 +17,10 @@ https://github.com/YunaiV/ruoyi-vue-pro + cn.iocoder.boot - yudao-framework-all - ${revision} + yudao-spring-boot-starter-biz-operatelog @@ -40,35 +40,33 @@ yudao-spring-boot-starter-mybatis - + - org.springframework.boot - spring-boot-starter-test - test + cn.iocoder.boot + yudao-spring-boot-starter-monitor - com.h2database - h2 - test + de.codecentric + spring-boot-admin-starter-server + - com.github.fppt - jedis-mock + cn.iocoder.boot + yudao-spring-boot-starter-test test + - uk.co.jemos.podam - podam - test + org.apache.velocity + velocity-engine-core - - cn.iocoder.boot - yudao-spring-boot-starter-operatelog + cn.smallbun.screw + screw-core diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java new file mode 100644 index 0000000..58096d5 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java @@ -0,0 +1,9 @@ +package cn.iocoder.dashboard.framework.async.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +@Configuration +@EnableAsync +public class AsyncConfiguration { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java new file mode 100644 index 0000000..3753589 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java @@ -0,0 +1,4 @@ +/** + * 异步执行,基于 Spring @Async 实现 + */ +package cn.iocoder.dashboard.framework.async; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md new file mode 100644 index 0000000..5822b83 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java new file mode 100644 index 0000000..77c166c --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java @@ -0,0 +1,9 @@ +package cn.iocoder.dashboard.framework.monitor.config; + +import de.codecentric.boot.admin.server.config.EnableAdminServer; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableAdminServer +public class AdminServerConfiguration { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java new file mode 100644 index 0000000..dec6e31 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java @@ -0,0 +1,4 @@ +/** + * 使用 Spring Boot Admin 实现简单的监控平台 + */ +package cn.iocoder.dashboard.framework.monitor; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md new file mode 100644 index 0000000..a1e3676 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/package-info.java new file mode 100644 index 0000000..991a69b --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于整个 yudao-admin-server 的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.dashboard.framework; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java index a4b6359..4fa9c4b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.controller.config; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.config.vo.*; import cn.iocoder.dashboard.modules.infra.convert.config.InfConfigConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExcelVO.java index 0a572ce..622034f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.controller.config.vo; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExportReqVO.java index 0b562fb..1e43758 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("参数配置导出 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigPageReqVO.java index 1fd550d..a862f35 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("参数配置分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java index d863022..1271e1b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.controller.doc; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.smallbun.screw.core.Configuration; import cn.smallbun.screw.core.engine.EngineConfig; import cn.smallbun.screw.core.engine.EngineFileType; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java index 8031b26..dbbfd7f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java @@ -8,7 +8,7 @@ import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFileRespVO; import cn.iocoder.dashboard.modules.infra.convert.file.InfFileConvert; import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO; import cn.iocoder.dashboard.modules.infra.service.file.InfFileService; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java index 2942770..41f792d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("文件分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java index 155abe6..c9df9a5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.controller.job; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.framework.quartz.core.util.CronUtils; import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.*; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java index bf5c92f..717ceb0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.controller.job; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobExcelVO.java index b4fa685..1488642 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.controller.job.vo.job; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.infra.enums.InfDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java index c64cae3..5ae2795 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; /** * 定时任务日志 Base VO,提供给添加、修改、详细的子 VO 使用 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java index ca8b25d..58a58d6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.controller.job.vo.log; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.infra.enums.InfDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java index 85906e8..4bbf562 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "定时任务 Excel 导出 Request VO", description = "参数和 InfJobLogPageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java index 8b80aac..4784cb6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("定时任务日志分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java index b4bdc61..1ca75db 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java index 9827d33..ff25f33 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java index e665889..5dcfbd9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; /** * API 访问日志 Base VO,提供给添加、修改、详细的子 VO 使用 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java index 9181da0..be9ec35 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java index 3ce54f4..43f852e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "API 访问日志 Excel 导出 Request VO", description = "参数和 InfApiAccessLogPageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java index 98a4cc1..14973d8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("API 访问日志分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java index a0c57a7..5e521a5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; /** * API 错误日志 Base VO,提供给添加、修改、详细的子 VO 使用 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java index 7d722fb..858be0a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.infra.enums.InfDictTypeConstants; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java index 920296d..1225e9d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "API 错误日志 Excel 导出 Request VO", description = "参数和 InfApiErrorLogPageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java index 4eef06b..b03fc22 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("API 错误日志分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java index 0c6ba96..dcc49a7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java @@ -1,8 +1,8 @@ package cn.iocoder.dashboard.modules.infra.controller.redis; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; -import cn.iocoder.dashboard.framework.redis.core.RedisKeyRegistry; +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; +import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry; import cn.iocoder.dashboard.modules.infra.controller.redis.vo.InfRedisKeyRespVO; import cn.iocoder.dashboard.modules.infra.controller.redis.vo.InfRedisMonitorRespVO; import cn.iocoder.dashboard.modules.infra.convert.redis.RedisConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java index d62297c..3ea923c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.infra.controller.redis.vo; -import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/redis/RedisConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/redis/RedisConvert.java index b4ae4e2..c539e1a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/redis/RedisConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/redis/RedisConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.convert.redis; import cn.hutool.core.util.StrUtil; -import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; import cn.iocoder.dashboard.modules.infra.controller.redis.vo.InfRedisKeyRespVO; import cn.iocoder.dashboard.modules.infra.controller.redis.vo.InfRedisMonitorRespVO; import org.mapstruct.Mapper; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java index 064fb31..9ad5652 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.mq.consumer.config; import cn.iocoder.dashboard.framework.apollo.internals.DBConfigRepository; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.infra.mq.message.config.InfConfigRefreshMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/message/config/InfConfigRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/message/config/InfConfigRefreshMessage.java index 9250f33..729cbde 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/message/config/InfConfigRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/message/config/InfConfigRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.infra.mq.message.config; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/producer/config/InfConfigProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/producer/config/InfConfigProducer.java index 1cb240d..6e54b04 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/producer/config/InfConfigProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/mq/producer/config/InfConfigProducer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.infra.mq.producer.config; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.infra.mq.message.config.InfConfigRefreshMessage; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java index 130fc53..cc534c9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java @@ -23,7 +23,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.util.collection.CollectionUtils.containsAny; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.containsAny; /** * 定时任务 Service 实现类 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java index 6c7b715..8aee702 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java @@ -16,7 +16,7 @@ import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.framework.util.collection.SetUtils; +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.validation.annotation.Validated; @@ -29,8 +29,8 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds; -import static cn.iocoder.yudao.framework.util.servlet.ServletUtils.getClientIP; -import static cn.iocoder.yudao.framework.util.servlet.ServletUtils.getUserAgent; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; @Api(tags = "认证") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java index 855dd22..7439bec 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java @@ -11,7 +11,7 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.framework.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -25,7 +25,7 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Api(tags = "用户 Session") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java index 5f87e38..c9b621d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.*; import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/post/SysPostExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/post/SysPostExcelVO.java index d31b4a5..b77b1d2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/post/SysPostExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/post/SysPostExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.dept.vo.post; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java index 4411d73..b09cf2a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.*; import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java index 21e1f75..8aedd65 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.*; import cn.iocoder.dashboard.modules.system.convert.dict.SysDictTypeConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java index f137b0e..ef1d62a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict.vo.data; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java index d3b47c4..391489f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict.vo.type; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java index a9a226b..5a3033c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("字典类型分页列表 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java index 0da843a..57b59c5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.Size; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("字典类型分页列表 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java index 80d7698..711c4ff 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.errorcode; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.convert.errorcode.SysErrorCodeConvert; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.*; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java index 43b8b7f..8ba6d8d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.errorcode.vo; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.infra.enums.InfDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java index a425b7d..6c8aa09 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "错误码 Excel 导出 Request VO", description = "参数和 InfErrorCodePageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java index 5c3c80a..1bdbf98 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("错误码分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java index 3758546..8109460 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java index 8637510..bb2fa41 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; @@ -13,8 +13,8 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java index c41a942..bf23e3a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java index 6b33ffa..9390d41 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("登陆日志分页列表 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java index 50a92b9..4becbc9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java @@ -9,7 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("登陆日志分页列表 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java index 74c35ae..d24704f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java index a09edb9..ae03dee 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("操作日志分页列表 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java index 9baafa1..bd127c3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("操作日志分页列表 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java index 0e660af..bd4aa70 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.*; import cn.iocoder.dashboard.modules.system.convert.permission.SysRoleConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExcelVO.java index a352090..8ef2a0b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.permission.vo.role; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java index 2b19afb..a08c6a6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("角色分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRolePageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRolePageReqVO.java index 4ce5a83..e5a6993 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRolePageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRolePageReqVO.java @@ -9,7 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("角色分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java index d2fe951..f576396 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java index 16745d7..e53b747 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.*; import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsTemplateConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java index 09d0b8c..161d853 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("短信渠道分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java index f1f2761..3df7b8e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java @@ -1,8 +1,8 @@ package cn.iocoder.dashboard.modules.system.controller.sms.vo.log; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; -import cn.iocoder.dashboard.framework.excel.core.convert.JsonConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java index 839fd0a..15f1dd6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "短信日志 Excel 导出 Request VO", description = "参数和 SysSmsLogPageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java index c3018eb..ec080bc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("短信日志分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java index 854f7dd..aab91e7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.sms.vo.template; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java index 4e88fdf..96500bf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "短信模板 Excel 导出 Request VO", description = "参数和 SysSmsTemplatePageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java index 084eb5b..6a72e3e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("短信模板分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java index 4a79d08..07ea900 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; @@ -13,8 +13,8 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.enums.common.SysSexEnum; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExcelVO.java index 16167ae..db5d058 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.user; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExportReqVO.java index fb3aefc..00559b2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExportReqVO.java @@ -9,7 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "用户导出 Request VO", description = "参数和 SysUserPageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserImportExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserImportExcelVO.java index 7c52bc6..25b8f3a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserImportExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserImportExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.user; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java index 72936e0..9dd9a95 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java @@ -11,7 +11,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("用户分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java index b90eae2..f29c17e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java @@ -9,7 +9,7 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysMenuDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.enums.permission.MenuIdEnum; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java index e1ba40b..e90f143 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.convert.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.dict.core.dto.DictDataRespDTO; +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.*; import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictDataDO; import org.mapstruct.Mapper; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java index 980510e..f1875af 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java @@ -6,7 +6,7 @@ import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOp import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogRespVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java index 38cdac0..e935174 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java @@ -1,9 +1,9 @@ package cn.iocoder.dashboard.modules.system.dal.redis; -import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; import cn.iocoder.yudao.framework.security.core.LoginUser; -import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; +import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; /** * System Redis Key 枚举类 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java index d960c20..15ebad2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.redis.auth; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; -import cn.iocoder.yudao.framework.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java index e6fa5a9..8ad82e8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.dept; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.dept.SysDeptRefreshMessage; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java index 12bf134..d929641 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.dict; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.dict.SysDictDataRefreshMessage; import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java index 3a0f22e..72cb8f2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.mail; -import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener; +import cn.iocoder.yudao.framework.redis.core.stream.AbstractStreamMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.mail.SysMailSendMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java index 3615242..044f126 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.permission; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysMenuRefreshMessage; import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java index 6927e14..6295f33 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.permission; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysRoleMenuRefreshMessage; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java index a5e77f7..022daae 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.permission; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysRoleRefreshMessage; import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java index 6105889..3d93ac5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.sms; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsChannelRefreshMessage; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java index 70b1671..80864ae 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.sms; -import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener; +import cn.iocoder.yudao.framework.redis.core.stream.AbstractStreamMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java index c310c48..7d117eb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.sms; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsTemplateService; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dept/SysDeptRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dept/SysDeptRefreshMessage.java index a78b125..22cdbda 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dept/SysDeptRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dept/SysDeptRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.dept; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dict/SysDictDataRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dict/SysDictDataRefreshMessage.java index 7fad277..c88c7d5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dict/SysDictDataRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/dict/SysDictDataRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.dict; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java index c9f5d2a..6a56f7d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.mail; -import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage; +import cn.iocoder.yudao.framework.redis.core.stream.StreamMessage; import lombok.Data; import javax.validation.constraints.NotNull; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysMenuRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysMenuRefreshMessage.java index 159682a..753cc2e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysMenuRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysMenuRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.permission; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java index 491c9b0..e32c5e0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.permission; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleRefreshMessage.java index b994010..0dc9c5d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/permission/SysRoleRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.permission; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java index fa28787..aaef601 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.sms; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java index ee12a22..3d3efda 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.mq.message.sms; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage; +import cn.iocoder.yudao.framework.redis.core.stream.StreamMessage; import lombok.Data; import javax.validation.constraints.NotNull; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java index 4925b09..927d0b8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.message.sms; -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dept/SysDeptProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dept/SysDeptProducer.java index 4ad7db4..2fe137c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dept/SysDeptProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dept/SysDeptProducer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.producer.dept; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.dept.SysDeptRefreshMessage; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dict/SysDictDataProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dict/SysDictDataProducer.java index 2ccfc51..8eb415b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dict/SysDictDataProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/dict/SysDictDataProducer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.producer.dict; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.dict.SysDictDataRefreshMessage; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java index 6d664c7..8818b40 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.producer.permission; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysMenuRefreshMessage; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysPermissionProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysPermissionProducer.java index f9eded6..64440a8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysPermissionProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysPermissionProducer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.producer.permission; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysRoleMenuRefreshMessage; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysRoleProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysRoleProducer.java index b398a27..e95b64f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysRoleProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysRoleProducer.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.mq.producer.permission; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysRoleRefreshMessage; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java index 9d8b72d..246ad31 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.mq.producer.sms; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsChannelRefreshMessage; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java index 860a9b9..fddd14b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.LoginUser; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; @@ -16,7 +16,7 @@ import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java index b9294f4..d04ccc4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java @@ -6,7 +6,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.config.SecurityProperties; import cn.iocoder.yudao.framework.security.core.LoginUser; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.auth.SysUserSessionDO; @@ -26,8 +26,8 @@ import java.time.Duration; import java.util.*; import java.util.stream.Collectors; -import static cn.iocoder.yudao.framework.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.framework.util.date.DateUtils.addTime; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; /** * 在线用户 Session Service 实现类 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java index 1711687..85d5451 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java @@ -5,7 +5,7 @@ import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptCreate import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptListReqVO; import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import java.util.Collection; import java.util.Collections; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java index b51cafb..5d1326d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java @@ -12,7 +12,7 @@ import org.springframework.lang.Nullable; import java.util.Collection; import java.util.List; -import static cn.iocoder.yudao.framework.util.collection.SetUtils.asSet; +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; /** * 岗位 Service 接口 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java index 8e9513f..872fa40 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.service.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService; +import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataExportReqVO; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java index 898781d..58eb32e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.dict.impl; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.dict.core.dto.DictDataRespDTO; +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java index 17e90f3..bff201e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java @@ -26,8 +26,8 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; /** * 错误码 Service 实现类 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java index 6263baf..04d908c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysOperateLogMapper; import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.framework.util.string.StrUtils; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; @@ -26,7 +26,7 @@ import java.util.concurrent.Future; import static cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; import static cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO.RESULT_MAX_LENGTH; -import static cn.iocoder.yudao.framework.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Service @Slf4j diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java index 1649a12..37fc180 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java @@ -14,7 +14,7 @@ import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum; import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysMenuProducer; import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 45a17ee..87d6d9d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java @@ -14,8 +14,8 @@ import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysPermissionP import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java index 74ff50b..74690a2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java @@ -11,7 +11,7 @@ import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImport import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import java.io.InputStream; import java.util.Collection; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index 956273d..a36b513 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -19,7 +19,7 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodegenController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodegenController.java index 3725cfe..1bfdb96 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodegenController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodegenController.java @@ -15,8 +15,8 @@ import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenColum import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java index 311f7fe..1b25084 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("表定义分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java index c8d84a9..6322f54 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java @@ -3,9 +3,9 @@ package cn.iocoder.dashboard.modules.tool.controller.test; import cn.hutool.core.thread.ThreadUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.dashboard.framework.tracer.core.annotation.BizTrace; +import cn.iocoder.yudao.framework.tracer.core.annotation.BizTrace; import cn.iocoder.dashboard.modules.tool.controller.test.vo.*; import cn.iocoder.dashboard.modules.tool.convert.test.ToolTestDemoConvert; import cn.iocoder.dashboard.modules.tool.dal.dataobject.test.ToolTestDemoDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java index 525db8c..25c3649 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.tool.controller.test.vo; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.modules.infra.enums.InfDictTypeConstants; import cn.iocoder.dashboard.modules.system.enums.SysDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java index 1809909..d655b98 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel(value = "字典类型 Excel 导出 Request VO", description = "参数和 ToolTestDemoPageReqVO 是一致的") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java index 0c007ae..053a021 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java @@ -10,7 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.util.Date; -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @ApiModel("字典类型分页 Request VO") @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java index 45f516e..848bb85 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java @@ -44,7 +44,7 @@ public class ToolTestDemoDO extends BaseDO { /** * 分类 * - * 枚举 {@link cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.TimeoutTypeEnum} + * 枚举 {@link cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.TimeoutTypeEnum} */ private Integer category; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java index e9b6592..2a270d0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.loader; import cn.hutool.core.collection.CollUtil; import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; -import cn.iocoder.yudao.framework.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.event.ApplicationReadyEvent; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java index b70f823..e959c14 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java @@ -10,9 +10,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.modules.system.framework.codegen.config.CodegenProperties; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; -import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -20,8 +20,8 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; import com.google.common.collect.Maps; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java index f50ec78..33d6962 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java @@ -16,7 +16,7 @@ import cn.iocoder.dashboard.modules.tool.dal.mysql.codegen.ToolSchemaColumnMappe import cn.iocoder.dashboard.modules.tool.dal.mysql.codegen.ToolSchemaTableMapper; import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenImportTypeEnum; import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.apache.commons.collections4.KeyValue; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/yudao-admin-server/src/main/resources/1logback-spring.xml b/yudao-admin-server/src/main/resources/1logback-spring.xml new file mode 100644 index 0000000..1d9bec6 --- /dev/null +++ b/yudao-admin-server/src/main/resources/1logback-spring.xml @@ -0,0 +1,76 @@ + + + + + + + + + +       + + + ${PATTERN_DEFAULT} + + + + + + + + + + ${PATTERN_DEFAULT} + + + + ${LOG_FILE} + + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + + + + + + 0 + + 256 + + + + + + + + ${PATTERN_DEFAULT} + + + + + + + + + + + + + + + + + + + + + + diff --git a/yudao-admin-server/src/main/resources/logback-spring.xml b/yudao-admin-server/src/main/resources/logback-spring.xml deleted file mode 100644 index 1d9bec6..0000000 --- a/yudao-admin-server/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - -       - - - ${PATTERN_DEFAULT} - - - - - - - - - - ${PATTERN_DEFAULT} - - - - ${LOG_FILE} - - - ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} - - ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} - - ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} - - ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} - - ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} - - - - - - 0 - - 256 - - - - - - - - ${PATTERN_DEFAULT} - - - - - - - - - - - - - - - - - - - - - - diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseDbAndRedisIntegrationTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseDbAndRedisIntegrationTest.java index 8c1816b..72216d2 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseDbAndRedisIntegrationTest.java +++ b/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseDbAndRedisIntegrationTest.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard; import cn.iocoder.yudao.framework.datasource.config.DataSourceConfiguration; import cn.iocoder.yudao.framework.mybatis.config.MybatisConfiguration; -import cn.iocoder.dashboard.framework.redis.config.RedisConfig; +import cn.iocoder.yudao.framework.redis.config.RedisConfig; import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java index e32eb24..287a5f3 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java +++ b/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard; -import cn.iocoder.dashboard.framework.redis.config.RedisConfig; +import cn.iocoder.yudao.framework.redis.config.RedisConfig; import org.redisson.spring.starter.RedissonAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java index 8883575..da82a2c 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java +++ b/yudao-admin-server/src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java @@ -1,8 +1,8 @@ -package cn.iocoder.dashboard.framework.redis.core.stream; +package cn.iocoder.yudao.framework.redis.core.stream; import cn.hutool.core.thread.ThreadUtil; import cn.iocoder.dashboard.BaseRedisIntegrationTest; -import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.redis.core.util.RedisMessageUtils; import cn.iocoder.dashboard.modules.system.mq.consumer.mail.SysMailSendConsumer; import cn.iocoder.dashboard.modules.system.mq.consumer.sms.SysSmsSendConsumer; import cn.iocoder.dashboard.modules.system.mq.message.mail.SysMailSendMessage; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java index f4fef60..5a6493c 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard; import cn.iocoder.dashboard.config.RedisTestConfiguration; -import cn.iocoder.dashboard.framework.redis.config.RedisConfig; +import cn.iocoder.yudao.framework.redis.config.RedisConfig; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java index a806e46..93affa2 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard; import cn.iocoder.dashboard.config.RedisTestConfiguration; -import cn.iocoder.dashboard.framework.redis.config.RedisConfig; +import cn.iocoder.yudao.framework.redis.config.RedisConfig; import org.redisson.spring.starter.RedissonAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceTest.java index d523f52..1d60143 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceTest.java @@ -11,8 +11,8 @@ import cn.iocoder.dashboard.modules.infra.dal.mysql.config.InfConfigMapper; import cn.iocoder.dashboard.modules.infra.enums.config.InfConfigTypeEnum; import cn.iocoder.dashboard.modules.infra.mq.producer.config.InfConfigProducer; import cn.iocoder.dashboard.modules.infra.service.config.impl.InfConfigServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -26,7 +26,7 @@ import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.*; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java index f15d82e..348abc8 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java @@ -8,7 +8,7 @@ import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO; import cn.iocoder.dashboard.modules.infra.dal.mysql.file.InfFileMapper; import cn.iocoder.dashboard.modules.infra.service.file.impl.InfFileServiceImpl; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -20,7 +20,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FI import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomString; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.*; @Import({InfFileServiceImpl.class, FileProperties.class}) diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java index b1124e7..a7e94dc 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java @@ -5,7 +5,7 @@ import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPo import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomString; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -25,7 +25,7 @@ import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO; import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobLogMapper; import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum; import cn.iocoder.dashboard.modules.infra.service.job.impl.InfJobLogServiceImpl; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; /** * {@link InfJobLogServiceImpl} 的单元测试 diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java index e7b3ae5..d426a1e 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java @@ -40,7 +40,7 @@ import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO; import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobMapper; import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum; import cn.iocoder.dashboard.modules.infra.service.job.impl.InfJobServiceImpl; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; /** * {@link InfJobServiceImpl} 的单元测试 diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java index f919016..89bcef3 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java @@ -12,7 +12,7 @@ import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogD import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiAccessLogMapper; import cn.iocoder.dashboard.modules.infra.service.logger.impl.InfApiAccessLogServiceImpl; import cn.iocoder.dashboard.framework.test.core.util.RandomUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -22,7 +22,7 @@ import java.util.List; import java.util.concurrent.Future; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java index 040fa40..4427244 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java @@ -12,7 +12,7 @@ import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiErrorLogMapper; import cn.iocoder.dashboard.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; import cn.iocoder.dashboard.modules.infra.service.logger.impl.InfApiErrorLogServiceImpl; import cn.iocoder.dashboard.framework.test.core.util.RandomUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -25,7 +25,7 @@ import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java index e812697..8302cf0 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java @@ -6,7 +6,7 @@ import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomDa import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomString; -import static cn.iocoder.yudao.framework.util.date.DateUtils.addTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -44,7 +44,7 @@ import cn.iocoder.dashboard.modules.system.service.logger.impl.SysLoginLogServic import cn.iocoder.dashboard.modules.system.service.user.SysUserServiceImpl; import cn.iocoder.dashboard.framework.test.core.util.AssertUtils; import cn.iocoder.dashboard.framework.test.core.util.RandomUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; /** * SysUserSessionServiceImpl Tester. diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptServiceTest.java index 193b00e..72300ec 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptServiceTest.java @@ -10,8 +10,8 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dept.SysDeptMapper; import cn.iocoder.dashboard.modules.system.enums.dept.DeptIdEnum; import cn.iocoder.dashboard.modules.system.mq.producer.dept.SysDeptProducer; import cn.iocoder.dashboard.modules.system.service.dept.impl.SysDeptServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import com.google.common.collect.Multimap; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostServiceTest.java index de3b666..641ad2d 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostServiceTest.java @@ -10,8 +10,8 @@ import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdate import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dept.SysPostMapper; import cn.iocoder.dashboard.modules.system.service.dept.impl.SysPostServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataServiceTest.java index 9fc81a8..60b0c87 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataServiceTest.java @@ -12,8 +12,8 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictDataMapper; import cn.iocoder.dashboard.modules.system.mq.producer.dict.SysDictDataProducer; import cn.iocoder.dashboard.modules.system.service.dict.impl.SysDictDataServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import com.google.common.collect.ImmutableTable; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeServiceTest.java index 2d5f4e6..a0c116c 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeServiceTest.java @@ -10,8 +10,8 @@ import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeUp import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictTypeMapper; import cn.iocoder.dashboard.modules.system.service.dict.impl.SysDictTypeServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -25,7 +25,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java index 701fb85..3dd14ba 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java @@ -12,8 +12,8 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.errorcode.SysErrorCode import cn.iocoder.dashboard.modules.system.dal.mysql.errorcode.SysErrorCodeMapper; import cn.iocoder.dashboard.modules.system.enums.errorcode.SysErrorCodeTypeEnum; import cn.iocoder.dashboard.modules.system.service.errorcode.impl.SysErrorCodeServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -30,7 +30,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.ER import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.*; /** diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java index d51b58f..e3ad2fb 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.logger; import cn.hutool.core.util.RandomUtil; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; @@ -13,7 +13,7 @@ import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; import cn.iocoder.dashboard.modules.system.service.logger.impl.SysLoginLogServiceImpl; import cn.iocoder.dashboard.framework.test.core.util.RandomUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -21,7 +21,7 @@ import javax.annotation.Resource; import java.util.List; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.assertEquals; @Import(SysLoginLogServiceImpl.class) diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java index e118ae7..ac34034 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; @@ -17,7 +17,7 @@ import cn.iocoder.dashboard.modules.system.enums.common.SysSexEnum; import cn.iocoder.dashboard.modules.system.service.logger.impl.SysOperateLogServiceImpl; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; import cn.iocoder.dashboard.framework.test.core.util.RandomUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -29,7 +29,7 @@ import java.util.concurrent.Future; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeServiceImplTest.java index 95a0f91..f3dab91 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeServiceImplTest.java @@ -10,7 +10,7 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.notice.SysNoticeDO; import cn.iocoder.dashboard.modules.system.dal.mysql.notice.SysNoticeMapper; import cn.iocoder.dashboard.modules.system.enums.notice.SysNoticeTypeEnum; import cn.iocoder.dashboard.modules.system.service.notice.impl.SysNoticeServiceImpl; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuServiceTest.java index 5659b8f..a804d46 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuServiceTest.java @@ -12,9 +12,9 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysMenuMapper; import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum; import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysMenuProducer; import cn.iocoder.dashboard.modules.system.service.permission.impl.SysMenuServiceImpl; -import cn.iocoder.yudao.framework.util.sping.SpringAopUtils; +import cn.iocoder.yudao.framework.common.util.sping.SpringAopUtils; import cn.iocoder.dashboard.framework.test.core.util.RandomUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import com.google.common.collect.Multimap; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java index 7cc87a3..fd2936e 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java @@ -13,7 +13,7 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysRoleMapper; import cn.iocoder.dashboard.modules.system.enums.permission.SysRoleTypeEnum; import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysRoleProducer; import cn.iocoder.dashboard.modules.system.service.permission.impl.SysRoleServiceImpl; -import cn.iocoder.yudao.framework.util.sping.SpringAopUtils; +import cn.iocoder.yudao.framework.common.util.sping.SpringAopUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -26,7 +26,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.object.ObjectUtils.max; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.verify; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java index 0bfff96..f233d60 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java @@ -12,8 +12,8 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO; import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsChannelMapper; import cn.iocoder.dashboard.modules.system.mq.producer.sms.SysSmsProducer; import cn.iocoder.dashboard.modules.system.service.sms.impl.SysSmsChannelServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -27,8 +27,8 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SM import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.*; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; -import static cn.iocoder.yudao.framework.util.object.ObjectUtils.max; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java index d54d497..ec778b4 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java @@ -14,8 +14,8 @@ import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsReceiveStatusEnum; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsTemplateTypeEnum; import cn.iocoder.dashboard.modules.system.service.sms.impl.SysSmsLogServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -29,7 +29,7 @@ import static cn.hutool.core.util.RandomUtil.randomBoolean; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.*; /** diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java index 92117a3..fb5cbd5 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java @@ -18,8 +18,8 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsTemplateMapper; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsTemplateTypeEnum; import cn.iocoder.dashboard.modules.system.mq.producer.sms.SysSmsProducer; import cn.iocoder.dashboard.modules.system.service.sms.impl.SysSmsTemplateServiceImpl; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import com.google.common.collect.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -37,8 +37,8 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; -import static cn.iocoder.yudao.framework.util.object.ObjectUtils.max; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java index 78b2946..88aaf51 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java @@ -17,9 +17,9 @@ import cn.iocoder.dashboard.modules.system.enums.common.SysSexEnum; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.framework.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.mockito.stubbing.Answer; import org.springframework.boot.test.mock.mockito.MockBean; @@ -38,7 +38,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.dashboard.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.assertj.core.util.Lists.newArrayList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index c2ee169..7522fff 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -70,6 +70,23 @@ + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + ${revision} + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + ${revision} + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-sms + ${revision} + + @@ -145,6 +162,12 @@ + cn.iocoder.boot + yudao-spring-boot-starter-redis + ${revision} + + + org.redisson redisson-spring-boot-starter ${redisson.version} @@ -152,12 +175,23 @@ + cn.iocoder.boot + yudao-spring-boot-starter-config + ${revision} + + + com.ctrip.framework.apollo apollo-client ${apollo.version} + + cn.iocoder.boot + yudao-spring-boot-starter-job + ${revision} + @@ -225,6 +259,12 @@ + cn.iocoder.boot + yudao-spring-boot-starter-test + ${revision} + + + org.springframework.boot spring-boot-starter-test ${spring.boot.version} @@ -257,7 +297,7 @@ cn.iocoder.boot - yudao-spring-boot-starter-operatelog + yudao-spring-boot-starter-excel ${revision} diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index cd02578..9424dde 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -13,15 +13,31 @@ yudao-common yudao-framework-all yudao-spring-boot-starter-mybatis + yudao-spring-boot-starter-redis yudao-spring-boot-starter-web yudao-spring-boot-starter-security yudao-spring-boot-starter-monitor yudao-spring-boot-starter-protection - yudao-spring-boot-starter-operatelog + yudao-spring-boot-starter-config + yudao-spring-boot-starter-job + yudao-spring-boot-starter-excel + yudao-spring-boot-starter-test + yudao-spring-boot-starter-biz-operatelog + yudao-spring-boot-starter-biz-dict + yudao-spring-boot-starter-biz-sms yudao-framework - 基础框架,各种组件的拓展 + + 该包是技术组件,每个子包,代表一个组件。每个组件包括两部分: + 1. core 包:是该组件的核心分装 + 2. config 包:是该组件基于 Spring 的配置 + + 技术组件,也分成两类: + 1. 框架组件:和我们熟悉的 MyBatis、Redis 等等的拓展 + 2. 业务组件:和业务相关的组件的封装,例如说数据字典、操作日志等等。 + 如果是业务组件,Maven 名字会包含 biz + https://github.com/YunaiV/ruoyi-vue-pro diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index 17d971c..ad84d6a 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -38,6 +38,13 @@ provided + + + org.springframework.boot + spring-boot-configuration-processor + true + + org.springframework diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java new file mode 100644 index 0000000..014742b --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.framework.common.util.collection; + +import cn.hutool.core.util.ArrayUtil; + +import java.util.function.Consumer; + +/** + * Array 工具类 + * + * @author 芋道源码 + */ +public class ArrayUtils { + + /** + * 将 object 和 newElements 合并成一个数组 + * + * @param object 对象 + * @param newElements 数组 + * @param 泛型 + * @return 结果数组 + */ + @SafeVarargs + public static Consumer[] append(Consumer object, Consumer... newElements) { + if (object == null) { + return newElements; + } + Consumer[] result = ArrayUtil.newArray(Consumer.class, 1 + newElements.length); + result[0] = object; + System.arraycopy(newElements, 0, result, 1, newElements.length); + return result; + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java new file mode 100644 index 0000000..44691c0 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -0,0 +1,150 @@ +package cn.iocoder.yudao.framework.common.util.collection; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; + +import java.util.*; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * Collection 工具类 + * + * @author 芋道源码 + */ +public class CollectionUtils { + + public static boolean containsAny(Object source, Object... targets) { + return Arrays.asList(targets).contains(source); + } + + public static boolean isAnyEmpty(Collection... collections) { + return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); + } + + public static List filterList(Collection from, Predicate predicate) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return from.stream().filter(predicate).collect(Collectors.toList()); + } + + public static List distinct(Collection from, Function keyMapper) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return distinct(from, keyMapper, (t1, t2) -> t1); + } + + public static List distinct(Collection from, Function keyMapper, BinaryOperator cover) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return new ArrayList<>(convertMap(from, keyMapper, Function.identity(), cover).values()); + } + + public static List convertList(Collection from, Function func) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return from.stream().map(func).collect(Collectors.toList()); + } + + public static Set convertSet(Collection from, Function func) { + if (CollUtil.isEmpty(from)) { + return new HashSet<>(); + } + return from.stream().map(func).collect(Collectors.toSet()); + } + + public static Map convertMap(Collection from, Function keyFunc) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return convertMap(from, keyFunc, Function.identity()); + } + + public static Map convertMap(Collection from, Function keyFunc, Supplier> supplier) { + if (CollUtil.isEmpty(from)) { + return supplier.get(); + } + return convertMap(from, keyFunc, Function.identity(), supplier); + } + + public static Map convertMap(Collection from, Function keyFunc, Function valueFunc) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1); + } + + public static Map convertMap(Collection from, Function keyFunc, Function valueFunc, BinaryOperator mergeFunction) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return convertMap(from, keyFunc, valueFunc, mergeFunction, HashMap::new); + } + + public static Map convertMap(Collection from, Function keyFunc, Function valueFunc, Supplier> supplier) { + if (CollUtil.isEmpty(from)) { + return supplier.get(); + } + return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1, supplier); + } + + public static Map convertMap(Collection from, Function keyFunc, Function valueFunc, BinaryOperator mergeFunction, Supplier> supplier) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return from.stream().collect(Collectors.toMap(keyFunc, valueFunc, mergeFunction, supplier)); + } + + public static Map> convertMultiMap(Collection from, Function keyFunc) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(t -> t, Collectors.toList()))); + } + + public static Map> convertMultiMap(Collection from, Function keyFunc, Function valueFunc) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return from.stream() + .collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toList()))); + } + + // 暂时没想好名字,先以 2 结尾噶 + public static Map> convertMultiMap2(Collection from, Function keyFunc, Function valueFunc) { + if (CollUtil.isEmpty(from)) { + return new HashMap<>(); + } + return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toSet()))); + } + + public static boolean containsAny(Collection source, Collection candidates) { + return org.springframework.util.CollectionUtils.containsAny(source, candidates); + } + + public static T getFirst(List from) { + return !CollectionUtil.isEmpty(from) ? from.get(0) : null; + } + + public static T findFirst(List from, Predicate predicate) { + if (CollUtil.isEmpty(from)) { + return null; + } + return from.stream().filter(predicate).findFirst().orElse(null); + } + + public static void addIfNotNull(Collection coll, T item) { + if (item == null) { + return; + } + coll.add(item); + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/MapUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/MapUtils.java new file mode 100644 index 0000000..f4a17b5 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/MapUtils.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.framework.common.util.collection; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +/** + * Map 工具类 + * + * @author 芋道源码 + */ +public class MapUtils { + + /** + * 从哈希表表中,获得 keys 对应的所有 value 数组 + * + * @param multimap 哈希表 + * @param keys keys + * @return value 数组 + */ + public static List getList(Multimap multimap, Collection keys) { + List result = new ArrayList<>(); + keys.forEach(k -> { + Collection values = multimap.get(k); + if (CollectionUtil.isEmpty(values)) { + return; + } + result.addAll(values); + }); + return result; + } + + /** + * 从哈希表查找到 key 对应的 value,然后进一步处理 + * 注意,如果查找到的 value 为 null 时,不进行处理 + * + * @param map 哈希表 + * @param key key + * @param consumer 进一步处理的逻辑 + */ + public static void findAndThen(Map map, K key, Consumer consumer) { + if (CollUtil.isEmpty(map)) { + return; + } + V value = map.get(key); + if (value == null) { + return; + } + consumer.accept(value); + } + + public static Map convertMap(List> keyValues) { + Map map = Maps.newLinkedHashMapWithExpectedSize(keyValues.size()); + keyValues.forEach(keyValue -> map.put(keyValue.getKey(), keyValue.getValue())); + return map; + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java new file mode 100644 index 0000000..ec38003 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.framework.common.util.collection; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Set 工具类 + * + * @author 芋道源码 + */ +public class SetUtils { + + public static Set asSet(T... objs) { + return new HashSet<>(Arrays.asList(objs)); + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java new file mode 100644 index 0000000..7837470 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.framework.common.util.date; + +import java.time.Duration; +import java.util.Calendar; +import java.util.Date; + +/** + * 时间工具类 + */ +public class DateUtils { + + /** + * 时区 - 默认 + */ + public static final String TIME_ZONE_DEFAULT = "GMT+8"; + + public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; + + public static Date addTime(Duration duration) { + return new Date(System.currentTimeMillis() + duration.toMillis()); + } + + public static boolean isExpired(Date time) { + return System.currentTimeMillis() > time.getTime(); + } + + public static long diff(Date endTime, Date startTime) { + return endTime.getTime() - startTime.getTime(); + } + + /** + * 创建指定时间 + * + * @param year 年 + * @param mouth 月 + * @param day 日 + * @return 指定时间 + */ + public static Date buildTime(int year, int mouth, int day) { + return buildTime(year, mouth, day, 0, 0, 0); + } + + /** + * 创建指定时间 + * + * @param year 年 + * @param mouth 月 + * @param day 日 + * @param hour 小时 + * @param minute 分钟 + * @param second 秒 + * @return 指定时间 + */ + public static Date buildTime(int year, int mouth, int day, + int hour, int minute, int second) { + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, mouth - 1); + calendar.set(Calendar.DAY_OF_MONTH, day); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + calendar.set(Calendar.SECOND, second); + calendar.set(Calendar.MILLISECOND, 0); // 一般情况下,都是 0 毫秒 + return calendar.getTime(); + } + + public static Date max(Date a, Date b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + return a.compareTo(b) > 0 ? a : b; + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java new file mode 100644 index 0000000..b1b641f --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.framework.common.util.json; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * JSON 工具类 + * + * @author 芋道源码 + */ +public class JsonUtils { + + private static ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 初始化 objectMapper 属性 + *

+ * 通过这样的方式,使用 Spring 创建的 ObjectMapper Bean + * + * @param objectMapper ObjectMapper 对象 + */ + public static void init(ObjectMapper objectMapper) { + JsonUtils.objectMapper = objectMapper; + } + + public static String toJsonString(Object object) { + try { + return objectMapper.writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, Class clazz) { + if (StrUtil.isEmpty(text)) { + return null; + } + try { + return objectMapper.readValue(text, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(byte[] bytes, Class clazz) { + if (ArrayUtil.isEmpty(bytes)) { + return null; + } + try { + return objectMapper.readValue(bytes, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, TypeReference typeReference) { + try { + return objectMapper.readValue(text, typeReference); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArray(String text, Class clazz) { + if (StrUtil.isEmpty(text)) { + return new ArrayList<>(); + } + try { + return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java new file mode 100644 index 0000000..81092b6 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/monitor/TracerUtils.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.framework.common.util.monitor; + +import org.apache.skywalking.apm.toolkit.trace.TraceContext; + +/** + * 链路追踪工具类 + * + * 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下 + * + * @author 芋道源码 + */ +public class TracerUtils { + + /** + * 私有化构造方法 + */ + private TracerUtils() { + } + + /** + * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。 + * 如果不存在的话为空字符串!!! + * + * @return 链路追踪编号 + */ + public static String getTraceId() { + return TraceContext.traceId(); + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java new file mode 100644 index 0000000..29a8d38 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.framework.common.util.object; + +import cn.hutool.core.util.ObjectUtil; + +import java.util.function.Consumer; + +/** + * Object 工具类 + * + * @author 芋道源码 + */ +public class ObjectUtils { + + public static T clone(T object, Consumer consumer) { + T result = ObjectUtil.clone(object); + if (result != null) { + consumer.accept(result); + } + return result; + } + + public static > T max(T obj1, T obj2) { + if (obj1 == null) { + return obj2; + } + if (obj2 == null) { + return obj1; + } + return obj1.compareTo(obj2) > 0 ? obj1 : obj2; + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/package-info.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/package-info.java new file mode 100644 index 0000000..cd8ae6b --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/package-info.java @@ -0,0 +1,7 @@ +/** + * 对于工具类的选择,优先查找 Hutool 中有没对应的方法 + * 如果没有,则自己封装对应的工具类,以 Utils 结尾,用于区分 + * + * ps:如果担心 Hutool 存在坑的问题,可以阅读 Hutool 的实现源码,以确保可靠性。并且,可以补充相关的单元测试。 + */ +package cn.iocoder.yudao.framework.common.util; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java new file mode 100644 index 0000000..eec306f --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.framework.common.util.servlet; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; + +/** + * 客户端工具类 + * + * @author 芋道源码 + */ +public class ServletUtils { + + /** + * 返回 JSON 字符串 + * + * @param response 响应 + * @param object 对象,会序列化成 JSON 字符串 + */ + @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 + public static void writeJSON(HttpServletResponse response, Object object) { + String content = JsonUtils.toJsonString(object); + ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); + } + + /** + * 返回附件 + * + * @param response 响应 + * @param filename 文件名 + * @param content 附件内容 + * @throws IOException + */ + public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { + // 设置 header 和 contentType + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + // 输出附件 + IoUtil.write(response.getOutputStream(), false, content); + } + + /** + * @param request 请求 + * @return ua + */ + public static String getUserAgent(HttpServletRequest request) { + String ua = request.getHeader("User-Agent"); + return ua != null ? ua : ""; + } + + /** + * 获得请求 + * + * @return HttpServletRequest + */ + public static HttpServletRequest getRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + if (!(requestAttributes instanceof ServletRequestAttributes)) { + return null; + } + return ((ServletRequestAttributes) requestAttributes).getRequest(); + } + + public static String getUserAgent() { + HttpServletRequest request = getRequest(); + if (request == null) { + return null; + } + return getUserAgent(request); + } + + public static String getClientIP() { + HttpServletRequest request = getRequest(); + if (request == null) { + return null; + } + return ServletUtil.getClientIP(request); + } + + public static boolean isJsonRequest(ServletRequest request) { + return StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringAopUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringAopUtils.java new file mode 100644 index 0000000..efd73c9 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringAopUtils.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.framework.common.util.sping; + +import cn.hutool.core.bean.BeanUtil; +import org.springframework.aop.framework.AdvisedSupport; +import org.springframework.aop.framework.AopProxy; +import org.springframework.aop.support.AopUtils; + +/** + * Spring AOP 工具类 + * + * 参考波克尔 http://www.bubuko.com/infodetail-3471885.html 实现 + */ +public class SpringAopUtils { + + /** + * 获取代理的目标对象 + * + * @param proxy 代理对象 + * @return 目标对象 + */ + public static Object getTarget(Object proxy) throws Exception { + // 不是代理对象 + if (!AopUtils.isAopProxy(proxy)) { + return proxy; + } + // Jdk 代理 + if (AopUtils.isJdkDynamicProxy(proxy)) { + return getJdkDynamicProxyTargetObject(proxy); + } + // Cglib 代理 + return getCglibProxyTargetObject(proxy); + } + + private static Object getCglibProxyTargetObject(Object proxy) throws Exception { + Object dynamicAdvisedInterceptor = BeanUtil.getFieldValue(proxy, "CGLIB$CALLBACK_0"); + AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(dynamicAdvisedInterceptor, "advised"); + return advisedSupport.getTargetSource().getTarget(); + } + + private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { + AopProxy aopProxy = (AopProxy) BeanUtil.getFieldValue(proxy, "h"); + AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(aopProxy, "advised"); + return advisedSupport.getTargetSource().getTarget(); + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringExpressionUtils.java new file mode 100644 index 0000000..cab09cc --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/sping/SpringExpressionUtils.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.framework.common.util.sping; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Spring EL 表达式的工具类 + * + * @author mashu + */ +public class SpringExpressionUtils { + + private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); + private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); + + private SpringExpressionUtils() { + } + + /** + * 从切面中,单个解析 EL 表达式的结果 + * + * @param joinPoint 切面点 + * @param expressionString EL 表达式数组 + * @return 执行界面 + */ + public static Object parseExpression(ProceedingJoinPoint joinPoint, String expressionString) { + Map result = parseExpressions(joinPoint, Collections.singletonList(expressionString)); + return result.get(expressionString); + } + + /** + * 从切面中,批量解析 EL 表达式的结果 + * + * @param joinPoint 切面点 + * @param expressionStrings EL 表达式数组 + * @return 结果,key 为表达式,value 为对应值 + */ + public static Map parseExpressions(ProceedingJoinPoint joinPoint, List expressionStrings) { + // 如果为空,则不进行解析 + if (CollUtil.isEmpty(expressionStrings)) { + return MapUtil.newHashMap(); + } + + // 第一步,构建解析的上下文 EvaluationContext + // 通过 joinPoint 获取被注解方法 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组 + String[] paramNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method); + // Spring 的表达式上下文对象 + EvaluationContext context = new StandardEvaluationContext(); + // 给上下文赋值 + if (ArrayUtil.isNotEmpty(paramNames)) { + Object[] args = joinPoint.getArgs(); + for (int i = 0; i < paramNames.length; i++) { + context.setVariable(paramNames[i], args[i]); + } + } + + // 第二步,逐个参数解析 + Map result = MapUtil.newHashMap(expressionStrings.size(), true); + expressionStrings.forEach(key -> { + Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context); + result.put(key, value); + }); + return result; + } +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java new file mode 100644 index 0000000..e81a522 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.common.util.string; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; + +import java.util.Map; + +/** + * 字符串工具类 + * + * @author 芋道源码 + */ +public class StrUtils { + + public static String maxLength(CharSequence str, int maxLength) { + return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好 + } + + /** + * 指定字符串的 + * @param str + * @param replaceMap + * @return + */ + public static String replace(String str, Map replaceMap) { + assert StrUtil.isNotBlank(str); + if (ObjectUtil.isEmpty(replaceMap)) { + return str; + } + String result = null; + for (String key : replaceMap.keySet()) { + result = str.replace(key, replaceMap.get(key)); + } + return result; + } + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java new file mode 100644 index 0000000..c2d56b0 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.common.validation; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.PARAMETER, + ElementType.TYPE_USE +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = InEnumValidator.class +) +public @interface InEnum { + + /** + * @return 实现 EnumValuable 接口的 + */ + Class value(); + + String message() default "必须在指定范围 {value}"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java new file mode 100644 index 0000000..6cd08ca --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.framework.common.validation; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; + +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 { + + private List values; + + @Override + public void initialize(InEnum annotation) { + IntArrayValuable[] values = annotation.value().getEnumConstants(); + if (values.length == 0) { + this.values = Collections.emptyList(); + } else { + this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList()); + } + } + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + // 为空时,默认不校验,即认为通过 + if (value == null) { + return true; + } + // 校验通过 + if (values.contains(value)) { + return true; + } + // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值) + context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 + context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate() + .replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句 + return false; + } + +} + diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/package-info.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/package-info.java new file mode 100644 index 0000000..aa95c69 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/package-info.java @@ -0,0 +1,4 @@ +/** + * 使用 Hibernate Validator 实现参数校验 + */ +package cn.iocoder.yudao.framework.common.validation; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/ArrayUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/ArrayUtils.java deleted file mode 100644 index 732c63c..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/ArrayUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.framework.util.collection; - -import cn.hutool.core.util.ArrayUtil; - -import java.util.function.Consumer; - -/** - * Array 工具类 - * - * @author 芋道源码 - */ -public class ArrayUtils { - - /** - * 将 object 和 newElements 合并成一个数组 - * - * @param object 对象 - * @param newElements 数组 - * @param 泛型 - * @return 结果数组 - */ - @SafeVarargs - public static Consumer[] append(Consumer object, Consumer... newElements) { - if (object == null) { - return newElements; - } - Consumer[] result = ArrayUtil.newArray(Consumer.class, 1 + newElements.length); - result[0] = object; - System.arraycopy(newElements, 0, result, 1, newElements.length); - return result; - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/CollectionUtils.java deleted file mode 100644 index 0781c2b..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/CollectionUtils.java +++ /dev/null @@ -1,150 +0,0 @@ -package cn.iocoder.yudao.framework.util.collection; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; - -import java.util.*; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -/** - * Collection 工具类 - * - * @author 芋道源码 - */ -public class CollectionUtils { - - public static boolean containsAny(Object source, Object... targets) { - return Arrays.asList(targets).contains(source); - } - - public static boolean isAnyEmpty(Collection... collections) { - return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); - } - - public static List filterList(Collection from, Predicate predicate) { - if (CollUtil.isEmpty(from)) { - return new ArrayList<>(); - } - return from.stream().filter(predicate).collect(Collectors.toList()); - } - - public static List distinct(Collection from, Function keyMapper) { - if (CollUtil.isEmpty(from)) { - return new ArrayList<>(); - } - return distinct(from, keyMapper, (t1, t2) -> t1); - } - - public static List distinct(Collection from, Function keyMapper, BinaryOperator cover) { - if (CollUtil.isEmpty(from)) { - return new ArrayList<>(); - } - return new ArrayList<>(convertMap(from, keyMapper, Function.identity(), cover).values()); - } - - public static List convertList(Collection from, Function func) { - if (CollUtil.isEmpty(from)) { - return new ArrayList<>(); - } - return from.stream().map(func).collect(Collectors.toList()); - } - - public static Set convertSet(Collection from, Function func) { - if (CollUtil.isEmpty(from)) { - return new HashSet<>(); - } - return from.stream().map(func).collect(Collectors.toSet()); - } - - public static Map convertMap(Collection from, Function keyFunc) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return convertMap(from, keyFunc, Function.identity()); - } - - public static Map convertMap(Collection from, Function keyFunc, Supplier> supplier) { - if (CollUtil.isEmpty(from)) { - return supplier.get(); - } - return convertMap(from, keyFunc, Function.identity(), supplier); - } - - public static Map convertMap(Collection from, Function keyFunc, Function valueFunc) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1); - } - - public static Map convertMap(Collection from, Function keyFunc, Function valueFunc, BinaryOperator mergeFunction) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return convertMap(from, keyFunc, valueFunc, mergeFunction, HashMap::new); - } - - public static Map convertMap(Collection from, Function keyFunc, Function valueFunc, Supplier> supplier) { - if (CollUtil.isEmpty(from)) { - return supplier.get(); - } - return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1, supplier); - } - - public static Map convertMap(Collection from, Function keyFunc, Function valueFunc, BinaryOperator mergeFunction, Supplier> supplier) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return from.stream().collect(Collectors.toMap(keyFunc, valueFunc, mergeFunction, supplier)); - } - - public static Map> convertMultiMap(Collection from, Function keyFunc) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(t -> t, Collectors.toList()))); - } - - public static Map> convertMultiMap(Collection from, Function keyFunc, Function valueFunc) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return from.stream() - .collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toList()))); - } - - // 暂时没想好名字,先以 2 结尾噶 - public static Map> convertMultiMap2(Collection from, Function keyFunc, Function valueFunc) { - if (CollUtil.isEmpty(from)) { - return new HashMap<>(); - } - return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toSet()))); - } - - public static boolean containsAny(Collection source, Collection candidates) { - return org.springframework.util.CollectionUtils.containsAny(source, candidates); - } - - public static T getFirst(List from) { - return !CollectionUtil.isEmpty(from) ? from.get(0) : null; - } - - public static T findFirst(List from, Predicate predicate) { - if (CollUtil.isEmpty(from)) { - return null; - } - return from.stream().filter(predicate).findFirst().orElse(null); - } - - public static void addIfNotNull(Collection coll, T item) { - if (item == null) { - return; - } - coll.add(item); - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/MapUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/MapUtils.java deleted file mode 100644 index 043b426..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/MapUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.framework.util.collection; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -/** - * Map 工具类 - * - * @author 芋道源码 - */ -public class MapUtils { - - /** - * 从哈希表表中,获得 keys 对应的所有 value 数组 - * - * @param multimap 哈希表 - * @param keys keys - * @return value 数组 - */ - public static List getList(Multimap multimap, Collection keys) { - List result = new ArrayList<>(); - keys.forEach(k -> { - Collection values = multimap.get(k); - if (CollectionUtil.isEmpty(values)) { - return; - } - result.addAll(values); - }); - return result; - } - - /** - * 从哈希表查找到 key 对应的 value,然后进一步处理 - * 注意,如果查找到的 value 为 null 时,不进行处理 - * - * @param map 哈希表 - * @param key key - * @param consumer 进一步处理的逻辑 - */ - public static void findAndThen(Map map, K key, Consumer consumer) { - if (CollUtil.isEmpty(map)) { - return; - } - V value = map.get(key); - if (value == null) { - return; - } - consumer.accept(value); - } - - public static Map convertMap(List> keyValues) { - Map map = Maps.newLinkedHashMapWithExpectedSize(keyValues.size()); - keyValues.forEach(keyValue -> map.put(keyValue.getKey(), keyValue.getValue())); - return map; - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/SetUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/SetUtils.java deleted file mode 100644 index fa7cd60..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/collection/SetUtils.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.framework.util.collection; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * Set 工具类 - * - * @author 芋道源码 - */ -public class SetUtils { - - public static Set asSet(T... objs) { - return new HashSet<>(Arrays.asList(objs)); - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/date/DateUtils.java deleted file mode 100644 index bc585bc..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/date/DateUtils.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.iocoder.yudao.framework.util.date; - -import java.time.Duration; -import java.util.Calendar; -import java.util.Date; - -/** - * 时间工具类 - */ -public class DateUtils { - - /** - * 时区 - 默认 - */ - public static final String TIME_ZONE_DEFAULT = "GMT+8"; - - public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; - - public static Date addTime(Duration duration) { - return new Date(System.currentTimeMillis() + duration.toMillis()); - } - - public static boolean isExpired(Date time) { - return System.currentTimeMillis() > time.getTime(); - } - - public static long diff(Date endTime, Date startTime) { - return endTime.getTime() - startTime.getTime(); - } - - /** - * 创建指定时间 - * - * @param year 年 - * @param mouth 月 - * @param day 日 - * @return 指定时间 - */ - public static Date buildTime(int year, int mouth, int day) { - return buildTime(year, mouth, day, 0, 0, 0); - } - - /** - * 创建指定时间 - * - * @param year 年 - * @param mouth 月 - * @param day 日 - * @param hour 小时 - * @param minute 分钟 - * @param second 秒 - * @return 指定时间 - */ - public static Date buildTime(int year, int mouth, int day, - int hour, int minute, int second) { - Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.YEAR, year); - calendar.set(Calendar.MONTH, mouth - 1); - calendar.set(Calendar.DAY_OF_MONTH, day); - calendar.set(Calendar.HOUR_OF_DAY, hour); - calendar.set(Calendar.MINUTE, minute); - calendar.set(Calendar.SECOND, second); - calendar.set(Calendar.MILLISECOND, 0); // 一般情况下,都是 0 毫秒 - return calendar.getTime(); - } - - public static Date max(Date a, Date b) { - if (a == null) { - return b; - } - if (b == null) { - return a; - } - return a.compareTo(b) > 0 ? a : b; - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/json/JsonUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/json/JsonUtils.java deleted file mode 100644 index 3bf7f1f..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/json/JsonUtils.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.iocoder.yudao.framework.util.json; - -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.StrUtil; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * JSON 工具类 - * - * @author 芋道源码 - */ -public class JsonUtils { - - private static ObjectMapper objectMapper = new ObjectMapper(); - - /** - * 初始化 objectMapper 属性 - *

- * 通过这样的方式,使用 Spring 创建的 ObjectMapper Bean - * - * @param objectMapper ObjectMapper 对象 - */ - public static void init(ObjectMapper objectMapper) { - JsonUtils.objectMapper = objectMapper; - } - - public static String toJsonString(Object object) { - try { - return objectMapper.writeValueAsString(object); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - public static T parseObject(String text, Class clazz) { - if (StrUtil.isEmpty(text)) { - return null; - } - try { - return objectMapper.readValue(text, clazz); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static T parseObject(byte[] bytes, Class clazz) { - if (ArrayUtil.isEmpty(bytes)) { - return null; - } - try { - return objectMapper.readValue(bytes, clazz); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static T parseObject(String text, TypeReference typeReference) { - try { - return objectMapper.readValue(text, typeReference); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static List parseArray(String text, Class clazz) { - if (StrUtil.isEmpty(text)) { - return new ArrayList<>(); - } - try { - return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java deleted file mode 100644 index 384a3df..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.framework.util.monitor; - -import org.apache.skywalking.apm.toolkit.trace.TraceContext; - -/** - * 链路追踪工具类 - * - * 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下 - * - * @author 芋道源码 - */ -public class TracerUtils { - - /** - * 私有化构造方法 - */ - private TracerUtils() { - } - - /** - * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。 - * 如果不存在的话为空字符串!!! - * - * @return 链路追踪编号 - */ - public static String getTraceId() { - return TraceContext.traceId(); - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/object/ObjectUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/object/ObjectUtils.java deleted file mode 100644 index 985c4e4..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/object/ObjectUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.framework.util.object; - -import cn.hutool.core.util.ObjectUtil; - -import java.util.function.Consumer; - -/** - * Object 工具类 - * - * @author 芋道源码 - */ -public class ObjectUtils { - - public static T clone(T object, Consumer consumer) { - T result = ObjectUtil.clone(object); - if (result != null) { - consumer.accept(result); - } - return result; - } - - public static > T max(T obj1, T obj2) { - if (obj1 == null) { - return obj2; - } - if (obj2 == null) { - return obj1; - } - return obj1.compareTo(obj2) > 0 ? obj1 : obj2; - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/package-info.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/package-info.java deleted file mode 100644 index 92c3bf2..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * 对于工具类的选择,优先查找 Hutool 中有没对应的方法 - * 如果没有,则自己封装对应的工具类,以 Utils 结尾,用于区分 - * - * ps:如果担心 Hutool 存在坑的问题,可以阅读 Hutool 的实现源码,以确保可靠性。并且,可以补充相关的单元测试。 - */ -package cn.iocoder.yudao.framework.util; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/servlet/ServletUtils.java deleted file mode 100644 index 50bc601..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/servlet/ServletUtils.java +++ /dev/null @@ -1,95 +0,0 @@ -package cn.iocoder.yudao.framework.util.servlet; - -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import org.springframework.http.MediaType; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.URLEncoder; - -/** - * 客户端工具类 - * - * @author 芋道源码 - */ -public class ServletUtils { - - /** - * 返回 JSON 字符串 - * - * @param response 响应 - * @param object 对象,会序列化成 JSON 字符串 - */ - @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 - public static void writeJSON(HttpServletResponse response, Object object) { - String content = JsonUtils.toJsonString(object); - ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); - } - - /** - * 返回附件 - * - * @param response 响应 - * @param filename 文件名 - * @param content 附件内容 - * @throws IOException - */ - public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { - // 设置 header 和 contentType - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - // 输出附件 - IoUtil.write(response.getOutputStream(), false, content); - } - - /** - * @param request 请求 - * @return ua - */ - public static String getUserAgent(HttpServletRequest request) { - String ua = request.getHeader("User-Agent"); - return ua != null ? ua : ""; - } - - /** - * 获得请求 - * - * @return HttpServletRequest - */ - public static HttpServletRequest getRequest() { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (!(requestAttributes instanceof ServletRequestAttributes)) { - return null; - } - return ((ServletRequestAttributes) requestAttributes).getRequest(); - } - - public static String getUserAgent() { - HttpServletRequest request = getRequest(); - if (request == null) { - return null; - } - return getUserAgent(request); - } - - public static String getClientIP() { - HttpServletRequest request = getRequest(); - if (request == null) { - return null; - } - return ServletUtil.getClientIP(request); - } - - public static boolean isJsonRequest(ServletRequest request) { - return StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringAopUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringAopUtils.java deleted file mode 100644 index 4565ea5..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringAopUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.framework.util.sping; - -import cn.hutool.core.bean.BeanUtil; -import org.springframework.aop.framework.AdvisedSupport; -import org.springframework.aop.framework.AopProxy; -import org.springframework.aop.support.AopUtils; - -/** - * Spring AOP 工具类 - * - * 参考波克尔 http://www.bubuko.com/infodetail-3471885.html 实现 - */ -public class SpringAopUtils { - - /** - * 获取代理的目标对象 - * - * @param proxy 代理对象 - * @return 目标对象 - */ - public static Object getTarget(Object proxy) throws Exception { - // 不是代理对象 - if (!AopUtils.isAopProxy(proxy)) { - return proxy; - } - // Jdk 代理 - if (AopUtils.isJdkDynamicProxy(proxy)) { - return getJdkDynamicProxyTargetObject(proxy); - } - // Cglib 代理 - return getCglibProxyTargetObject(proxy); - } - - private static Object getCglibProxyTargetObject(Object proxy) throws Exception { - Object dynamicAdvisedInterceptor = BeanUtil.getFieldValue(proxy, "CGLIB$CALLBACK_0"); - AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(dynamicAdvisedInterceptor, "advised"); - return advisedSupport.getTargetSource().getTarget(); - } - - private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { - AopProxy aopProxy = (AopProxy) BeanUtil.getFieldValue(proxy, "h"); - AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(aopProxy, "advised"); - return advisedSupport.getTargetSource().getTarget(); - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringExpressionUtils.java deleted file mode 100644 index d836399..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/sping/SpringExpressionUtils.java +++ /dev/null @@ -1,82 +0,0 @@ -package cn.iocoder.yudao.framework.util.sping; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ArrayUtil; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.core.DefaultParameterNameDiscoverer; -import org.springframework.core.ParameterNameDiscoverer; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Spring EL 表达式的工具类 - * - * @author mashu - */ -public class SpringExpressionUtils { - - private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); - private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); - - private SpringExpressionUtils() { - } - - /** - * 从切面中,单个解析 EL 表达式的结果 - * - * @param joinPoint 切面点 - * @param expressionString EL 表达式数组 - * @return 执行界面 - */ - public static Object parseExpression(ProceedingJoinPoint joinPoint, String expressionString) { - Map result = parseExpressions(joinPoint, Collections.singletonList(expressionString)); - return result.get(expressionString); - } - - /** - * 从切面中,批量解析 EL 表达式的结果 - * - * @param joinPoint 切面点 - * @param expressionStrings EL 表达式数组 - * @return 结果,key 为表达式,value 为对应值 - */ - public static Map parseExpressions(ProceedingJoinPoint joinPoint, List expressionStrings) { - // 如果为空,则不进行解析 - if (CollUtil.isEmpty(expressionStrings)) { - return MapUtil.newHashMap(); - } - - // 第一步,构建解析的上下文 EvaluationContext - // 通过 joinPoint 获取被注解方法 - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - Method method = methodSignature.getMethod(); - // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组 - String[] paramNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method); - // Spring 的表达式上下文对象 - EvaluationContext context = new StandardEvaluationContext(); - // 给上下文赋值 - if (ArrayUtil.isNotEmpty(paramNames)) { - Object[] args = joinPoint.getArgs(); - for (int i = 0; i < paramNames.length; i++) { - context.setVariable(paramNames[i], args[i]); - } - } - - // 第二步,逐个参数解析 - Map result = MapUtil.newHashMap(expressionStrings.size(), true); - expressionStrings.forEach(key -> { - Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context); - result.put(key, value); - }); - return result; - } -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/string/StrUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/string/StrUtils.java deleted file mode 100644 index 171d82b..0000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/string/StrUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.framework.util.string; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; - -import java.util.Map; - -/** - * 字符串工具类 - * - * @author 芋道源码 - */ -public class StrUtils { - - public static String maxLength(CharSequence str, int maxLength) { - return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好 - } - - /** - * 指定字符串的 - * @param str - * @param replaceMap - * @return - */ - public static String replace(String str, Map replaceMap) { - assert StrUtil.isNotBlank(str); - if (ObjectUtil.isEmpty(replaceMap)) { - return str; - } - String result = null; - for (String key : replaceMap.keySet()) { - result = str.replace(key, replaceMap.get(key)); - } - return result; - } - -} diff --git a/yudao-framework/yudao-common/《芋道 Spring Boot 参数校验 Validation 入门》.md b/yudao-framework/yudao-common/《芋道 Spring Boot 参数校验 Validation 入门》.md new file mode 100644 index 0000000..b2c2cf8 --- /dev/null +++ b/yudao-framework/yudao-common/《芋道 Spring Boot 参数校验 Validation 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-framework-all/pom.xml b/yudao-framework/yudao-framework-all/pom.xml deleted file mode 100644 index 5bca4c8..0000000 --- a/yudao-framework/yudao-framework-all/pom.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - - cn.iocoder.boot - yudao-framework - ${revision} - - 4.0.0 - yudao-framework-all - jar - - ${artifactId} - 基础框架,各种组件的拓展 - https://github.com/YunaiV/ruoyi-vue-pro - - - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - org.redisson - redisson-spring-boot-starter - - - - - com.ctrip.framework.apollo - apollo-client - - - - - org.springframework.boot - spring-boot-starter-quartz - - - - - com.baomidou - lock4j-redisson-spring-boot-starter - - - - io.github.resilience4j - resilience4j-spring-boot2 - - - - - org.apache.skywalking - apm-toolkit-trace - - - org.apache.skywalking - apm-toolkit-logback-1.x - - - org.apache.skywalking - apm-toolkit-opentracing - - - - de.codecentric - spring-boot-admin-starter-server - - - de.codecentric - spring-boot-admin-starter-client - - - - - org.springframework.boot - spring-boot-starter-test - provided - true - - - - com.h2database - h2 - true - - - - com.github.fppt - jedis-mock - provided - true - - - - uk.co.jemos.podam - podam - provided - true - - - - - cn.iocoder.boot - yudao-common - - - - com.alibaba - easyexcel - - - - org.apache.velocity - velocity-engine-core - - - - cn.smallbun.screw - screw-core - - - - - - - com.yunpian.sdk - yunpian-java-sdk - - - - com.aliyun - aliyun-java-sdk-core - - - com.aliyun - aliyun-java-sdk-dysmsapi - - - - - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java deleted file mode 100644 index 8e0fe57..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.core; - -/** - * 针对 {@link com.ctrip.framework.apollo.core.ConfigConsts} 的补充,主要增加: - * - * 1. apollo.jdbc.* 配置项的枚举 - * - * @author 芋道源码 - */ -public class ConfigConsts { - - /** - * {@link cn.iocoder.dashboard.framework.apollo.internals.ConfigFrameworkDAO} 的实现类 - */ - public static final String APOLLO_JDBC_DAO = "apollo.jdbc.dao"; - public static final String APOLLO_JDBC_URL = "apollo.jdbc.url"; - public static final String APOLLO_JDBC_USERNAME = "apollo.jdbc.username"; - public static final String APOLLO_JDBC_PASSWORD = "apollo.jdbc.password"; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java deleted file mode 100644 index 8f46b2d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.internals; - -import cn.iocoder.dashboard.framework.apollo.internals.dto.ConfigRespDTO; - -import java.util.Date; -import java.util.List; - -/** - * 配置 Framework DAO 接口 - * - * 注意,实现类必须提供 (String jdbcUrl, String username, String password) 构造方法 - * - * @author 芋道源码 - */ -public interface ConfigFrameworkDAO { - - /** - * 查询是否存在比 maxUpdateTime 更新记录更晚的配置 - * - * @param maxUpdateTime 最大更新时间 - * @return 是否存在 - */ - boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime); - - /** - * 查询配置列表 - * - * @return 配置列表 - */ - List selectList(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java deleted file mode 100644 index 97726d3..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java +++ /dev/null @@ -1,183 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.internals; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ClassUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.dashboard.framework.apollo.core.ConfigConsts; -import cn.iocoder.dashboard.framework.apollo.internals.dto.ConfigRespDTO; -import com.ctrip.framework.apollo.Apollo; -import com.ctrip.framework.apollo.build.ApolloInjector; -import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; -import com.ctrip.framework.apollo.enums.ConfigSourceType; -import com.ctrip.framework.apollo.internals.AbstractConfigRepository; -import com.ctrip.framework.apollo.internals.ConfigRepository; -import com.ctrip.framework.apollo.tracer.Tracer; -import com.ctrip.framework.apollo.util.ConfigUtil; -import com.ctrip.framework.apollo.util.factory.PropertiesFactory; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; - -import java.lang.reflect.Constructor; -import java.util.Comparator; -import java.util.Date; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -@Slf4j -public class DBConfigRepository extends AbstractConfigRepository { - - private final static ScheduledExecutorService m_executorService; - - private static DBConfigRepository INSTANCE; - - static { - m_executorService = Executors.newScheduledThreadPool(1, - ApolloThreadFactory.create(DBConfigRepository.class.getSimpleName(), true)); - } - - private final ConfigUtil m_configUtil; - private final PropertiesFactory propertiesFactory; - private final String m_namespace; - - /** - * 配置缓存,使用 Properties 存储 - */ - private volatile Properties m_configCache; - /** - * 缓存配置的最大更新时间,用于后续的增量轮询,判断是否有更新 - */ - private volatile Date maxUpdateTime; - - /** - * 配置读取 DAO - */ - private final ConfigFrameworkDAO configFrameworkDAO; - - public DBConfigRepository(String namespace) { - // 初始化变量 - this.m_namespace = namespace; - this.propertiesFactory = ApolloInjector.getInstance(PropertiesFactory.class); - this.m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); - // 初始化 DB - this.configFrameworkDAO = createConfigFrameworkDAO(); - - // 初始化加载 - this.trySync(); - // 初始化定时任务 - this.schedulePeriodicRefresh(); - - // 设置单例 - INSTANCE = this; - } - - @SneakyThrows - private static ConfigFrameworkDAO createConfigFrameworkDAO() { - String dao = System.getProperty(ConfigConsts.APOLLO_JDBC_DAO); - String url = System.getProperty(ConfigConsts.APOLLO_JDBC_URL); - String username = System.getProperty(ConfigConsts.APOLLO_JDBC_USERNAME); - String password = System.getProperty(ConfigConsts.APOLLO_JDBC_PASSWORD); - // 创建 DBConfigRepository 对象 - Class clazz = ClassUtil.loadClass(dao); - Constructor constructor = ReflectUtil.getConstructor(clazz, String.class, String.class, String.class); - return constructor.newInstance(url, username, password); - } - - /** - * 通知同步, - */ - public static void noticeSync() { - // 提交到线程池中,避免和 schedulePeriodicRefresh 并发问题 - m_executorService.submit(() -> { - INSTANCE.trySync(); - }); - } - - @Override - protected void sync() { - // 第一步,尝试获取配置 - List configs = this.loadConfigIfUpdate(this.maxUpdateTime); - if (CollUtil.isEmpty(configs)) { // 如果没有更新,则返回 - return; - } - - // 第二步,构建新的 Properties - Properties newProperties = this.buildProperties(configs); - this.m_configCache = newProperties; - // 第三步,获取最大的配置时间 - assert configs.size() > 0; // 断言,避免告警 - this.maxUpdateTime = configs.stream().max(Comparator.comparing(ConfigRespDTO::getUpdateTime)).get().getUpdateTime(); - // 第四部,触发配置刷新!重要!!!! - super.fireRepositoryChange(m_namespace, newProperties); - log.info("[sync][缓存配置,数量为:{}]", configs.size()); - } - - @Override - public Properties getConfig() { - // 兜底,避免可能存在配置为 null 的情况 - if (m_configCache == null) { - this.trySync(); - } - // 返回配置 - return m_configCache; - } - - @Override - public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) { - // 啥事不做 - } - - @Override - public ConfigSourceType getSourceType() { - return ConfigSourceType.REMOTE; - } - - private Properties buildProperties(List configs) { - Properties properties = propertiesFactory.getPropertiesInstance(); - configs.stream().filter(ConfigRespDTO::getDeleted) // 过滤掉被删除的配置 - .forEach(config -> properties.put(config.getKey(), config.getValue())); - return properties; - } - - // ========== 定时器相关操作 ========== - - private void schedulePeriodicRefresh() { - log.debug("Schedule periodic refresh with interval: {} {}", - m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit()); - m_executorService.scheduleAtFixedRate(() -> { - Tracer.logEvent("Apollo.ConfigService", String.format("periodicRefresh: %s", m_namespace)); - log.debug("refresh config for namespace: {}", m_namespace); - - // 执行同步. 内部已经 try catch 掉异常,无需在处理 - trySync(); - - Tracer.logEvent("Apollo.Client.Version", Apollo.VERSION); - }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(), - m_configUtil.getRefreshIntervalTimeUnit()); - } - - // ========== 数据库相关操作 ========== - - /** - * 如果配置发生变化,从数据库中获取最新的全量配置。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前配置的最大更新时间 - * @return 配置列表 - */ - private List loadConfigIfUpdate(Date maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadConfigIfUpdate][首次加载全量配置]"); - } else { // 判断数据库中是否有更新的配置 - if (!configFrameworkDAO.selectExistsByUpdateTimeAfter(maxUpdateTime)) { - return null; - } - log.info("[loadConfigIfUpdate][增量加载全量配置]"); - } - // 第二步,如果有更新,则从数据库加载所有配置 - return configFrameworkDAO.selectList(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java deleted file mode 100644 index 587a850..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.internals; - -import cn.iocoder.dashboard.framework.apollo.spi.DBConfigFactory; -import com.ctrip.framework.apollo.exceptions.ApolloConfigException; -import com.ctrip.framework.apollo.internals.*; -import com.ctrip.framework.apollo.spi.*; -import com.ctrip.framework.apollo.tracer.Tracer; -import com.ctrip.framework.apollo.util.ConfigUtil; -import com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory; -import com.ctrip.framework.apollo.util.factory.PropertiesFactory; -import com.ctrip.framework.apollo.util.http.HttpUtil; -import com.ctrip.framework.apollo.util.yaml.YamlParser; -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Singleton; - -/** - * Guice injector - * - * 基于 Guice 注入器实现类 - * - * @author Jason Song(song_s@ctrip.com) - */ -public class DefaultXInjector implements Injector { - - private final com.google.inject.Injector m_injector; - - public DefaultXInjector() { - try { - m_injector = Guice.createInjector(new ApolloModule()); - } catch (Throwable ex) { - ApolloConfigException exception = new ApolloConfigException("Unable to initialize Guice Injector!", ex); - Tracer.logError(exception); - throw exception; - } - } - - @Override - public T getInstance(Class clazz) { - try { - return m_injector.getInstance(clazz); - } catch (Throwable ex) { - Tracer.logError(ex); - throw new ApolloConfigException(String.format("Unable to load instance for %s!", clazz.getName()), ex); - } - } - - @Override - public T getInstance(Class clazz, String name) { - // Guice does not support get instance by type and name - return null; - } - - private static class ApolloModule extends AbstractModule { - - @Override - protected void configure() { - bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class); - bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class); - bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class); - - // 自定义 ConfigFactory 实现,使用 DB 作为数据源 - bind(ConfigFactory.class).to(DBConfigFactory.class).in(Singleton.class); - - bind(ConfigUtil.class).in(Singleton.class); - bind(HttpUtil.class).in(Singleton.class); - bind(ConfigServiceLocator.class).in(Singleton.class); - bind(RemoteConfigLongPollService.class).in(Singleton.class); - bind(YamlParser.class).in(Singleton.class); - bind(PropertiesFactory.class).to(DefaultPropertiesFactory.class).in(Singleton.class); - } - - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java deleted file mode 100644 index 3945dfb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.internals.dto; - -import lombok.Data; - -import java.util.Date; - -/** - * 配置 Response DTO - * - * @author 芋道源码 - */ -@Data -public class ConfigRespDTO { - - /** - * 参数键名 - */ - private String key; - /** - * 参数键值 - */ - private String value; - - /** - * 是否删除 - */ - private Boolean deleted; - /** - * 更新时间 - */ - private Date updateTime; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java deleted file mode 100644 index 0330411..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 配置中心客户端,基于 Apollo Client 进行简化 - * - * 差别在于,我们使用 {@link cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO} 表作为配置源。 - * 当然,功能肯定也会相对少些,满足最小化诉求。 - * - * 1. 项目初始化时,可以使用 SysConfigDO 表的配置 - * 2. 使用 Spring @Value 可以注入属性 - * 3. SysConfigDO 表的配置修改时,注入到 @Value 的属性可以刷新 - * - * 另外,整个包结构会参考 Apollo 为主,方便维护与理解 - */ -package cn.iocoder.dashboard.framework.apollo; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java deleted file mode 100644 index bfa9e53..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.spi; - -import cn.iocoder.dashboard.framework.apollo.internals.DBConfigRepository; -import com.ctrip.framework.apollo.Config; -import com.ctrip.framework.apollo.ConfigFile; -import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; -import com.ctrip.framework.apollo.internals.ConfigRepository; -import com.ctrip.framework.apollo.internals.DefaultConfig; -import com.ctrip.framework.apollo.spi.ConfigFactory; - -/** - * 基于 DB 的 ConfigFactory 实现类 - * - * @author 芋道源码 - */ -public class DBConfigFactory implements ConfigFactory { - - @Override - public Config create(String namespace) { - return new DefaultConfig(namespace, this.createDBConfigRepository(namespace)); - } - - @Override - public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) { - throw new UnsupportedOperationException("暂不支持 Apollo 配置文件"); - } - - private ConfigRepository createDBConfigRepository(String namespace) { - return new DBConfigRepository(namespace); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java deleted file mode 100644 index 47af6b5..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.iocoder.dashboard.framework.apollo.spring.boot; - -import cn.iocoder.dashboard.framework.apollo.core.ConfigConsts; -import com.google.common.base.Strings; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * 对 {@link com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer} 的补充,目前的目的有: - * - * 1. 将自定义的 apollo.jdbc 设置到 System 变量中 - * - * @author 芋道源码 - */ -public class ApolloApplicationContextInitializer implements EnvironmentPostProcessor, Ordered { - - /** - * 优先级更高,要早于 Apollo 的 ApolloApplicationContextInitializer 的初始化 - */ - public static final int DEFAULT_ORDER = -1; - - private int order = DEFAULT_ORDER; - - private static final String[] APOLLO_SYSTEM_PROPERTIES = {ConfigConsts.APOLLO_JDBC_DAO, - ConfigConsts.APOLLO_JDBC_URL, ConfigConsts.APOLLO_JDBC_USERNAME, ConfigConsts.APOLLO_JDBC_PASSWORD}; - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - initializeSystemProperty(environment); - } - - /** - * To fill system properties from environment config - */ - void initializeSystemProperty(ConfigurableEnvironment environment) { - for (String propertyName : APOLLO_SYSTEM_PROPERTIES) { - fillSystemPropertyFromEnvironment(environment, propertyName); - } - } - - private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environment, String propertyName) { - if (System.getProperty(propertyName) != null) { - return; - } - String propertyValue = environment.getProperty(propertyName); - if (Strings.isNullOrEmpty(propertyValue)) { - return; - } - System.setProperty(propertyName, propertyValue); - } - - @Override - public int getOrder() { - return order; - } - - public void setOrder(int order) { - this.order = order; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java deleted file mode 100644 index 58096d5..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.dashboard.framework.async.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableAsync; - -@Configuration -@EnableAsync -public class AsyncConfiguration { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java deleted file mode 100644 index 3753589..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 异步执行,基于 Spring @Async 实现 - */ -package cn.iocoder.dashboard.framework.async; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md deleted file mode 100644 index 5822b83..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/async/《芋道 Spring Boot 异步任务入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/config/DictConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/config/DictConfiguration.java deleted file mode 100644 index d2ff54d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/config/DictConfiguration.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.dashboard.framework.dict.config; - -import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService; -import cn.iocoder.dashboard.framework.dict.core.util.DictUtils; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class DictConfiguration { - - @Bean - @SuppressWarnings("InstantiationOfUtilityClass") - public DictUtils dictUtils(DictDataFrameworkService service) { - DictUtils.init(service); - return new DictUtils(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/dto/DictDataRespDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/dto/DictDataRespDTO.java deleted file mode 100644 index 886b05f..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/dto/DictDataRespDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.dashboard.framework.dict.core.dto; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import lombok.Data; - -/** - * 字典数据 Response DTO - * - * @author 芋道源码 - */ -@Data -public class DictDataRespDTO { - - /** - * 字典标签 - */ - private String label; - /** - * 字典值 - */ - private String value; - /** - * 字典类型 - */ - private String dictType; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/service/DictDataFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/service/DictDataFrameworkService.java deleted file mode 100644 index e312411..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/service/DictDataFrameworkService.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.dashboard.framework.dict.core.service; - -import cn.iocoder.dashboard.framework.dict.core.dto.DictDataRespDTO; - -import java.util.List; - -public interface DictDataFrameworkService { - - /** - * 获得指定的字典数据,从缓存中 - * - * @param type 字典类型 - * @param value 字典数据值 - * @return 字典数据 - */ - DictDataRespDTO getDictDataFromCache(String type, String value); - - /** - * 解析获得指定的字典数据,从缓存中 - * - * @param type 字典类型 - * @param label 字典数据标签 - * @return 字典数据 - */ - DictDataRespDTO parseDictDataFromCache(String type, String label); - - /** - * 获得指定类型的字典数据,从缓存中 - * - * @param type 字典类型 - * @return 字典数据列表 - */ - List listDictDatasFromCache(String type); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/util/DictUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/util/DictUtils.java deleted file mode 100644 index b80f742..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/core/util/DictUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.dict.core.util; - -import cn.iocoder.dashboard.framework.dict.core.dto.DictDataRespDTO; -import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService; -import lombok.extern.slf4j.Slf4j; - -/** - * 字典工具类 - */ -@Slf4j -public class DictUtils { - - private static DictDataFrameworkService service; - - public static void init(DictDataFrameworkService service) { - DictUtils.service = service; - log.info("[init][初始化 DictUtils 成功]"); - } - - public static DictDataRespDTO getDictDataFromCache(String type, String value) { - return service.getDictDataFromCache(type, value); - } - - public static DictDataRespDTO parseDictDataFromCache(String type, String label) { - return service.getDictDataFromCache(type, label); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/package-info.java deleted file mode 100644 index adc37f7..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/dict/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 字典数据模块,提供 {@link cn.iocoder.dashboard.framework.dict.core.util.DictUtils} 工具类 - * - * 通过将字典缓存在内存中,保证性能 - */ -package cn.iocoder.dashboard.framework.dict; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/annotations/DictFormat.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/annotations/DictFormat.java deleted file mode 100644 index ae39734..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/annotations/DictFormat.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.dashboard.framework.excel.core.annotations; - -import java.lang.annotation.*; - -/** - * 字典格式化 - * - * 实现将字典数据的值,格式化成字典数据的标签 - */ -@Target({ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface DictFormat { - - /** - * 例如说,SysDictTypeConstants、InfDictTypeConstants - * - * @return 字典类型 - */ - String value(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java deleted file mode 100644 index c16c669..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java +++ /dev/null @@ -1,73 +0,0 @@ -package cn.iocoder.dashboard.framework.excel.core.convert; - - -import cn.hutool.core.convert.Convert; -import cn.iocoder.dashboard.framework.dict.core.dto.DictDataRespDTO; -import cn.iocoder.dashboard.framework.dict.core.util.DictUtils; -import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.property.ExcelContentProperty; -import lombok.extern.slf4j.Slf4j; - -/** - * Excel {@link DictDataRespDTO} 数据字典转换器 - * - * @author 芋道源码 - */ -@Slf4j -public class DictConvert implements Converter { - - @Override - public Class supportJavaTypeKey() { - throw new UnsupportedOperationException("暂不支持,也不需要"); - } - - @Override - public CellDataTypeEnum supportExcelTypeKey() { - throw new UnsupportedOperationException("暂不支持,也不需要"); - } - - @Override - public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - // 使用字典解析 - String type = getType(contentProperty); - String label = cellData.getStringValue(); - DictDataRespDTO dictData = DictUtils.parseDictDataFromCache(type, label); - if (dictData == null) { - log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label); - return null; - } - // 将 String 的 value 转换成对应的属性 - Class fieldClazz = contentProperty.getField().getType(); - return Convert.convert(fieldClazz, dictData.getValue()); - } - - @Override - public CellData convertToExcelData(Object object, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - // 空时,返回空 - if (object == null) { - return new CellData<>(""); - } - - // 使用字典格式化 - String type = getType(contentProperty); - String value = String.valueOf(object); - DictDataRespDTO dictData = DictUtils.getDictDataFromCache(type, value); - if (dictData == null) { - log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value); - return new CellData<>(""); - } - // 生成 Excel 小表格 - return new CellData<>(dictData.getLabel()); - } - - private static String getType(ExcelContentProperty contentProperty) { - return contentProperty.getField().getAnnotation(DictFormat.class).value(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/JsonConvert.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/JsonConvert.java deleted file mode 100644 index b1a88c3..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/JsonConvert.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.dashboard.framework.excel.core.convert; - -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.property.ExcelContentProperty; - -/** - * Excel Json 转换器 - * - * @author 芋道源码 - */ -public class JsonConvert implements Converter { - - @Override - public Class supportJavaTypeKey() { - throw new UnsupportedOperationException("暂不支持,也不需要"); - } - - @Override - public CellDataTypeEnum supportExcelTypeKey() { - throw new UnsupportedOperationException("暂不支持,也不需要"); - } - - @Override - public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("暂不支持,也不需要"); - } - - @Override - public CellData convertToExcelData(Object value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - // 生成 Excel 小表格 - return new CellData<>(JsonUtils.toJsonString(value)); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/util/ExcelUtils.java deleted file mode 100644 index a673e38..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/core/util/ExcelUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.dashboard.framework.excel.core.util; - -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.List; - -/** - * Excel 工具类 - * - * @author 芋道源码 - */ -public class ExcelUtils { - - /** - * 将列表以 Excel 响应给前端 - * - * @param response 响应 - * @param filename 文件名 - * @param sheetName Excel sheet 名 - * @param head Excel head 头 - * @param data 数据列表哦 - * @param 泛型,保证 head 和 data 类型的一致性 - * @throws IOException 写入失败的情况 - */ - public static void write(HttpServletResponse response, String filename, String sheetName, - Class head, List data) throws IOException { - // 输出 Excel - EasyExcel.write(response.getOutputStream(), head) - .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 - .sheet(sheetName).doWrite(data); - // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); - response.setContentType("application/vnd.ms-excel;charset=UTF-8"); - } - - public static List raed(MultipartFile file, Class head) throws IOException { - return EasyExcel.read(file.getInputStream(), head, null) - .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 - .doReadAllSync(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/package-info.java deleted file mode 100644 index 293498c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/excel/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 基于 EasyExcel 实现 Excel 相关的操作 - */ -package cn.iocoder.dashboard.framework.excel; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/config/IdempotentConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/config/IdempotentConfiguration.java deleted file mode 100644 index 7730ec8..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/config/IdempotentConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.config; - -import cn.iocoder.dashboard.framework.idempotent.core.aop.IdempotentAspect; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.IdempotentKeyResolver; -import cn.iocoder.dashboard.framework.idempotent.core.redis.IdempotentRedisDAO; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.core.StringRedisTemplate; - -import java.util.List; - -@Configuration(proxyBeanMethods = false) -@AutoConfigureAfter(RedisAutoConfiguration.class) -public class IdempotentConfiguration { - - @Bean - public IdempotentAspect idempotentAspect(List keyResolvers, IdempotentRedisDAO idempotentRedisDAO) { - return new IdempotentAspect(keyResolvers, idempotentRedisDAO); - } - - @Bean - public IdempotentRedisDAO idempotentRedisDAO(StringRedisTemplate stringRedisTemplate) { - return new IdempotentRedisDAO(stringRedisTemplate); - } - - // ========== 各种 IdempotentKeyResolver Bean ========== - - @Bean - public DefaultIdempotentKeyResolver defaultIdempotentKeyResolver() { - return new DefaultIdempotentKeyResolver(); - } - - @Bean - public ExpressionIdempotentKeyResolver expressionIdempotentKeyResolver() { - return new ExpressionIdempotentKeyResolver(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/annotation/Idempotent.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/annotation/Idempotent.java deleted file mode 100644 index f5981d0..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/annotation/Idempotent.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.core.annotation; - -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.IdempotentKeyResolver; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.concurrent.TimeUnit; - -/** - * 幂等注解 - * - * @author 芋道源码 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Idempotent { - - /** - * 幂等的超时时间,默认为 1 秒 - * - * 注意,如果执行时间超过它,请求还是会进来 - */ - int timeout() default 1; - /** - * 时间单位,默认为 SECONDS 秒 - */ - TimeUnit timeUnit() default TimeUnit.SECONDS; - - /** - * 提示信息,正在执行中的提示 - */ - String message() default "重复请求,请稍后重试"; - - /** - * 使用的 Key 解析器 - */ - Class keyResolver() default DefaultIdempotentKeyResolver.class; - /** - * 使用的 Key 参数 - */ - String keyArg() default ""; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/aop/IdempotentAspect.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/aop/IdempotentAspect.java deleted file mode 100644 index 0e7a4d9..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/aop/IdempotentAspect.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.core.aop; - -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.idempotent.core.annotation.Idempotent; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.IdempotentKeyResolver; -import cn.iocoder.dashboard.framework.idempotent.core.redis.IdempotentRedisDAO; -import cn.iocoder.yudao.framework.util.collection.CollectionUtils; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.springframework.util.Assert; - -import java.util.List; -import java.util.Map; - -/** - * 拦截声明了 {@link Idempotent} 注解的方法,实现幂等操作 - * - * @author 芋道源码 - */ -@Aspect -@Slf4j -public class IdempotentAspect { - - /** - * IdempotentKeyResolver 集合 - */ - private final Map, IdempotentKeyResolver> keyResolvers; - - private final IdempotentRedisDAO idempotentRedisDAO; - - public IdempotentAspect(List keyResolvers, IdempotentRedisDAO idempotentRedisDAO) { - this.keyResolvers = CollectionUtils.convertMap(keyResolvers, IdempotentKeyResolver::getClass); - this.idempotentRedisDAO = idempotentRedisDAO; - } - - @Before("@annotation(idempotent)") - public void beforePointCut(JoinPoint joinPoint, Idempotent idempotent) { - // 获得 IdempotentKeyResolver - IdempotentKeyResolver keyResolver = keyResolvers.get(idempotent.keyResolver()); - Assert.notNull(keyResolver, "找不到对应的 IdempotentKeyResolver"); - // 解析 Key - String key = keyResolver.resolver(joinPoint, idempotent); - - // 锁定 Key。 - boolean success = idempotentRedisDAO.setIfAbsent(key, idempotent.timeout(), idempotent.timeUnit()); - // 锁定失败,抛出异常 - if (!success) { - log.info("[beforePointCut][方法({}) 参数({}) 存在重复请求]", joinPoint.getSignature().toString(), joinPoint.getArgs()); - throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), idempotent.message()); - } - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java deleted file mode 100644 index a81d6c8..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.core.keyresolver; - -import cn.iocoder.dashboard.framework.idempotent.core.annotation.Idempotent; -import org.aspectj.lang.JoinPoint; - -/** - * 幂等 Key 解析器接口 - * - * @author 芋道源码 - */ -public interface IdempotentKeyResolver { - - /** - * 解析一个 Key - * - * @param idempotent 幂等注解 - * @param joinPoint AOP 切面 - * @return Key - */ - String resolver(JoinPoint joinPoint, Idempotent idempotent); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java deleted file mode 100644 index 900959b..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.core.keyresolver.impl; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.SecureUtil; -import cn.iocoder.dashboard.framework.idempotent.core.annotation.Idempotent; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.IdempotentKeyResolver; -import org.aspectj.lang.JoinPoint; - -/** - * 默认幂等 Key 解析器,使用方法名 + 方法参数,组装成一个 Key - * - * 为了避免 Key 过长,使用 MD5 进行“压缩” - * - * @author 芋道源码 - */ -public class DefaultIdempotentKeyResolver implements IdempotentKeyResolver { - - @Override - public String resolver(JoinPoint joinPoint, Idempotent idempotent) { - String methodName = joinPoint.getSignature().toString(); - String argsStr = StrUtil.join(",", joinPoint.getArgs()); - return SecureUtil.md5(methodName + argsStr); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java deleted file mode 100644 index f67e525..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.core.keyresolver.impl; - -import cn.hutool.core.util.ArrayUtil; -import cn.iocoder.dashboard.framework.idempotent.core.annotation.Idempotent; -import cn.iocoder.dashboard.framework.idempotent.core.keyresolver.IdempotentKeyResolver; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.core.LocalVariableTableParameterNameDiscoverer; -import org.springframework.core.ParameterNameDiscoverer; -import org.springframework.expression.Expression; -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; - -import java.lang.reflect.Method; - -/** - * 基于 Spring EL 表达式, - * - * @author 芋道源码 - */ -public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver { - - private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); - private final ExpressionParser expressionParser = new SpelExpressionParser(); - - @Override - public String resolver(JoinPoint joinPoint, Idempotent idempotent) { - // 获得被拦截方法参数名列表 - Method method = getMethod(joinPoint); - Object[] args = joinPoint.getArgs(); - String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method); - // 准备 Spring EL 表达式解析的上下文 - StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); - if (ArrayUtil.isNotEmpty(parameterNames)) { - for (int i = 0; i < parameterNames.length; i++) { - evaluationContext.setVariable(parameterNames[i], args[i]); - } - } - - // 解析参数 - Expression expression = expressionParser.parseExpression(idempotent.keyArg()); - return expression.getValue(evaluationContext, String.class); - } - - private static Method getMethod(JoinPoint point) { - // 处理,声明在类上的情况 - MethodSignature signature = (MethodSignature) point.getSignature(); - Method method = signature.getMethod(); - if (!method.getDeclaringClass().isInterface()) { - return method; - } - - // 处理,声明在接口上的情况 - try { - return point.getTarget().getClass().getDeclaredMethod( - point.getSignature().getName(), method.getParameterTypes()); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/redis/IdempotentRedisDAO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/redis/IdempotentRedisDAO.java deleted file mode 100644 index 16b88cb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/core/redis/IdempotentRedisDAO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.dashboard.framework.idempotent.core.redis; - -import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; -import lombok.AllArgsConstructor; -import org.springframework.data.redis.core.StringRedisTemplate; - -import java.util.concurrent.TimeUnit; - -import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; - -/** - * 幂等 Redis DAO - * - * @author 芋道源码 - */ -@AllArgsConstructor -public class IdempotentRedisDAO { - - private static final RedisKeyDefine IDEMPOTENT = new RedisKeyDefine("幂等操作", - "idempotent:%s", // 参数为 uuid - STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); - - private final StringRedisTemplate redisTemplate; - - public Boolean setIfAbsent(String key, long timeout, TimeUnit timeUnit) { - String redisKey = formatKey(key); - return redisTemplate.opsForValue().setIfAbsent(redisKey, "", timeout, timeUnit); - } - - private static String formatKey(String key) { - return String.format(IDEMPOTENT.getKeyTemplate(), key); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/package-info.java deleted file mode 100644 index b8b54ba..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/idempotent/package-info.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 幂等组件,参考 https://github.com/it4alla/idempotent 项目实现 - * 实现原理是,相同参数的方法,一段时间内,有且仅能执行一次。通过这样的方式,保证幂等性。 - * - * 使用场景:例如说,用户快速的双击了某个按钮,前端没有禁用该按钮,导致发送了两次重复的请求。 - * - * 和 it4alla/idempotent 组件的差异点,主要体现在两点: - * 1. 我们去掉了 @Idempotent 注解的 delKey 属性。原因是,本质上 delKey 为 true 时,实现的是分布式锁的能力 - * 此时,我们偏向使用 Lock4j 组件。原则上,一个组件只提供一种单一的能力。 - * 2. 考虑到组件的通用性,我们并未像 it4alla/idempotent 组件一样使用 Redisson RMap 结构,而是直接使用 Redis 的 String 数据格式。 - */ -package cn.iocoder.dashboard.framework.idempotent; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/config/Lock4jConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/config/Lock4jConfiguration.java deleted file mode 100644 index 12dc59d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/config/Lock4jConfiguration.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.dashboard.framework.lock4j.config; - -import cn.hutool.core.util.ClassUtil; -import cn.iocoder.dashboard.framework.lock4j.core.DefaultLockFailureStrategy; -import cn.iocoder.dashboard.framework.lock4j.core.Lock4jRedisKeyConstants; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class Lock4jConfiguration { - - static { - // 手动加载 Lock4jRedisKeyConstants 类,因为它不会被使用到 - // 如果不加载,会导致 Redis 监控,看到它的 Redis Key 枚举 - ClassUtil.loadClass(Lock4jRedisKeyConstants.class.getName()); - } - - @Bean - public DefaultLockFailureStrategy lockFailureStrategy() { - return new DefaultLockFailureStrategy(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/DefaultLockFailureStrategy.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/DefaultLockFailureStrategy.java deleted file mode 100644 index b186203..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/DefaultLockFailureStrategy.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.dashboard.framework.lock4j.core; - -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import com.baomidou.lock.LockFailureStrategy; -import lombok.extern.slf4j.Slf4j; - -/** - * 自定义获取锁失败策略,抛出 {@link ServiceException} 异常 - */ -@Slf4j -public class DefaultLockFailureStrategy implements LockFailureStrategy { - - @Override - public void onLockFailure(String key, long acquireTimeout, int acquireCount) { - log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取超时时长:{} ms]", Thread.currentThread().getName(), key, acquireTimeout); - throw new ServiceException(GlobalErrorCodeConstants.LOCKED); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/Lock4jRedisKeyConstants.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/Lock4jRedisKeyConstants.java deleted file mode 100644 index 33917da..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/core/Lock4jRedisKeyConstants.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.dashboard.framework.lock4j.core; - -import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; -import org.redisson.api.RLock; - -import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH; - -/** - * Lock4j Redis Key 枚举类 - * - * @author 芋道源码 - */ -public interface Lock4jRedisKeyConstants { - - RedisKeyDefine LOCK4J = new RedisKeyDefine("分布式锁", - "lock4j:%s", // 参数来自 DefaultLockKeyBuilder 类 - HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/package-info.java deleted file mode 100644 index 6000939..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/lock4j/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 分布式锁组件,使用 https://gitee.com/baomidou/lock4j 开源项目 - */ -package cn.iocoder.dashboard.framework.lock4j; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java deleted file mode 100644 index 77c166c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/config/AdminServerConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.dashboard.framework.monitor.config; - -import de.codecentric.boot.admin.server.config.EnableAdminServer; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableAdminServer -public class AdminServerConfiguration { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java deleted file mode 100644 index dec6e31..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 使用 Spring Boot Admin 实现简单的监控平台 - */ -package cn.iocoder.dashboard.framework.monitor; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md deleted file mode 100644 index a1e3676..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/package-info.java deleted file mode 100644 index e8231cb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 该包是技术组件,每个子包,代表一个组件。每个组件包括两部分: - * 1. core 包:是该组件的核心分装 - * 2. config 包:是该组件基于 Spring 的配置 - * - * 技术组件,也分成两类: - * 1. 框架组件:和我们熟悉的 MyBatis、Redis 等等的拓展 - * 2. 业务组件:和业务相关的组件的封装,例如说数据字典、操作日志等等。 - */ -package cn.iocoder.dashboard.framework; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java deleted file mode 100644 index 30d8837..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.config; - -import cn.iocoder.dashboard.framework.quartz.core.scheduler.SchedulerManager; -import org.quartz.Scheduler; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableScheduling; - -@Configuration -@EnableScheduling // 开启 Spring 自带的定时任务 -public class QuartzConfig { - - @Bean - public SchedulerManager schedulerManager(Scheduler scheduler) { - return new SchedulerManager(scheduler); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java deleted file mode 100644 index 2849d1a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.core.enums; - -/** - * Quartz Job Data 的 key 枚举 - */ -public enum JobDataKeyEnum { - - JOB_ID, - JOB_HANDLER_NAME, - JOB_HANDLER_PARAM, - JOB_RETRY_COUNT, // 最大重试次数 - JOB_RETRY_INTERVAL, // 每次重试间隔 - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java deleted file mode 100644 index bdf8a1b..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.core.handler; - -/** - * 任务处理器 - * - * @author 芋道源码 - */ -public interface JobHandler { - - /** - * 执行任务 - * - * @param param 参数 - * @return 结果 - * @throws Exception 异常 - */ - String execute(String param) throws Exception; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java deleted file mode 100644 index 8ab21ba..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java +++ /dev/null @@ -1,113 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.core.handler; - -import cn.hutool.core.lang.Assert; -import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.dashboard.framework.quartz.core.enums.JobDataKeyEnum; -import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService; -import lombok.extern.slf4j.Slf4j; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.quartz.PersistJobDataAfterExecution; -import org.springframework.context.ApplicationContext; -import org.springframework.scheduling.quartz.QuartzJobBean; - -import javax.annotation.Resource; -import java.util.Date; - -import static cn.iocoder.yudao.framework.util.date.DateUtils.diff; -import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCauseMessage; - -/** - * 基础 Job 调用者,负责调用 {@link JobHandler#execute(String)} 执行任务 - * - * @author 芋道源码 - */ -@DisallowConcurrentExecution -@PersistJobDataAfterExecution -@Slf4j -public class JobHandlerInvoker extends QuartzJobBean { - - @Resource - private ApplicationContext applicationContext; - - @Resource - private JobLogFrameworkService jobLogFrameworkService; - - @Override - protected void executeInternal(JobExecutionContext executionContext) throws JobExecutionException { - // 第一步,获得 Job 数据 - Long jobId = executionContext.getMergedJobDataMap().getLong(JobDataKeyEnum.JOB_ID.name()); - String jobHandlerName = executionContext.getMergedJobDataMap().getString(JobDataKeyEnum.JOB_HANDLER_NAME.name()); - String jobHandlerParam = executionContext.getMergedJobDataMap().getString(JobDataKeyEnum.JOB_HANDLER_PARAM.name()); - int refireCount = executionContext.getRefireCount(); - int retryCount = (Integer) executionContext.getMergedJobDataMap().getOrDefault(JobDataKeyEnum.JOB_RETRY_COUNT.name(), 0); - int retryInterval = (Integer) executionContext.getMergedJobDataMap().getOrDefault(JobDataKeyEnum.JOB_RETRY_INTERVAL.name(), 0); - - // 第二步,执行任务 - Long jobLogId = null; - Date startTime = new Date(); - String data = null; - Throwable exception = null; - try { - // 记录 Job 日志(初始) - jobLogId = jobLogFrameworkService.createJobLog(jobId, startTime, jobHandlerName, jobHandlerParam, refireCount + 1); - // 执行任务 - data = this.executeInternal(jobHandlerName, jobHandlerParam); - } catch (Throwable ex) { - exception = ex; - } - - // 第三步,记录执行日志 - this.updateJobLogResultAsync(jobLogId, startTime, data, exception, executionContext); - - // 第四步,处理有异常的情况 - handleException(exception, refireCount, retryCount, retryInterval); - } - - private String executeInternal(String jobHandlerName, String jobHandlerParam) throws Exception { - // 获得 JobHandler 对象 - JobHandler jobHandler = applicationContext.getBean(jobHandlerName, JobHandler.class); - Assert.notNull(jobHandler, "JobHandler 不会为空"); - // 执行任务 - return jobHandler.execute(jobHandlerParam); - } - - private void updateJobLogResultAsync(Long jobLogId, Date startTime, String data, Throwable exception, - JobExecutionContext executionContext) { - Date endTime = new Date(); - // 处理是否成功 - boolean success = exception == null; - if (!success) { - data = getRootCauseMessage(exception); - } - // 更新日志 - try { - jobLogFrameworkService.updateJobLogResultAsync(jobLogId, endTime, (int) diff(endTime, startTime), success, data); - } catch (Exception ex) { - log.error("[executeInternal][Job({}) logId({}) 记录执行日志失败({}/{})]", - executionContext.getJobDetail().getKey(), jobLogId, success, data); - } - } - - private void handleException(Throwable exception, - int refireCount, int retryCount, int retryInterval) throws JobExecutionException { - // 如果有异常,则进行重试 - if (exception == null) { - return; - } - // 情况一:如果到达重试上限,则直接抛出异常即可 - if (refireCount >= retryCount) { - throw new JobExecutionException(exception); - } - - // 情况二:如果未到达重试上限,则 sleep 一定间隔时间,然后重试 - // 这里使用 sleep 来实现,主要还是希望实现比较简单。因为,同一时间,不会存在大量失败的 Job。 - if (retryInterval > 0) { - ThreadUtil.sleep(retryInterval); - } - // 第二个参数,refireImmediately = true,表示立即重试 - throw new JobExecutionException(exception, true); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java deleted file mode 100644 index e72c909..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java +++ /dev/null @@ -1,130 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.core.scheduler; - -import cn.iocoder.dashboard.framework.quartz.core.enums.JobDataKeyEnum; -import cn.iocoder.dashboard.framework.quartz.core.handler.JobHandlerInvoker; -import org.quartz.*; - -/** - * {@link org.quartz.Scheduler} 的管理器,负责创建任务 - * - * 考虑到实现的简洁性,我们使用 jobHandlerName 作为唯一标识,即: - * 1. Job 的 {@link JobDetail#getKey()} - * 2. Trigger 的 {@link Trigger#getKey()} - * - * 另外,jobHandlerName 对应到 Spring Bean 的名字,直接调用 - * - * @author 芋道源码 - */ -public class SchedulerManager { - - private final Scheduler scheduler; - - public SchedulerManager(Scheduler scheduler) { - this.scheduler = scheduler; - } - - /** - * 添加 Job 到 Quartz 中 - * - * @param jobId 任务编号 - * @param jobHandlerName 任务处理器的名字 - * @param jobHandlerParam 任务处理器的参数 - * @param cronExpression CRON 表达式 - * @param retryCount 重试次数 - * @param retryInterval 重试间隔 - * @throws SchedulerException 添加异常 - */ - public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression, - Integer retryCount, Integer retryInterval) - throws SchedulerException { - // 创建 JobDetail 对象 - JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class) - .usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId) - .usingJobData(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName) - .withIdentity(jobHandlerName).build(); - // 创建 Trigger 对象 - Trigger trigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); - // 新增调度 - scheduler.scheduleJob(jobDetail, trigger); - } - - /** - * 更新 Job 到 Quartz - * - * @param jobHandlerName 任务处理器的名字 - * @param jobHandlerParam 任务处理器的参数 - * @param cronExpression CRON 表达式 - * @param retryCount 重试次数 - * @param retryInterval 重试间隔 - * @throws SchedulerException 更新异常 - */ - public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression, - Integer retryCount, Integer retryInterval) - throws SchedulerException { - // 创建新 Trigger 对象 - Trigger newTrigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); - // 修改调度 - scheduler.rescheduleJob(new TriggerKey(jobHandlerName), newTrigger); - } - - /** - * 删除 Quartz 中的 Job - * - * @param jobHandlerName 任务处理器的名字 - * @throws SchedulerException 删除异常 - */ - public void deleteJob(String jobHandlerName) throws SchedulerException { - scheduler.deleteJob(new JobKey(jobHandlerName)); - } - - /** - * 暂停 Quartz 中的 Job - * - * @param jobHandlerName 任务处理器的名字 - * @throws SchedulerException 暂停异常 - */ - public void pauseJob(String jobHandlerName) throws SchedulerException { - scheduler.pauseJob(new JobKey(jobHandlerName)); - } - - /** - * 启动 Quartz 中的 Job - * - * @param jobHandlerName 任务处理器的名字 - * @throws SchedulerException 启动异常 - */ - public void resumeJob(String jobHandlerName) throws SchedulerException { - scheduler.resumeJob(new JobKey(jobHandlerName)); - scheduler.resumeTrigger(new TriggerKey(jobHandlerName)); - } - - /** - * 立即触发一次 Quartz 中的 Job - * - * @param jobId 任务编号 - * @param jobHandlerName 任务处理器的名字 - * @param jobHandlerParam 任务处理器的参数 - * @throws SchedulerException 触发异常 - */ - public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam) - throws SchedulerException { - JobDataMap data = new JobDataMap(); // 无需重试,所以不设置 retryCount 和 retryInterval - data.put(JobDataKeyEnum.JOB_ID.name(), jobId); - data.put(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName); - data.put(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam); - // 触发任务 - scheduler.triggerJob(new JobKey(jobHandlerName), data); - } - - private Trigger buildTrigger(String jobHandlerName, String jobHandlerParam, String cronExpression, - Integer retryCount, Integer retryInterval) { - return TriggerBuilder.newTrigger() - .withIdentity(jobHandlerName) - .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) - .usingJobData(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam) - .usingJobData(JobDataKeyEnum.JOB_RETRY_COUNT.name(), retryCount) - .usingJobData(JobDataKeyEnum.JOB_RETRY_INTERVAL.name(), retryInterval) - .build(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java deleted file mode 100644 index a93dfdf..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.core.service; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * Job 日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface JobLogFrameworkService { - - /** - * 创建 Job 日志 - * - * @param jobId 任务编号 - * @param beginTime 开始时间 - * @param jobHandlerName Job 处理器的名字 - * @param jobHandlerParam Job 处理器的参数 - * @param executeIndex 第几次执行 - * @return Job 日志的编号 - */ - Long createJobLog(@NotNull(message = "任务编号不能为空") Long jobId, - @NotNull(message = "开始时间") Date beginTime, - @NotEmpty(message = "Job 处理器的名字不能为空") String jobHandlerName, - String jobHandlerParam, - @NotNull(message = "第几次执行不能为空") Integer executeIndex); - - /** - * 更新 Job 日志的执行结果 - * - * @param logId 日志编号 - * @param endTime 结束时间。因为是异步,避免记录时间不准去 - * @param duration 运行时长,单位:毫秒 - * @param success 是否成功 - * @param result 成功数据 - */ - void updateJobLogResultAsync(@NotNull(message = "日志编号不能为空") Long logId, - @NotNull(message = "结束时间不能为空") Date endTime, - @NotNull(message = "运行时长不能为空") Integer duration, - boolean success, String result); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java deleted file mode 100644 index 62ba408..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.dashboard.framework.quartz.core.util; - -import org.quartz.CronExpression; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Quartz Cron 表达式的工具类 - * - * @author 芋道源码 - */ -public class CronUtils { - - /** - * 校验 CRON 表达式是否有效 - * - * @param cronExpression CRON 表达式 - * @return 是否有效 - */ - public static boolean isValid(String cronExpression) { - return CronExpression.isValidExpression(cronExpression); - } - - /** - * 基于 CRON 表达式,获得下 n 个满足执行的时间 - * - * @param cronExpression CRON 表达式 - * @param n 数量 - * @return 满足条件的执行时间 - */ - public static List getNextTimes(String cronExpression, int n) { - // 获得 CronExpression 对象 - CronExpression cron; - try { - cron = new CronExpression(cronExpression); - } catch (ParseException e) { - throw new IllegalArgumentException(e.getMessage()); - } - // 从当前开始计算,n 个满足条件的 - Date now = new Date(); - List nextTimes = new ArrayList<>(n); - for (int i = 0; i < n; i++) { - Date nextTime = cron.getNextValidTimeAfter(now); - nextTimes.add(nextTime); - // 切换现在,为下一个触发时间; - now = nextTime; - } - return nextTimes; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java deleted file mode 100644 index 79d9eeb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * 定时任务,采用 Quartz 实现进程内的任务执行。 - * 考虑到高可用,使用 Quartz 自带的 MySQL 集群方案。 - */ -package cn.iocoder.dashboard.framework.quartz; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/《芋道 Spring Boot 定时任务入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/《芋道 Spring Boot 定时任务入门》.md deleted file mode 100644 index 6564701..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/quartz/《芋道 Spring Boot 定时任务入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java deleted file mode 100644 index 52bef80..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.config; - -import cn.hutool.system.SystemUtil; -import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.ObjectRecord; -import org.springframework.data.redis.connection.stream.ReadOffset; -import org.springframework.data.redis.connection.stream.StreamOffset; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.listener.ChannelTopic; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.data.redis.stream.StreamMessageListenerContainer; - -import java.util.List; - -/** - * Redis 配置类 - */ -@Configuration -@Slf4j -public class RedisConfig { - - /** - * 创建 RedisTemplate Bean,使用 JSON 序列化方式 - */ - @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory factory) { - // 创建 RedisTemplate 对象 - RedisTemplate template = new RedisTemplate<>(); - // 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。 - template.setConnectionFactory(factory); - // 使用 String 序列化方式,序列化 KEY 。 - template.setKeySerializer(RedisSerializer.string()); - template.setHashKeySerializer(RedisSerializer.string()); - // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。 - template.setValueSerializer(RedisSerializer.json()); - template.setHashValueSerializer(RedisSerializer.json()); - return template; - } - - /** - * 创建 Redis Pub/Sub 广播消费的容器 - */ - @Bean - public RedisMessageListenerContainer redisMessageListenerContainer( - RedisConnectionFactory factory, List> listeners) { - // 创建 RedisMessageListenerContainer 对象 - RedisMessageListenerContainer container = new RedisMessageListenerContainer(); - // 设置 RedisConnection 工厂。 - container.setConnectionFactory(factory); - // 添加监听器 - listeners.forEach(listener -> { - container.addMessageListener(listener, new ChannelTopic(listener.getChannel())); - log.info("[redisMessageListenerContainer][注册 Channel({}) 对应的监听器({})]", - listener.getChannel(), listener.getClass().getName()); - }); - return container; - } - - /** - * 创建 Redis Stream 集群消费的容器 - * - * Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html - */ - @Bean(initMethod = "start", destroyMethod = "stop") - public StreamMessageListenerContainer> redisStreamMessageListenerContainer( - RedisTemplate redisTemplate, List> listeners) { - // 第一步,创建 StreamMessageListenerContainer 容器 - // 创建 options 配置 - StreamMessageListenerContainer.StreamMessageListenerContainerOptions> containerOptions = - StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder() - .batchSize(10) // 一次性最多拉取多少条消息 - .targetType(String.class) // 目标类型。统一使用 String,通过自己封装的 AbstractStreamMessageListener 去反序列化 - .build(); - // 创建 container 对象 - StreamMessageListenerContainer> container = StreamMessageListenerContainer.create( - redisTemplate.getRequiredConnectionFactory(), containerOptions); - - // 第二步,注册监听器,消费对应的 Stream 主题 - String consumerName = buildConsumerName(); -// String consumerName = "110"; - listeners.forEach(listener -> { - // 创建 listener 对应的消费者分组 - try { - redisTemplate.opsForStream().createGroup(listener.getStreamKey(), listener.getGroup()); - } catch (Exception ignore) {} - // 设置 listener 对应的 redisTemplate - listener.setRedisTemplate(redisTemplate); - // 创建 Consumer 对象 - Consumer consumer = Consumer.from(listener.getGroup(), consumerName); - // 设置 Consumer 消费进度,以最小消费进度为准 - StreamOffset streamOffset = StreamOffset.create(listener.getStreamKey(), ReadOffset.lastConsumed()); - // 设置 Consumer 监听 - StreamMessageListenerContainer.StreamReadRequestBuilder builder = StreamMessageListenerContainer.StreamReadRequest - .builder(streamOffset).consumer(consumer) - .autoAcknowledge(false) // 不自动 ack - .cancelOnError(throwable -> false); // 默认配置,发生异常就取消消费,显然不符合预期;因此,我们设置为 false - container.register(builder.build(), listener); - }); - return container; - } - - /** - * 构建消费者名字,使用本地 IP + 进程编号的方式。 - * 参考自 RocketMQ clientId 的实现 - * - * @return 消费者名字 - */ - private static String buildConsumerName() { - return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java deleted file mode 100644 index 1238abe..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java +++ /dev/null @@ -1,101 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core; - -import com.fasterxml.jackson.annotation.JsonValue; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; - -import java.time.Duration; - -/** - * Redis Key 定义类 - * - * @author 芋道源码 - */ -@Data -public class RedisKeyDefine { - - @Getter - @AllArgsConstructor - public enum KeyTypeEnum { - - STRING("String"), - LIST("List"), - HASH("Hash"), - SET("Set"), - ZSET("Sorted Set"), - STREAM("Stream"), - PUBSUB("Pub/Sub"); - - /** - * 类型 - */ - @JsonValue - private final String type; - - } - - @Getter - @AllArgsConstructor - public enum TimeoutTypeEnum { - - FOREVER(1), // 永不超时 - DYNAMIC(2), // 动态超时 - FIXED(3); // 固定超时 - - /** - * 类型 - */ - @JsonValue - private final Integer type; - - } - - /** - * Key 模板 - */ - private final String keyTemplate; - /** - * Key 类型的枚举 - */ - private final KeyTypeEnum keyType; - /** - * Value 类型 - * - * 如果是使用分布式锁,设置为 {@link java.util.concurrent.locks.Lock} 类型 - */ - private final Class valueType; - /** - * 超时类型 - */ - private final TimeoutTypeEnum timeoutType; - /** - * 过期时间 - */ - private final Duration timeout; - /** - * 备注 - */ - private final String memo; - - private RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class valueType, - TimeoutTypeEnum timeoutType, Duration timeout) { - this.memo = memo; - this.keyTemplate = keyTemplate; - this.keyType = keyType; - this.valueType = valueType; - this.timeout = timeout; - this.timeoutType = timeoutType; - // 添加注册表 - RedisKeyRegistry.add(this); - } - - public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class valueType, Duration timeout) { - this(memo, keyTemplate, keyType, valueType, TimeoutTypeEnum.FIXED, timeout); - } - - public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class valueType, TimeoutTypeEnum timeoutType) { - this(memo, keyTemplate, keyType, valueType, timeoutType, Duration.ZERO); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java deleted file mode 100644 index 6da1a36..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link RedisKeyDefine} 注册表 - */ -public class RedisKeyRegistry { - - /** - * Redis RedisKeyDefine 数组 - */ - private static final List defines = new ArrayList<>(); - - public static void add(RedisKeyDefine define) { - defines.add(define); - } - - public static List list() { - return defines; - } - - public static int size() { - return defines.size(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java deleted file mode 100644 index fd8687d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core.pubsub; - -import cn.hutool.core.util.TypeUtil; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import lombok.SneakyThrows; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.connection.MessageListener; - -import java.lang.reflect.Type; - -/** - * Redis Pub/Sub 监听器抽象类,用于实现广播消费 - * - * @param 消息类型。一定要填写噢,不然会报错 - * - * @author 芋道源码 - */ -public abstract class AbstractChannelMessageListener implements MessageListener { - - /** - * 消息类型 - */ - private final Class messageType; - /** - * Redis Channel - */ - private final String channel; - - @SneakyThrows - protected AbstractChannelMessageListener() { - this.messageType = getMessageClass(); - this.channel = messageType.newInstance().getChannel(); - } - - /** - * 获得 Sub 订阅的 Redis Channel 通道 - * - * @return channel - */ - public final String getChannel() { - return channel; - } - - @Override - public final void onMessage(Message message, byte[] bytes) { - T messageObj = JsonUtils.parseObject(message.getBody(), messageType); - this.onMessage(messageObj); - } - - /** - * 处理消息 - * - * @param message 消息 - */ - public abstract void onMessage(T message); - - /** - * 通过解析类上的泛型,获得消息类型 - * - * @return 消息类型 - */ - @SuppressWarnings("unchecked") - private Class getMessageClass() { - Type type = TypeUtil.getTypeArgument(getClass(), 0); - if (type == null) { - throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); - } - return (Class) type; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java deleted file mode 100644 index 93ea99f..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core.pubsub; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Redis Channel Message 接口 - * - * @author 芋道源码 - */ -public interface ChannelMessage { - - /** - * 获得 Redis Channel - * - * @return Channel - */ - @JsonIgnore // 避免序列化 - String getChannel(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java deleted file mode 100644 index 8593a11..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core.stream; - -import cn.hutool.core.util.TypeUtil; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import lombok.Getter; -import lombok.Setter; -import lombok.SneakyThrows; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.connection.stream.ObjectRecord; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.stream.StreamListener; - -import java.lang.reflect.Type; - -/** - * Redis Stream 监听器抽象类,用于实现集群消费 - * - * @param 消息类型。一定要填写噢,不然会报错 - * - * @author 芋道源码 - */ -public abstract class AbstractStreamMessageListener - implements StreamListener> { - - /** - * 消息类型 - */ - private final Class messageType; - /** - * Redis Channel - */ - @Getter - private final String streamKey; - - /** - * Redis 消费者分组,默认使用 spring.application.name 名字 - */ - @Value("${spring.application.name}") - @Getter - private String group; - /** - * - */ - @Setter - private RedisTemplate redisTemplate; - - @SneakyThrows - protected AbstractStreamMessageListener() { - this.messageType = getMessageClass(); - this.streamKey = messageType.newInstance().getStreamKey(); - } - - @Override - public void onMessage(ObjectRecord message) { - // 消费消息 - T messageObj = JsonUtils.parseObject(message.getValue(), messageType); - this.onMessage(messageObj); - // ack 消息消费完成 - redisTemplate.opsForStream().acknowledge(group, message); - // TODO 芋艿:需要额外考虑以下几个点: - // 1. 处理异常的情况 - // 2. 发送日志;以及事务的结合 - // 3. 消费日志;以及通用的幂等性 - // 4. 消费失败的重试,https://zhuanlan.zhihu.com/p/60501638 - } - - /** - * 处理消息 - * - * @param message 消息 - */ - public abstract void onMessage(T message); - - /** - * 通过解析类上的泛型,获得消息类型 - * - * @return 消息类型 - */ - @SuppressWarnings("unchecked") - private Class getMessageClass() { - Type type = TypeUtil.getTypeArgument(getClass(), 0); - if (type == null) { - throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); - } - return (Class) type; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java deleted file mode 100644 index 7b0204d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core.stream; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Redis Stream Message 接口 - * - * @author 芋道源码 - */ -public interface StreamMessage { - - /** - * 获得 Redis Stream Key - * - * @return Channel - */ - @JsonIgnore // 避免序列化 - String getStreamKey(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java deleted file mode 100644 index f0c9c05..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.dashboard.framework.redis.core.util; - -import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; -import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import org.springframework.data.redis.connection.stream.RecordId; -import org.springframework.data.redis.connection.stream.StreamRecords; -import org.springframework.data.redis.core.RedisTemplate; - -/** - * Redis 消息工具类 - * - * @author 芋道源码 - */ -public class RedisMessageUtils { - - /** - * 发送 Redis 消息,基于 Redis pub/sub 实现 - * - * @param redisTemplate Redis 操作模板 - * @param message 消息 - */ - public static void sendChannelMessage(RedisTemplate redisTemplate, T message) { - redisTemplate.convertAndSend(message.getChannel(), JsonUtils.toJsonString(message)); - } - - /** - * 发送 Redis 消息,基于 Redis Stream 实现 - * - * @param redisTemplate Redis 操作模板 - * @param message 消息 - * @return 消息记录的编号对象 - */ - public static RecordId sendStreamMessage(RedisTemplate redisTemplate, T message) { - return redisTemplate.opsForStream().add(StreamRecords.newRecord() - .ofObject(JsonUtils.toJsonString(message)) // 设置内容 - .withStreamKey(message.getStreamKey())); // 设置 stream key - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/package-info.java deleted file mode 100644 index 8d1562a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 采用 Spring Data Redis 操作 Redis,底层使用 Redisson 作为客户端 - */ -package cn.iocoder.dashboard.framework.redis; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/《芋道 Spring Boot Redis 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/《芋道 Spring Boot Redis 入门》.md deleted file mode 100644 index 80c5445..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/redis/《芋道 Spring Boot Redis 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/package-info.java deleted file mode 100644 index 8fb7760..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/package-info.java +++ /dev/null @@ -1,9 +0,0 @@ -/** - * 使用 Resilience4j 组件,实现服务保障,包括: - * 1. 熔断器 - * 2. 限流器 - * 3. 舱壁隔离 - * 4. 重试 - * 5. 限时器 - */ -package cn.iocoder.dashboard.framework.resilience4j; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md deleted file mode 100644 index 8d6d033..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java deleted file mode 100644 index e5441c9..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.config; - -import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.dashboard.framework.sms.core.client.impl.SmsClientFactoryImpl; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * 短信配置类 - * - * @author 芋道源码 - */ -@Configuration -public class SmsConfiguration { - - @Bean - public SmsClientFactory smsClientFactory() { - return new SmsClientFactoryImpl(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java deleted file mode 100644 index ee7bbc1..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client; - -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; - -import java.util.List; - -/** - * 短信客户端接口 - * - * @author zzf - * @date 2021/1/25 14:14 - */ -public interface SmsClient { - - /** - * 获得渠道编号 - * - * @return 渠道编号 - */ - Long getId(); - - /** - * 发送消息 - * - * @param logId 日志编号 - * @param mobile 手机号 - * @param apiTemplateId 短信 API 的模板编号 - * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序 - * @return 短信发送结果 - */ - SmsCommonResult sendSms(Long logId, String mobile, String apiTemplateId, - List> templateParams); - - /** - * 解析接收短信的接收结果 - * - * @param text 结果 - * @return 结果内容 - * @throws Throwable 当解析 text 发生异常时,则会抛出异常 - */ - List parseSmsReceiveStatus(String text) throws Throwable; - - /** - * 查询指定的短信模板 - * - * @param apiTemplateId 短信 API 的模板编号 - * @return 短信模板 - */ - SmsCommonResult getSmsTemplate(String apiTemplateId); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java deleted file mode 100644 index 83fb88c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client; - -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; - -/** - * 短信客户端工厂接口 - * - * @author zzf - * @date 2021/1/28 14:01 - */ -public interface SmsClientFactory { - - /** - * 获得短信 Client - * - * @param channelId 渠道编号 - * @return 短信 Client - */ - SmsClient getSmsClient(Long channelId); - - /** - * 获得短信 Client - * - * @param channelCode 渠道编码 - * @return 短信 Client - */ - SmsClient getSmsClient(String channelCode); - - /** - * 创建短信 Client - * - * @param properties 配置对象 - */ - void createOrUpdateSmsClient(SmsChannelProperties properties); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java deleted file mode 100644 index d2a726b..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; - -import java.util.function.Function; - -/** - * 将 API 的错误码,转换为通用的错误码 - * - * @see SmsCommonResult - * @see SmsFrameworkErrorCodeConstants - * - * @author 芋道源码 - */ -public interface SmsCodeMapping extends Function { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java deleted file mode 100644 index 2780c8d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -/** - * 短信的 CommonResult 拓展类 - * - * 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段 - * - * 另外,一些短信平台(例如说阿里云、腾讯云)会返回一个请求编号,用于排查请求失败的问题,我们设置到 {@link #apiRequestId} 字段 - * - * @author 芋道源码 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsCommonResult extends CommonResult { - - /** - * API 返回错误码 - * - * 由于第三方的错误码可能是字符串,所以使用 String 类型 - */ - private String apiCode; - /** - * API 返回提示 - */ - private String apiMsg; - - /** - * API 请求编号 - */ - private String apiRequestId; - - private SmsCommonResult() { - } - - public static SmsCommonResult build(String apiCode, String apiMsg, String apiRequestId, - T data, SmsCodeMapping codeMapping) { - Assert.notNull(codeMapping, "参数 codeMapping 不能为空"); - SmsCommonResult result = new SmsCommonResult().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId); - result.setData(data); - // 翻译错误码 - if (codeMapping != null) { - ErrorCode errorCode = codeMapping.apply(apiCode); - if (errorCode == null) { - errorCode = SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - } - result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg()); - } - return result; - } - - public static SmsCommonResult error(Throwable ex) { - SmsCommonResult result = new SmsCommonResult<>(); - result.setCode(SmsFrameworkErrorCodeConstants.EXCEPTION.getCode()); - result.setMsg(ExceptionUtil.getRootCauseMessage(ex)); - return result; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java deleted file mode 100644 index ecfdb04..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.dto; - -import lombok.Data; - -import java.util.Date; - -/** - * 消息接收 Response DTO - * - * @author 芋道源码 - */ -@Data -public class SmsReceiveRespDTO { - - /** - * 是否接收成功 - */ - private Boolean success; - /** - * API 接收结果的编码 - */ - private String errorCode; - /** - * API 接收结果的说明 - */ - private String errorMsg; - - /** - * 手机号 - */ - private String mobile; - /** - * 用户接收时间 - */ - private Date receiveTime; - - /** - * 短信 API 发送返回的序号 - */ - private String serialNo; - /** - * 短信日志编号 - * - * 对应 SysSmsLogDO 的编号 - */ - private Long logId; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java deleted file mode 100644 index c3f6b51..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.dto; - -import lombok.Data; - -/** - * 短信发送 Response DTO - * - * @author 芋道源码 - */ -@Data -public class SmsSendRespDTO { - - /** - * 短信 API 发送返回的序号 - */ - private String serialNo; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java deleted file mode 100644 index 938310e..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.dto; - -import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import lombok.Data; - -/** - * 短信模板 Response DTO - * - * @author 芋道源码 - */ -@Data -public class SmsTemplateRespDTO { - - /** - * 模板编号 - */ - private String id; - /** - * 短信内容 - */ - private String content; - /** - * 审核状态 - * - * 枚举 {@link SmsTemplateAuditStatusEnum} - */ - private Integer auditStatus; - /** - * 审核未通过的理由 - */ - private String auditReason; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java deleted file mode 100644 index bad40fd..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java +++ /dev/null @@ -1,122 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl; - -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import lombok.extern.slf4j.Slf4j; - -import java.util.List; - -/** - * 短信客户端抽象类 - * - * @author zzf - * @date 2021/2/1 9:28 - */ -@Slf4j -public abstract class AbstractSmsClient implements SmsClient { - - /** - * 短信渠道配置 - */ - protected volatile SmsChannelProperties properties; - /** - * 错误码枚举类 - */ - protected final SmsCodeMapping codeMapping; - - /** - * 短信客户端有参构造函数 - * - * @param properties 短信配置 - */ - public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) { - this.properties = properties; - this.codeMapping = codeMapping; - } - - /** - * 初始化 - */ - public final void init() { - doInit(); - log.info("[init][配置({}) 初始化完成]", properties); - } - - public final void refresh(SmsChannelProperties properties) { - // 判断是否更新 - if (properties.equals(this.properties)) { - return; - } - log.info("[refresh][配置({})发生变化,重新初始化]", properties); - this.properties = properties; - // 初始化 - this.init(); - } - - /** - * 自定义初始化 - */ - protected abstract void doInit(); - - @Override - public Long getId() { - return properties.getId(); - } - - @Override - public final SmsCommonResult sendSms(Long logId, String mobile, - String apiTemplateId, List> templateParams) { - // 执行短信发送 - SmsCommonResult result; - try { - result = doSendSms(logId, mobile, apiTemplateId, templateParams); - } catch (Throwable ex) { - // 打印异常日志 - log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]", - logId, mobile, apiTemplateId, templateParams, ex); - // 封装返回 - return SmsCommonResult.error(ex); - } - return result; - } - - protected abstract SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) - throws Throwable; - - @Override - public List parseSmsReceiveStatus(String text) throws Throwable { - try { - return doParseSmsReceiveStatus(text); - } catch (Throwable ex) { - log.error("[parseSmsReceiveStatus][text({}) 解析发生异常]", text, ex); - throw ex; - } - } - - protected abstract List doParseSmsReceiveStatus(String text) throws Throwable; - - @Override - public SmsCommonResult getSmsTemplate(String apiTemplateId) { - // 执行短信发送 - SmsCommonResult result; - try { - result = doGetSmsTemplate(apiTemplateId); - } catch (Throwable ex) { - // 打印异常日志 - log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex); - // 封装返回 - return SmsCommonResult.error(ex); - } - return result; - } - - protected abstract SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java deleted file mode 100644 index 44f87d7..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl; - -import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; -import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun.AliyunSmsClient; -import cn.iocoder.dashboard.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; -import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import lombok.extern.slf4j.Slf4j; -import org.springframework.util.Assert; -import org.springframework.validation.annotation.Validated; - -import java.util.Arrays; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * 短信客户端工厂接口 - * - * @author zzf - */ -@Validated -@Slf4j -public class SmsClientFactoryImpl implements SmsClientFactory { - - /** - * 短信客户端 Map - * key:渠道编号,使用 {@link SmsChannelProperties#getId()} - */ - private final ConcurrentMap channelIdClients = new ConcurrentHashMap<>(); - - /** - * 短信客户端 Map - * key:渠道编码,使用 {@link SmsChannelProperties#getCode()} ()} - * - * 注意,一些场景下,需要获得某个渠道类型的客户端,所以需要使用它。 - * 例如说,解析短信接收结果,是相对通用的,不需要使用某个渠道编号的 {@link #channelIdClients} - */ - private final ConcurrentMap channelCodeClients = new ConcurrentHashMap<>(); - - public SmsClientFactoryImpl() { - // 初始化 channelCodeClients 集合 - Arrays.stream(SmsChannelEnum.values()).forEach(channel -> { - // 创建一个空的 SmsChannelProperties 对象 - SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode()) - .setApiKey("default").setApiSecret("default"); - // 创建 Sms 客户端 - AbstractSmsClient smsClient = createSmsClient(properties); - channelCodeClients.put(channel.getCode(), smsClient); - }); - } - - @Override - public SmsClient getSmsClient(Long channelId) { - return channelIdClients.get(channelId); - } - - @Override - public SmsClient getSmsClient(String channelCode) { - return channelCodeClients.get(channelCode); - } - - @Override - public void createOrUpdateSmsClient(SmsChannelProperties properties) { - AbstractSmsClient client = channelIdClients.get(properties.getId()); - if (client == null) { - client = this.createSmsClient(properties); - client.init(); - channelIdClients.put(client.getId(), client); - } else { - client.refresh(properties); - } - } - - private AbstractSmsClient createSmsClient(SmsChannelProperties properties) { - SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(properties.getCode()); - Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channelEnum)); - // 创建客户端 - switch (channelEnum) { - case ALIYUN: return new AliyunSmsClient(properties); - case YUN_PIAN: return new YunpianSmsClient(properties); - case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties); - } - // 创建失败,错误日志 + 抛出异常 - log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties); - throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", properties)); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java deleted file mode 100644 index c364722..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ /dev/null @@ -1,212 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; - -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ReflectUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.util.collection.MapUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import com.aliyuncs.AcsRequest; -import com.aliyuncs.AcsResponse; -import com.aliyuncs.DefaultAcsClient; -import com.aliyuncs.IAcsClient; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; -import com.aliyuncs.exceptions.ClientException; -import com.aliyuncs.profile.DefaultProfile; -import com.aliyuncs.profile.IClientProfile; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.annotations.VisibleForTesting; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; - -import java.util.Date; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -import static cn.iocoder.yudao.framework.util.date.DateUtils.TIME_ZONE_DEFAULT; - -/** - * 阿里短信客户端的实现类 - * - * @author zzf - * @date 2021/1/25 14:17 - */ -@Slf4j -public class AliyunSmsClient extends AbstractSmsClient { - - /** - * REGION, 使用杭州 - */ - private static final String ENDPOINT = "cn-hangzhou"; - - /** - * 阿里云客户端 - */ - private volatile IAcsClient client; - - public AliyunSmsClient(SmsChannelProperties properties) { - super(properties, new AliyunSmsCodeMapping()); - Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); - Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); - } - - @Override - protected void doInit() { - IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); - client = new DefaultAcsClient(profile); - } - - @Override - protected SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) { - // 构建参数 - SendSmsRequest request = new SendSmsRequest(); - request.setPhoneNumbers(mobile); - request.setSignName(properties.getSignature()); - request.setTemplateCode(apiTemplateId); - request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); - request.setOutId(String.valueOf(sendLogId)); - // 执行请求 - return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId())); - } - - @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { - List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); - return statuses.stream().map(status -> { - SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); - resp.setSuccess(status.getSuccess()); - resp.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()); - resp.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()); - resp.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId())); - return resp; - }).collect(Collectors.toList()); - } - - @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) { - // 构建参数 - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); - request.setTemplateCode(apiTemplateId); - // 执行请求 - return invoke(request, response -> { - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); - data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); - data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); - return data; - }); - } - - @VisibleForTesting - Integer convertSmsTemplateAuditStatus(Integer templateStatus) { - switch (templateStatus) { - case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); - case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); - case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); - default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); - } - } - - @VisibleForTesting - SmsCommonResult invoke(AcsRequest request, Function responseConsumer) { - try { - // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射 - T sendResult = client.getAcsResponse(request); - String code = (String) ReflectUtil.getFieldValue(sendResult, "code"); - String message = (String) ReflectUtil.getFieldValue(sendResult, "message"); - String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId"); - // 解析结果 - R data = null; - if (Objects.equals(code, "OK")) { // 请求成功的情况下 - data = responseConsumer.apply(sendResult); - } - // 拼接结果 - return SmsCommonResult.build(code, message, requestId, data, codeMapping); - } catch (ClientException ex) { - return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping); - } - } - - private static String formatResultMsg(ClientException ex) { - if (StrUtil.isEmpty(ex.getErrorDescription())) { - return ex.getErrMsg(); - } - return ex.getErrMsg() + " => " + ex.getErrorDescription(); - } - - /** - * 短信接收状态 - * - * 参见 https://help.aliyun.com/document_detail/101867.html 文档 - * - * @author 芋道源码 - */ - @Data - public static class SmsReceiveStatus { - - /** - * 手机号 - */ - @JsonProperty("phone_number") - private String phoneNumber; - /** - * 发送时间 - */ - @JsonProperty("send_time") - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date sendTime; - /** - * 状态报告时间 - */ - @JsonProperty("report_time") - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date reportTime; - /** - * 是否接收成功 - */ - private Boolean success; - /** - * 状态报告说明 - */ - @JsonProperty("err_msg") - private String errMsg; - /** - * 状态报告编码 - */ - @JsonProperty("err_code") - private String errCode; - /** - * 发送序列号 - */ - @JsonProperty("biz_id") - private String bizId; - /** - * 用户序列号 - * - * 这里我们传递的是 SysSmsLogDO 的日志编号 - */ - @JsonProperty("out_id") - private String outId; - /** - * 短信长度,例如说 1、2、3 - * - * 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送 - */ - @JsonProperty("sms_size") - private Integer smsSize; - - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java deleted file mode 100644 index 18ab0e7..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; - -import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; - -/** - * 阿里云的 SmsCodeMapping 实现类 - * - * 参见 https://help.aliyun.com/document_detail/101346.htm 文档 - * - * @author 芋道源码 - */ -public class AliyunSmsCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - switch (apiCode) { - case "OK": return GlobalErrorCodeConstants.SUCCESS; - case "isv.ACCOUNT_NOT_EXISTS": - case "isv.ACCOUNT_ABNORMAL": - case "MissingAccessKeyId": return SMS_ACCOUNT_INVALID; - case "isp.RAM_PERMISSION_DENY": return SMS_PERMISSION_DENY; - case "isv.INVALID_JSON_PARAM": - case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR; - case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_BUSINESS_LIMIT_CONTROL; - case "isv.DAY_LIMIT_CONTROL": return SMS_SEND_DAY_LIMIT_CONTROL; - case "isv.SMS_CONTENT_ILLEGAL": return SMS_SEND_CONTENT_INVALID; - case "isv.SMS_TEMPLATE_ILLEGAL": return SMS_TEMPLATE_INVALID; - case "isv.SMS_SIGNATURE_ILLEGAL": - case "isv.SIGN_NAME_ILLEGAL": - case "isv.SMS_SIGN_ILLEGAL": return SMS_SIGN_INVALID; - case "isv.AMOUNT_NOT_ENOUGH": - case "isv.OUT_OF_SERVICE": return SMS_ACCOUNT_MONEY_NOT_ENOUGH; - case "isv.MOBILE_NUMBER_ILLEGAL": return SMS_MOBILE_INVALID; - case "isv.TEMPLATE_MISSING_PARAMETERS": return SMS_TEMPLATE_PARAM_ERROR; - } - return SMS_UNKNOWN; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java deleted file mode 100644 index efd50a4..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.debug; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; - -import java.util.Objects; - -import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - -/** - * 钉钉的 SmsCodeMapping 实现类 - * - * @author 芋道源码 - */ -public class DebugDingTalkCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - return Objects.equals(apiCode, "0") ? GlobalErrorCodeConstants.SUCCESS : SMS_UNKNOWN; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java deleted file mode 100644 index 2a52abb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.debug; - -import cn.hutool.core.codec.Base64; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.digest.DigestUtil; -import cn.hutool.crypto.digest.HmacAlgorithm; -import cn.hutool.http.HttpUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.util.collection.MapUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 基于钉钉 WebHook 实现的调试的短信客户端实现类 - * - * 考虑到省钱,我们使用钉钉 WebHook 模拟发送短信,方便调试。 - * - * @author 芋道源码 - */ -public class DebugDingTalkSmsClient extends AbstractSmsClient { - - public DebugDingTalkSmsClient(SmsChannelProperties properties) { - super(properties, new DebugDingTalkCodeMapping()); - Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); - Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); - } - - @Override - protected void doInit() { - } - - @Override - protected SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) throws Throwable { - // 构建请求 - String url = buildUrl("robot/send"); - Map params = new HashMap<>(); - params.put("msgtype", "text"); - String content = String.format("【模拟短信】\n手机号:%s\n短信日志编号:%d\n模板参数:%s", - mobile, sendLogId, MapUtils.convertMap(templateParams)); - params.put("text", MapUtil.builder().put("content", content).build()); - // 执行请求 - String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params)); - // 解析结果 - Map responseObj = JsonUtils.parseObject(responseText, Map.class); - return SmsCommonResult.build(MapUtil.getStr(responseObj, "errcode"), MapUtil.getStr(responseObj, "errorMsg"), - null, new SmsSendRespDTO().setSerialNo(StrUtil.uuid()), codeMapping); - } - - /** - * 构建请求地址 - * - * 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档 - * - * @param path 请求路径 - * @return 请求地址 - */ - @SuppressWarnings("SameParameterValue") - private String buildUrl(String path) { - // 生成 timestamp - long timestamp = System.currentTimeMillis(); - // 生成 sign - String secret = properties.getApiSecret(); - String stringToSign = timestamp + "\n" + secret; - byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign); - String sign = Base64.encode(signData); - // 构建最终 URL - return String.format("https://oapi.dingtalk.com/%s?access_token=%s×tamp=%d&sign=%s", - path, properties.getApiKey(), timestamp, sign); - } - - @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { - throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调"); - } - - @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) { - SmsTemplateRespDTO data = new SmsTemplateRespDTO().setId(apiTemplateId).setContent("") - .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(""); - return SmsCommonResult.build("0", "success", null, data, codeMapping); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java deleted file mode 100644 index 44bcfdc..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java +++ /dev/null @@ -1,204 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.URLUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.annotations.VisibleForTesting; -import com.yunpian.sdk.YunpianClient; -import com.yunpian.sdk.constant.YunpianConstant; -import com.yunpian.sdk.model.Result; -import com.yunpian.sdk.model.Template; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; - -import java.util.*; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -import static cn.iocoder.yudao.framework.util.date.DateUtils.TIME_ZONE_DEFAULT; - -/** - * 云片短信客户端的实现类 - * - * @author zzf - * @date 9:48 2021/3/5 - */ -@Slf4j -public class YunpianSmsClient extends AbstractSmsClient { - - /** - * 云信短信客户端 - */ - private volatile YunpianClient client; - - public YunpianSmsClient(SmsChannelProperties properties) { - super(properties, new YunpianSmsCodeMapping()); - Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); - } - - @Override - public void doInit() { - YunpianClient oldClient = client; - // 初始化新的客户端 - YunpianClient newClient = new YunpianClient(properties.getApiKey()); - newClient.init(); - this.client = newClient; - // 销毁老的客户端 - if (oldClient != null) { - oldClient.close(); - } - } - - @Override - protected SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) throws Throwable { - return invoke(() -> { - Map request = new HashMap<>(); - request.put(YunpianConstant.MOBILE, mobile); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - request.put(YunpianConstant.TPL_VALUE, formatTplValue(templateParams)); - request.put(YunpianConstant.UID, String.valueOf(sendLogId)); - request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl()); - return client.sms().tpl_single_send(request); - }, response -> new SmsSendRespDTO().setSerialNo(String.valueOf(response.getSid()))); - } - - private static String formatTplValue(List> templateParams) { - if (CollUtil.isEmpty(templateParams)) { - return ""; - } - // 参考 https://www.yunpian.com/official/document/sms/zh_cn/introduction_demos_encode_sample 格式化 - StringJoiner joiner = new StringJoiner("&"); - templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), URLUtil.encode(String.valueOf(param.getValue()))))); - return joiner.toString(); - } - - @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { - List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); - return statuses.stream().map(status -> { - SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); - resp.setSuccess(Objects.equals(status.getReportStatus(), "SUCCESS")); - resp.setErrorCode(status.getErrorMsg()).setErrorMsg(status.getErrorDetail()); - resp.setMobile(status.getMobile()).setReceiveTime(status.getUserReceiveTime()); - resp.setSerialNo(String.valueOf(status.getSid())).setLogId(status.getUid()); - return resp; - }).collect(Collectors.toList()); - } - - @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable { - return invoke(() -> { - Map request = new HashMap<>(); - request.put(YunpianConstant.APIKEY, properties.getApiKey()); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - return client.tpl().get(request); - }, response -> { - Template template = response.get(0); - return new SmsTemplateRespDTO().setId(String.valueOf(template.getTpl_id())).setContent(template.getTpl_content()) - .setAuditStatus(convertSmsTemplateAuditStatus(template.getCheck_status())).setAuditReason(template.getReason()); - }); - } - - @VisibleForTesting - Integer convertSmsTemplateAuditStatus(String checkStatus) { - switch (checkStatus) { - case "CHECKING": return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); - case "SUCCESS": return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); - case "FAIL": return SmsTemplateAuditStatusEnum.FAIL.getStatus(); - default: throw new IllegalArgumentException(String.format("未知审核状态(%s)", checkStatus)); - } - } - - @VisibleForTesting - SmsCommonResult invoke(Supplier> requestConsumer, Function responseConsumer) throws Throwable { - // 执行请求 - Result result = requestConsumer.get(); - if (result.getThrowable() != null) { - throw result.getThrowable(); - } - // 解析结果 - R data = null; - if (result.getData() != null) { - data = responseConsumer.apply(result.getData()); - } - // 拼接结果 - return SmsCommonResult.build(String.valueOf(result.getCode()), formatResultMsg(result), null, data, codeMapping); - } - - private static String formatResultMsg(Result sendResult) { - if (StrUtil.isEmpty(sendResult.getDetail())) { - return sendResult.getMsg(); - } - return sendResult.getMsg() + " => " + sendResult.getDetail(); - } - - /** - * 短信接收状态 - * - * 参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档 - * - * @author 芋道源码 - */ - @Data - public static class SmsReceiveStatus { - - /** - * 接收状态 - * - * 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收 - */ - @JsonProperty("report_status") - private String reportStatus; - /** - * 接收手机号 - */ - private String mobile; - /** - * 运营商返回的代码,如:"DB:0103" - * - * 由于不同运营商信息不同,此字段仅供参考; - */ - @JsonProperty("error_msg") - private String errorMsg; - /** - * 运营商反馈代码的中文解释 - * - * 默认不推送此字段,如需推送,请联系客服 - */ - @JsonProperty("error_detail") - private String errorDetail; - /** - * 短信编号 - */ - private Long sid; - /** - * 用户自定义 id - * - * 这里我们传递的是 SysSmsLogDO 的日志编号 - */ - private Long uid; - /** - * 用户接收时间 - */ - @JsonProperty("user_receive_time") - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private Date userReceiveTime; - - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java deleted file mode 100644 index 9261684..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; -import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; -import static com.yunpian.sdk.constant.Code.*; - -/** - * 云片的 SmsCodeMapping 实现类 - * - * 参见 https://www.yunpian.com/official/document/sms/zh_CN/returnvalue_common 文档 - * - * @author 芋道源码 - */ -public class YunpianSmsCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - int code = Integer.parseInt(apiCode); - switch (code) { - case OK: return SUCCESS; - case ARGUMENT_MISSING: return SMS_API_PARAM_ERROR; - case BAD_ARGUMENT_FORMAT: return SMS_TEMPLATE_PARAM_ERROR; - case TPL_NOT_FOUND: - case TPL_NOT_VALID: return SMS_TEMPLATE_INVALID; - case MONEY_NOT_ENOUGH: return SMS_ACCOUNT_MONEY_NOT_ENOUGH; - case BLACK_WORD: return SMS_SEND_CONTENT_INVALID; - case DUP_IN_SHORT_TIME: - case TOO_MANY_TIME_IN_5: - case DAY_LIMIT_PER_MOBILE: - case HOUR_LIMIT_PER_MOBILE: return SMS_SEND_BUSINESS_LIMIT_CONTROL; - case BLACK_PHONE_FILTER: return SMS_MOBILE_BLACK; - case SIGN_NOT_MATCH: - case BAD_SIGN_FORMAT: - case SIGN_NOT_VALID: return SMS_SIGN_INVALID; - case BAD_API_KEY: return SMS_ACCOUNT_INVALID; - case API_NOT_ALLOWED: return SMS_PERMISSION_DENY; - case IP_NOT_ALLOWED: return SMS_IP_DENY; - } - return SMS_UNKNOWN; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java deleted file mode 100644 index ba2615d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.enums; - -import cn.hutool.core.util.ArrayUtil; -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 短信渠道枚举 - * - * @author zzf - * @date 2021/1/25 10:56 - */ -@Getter -@AllArgsConstructor -public enum SmsChannelEnum { - - DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"), - YUN_PIAN("YUN_PIAN", "云片"), - ALIYUN("ALIYUN", "阿里云"), -// TENCENT("TENCENT", "腾讯云"), -// HUA_WEI("HUA_WEI", "华为云"), - ; - - /** - * 编码 - */ - private final String code; - /** - * 名字 - */ - private final String name; - - public static SmsChannelEnum getByCode(String code) { - return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java deleted file mode 100644 index bfd77fb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * 短信框架的错误码枚举 - * - * 短信框架,使用 2-001-000-000 段 - * - * @author 芋道源码 - */ -public interface SmsFrameworkErrorCodeConstants { - - ErrorCode SMS_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析"); - - // ========== 权限 / 限流等相关 2001000100 ========== - - ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); - // 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信 - ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); - - // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 - ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流"); - // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 - ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流"); - - ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词"); - - // ========== 模板相关 2001000200 ========== - ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在 - ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确"); - - // ========== 签名相关 2001000300 ========== - ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用"); - - // ========== 账户相关 2001000400 ========== - ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足"); - ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在"); - - // ========== 其它相关 2001000900 开头 ========== - ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失"); - ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确"); - ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中"); - - ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常"); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java deleted file mode 100644 index 888b2ee..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 短信模板的审核状态枚举 - * - * @author 芋道源码 - */ -@AllArgsConstructor -@Getter -public enum SmsTemplateAuditStatusEnum { - - CHECKING(1), - SUCCESS(2), - FAIL(3); - - private final Integer status; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java deleted file mode 100644 index 750f2e7..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.property; - -import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; -import lombok.Data; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -/** - * 短信渠道配置类 - * - * @author zzf - * @date 2021/1/25 17:01 - */ -@Data -@Validated -public class SmsChannelProperties { - - /** - * 渠道编号 - */ - @NotNull(message = "短信渠道 ID 不能为空") - private Long id; - /** - * 短信签名 - */ - @NotEmpty(message = "短信签名不能为空") - private String signature; - /** - * 渠道编码 - * - * 枚举 {@link SmsChannelEnum} - */ - @NotEmpty(message = "渠道编码不能为空") - private String code; - /** - * 短信 API 的账号 - */ - @NotEmpty(message = "短信 API 的账号不能为空") - private String apiKey; - /** - * 短信 API 的秘钥 - */ - @NotEmpty(message = "短信 API 的秘钥不能为空") - private String apiSecret; - /** - * 短信发送回调 URL - */ - private String callbackUrl; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/package-info.java deleted file mode 100644 index 3d9e7de..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.framework.test.core; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java deleted file mode 100644 index 9f7e501..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.iocoder.dashboard.framework.test.core.util; - -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.function.Executable; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Objects; - -import static org.junit.jupiter.api.Assertions.assertThrows; - -/** - * 单元测试,assert 断言工具类 - * - * @author 芋道源码 - */ -public class AssertUtils { - - /** - * 比对两个对象的属性是否一致 - * - * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略 - * - * @param expected 期望对象 - * @param actual 实际对象 - * @param ignoreFields 忽略的属性数组 - */ - public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) { - Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); - Arrays.stream(expectedFields).forEach(expectedField -> { - // 如果是忽略的属性,则不进行比对 - if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { - return; - } - // 忽略不存在的属性 - Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); - if (actualField == null) { - return; - } - // 比对 - Assertions.assertEquals( - ReflectUtil.getFieldValue(expected, expectedField), - ReflectUtil.getFieldValue(actual, actualField), - String.format("Field(%s) 不匹配", expectedField.getName()) - ); - }); - } - - /** - * 比对两个对象的属性是否一致 - * - * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略 - * - * @param expected 期望对象 - * @param actual 实际对象 - * @param ignoreFields 忽略的属性数组 - * @return 是否一致 - */ - public static boolean isPojoEquals(Object expected, Object actual, String... ignoreFields) { - Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); - return Arrays.stream(expectedFields).allMatch(expectedField -> { - // 如果是忽略的属性,则不进行比对 - if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { - return true; - } - // 忽略不存在的属性 - Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); - if (actualField == null) { - return true; - } - return Objects.equals(ReflectUtil.getFieldValue(expected, expectedField), - ReflectUtil.getFieldValue(actual, actualField)); - }); - } - - /** - * 执行方法,校验抛出的 Service 是否符合条件 - * - * @param executable 业务异常 - * @param errorCode 错误码对象 - * @param messageParams 消息参数 - */ - public static void assertServiceException(Executable executable, ErrorCode errorCode, Object... messageParams) { - // 调用方法 - ServiceException serviceException = assertThrows(ServiceException.class, executable); - // 校验错误码 - Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配"); - String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), messageParams); - Assertions.assertEquals(message, serviceException.getMessage(), "错误提示不匹配"); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java deleted file mode 100644 index 7ac7b28..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -package cn.iocoder.dashboard.framework.test.core.util; - -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.lang.reflect.Type; -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * 随机工具类 - * - * @author 芋道源码 - */ -public class RandomUtils { - - private static final int RANDOM_STRING_LENGTH = 10; - - private static final int RANDOM_DATE_MAX = 30; - - private static final int RANDOM_COLLECTION_LENGTH = 5; - - private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl(); - - static { - // 字符串 - PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class, - (dataProviderStrategy, attributeMetadata, map) -> randomString()); - // Boolean - PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { - // 如果是 deleted 的字段,返回非删除 - if (attributeMetadata.getAttributeName().equals("deleted")) { - return false; - } - return RandomUtil.randomBoolean(); - }); - } - - public static String randomString() { - return RandomUtil.randomString(RANDOM_STRING_LENGTH); - } - - public static Long randomLongId() { - return RandomUtil.randomLong(0, Long.MAX_VALUE); - } - - public static Integer randomInteger() { - return RandomUtil.randomInt(0, Integer.MAX_VALUE); - } - - public static Date randomDate() { - return RandomUtil.randomDay(0, RANDOM_DATE_MAX); - } - - public static Short randomShort() { - return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); - } - - public static Set randomSet(Class clazz) { - return Stream.iterate(0, i -> i).limit(RandomUtil.randomInt(0, RANDOM_DATE_MAX)) - .map(i -> randomPojo(clazz)).collect(Collectors.toSet()); - } - - public static Integer randomCommonStatus() { - return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); - } - - @SafeVarargs - public static T randomPojo(Class clazz, Consumer... consumers) { - T pojo = PODAM_FACTORY.manufacturePojo(clazz); - // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 - if (ArrayUtil.isNotEmpty(consumers)) { - Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo)); - } - return pojo; - } - - @SafeVarargs - public static T randomPojo(Class clazz, Type type, Consumer... consumers) { - T pojo = PODAM_FACTORY.manufacturePojo(clazz, type); - // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 - if (ArrayUtil.isNotEmpty(consumers)) { - Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo)); - } - return pojo; - } - - @SafeVarargs - public static List randomPojoList(Class clazz, Consumer... consumers) { - int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH); - return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers)) - .collect(Collectors.toList()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java deleted file mode 100644 index fa02213..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 测试组件,用于单元测试、集成测试等等 - */ -package cn.iocoder.dashboard.framework.test; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java deleted file mode 100644 index 7918c8c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.dashboard.framework.tracer.config; - -import cn.iocoder.dashboard.framework.tracer.core.aop.BizTraceAspect; -import cn.iocoder.dashboard.framework.tracer.core.filter.TraceFilter; -import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; -import io.opentracing.Tracer; -import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Tracer 配置类 - * - * @author mashu - */ -@Configuration -@ConditionalOnClass({BizTraceAspect.class}) -@EnableConfigurationProperties(TracerProperties.class) -@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) -public class TracerAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public TracerProperties bizTracerProperties() { - return new TracerProperties(); - } - - @Bean - @ConditionalOnMissingBean - public BizTraceAspect bizTracingAop() { - return new BizTraceAspect(); - } - - @Bean - @ConditionalOnMissingBean - public Tracer tracer() { - return new SkywalkingTracer(); - } - - /** - * 创建 TraceFilter 过滤器,响应 header 设置 traceId - */ - @Bean - public FilterRegistrationBean traceFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); - registrationBean.setFilter(new TraceFilter()); - registrationBean.setOrder(WebFilterOrderEnum.TRACE_FILTER); - return registrationBean; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerProperties.java deleted file mode 100644 index 093179c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerProperties.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.dashboard.framework.tracer.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * BizTracer配置类 - * - * @author 麻薯 - */ -@ConfigurationProperties("yudao.tracer") -@Data -public class TracerProperties { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/annotation/BizTrace.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/annotation/BizTrace.java deleted file mode 100644 index 3907cac..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/annotation/BizTrace.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.dashboard.framework.tracer.core.annotation; - -import java.lang.annotation.*; - -/** - * 打印业务编号 / 业务类型注解 - * - * 使用时,需要设置 SkyWalking OAP Server 的 application.yaml 配置文件,修改 SW_SEARCHABLE_TAG_KEYS 配置项, - * 增加 biz.type 和 biz.id 两值,然后重启 SkyWalking OAP Server 服务器。 - * - * @author 麻薯 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface BizTrace { - - /** - * 业务编号 tag 名 - */ - String ID_TAG = "biz.id"; - /** - * 业务类型 tag 名 - */ - String TYPE_TAG = "biz.type"; - - /** - * @return 操作名 - */ - String operationName() default ""; - - /** - * @return 业务编号 - */ - String id(); - - /** - * @return 业务类型 - */ - String type(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/aop/BizTraceAspect.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/aop/BizTraceAspect.java deleted file mode 100644 index dce9fce..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/aop/BizTraceAspect.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.dashboard.framework.tracer.core.aop; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.dashboard.framework.tracer.core.annotation.BizTrace; -import cn.iocoder.yudao.framework.util.sping.SpringExpressionUtils; -import io.opentracing.Span; -import io.opentracing.Tracer; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; - -import javax.annotation.Resource; -import java.util.Map; - -import static java.util.Arrays.asList; - -/** - * {@link BizTrace} 切面,记录业务链路 - * - * @author mashu - */ -@Aspect -@Slf4j -public class BizTraceAspect { - - private static final String BIZ_OPERATION_NAME_PREFIX = "Biz/"; - - @Resource - private Tracer tracer; - - @Around(value = "@annotation(trace)") - public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable { - // 创建 span - String operationName = getOperationName(joinPoint, trace); - Span span = tracer.buildSpan(operationName).startManual(); - try { - // 执行原有方法 - return joinPoint.proceed(); - } finally { - // 设置 Span 的 biz 属性 - setBizTag(span, joinPoint, trace); - // 完成 Span - span.finish(); - } - } - - private String getOperationName(ProceedingJoinPoint joinPoint, BizTrace trace) { - // 自定义操作名 - if (StrUtil.isNotEmpty(trace.operationName())) { - return BIZ_OPERATION_NAME_PREFIX + trace.operationName(); - } - // 默认操作名,使用方法名 - return BIZ_OPERATION_NAME_PREFIX - + joinPoint.getSignature().getDeclaringType().getSimpleName() - + "/" + joinPoint.getSignature().getName(); - } - - private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) { - try { - Map result = SpringExpressionUtils.parseExpressions(joinPoint, asList(trace.type(), trace.id())); - span.setTag(BizTrace.TYPE_TAG, MapUtil.getStr(result, trace.type())); - span.setTag(BizTrace.ID_TAG, MapUtil.getStr(result, trace.id())); - } catch (Exception ex) { - log.error("[setBizTag][解析 bizType 与 bizId 发生异常]", ex); - } - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java deleted file mode 100644 index 49294cc..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.dashboard.framework.tracer.core.filter; - -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Trace 过滤器,打印 traceId 到 header 中返回 - * - * @author 芋道源码 - */ -public class TraceFilter extends OncePerRequestFilter { - - /** - * Header 名 - 链路追踪编号 - */ - private static final String HEADER_NAME_TRACE_ID = "trace-id"; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) - throws IOException, ServletException { - // 设置响应 traceId - response.addHeader(HEADER_NAME_TRACE_ID, TracerUtils.getTraceId()); - // 继续过滤 - chain.doFilter(request, response); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/package-info.java deleted file mode 100644 index c0c3df4..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 使用 SkyWalking 组件,作为链路追踪、日志中心。 - * - * @author 芋道源码 - */ -package cn.iocoder.dashboard.framework.tracer; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md deleted file mode 100644 index ed9d4fe..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnum.java deleted file mode 100644 index 61829e0..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnum.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.dashboard.framework.validator; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.*; - -@Target({ - ElementType.METHOD, - ElementType.FIELD, - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.PARAMETER, - ElementType.TYPE_USE -}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Constraint( - validatedBy = InEnumValidator.class -) -public @interface InEnum { - - /** - * @return 实现 EnumValuable 接口的 - */ - Class value(); - - String message() default "必须在指定范围 {value}"; - - Class[] groups() default {}; - - Class[] payload() default {}; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnumValidator.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnumValidator.java deleted file mode 100644 index b20e73d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/InEnumValidator.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.dashboard.framework.validator; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; - -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 { - - private List values; - - @Override - public void initialize(InEnum annotation) { - IntArrayValuable[] values = annotation.value().getEnumConstants(); - if (values.length == 0) { - this.values = Collections.emptyList(); - } else { - this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList()); - } - } - - @Override - public boolean isValid(Integer value, ConstraintValidatorContext context) { - // 为空时,默认不校验,即认为通过 - if (value == null) { - return true; - } - // 校验通过 - if (values.contains(value)) { - return true; - } - // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值) - context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 - context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate() - .replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句 - return false; - } - -} - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/package-info.java deleted file mode 100644 index e6a861e..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 使用 Hibernate Validator 实现参数校验 - */ -package cn.iocoder.dashboard.framework.validator; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/《芋道 Spring Boot 参数校验 Validation 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/《芋道 Spring Boot 参数校验 Validation 入门》.md deleted file mode 100644 index b2c2cf8..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/validator/《芋道 Spring Boot 参数校验 Validation 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/BaseMockitoUnitTest.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/BaseMockitoUnitTest.java deleted file mode 100644 index 15d6a52..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/BaseMockitoUnitTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.dashboard.framework; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; - -/** - * 纯 Mockito 的单元测试 - * - * @author 芋道源码 - */ -@ExtendWith(MockitoExtension.class) -public class BaseMockitoUnitTest { -} diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java deleted file mode 100644 index 0928eb2..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ /dev/null @@ -1,224 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; - -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.dashboard.framework.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.util.collection.MapUtils; -import cn.iocoder.yudao.framework.util.date.DateUtils; -import com.aliyuncs.AcsRequest; -import com.aliyuncs.IAcsClient; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; -import com.aliyuncs.exceptions.ClientException; -import com.google.common.collect.Lists; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatcher; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import java.util.List; -import java.util.function.Function; - -import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR; -import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.util.json.JsonUtils.toJsonString; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.when; - -/** - * {@link AliyunSmsClient} 的单元测试 - * - * @author 芋道源码 - */ -public class AliyunSmsClientTest extends BaseMockitoUnitTest { - - private final SmsChannelProperties properties = new SmsChannelProperties() - .setApiKey(randomString()) // 随机一个 apiKey,避免构建报错 - .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错 - .setSignature("芋道源码"); - - @InjectMocks - private final AliyunSmsClient smsClient = new AliyunSmsClient(properties); - - @Mock - private IAcsClient client; - - @Test - public void testDoInit() { - // 准备参数 - // mock 方法 - - // 调用 - smsClient.doInit(); - // 断言 - assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "acsClient")); - } - - @Test - @SuppressWarnings("unchecked") - public void testDoSendSms() throws ClientException { - // 准备参数 - Long sendLogId = randomLongId(); - String mobile = randomString(); - String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); - // mock 方法 - SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("OK")); - when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { - assertEquals(mobile, acsRequest.getPhoneNumbers()); - assertEquals(properties.getSignature(), acsRequest.getSignName()); - assertEquals(apiTemplateId, acsRequest.getTemplateCode()); - assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); - assertEquals(sendLogId.toString(), acsRequest.getOutId()); - return true; - }))).thenReturn(response); - - // 调用 - SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, - apiTemplateId, templateParams); - // 断言 - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getBizId(), result.getData().getSerialNo()); - } - - @Test - public void testDoTParseSmsReceiveStatus() throws Throwable { - // 准备参数 - String text = "[\n" + - " {\n" + - " \"phone_number\" : \"13900000001\",\n" + - " \"send_time\" : \"2017-01-01 11:12:13\",\n" + - " \"report_time\" : \"2017-02-02 22:23:24\",\n" + - " \"success\" : true,\n" + - " \"err_code\" : \"DELIVERED\",\n" + - " \"err_msg\" : \"用户接收成功\",\n" + - " \"sms_size\" : \"1\",\n" + - " \"biz_id\" : \"12345\",\n" + - " \"out_id\" : \"67890\"\n" + - " }\n" + - "]"; - // mock 方法 - - // 调用 - List statuses = smsClient.doParseSmsReceiveStatus(text); - // 断言 - assertEquals(1, statuses.size()); - assertTrue(statuses.get(0).getSuccess()); - assertEquals("DELIVERED", statuses.get(0).getErrorCode()); - assertEquals("用户接收成功", statuses.get(0).getErrorMsg()); - assertEquals("13900000001", statuses.get(0).getMobile()); - assertEquals(DateUtils.buildTime(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime()); - assertEquals("12345", statuses.get(0).getSerialNo()); - assertEquals(67890L, statuses.get(0).getLogId()); - } - - @Test - public void testDoGetSmsTemplate() throws ClientException { - // 准备参数 - String apiTemplateId = randomString(); - // mock 方法 - QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { - o.setCode("OK"); - o.setTemplateStatus(1); // 设置模板通过 - }); - when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { - assertEquals(apiTemplateId, acsRequest.getTemplateCode()); - return true; - }))).thenReturn(response); - - // 调用 - SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId); - // 断言 - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getTemplateCode(), result.getData().getId()); - assertEquals(response.getTemplateContent(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(response.getReason(), result.getData().getAuditReason()); - } - - @Test - public void testConvertSmsTemplateAuditStatus() { - assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), - smsClient.convertSmsTemplateAuditStatus(0)); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), - smsClient.convertSmsTemplateAuditStatus(1)); - assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), - smsClient.convertSmsTemplateAuditStatus(2)); - assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus(3), - "未知审核状态(3)"); - } - - @Test - @SuppressWarnings("unchecked") - public void testInvoke_throwable() throws ClientException { - // 准备参数 - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); - // mock 方法 - ClientException ex = new ClientException("isv.INVALID_PARAMETERS", "参数不正确", randomString()); - when(client.getAcsResponse(any(AcsRequest.class))).thenThrow(ex); - - // 调用,并断言异常 - SmsCommonResult result = smsClient.invoke(request,null); - // 断言 - assertEquals(ex.getErrCode(), result.getApiCode()); - assertEquals(ex.getErrMsg(), result.getApiMsg()); - assertEquals(SMS_API_PARAM_ERROR.getCode(), result.getCode()); - assertEquals(SMS_API_PARAM_ERROR.getMsg(), result.getMsg()); - assertEquals(ex.getRequestId(), result.getApiRequestId()); - } - - @Test - public void testInvoke_success() throws ClientException { - // 准备参数 - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); - Function responseConsumer = response -> { - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); - data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); - data.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(response.getReason()); - return data; - }; - // mock 方法 - QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { - o.setCode("OK"); - o.setTemplateStatus(1); // 设置模板通过 - }); - when(client.getAcsResponse(any(AcsRequest.class))).thenReturn(response); - - // 调用 - SmsCommonResult result = smsClient.invoke(request, responseConsumer); - // 断言 - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getTemplateCode(), result.getData().getId()); - assertEquals(response.getTemplateContent(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(response.getReason(), result.getData().getAuditReason()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java deleted file mode 100644 index da0f2ef..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; - -import cn.iocoder.dashboard.framework.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link AliyunSmsCodeMapping} 的单元测试 - * - * @author 芋道源码 - */ -public class AliyunSmsCodeMappingTest extends BaseMockitoUnitTest { - - @InjectMocks - private AliyunSmsCodeMapping codeMapping; - - @Test - public void testApply() { - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply("OK")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("MissingAccessKeyId")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_NOT_EXISTS")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_ABNORMAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("isv.DAY_LIMIT_CONTROL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("isv.SMS_CONTENT_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGN_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SIGN_NAME_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("isp.RAM_PERMISSION_DENY")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.OUT_OF_SERVICE")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.AMOUNT_NOT_ENOUGH")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("isv.SMS_TEMPLATE_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGNATURE_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_PARAMETERS")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_JSON_PARAM")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("isv.MOBILE_NUMBER_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("isv.TEMPLATE_MISSING_PARAMETERS")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("isv.BUSINESS_LIMIT_CONTROL")); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/package-info.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/package-info.java deleted file mode 100644 index 42e9b06..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl; diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java deleted file mode 100644 index ba50ce1..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java +++ /dev/null @@ -1,202 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; - -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.dashboard.framework.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.util.date.DateUtils; -import com.google.common.collect.Lists; -import com.yunpian.sdk.YunpianClient; -import com.yunpian.sdk.api.SmsApi; -import com.yunpian.sdk.api.TplApi; -import com.yunpian.sdk.constant.YunpianConstant; -import com.yunpian.sdk.model.Result; -import com.yunpian.sdk.model.SmsSingleSend; -import com.yunpian.sdk.model.Template; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; - -import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; -import static com.yunpian.sdk.constant.Code.OK; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * 对 {@link YunpianSmsClient} 的单元测试 - * - * @author 芋道源码 - */ -public class YunpianSmsClientTest extends BaseMockitoUnitTest { - - private final SmsChannelProperties properties = new SmsChannelProperties() - .setApiKey(randomString()); // 随机一个 apiKey,避免构建报错 - - @InjectMocks - private final YunpianSmsClient smsClient = new YunpianSmsClient(properties); - - @Mock - private YunpianClient client; - - @Test - public void testDoInit() { - // 准备参数 - // mock 方法 - - // 调用 - smsClient.doInit(); - // 断言 - assertNotEquals(client, ReflectUtil.getFieldValue(smsClient, "client")); - verify(client, times(1)).close(); - } - - @Test - @SuppressWarnings("unchecked") - public void testDoSendSms() throws Throwable { - // 准备参数 - Long sendLogId = randomLongId(); - String mobile = randomString(); - String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); - // mock sms 方法 - SmsApi smsApi = mock(SmsApi.class); - when(client.sms()).thenReturn(smsApi); - // mock tpl_single_send 方法 - Map request = new HashMap<>(); - request.put(YunpianConstant.MOBILE, mobile); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - request.put(YunpianConstant.TPL_VALUE, "#code#=1234&#op#=login"); - request.put(YunpianConstant.UID, String.valueOf(sendLogId)); - request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl()); - Result responseResult = randomPojo(Result.class, SmsSingleSend.class, - o -> o.setCode(OK)); // API 发送成功的 code - when(smsApi.tpl_single_send(eq(request))).thenReturn(responseResult); - - // 调用 - SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, - apiTemplateId, templateParams); - // 断言 - assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); - assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertNull(result.getApiRequestId()); - // 断言结果 - assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo()); - } - - @Test - public void testDoParseSmsReceiveStatus() throws Throwable { - // 准备参数 - String text = "[{\"sid\":9527,\"uid\":1024,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"}]"; - // mock 方法 - - // 调用 - - // 断言 - // 调用 - List statuses = smsClient.doParseSmsReceiveStatus(text); - // 断言 - assertEquals(1, statuses.size()); - assertTrue(statuses.get(0).getSuccess()); - assertEquals("", statuses.get(0).getErrorCode()); - assertNull(statuses.get(0).getErrorMsg()); - assertEquals("15205201314", statuses.get(0).getMobile()); - assertEquals(DateUtils.buildTime(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime()); - assertEquals("9527", statuses.get(0).getSerialNo()); - assertEquals(1024L, statuses.get(0).getLogId()); - } - - @Test - @SuppressWarnings("unchecked") - public void testDoGetSmsTemplate() throws Throwable { - // 准备参数 - String apiTemplateId = randomString(); - // mock tpl 方法 - TplApi tplApi = mock(TplApi.class); - when(client.tpl()).thenReturn(tplApi); - // mock get 方法 - Map request = new HashMap<>(); - request.put(YunpianConstant.APIKEY, properties.getApiKey()); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - Result> responseResult = randomPojo(Result.class, List.class, o -> { - o.setCode(OK); // API 发送成功的 code - o.setData(randomPojoList(Template.class, t -> t.setCheck_status("SUCCESS"))); - }); - when(tplApi.get(eq(request))).thenReturn(responseResult); - - // 调用 - SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId); - // 断言 - assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); - assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertNull(result.getApiRequestId()); - // 断言结果 - Template template = responseResult.getData().get(0); - assertEquals(template.getTpl_id().toString(), result.getData().getId()); - assertEquals(template.getTpl_content(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(template.getReason(), result.getData().getAuditReason()); - } - - @Test - public void testConvertSmsTemplateAuditStatus() { - assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), - smsClient.convertSmsTemplateAuditStatus("CHECKING")); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), - smsClient.convertSmsTemplateAuditStatus("SUCCESS")); - assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), - smsClient.convertSmsTemplateAuditStatus("FAIL")); - assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus("test"), - "未知审核状态(test)"); - } - - @Test - public void testInvoke_throwable() { - // 准备参数 - Supplier> requestConsumer = - () -> new Result<>().setThrowable(new NullPointerException()); - // mock 方法 - - // 调用,并断言异常 - assertThrows(NullPointerException.class, - () -> smsClient.invoke(requestConsumer, null)); - } - - @Test - @SuppressWarnings("unchecked") - public void testInvoke_success() throws Throwable { - // 准备参数 - Result responseResult = randomPojo(Result.class, SmsSingleSend.class, o -> o.setCode(OK)); - Supplier> requestConsumer = () -> responseResult; - Function responseConsumer = - smsSingleSend -> new SmsSendRespDTO().setSerialNo(String.valueOf(responseResult.getData().getSid())); - // mock 方法 - - // 调用 - SmsCommonResult result = smsClient.invoke(requestConsumer, responseConsumer); - // 断言 - assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); - assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertNull(result.getApiRequestId()); - assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java deleted file mode 100644 index b2d7baa..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; - -import cn.iocoder.dashboard.framework.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; - -import static com.yunpian.sdk.constant.Code.*; -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link YunpianSmsCodeMapping} 的单元测试 - * - * @author 芋道源码 - */ -class YunpianSmsCodeMappingTest extends BaseMockitoUnitTest { - - @InjectMocks - private YunpianSmsCodeMapping codeMapping; - - @Test - public void testApply() { - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(String.valueOf(OK))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply(String.valueOf(ARGUMENT_MISSING))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply(String.valueOf(BAD_ARGUMENT_FORMAT))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply(String.valueOf(MONEY_NOT_ENOUGH))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_FOUND))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_VALID))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DUP_IN_SHORT_TIME))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(TOO_MANY_TIME_IN_5))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DAY_LIMIT_PER_MOBILE))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(HOUR_LIMIT_PER_MOBILE))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply(String.valueOf(BLACK_PHONE_FILTER))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_MATCH))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_VALID))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(BAD_SIGN_FORMAT))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply(String.valueOf(BAD_API_KEY))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply(String.valueOf(API_NOT_ALLOWED))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply(String.valueOf(IP_NOT_ALLOWED))); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/package-info.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/package-info.java deleted file mode 100644 index 037ce8c..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core.client; diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/package-info.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/package-info.java deleted file mode 100644 index ec8f3ea..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.framework.sms.core; diff --git a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/package-info.java b/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/package-info.java deleted file mode 100644 index ba591dc..0000000 --- a/yudao-framework/yudao-framework-all/src/test/java/cn/iocoder/dashboard/framework/sms/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.framework.sms; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-dict/pom.xml new file mode 100644 index 0000000..d40b1a8 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/pom.xml @@ -0,0 +1,30 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-biz-dict + jar + + ${artifactId} + 字典类型、数据 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter + + + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/DictConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/DictConfiguration.java new file mode 100644 index 0000000..551872f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/DictConfiguration.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.framework.dict.config; + +import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService; +import cn.iocoder.yudao.framework.dict.core.util.DictUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DictConfiguration { + + @Bean + @SuppressWarnings("InstantiationOfUtilityClass") + public DictUtils dictUtils(DictDataFrameworkService service) { + DictUtils.init(service); + return new DictUtils(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/dto/DictDataRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/dto/DictDataRespDTO.java new file mode 100644 index 0000000..150ee75 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/dto/DictDataRespDTO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.framework.dict.core.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +/** + * 字典数据 Response DTO + * + * @author 芋道源码 + */ +@Data +public class DictDataRespDTO { + + /** + * 字典标签 + */ + private String label; + /** + * 字典值 + */ + private String value; + /** + * 字典类型 + */ + private String dictType; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/service/DictDataFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/service/DictDataFrameworkService.java new file mode 100644 index 0000000..6ff51c3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/service/DictDataFrameworkService.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.dict.core.service; + +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; + +import java.util.List; + +public interface DictDataFrameworkService { + + /** + * 获得指定的字典数据,从缓存中 + * + * @param type 字典类型 + * @param value 字典数据值 + * @return 字典数据 + */ + DictDataRespDTO getDictDataFromCache(String type, String value); + + /** + * 解析获得指定的字典数据,从缓存中 + * + * @param type 字典类型 + * @param label 字典数据标签 + * @return 字典数据 + */ + DictDataRespDTO parseDictDataFromCache(String type, String label); + + /** + * 获得指定类型的字典数据,从缓存中 + * + * @param type 字典类型 + * @return 字典数据列表 + */ + List listDictDatasFromCache(String type); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictUtils.java new file mode 100644 index 0000000..1e2ce43 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictUtils.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.dict.core.util; + +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; +import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService; +import lombok.extern.slf4j.Slf4j; + +/** + * 字典工具类 + */ +@Slf4j +public class DictUtils { + + private static DictDataFrameworkService service; + + public static void init(DictDataFrameworkService service) { + DictUtils.service = service; + log.info("[init][初始化 DictUtils 成功]"); + } + + public static DictDataRespDTO getDictDataFromCache(String type, String value) { + return service.getDictDataFromCache(type, value); + } + + public static DictDataRespDTO parseDictDataFromCache(String type, String label) { + return service.getDictDataFromCache(type, label); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/package-info.java new file mode 100644 index 0000000..a3226af --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/package-info.java @@ -0,0 +1,6 @@ +/** + * 字典数据模块,提供 {@link cn.iocoder.yudao.framework.dict.core.util.DictUtils} 工具类 + * + * 通过将字典缓存在内存中,保证性能 + */ +package cn.iocoder.yudao.framework.dict; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml new file mode 100644 index 0000000..233572b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml @@ -0,0 +1,44 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-biz-operatelog + jar + + ${artifactId} + 操作日志 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + provided + + + + + com.google.guava + guava + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java new file mode 100644 index 0000000..c4e784b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.framework.operatelog.config; + +import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class YudaoOperateLogAutoConfiguration { + + @Bean + public OperateLogAspect operateLogAspect() { + return new OperateLogAspect(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java new file mode 100644 index 0000000..2f9ecaf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.framework.operatelog.core.annotations; + +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 操作日志注解 + * + * @author 芋道源码 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface OperateLog { + + // ========== 模块字段 ========== + + /** + * 操作模块 + * + * 为空时,会尝试读取 {@link Api#value()} 属性 + */ + String module() default ""; + /** + * 操作名 + * + * 为空时,会尝试读取 {@link ApiOperation#value()} 属性 + */ + String name() default ""; + /** + * 操作分类 + * + * 实际并不是数组,因为枚举不能设置 null 作为默认值 + */ + OperateTypeEnum[] type() default {}; + + // ========== 开关字段 ========== + + /** + * 是否记录操作日志 + */ + boolean enable() default true; + /** + * 是否记录方法参数 + */ + boolean logArgs() default true; + /** + * 是否记录方法结果的数据 + */ + boolean logResultData() default true; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java new file mode 100644 index 0000000..1c5580c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java @@ -0,0 +1,354 @@ +package cn.iocoder.yudao.framework.operatelog.core.aop; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import com.google.common.collect.Maps; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.IntStream; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; + +/** + * 拦截使用 @OperateLog 注解,如果满足条件,则生成操作日志。 + * 满足如下任一条件,则会进行记录: + * 1. 使用 @ApiOperation + 非 @GetMapping + * 2. 使用 @OperateLog 注解 + * + * 但是,如果声明 @OperateLog 注解时,将 enable 属性设置为 false 时,强制不记录。 + * + * @author 芋道源码 + */ +@Aspect +@Slf4j +public class OperateLogAspect { + + /** + * 用于记录操作内容的上下文 + * + * @see OperateLogCreateReqDTO#getContent() + */ + private static final ThreadLocal CONTENT = new ThreadLocal<>(); + /** + * 用于记录拓展字段的上下文 + * + * @see OperateLogCreateReqDTO#getExts() + */ + private static final ThreadLocal> EXTS = new ThreadLocal<>(); + + @Resource + private OperateLogFrameworkService operateLogFrameworkService; + + @Around("@annotation(apiOperation)") + public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable { + // 可能也添加了 @ApiOperation 注解 + OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class); + return around0(joinPoint, operateLog, apiOperation); + } + + @Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况 + public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable { + return around0(joinPoint, operateLog, null); + } + + private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable { + // 记录开始时间 + Date startTime = new Date(); + try { + // 执行原有方法 + Object result = joinPoint.proceed(); + // 记录正常执行时的操作日志 + this.log(joinPoint, operateLog, apiOperation, startTime, result, null); + return result; + } catch (Throwable exception) { + this.log(joinPoint, operateLog, apiOperation, startTime, null, exception); + throw exception; + } finally { + clearThreadLocal(); + } + } + + public static void setContent(String content) { + CONTENT.set(content); + } + + public static void addExt(String key, Object value) { + if (EXTS.get() == null) { + EXTS.set(new HashMap<>()); + } + EXTS.get().put(key, value); + } + + private static void clearThreadLocal() { + CONTENT.remove(); + EXTS.remove(); + } + + private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, + Date startTime, Object result, Throwable exception) { + try { + // 判断不记录的情况 + if (!isLogEnable(joinPoint, operateLog)) { + return; + } + // 真正记录操作日志 + this.log0(joinPoint, operateLog, apiOperation, startTime, result, exception); + } catch (Throwable ex) { + log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) operateLog({}) apiOperation({}) result({}) exception({}) ]", + joinPoint, operateLog, apiOperation, result, exception, ex); + } + } + + private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, + Date startTime, Object result, Throwable exception) { + OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO(); + // 补全通用字段 + operateLogDTO.setTraceId(TracerUtils.getTraceId()); + operateLogDTO.setStartTime(startTime); + // 补充用户信息 + fillUserFields(operateLogDTO); + // 补全模块信息 + fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation); + // 补全请求信息 + fillRequestFields(operateLogDTO); + // 补全方法信息 + fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception); + + // 异步记录日志 + operateLogFrameworkService.createOperateLogAsync(operateLogDTO); + } + + private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { + operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId()); + } + + private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, + ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) { + // module 属性 + if (operateLog != null) { + operateLogDTO.setModule(operateLog.module()); + } + if (StrUtil.isEmpty(operateLogDTO.getModule())) { + Api api = getClassAnnotation(joinPoint, Api.class); + if (api != null) { + // 优先读取 @API 的 name 属性 + if (StrUtil.isNotEmpty(api.value())) { + operateLogDTO.setModule(api.value()); + } + // 没有的话,读取 @API 的 tags 属性 + if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) { + operateLogDTO.setModule(api.tags()[0]); + } + } + } + // name 属性 + if (operateLog != null) { + operateLogDTO.setName(operateLog.name()); + } + if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) { + operateLogDTO.setName(apiOperation.value()); + } + // type 属性 + if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) { + operateLogDTO.setType(operateLog.type()[0].getType()); + } + if (operateLogDTO.getType() == null) { + RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); + OperateTypeEnum operateLogType = convertOperateLogType(requestMethod); + operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null); + } + // content 和 exts 属性 + operateLogDTO.setContent(CONTENT.get()); + operateLogDTO.setExts(EXTS.get()); + } + + private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) { + // 获得 Request 对象 + HttpServletRequest request = ServletUtils.getRequest(); + if (request == null) { + return; + } + // 补全请求信息 + operateLogDTO.setRequestMethod(request.getMethod()); + operateLogDTO.setRequestUrl(request.getRequestURI()); + operateLogDTO.setUserIp(ServletUtil.getClientIP(request)); + operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request)); + } + + private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO, + ProceedingJoinPoint joinPoint, OperateLog operateLog, + Date startTime, Object result, Throwable exception) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + operateLogDTO.setJavaMethod(methodSignature.toString()); + if (operateLog == null || operateLog.logArgs()) { + operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); + } + if (operateLog == null || operateLog.logResultData()) { + operateLogDTO.setResultData(obtainResultData(result)); + } + operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); + // (正常)处理 resultCode 和 resultMsg 字段 + if (result != null) { + if (result instanceof CommonResult) { + CommonResult commonResult = (CommonResult) result; + operateLogDTO.setResultCode(commonResult.getCode()); + operateLogDTO.setResultMsg(commonResult.getMsg()); + } else { + operateLogDTO.setResultCode(SUCCESS.getCode()); + } + } + // (异常)处理 resultCode 和 resultMsg 字段 + if (exception != null) { + operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); + operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); + } + } + + private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) { + // 有 @OperateLog 注解的情况下 + if (operateLog != null) { + return operateLog.enable(); + } + // 没有 @ApiOperation 注解的情况下,只记录 POST、PUT、DELETE 的情况 + return obtainFirstLogRequestMethod(obtainRequestMethod(joinPoint)) != null; + } + + private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + return Arrays.stream(requestMethods).filter(requestMethod -> + requestMethod == RequestMethod.POST + || requestMethod == RequestMethod.PUT + || requestMethod == RequestMethod.DELETE) + .findFirst().orElse(null); + } + + private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + // 优先,匹配最优的 POST、PUT、DELETE + RequestMethod result = obtainFirstLogRequestMethod(requestMethods); + if (result != null) { + return result; + } + // 然后,匹配次优的 GET + result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) + .findFirst().orElse(null); + if (result != null) { + return result; + } + // 兜底,获得第一个 + return requestMethods[0]; + } + + private static OperateTypeEnum convertOperateLogType(RequestMethod requestMethod) { + if (requestMethod == null) { + return null; + } + switch (requestMethod) { + case GET: + return OperateTypeEnum.GET; + case POST: + return OperateTypeEnum.CREATE; + case PUT: + return OperateTypeEnum.UPDATE; + case DELETE: + return OperateTypeEnum.DELETE; + default: + return OperateTypeEnum.OTHER; + } + } + + private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { + RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 + ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); + return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; + } + + @SuppressWarnings("SameParameterValue") + private static T getMethodAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { + return ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(annotationClass); + } + + @SuppressWarnings("SameParameterValue") + private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { + return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); + } + + private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { + // TODO 提升:参数脱敏和忽略 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + String[] argNames = methodSignature.getParameterNames(); + Object[] argValues = joinPoint.getArgs(); + // 拼接参数 + Map args = Maps.newHashMapWithExpectedSize(argValues.length); + for (int i = 0; i < argNames.length; i++) { + String argName = argNames[i]; + Object argValue = argValues[i]; + // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 + args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); + } + return JsonUtils.toJsonString(args); + } + + private static String obtainResultData(Object result) { + // TODO 提升:结果脱敏和忽略 + if (result instanceof CommonResult) { + result = ((CommonResult) result).getData(); + } + return JsonUtils.toJsonString(result); + } + + private static boolean isIgnoreArgs(Object object) { + Class clazz = object.getClass(); + // 处理数组的情况 + if (clazz.isArray()) { + return IntStream.range(0, Array.getLength(object)) + .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); + } + // 递归,处理数组、Collection、Map 的情况 + if (Collection.class.isAssignableFrom(clazz)) { + return ((Collection) object).stream() + .anyMatch((Predicate) o -> isIgnoreArgs(object)); + } + if (Map.class.isAssignableFrom(clazz)) { + return isIgnoreArgs(((Map) object).values()); + } + // obj + return object instanceof MultipartFile + || object instanceof HttpServletRequest + || object instanceof HttpServletResponse; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java new file mode 100644 index 0000000..8dd98d4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.framework.operatelog.core.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.Map; + +/** + * 操作日志创建 Request DTO + */ +@Data +public class OperateLogCreateReqDTO { + + @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") + @NotEmpty(message = "链路追踪编号不能为空") + private String traceId; + + @ApiModelProperty(value = "用户编号", required = true, example = "1024") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @ApiModelProperty(value = "操作模块", required = true, example = "订单") + @NotEmpty(message = "操作模块不能为空") + private String module; + + @ApiModelProperty(value = "操作名", required = true, example = "创建订单") + @NotEmpty(message = "操作名") + private String name; + + @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") + @NotNull(message = "操作分类不能为空") + private Integer type; + + @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") + private String content; + + @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}") + private Map exts; + + @ApiModelProperty(value = "请求方法名", required = true, example = "GET") + @NotEmpty(message = "请求方法名不能为空") + private String requestMethod; + + @ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy") + @NotEmpty(message = "请求地址不能为空") + private String requestUrl; + + @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") + @NotEmpty(message = "用户 IP 不能为空") + private String userIp; + + @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0") + @NotEmpty(message = "浏览器 UserAgent 不能为空") + private String userAgent; + + @ApiModelProperty(value = "Java 方法名", required = true, example = "cn.iocoder.dashboard.UserController.save(...)") + @NotEmpty(message = "Java 方法名不能为空") + private String javaMethod; + + @ApiModelProperty(value = "Java 方法的参数") + private String javaMethodArgs; + + @ApiModelProperty(value = "开始时间", required = true) + @NotNull(message = "开始时间不能为空") + private Date startTime; + + @ApiModelProperty(value = "执行时长,单位:毫秒", required = true) + @NotNull(message = "执行时长不能为空") + private Integer duration; + + @ApiModelProperty(value = "结果码", required = true) + @NotNull(message = "结果码不能为空") + private Integer resultCode; + + @ApiModelProperty(value = "结果提示") + private String resultMsg; + + @ApiModelProperty(value = "结果数据") + private String resultData; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java new file mode 100644 index 0000000..65ee26d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.framework.operatelog.core.enums; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 操作日志的操作类型 + * + * @author ruoyi + */ +@Getter +@AllArgsConstructor +public enum OperateTypeEnum { + + /** + * 查询 + * + * 绝大多数情况下,不会记录查询动作,因为过于大量显得没有意义。 + * 在有需要的时候,通过声明 {@link OperateLog} 注解来记录 + */ + GET(1), + /** + * 新增 + */ + CREATE(2), + /** + * 修改 + */ + UPDATE(3), + /** + * 删除 + */ + DELETE(4), + /** + * 导出 + */ + EXPORT(5), + /** + * 导入 + */ + IMPORT(6), + /** + * 其它 + * + * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识 + */ + OTHER(0); + + /** + * 类型 + */ + private final Integer type; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java new file mode 100644 index 0000000..58aa3d5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelog.core; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java new file mode 100644 index 0000000..ef20e2e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.framework.operatelog.core.service; + +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; + +import java.util.concurrent.Future; + +public interface OperateLogFrameworkService { + + /** + * 异步记录操作日志 + * + * @param reqVO 操作日志请求 + * @return true: 记录成功,false: 记录失败 + */ + Future createOperateLogAsync(OperateLogCreateReqDTO reqVO); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java new file mode 100644 index 0000000..a9801e5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.operatelog.core.util; + +import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; + +/** + * 操作日志工具类 + * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 + * + * @author 芋道源码 + */ +public class OperateLogUtils { + + public static void setContent(String content) { + OperateLogAspect.setContent(content); + } + + public static void addExt(String key, Object value) { + OperateLogAspect.addExt(key, value); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java new file mode 100644 index 0000000..d272b53 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java @@ -0,0 +1,6 @@ +/** + * 用户操作日志:记录用户的操作,用于对用户的操作的审计与追溯,永久保存。 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.operatelog; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml new file mode 100644 index 0000000..24a8133 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml @@ -0,0 +1,70 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-biz-sms + jar + + ${artifactId} + 短信拓展,支持阿里云、云片 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + + jakarta.validation + jakarta.validation-api + + + + + + + com.yunpian.sdk + yunpian-java-sdk + + + + com.aliyun + aliyun-java-sdk-core + + + com.aliyun + aliyun-java-sdk-dysmsapi + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java new file mode 100644 index 0000000..e5441c9 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/config/SmsConfiguration.java @@ -0,0 +1,21 @@ +package cn.iocoder.dashboard.framework.sms.config; + +import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.dashboard.framework.sms.core.client.impl.SmsClientFactoryImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 短信配置类 + * + * @author 芋道源码 + */ +@Configuration +public class SmsConfiguration { + + @Bean + public SmsClientFactory smsClientFactory() { + return new SmsClientFactoryImpl(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java new file mode 100644 index 0000000..ee7bbc1 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClient.java @@ -0,0 +1,54 @@ +package cn.iocoder.dashboard.framework.sms.core.client; + +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; + +import java.util.List; + +/** + * 短信客户端接口 + * + * @author zzf + * @date 2021/1/25 14:14 + */ +public interface SmsClient { + + /** + * 获得渠道编号 + * + * @return 渠道编号 + */ + Long getId(); + + /** + * 发送消息 + * + * @param logId 日志编号 + * @param mobile 手机号 + * @param apiTemplateId 短信 API 的模板编号 + * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序 + * @return 短信发送结果 + */ + SmsCommonResult sendSms(Long logId, String mobile, String apiTemplateId, + List> templateParams); + + /** + * 解析接收短信的接收结果 + * + * @param text 结果 + * @return 结果内容 + * @throws Throwable 当解析 text 发生异常时,则会抛出异常 + */ + List parseSmsReceiveStatus(String text) throws Throwable; + + /** + * 查询指定的短信模板 + * + * @param apiTemplateId 短信 API 的模板编号 + * @return 短信模板 + */ + SmsCommonResult getSmsTemplate(String apiTemplateId); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java new file mode 100644 index 0000000..83fb88c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsClientFactory.java @@ -0,0 +1,36 @@ +package cn.iocoder.dashboard.framework.sms.core.client; + +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; + +/** + * 短信客户端工厂接口 + * + * @author zzf + * @date 2021/1/28 14:01 + */ +public interface SmsClientFactory { + + /** + * 获得短信 Client + * + * @param channelId 渠道编号 + * @return 短信 Client + */ + SmsClient getSmsClient(Long channelId); + + /** + * 获得短信 Client + * + * @param channelCode 渠道编码 + * @return 短信 Client + */ + SmsClient getSmsClient(String channelCode); + + /** + * 创建短信 Client + * + * @param properties 配置对象 + */ + void createOrUpdateSmsClient(SmsChannelProperties properties); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java new file mode 100644 index 0000000..d2a726b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCodeMapping.java @@ -0,0 +1,17 @@ +package cn.iocoder.dashboard.framework.sms.core.client; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; + +import java.util.function.Function; + +/** + * 将 API 的错误码,转换为通用的错误码 + * + * @see SmsCommonResult + * @see SmsFrameworkErrorCodeConstants + * + * @author 芋道源码 + */ +public interface SmsCodeMapping extends Function { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java new file mode 100644 index 0000000..2780c8d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/SmsCommonResult.java @@ -0,0 +1,68 @@ +package cn.iocoder.dashboard.framework.sms.core.client; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * 短信的 CommonResult 拓展类 + * + * 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段 + * + * 另外,一些短信平台(例如说阿里云、腾讯云)会返回一个请求编号,用于排查请求失败的问题,我们设置到 {@link #apiRequestId} 字段 + * + * @author 芋道源码 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SmsCommonResult extends CommonResult { + + /** + * API 返回错误码 + * + * 由于第三方的错误码可能是字符串,所以使用 String 类型 + */ + private String apiCode; + /** + * API 返回提示 + */ + private String apiMsg; + + /** + * API 请求编号 + */ + private String apiRequestId; + + private SmsCommonResult() { + } + + public static SmsCommonResult build(String apiCode, String apiMsg, String apiRequestId, + T data, SmsCodeMapping codeMapping) { + Assert.notNull(codeMapping, "参数 codeMapping 不能为空"); + SmsCommonResult result = new SmsCommonResult().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId); + result.setData(data); + // 翻译错误码 + if (codeMapping != null) { + ErrorCode errorCode = codeMapping.apply(apiCode); + if (errorCode == null) { + errorCode = SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; + } + result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg()); + } + return result; + } + + public static SmsCommonResult error(Throwable ex) { + SmsCommonResult result = new SmsCommonResult<>(); + result.setCode(SmsFrameworkErrorCodeConstants.EXCEPTION.getCode()); + result.setMsg(ExceptionUtil.getRootCauseMessage(ex)); + return result; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java new file mode 100644 index 0000000..ecfdb04 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsReceiveRespDTO.java @@ -0,0 +1,48 @@ +package cn.iocoder.dashboard.framework.sms.core.client.dto; + +import lombok.Data; + +import java.util.Date; + +/** + * 消息接收 Response DTO + * + * @author 芋道源码 + */ +@Data +public class SmsReceiveRespDTO { + + /** + * 是否接收成功 + */ + private Boolean success; + /** + * API 接收结果的编码 + */ + private String errorCode; + /** + * API 接收结果的说明 + */ + private String errorMsg; + + /** + * 手机号 + */ + private String mobile; + /** + * 用户接收时间 + */ + private Date receiveTime; + + /** + * 短信 API 发送返回的序号 + */ + private String serialNo; + /** + * 短信日志编号 + * + * 对应 SysSmsLogDO 的编号 + */ + private Long logId; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java new file mode 100644 index 0000000..c3f6b51 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsSendRespDTO.java @@ -0,0 +1,18 @@ +package cn.iocoder.dashboard.framework.sms.core.client.dto; + +import lombok.Data; + +/** + * 短信发送 Response DTO + * + * @author 芋道源码 + */ +@Data +public class SmsSendRespDTO { + + /** + * 短信 API 发送返回的序号 + */ + private String serialNo; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java new file mode 100644 index 0000000..938310e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/dto/SmsTemplateRespDTO.java @@ -0,0 +1,33 @@ +package cn.iocoder.dashboard.framework.sms.core.client.dto; + +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import lombok.Data; + +/** + * 短信模板 Response DTO + * + * @author 芋道源码 + */ +@Data +public class SmsTemplateRespDTO { + + /** + * 模板编号 + */ + private String id; + /** + * 短信内容 + */ + private String content; + /** + * 审核状态 + * + * 枚举 {@link SmsTemplateAuditStatusEnum} + */ + private Integer auditStatus; + /** + * 审核未通过的理由 + */ + private String auditReason; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java new file mode 100644 index 0000000..bad40fd --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/AbstractSmsClient.java @@ -0,0 +1,122 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl; + +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * 短信客户端抽象类 + * + * @author zzf + * @date 2021/2/1 9:28 + */ +@Slf4j +public abstract class AbstractSmsClient implements SmsClient { + + /** + * 短信渠道配置 + */ + protected volatile SmsChannelProperties properties; + /** + * 错误码枚举类 + */ + protected final SmsCodeMapping codeMapping; + + /** + * 短信客户端有参构造函数 + * + * @param properties 短信配置 + */ + public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) { + this.properties = properties; + this.codeMapping = codeMapping; + } + + /** + * 初始化 + */ + public final void init() { + doInit(); + log.info("[init][配置({}) 初始化完成]", properties); + } + + public final void refresh(SmsChannelProperties properties) { + // 判断是否更新 + if (properties.equals(this.properties)) { + return; + } + log.info("[refresh][配置({})发生变化,重新初始化]", properties); + this.properties = properties; + // 初始化 + this.init(); + } + + /** + * 自定义初始化 + */ + protected abstract void doInit(); + + @Override + public Long getId() { + return properties.getId(); + } + + @Override + public final SmsCommonResult sendSms(Long logId, String mobile, + String apiTemplateId, List> templateParams) { + // 执行短信发送 + SmsCommonResult result; + try { + result = doSendSms(logId, mobile, apiTemplateId, templateParams); + } catch (Throwable ex) { + // 打印异常日志 + log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]", + logId, mobile, apiTemplateId, templateParams, ex); + // 封装返回 + return SmsCommonResult.error(ex); + } + return result; + } + + protected abstract SmsCommonResult doSendSms(Long sendLogId, String mobile, + String apiTemplateId, List> templateParams) + throws Throwable; + + @Override + public List parseSmsReceiveStatus(String text) throws Throwable { + try { + return doParseSmsReceiveStatus(text); + } catch (Throwable ex) { + log.error("[parseSmsReceiveStatus][text({}) 解析发生异常]", text, ex); + throw ex; + } + } + + protected abstract List doParseSmsReceiveStatus(String text) throws Throwable; + + @Override + public SmsCommonResult getSmsTemplate(String apiTemplateId) { + // 执行短信发送 + SmsCommonResult result; + try { + result = doGetSmsTemplate(apiTemplateId); + } catch (Throwable ex) { + // 打印异常日志 + log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex); + // 封装返回 + return SmsCommonResult.error(ex); + } + return result; + } + + protected abstract SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java new file mode 100644 index 0000000..44f87d7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/SmsClientFactoryImpl.java @@ -0,0 +1,90 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl; + +import cn.iocoder.dashboard.framework.sms.core.client.SmsClient; +import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun.AliyunSmsClient; +import cn.iocoder.dashboard.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; +import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.Assert; +import org.springframework.validation.annotation.Validated; + +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * 短信客户端工厂接口 + * + * @author zzf + */ +@Validated +@Slf4j +public class SmsClientFactoryImpl implements SmsClientFactory { + + /** + * 短信客户端 Map + * key:渠道编号,使用 {@link SmsChannelProperties#getId()} + */ + private final ConcurrentMap channelIdClients = new ConcurrentHashMap<>(); + + /** + * 短信客户端 Map + * key:渠道编码,使用 {@link SmsChannelProperties#getCode()} ()} + * + * 注意,一些场景下,需要获得某个渠道类型的客户端,所以需要使用它。 + * 例如说,解析短信接收结果,是相对通用的,不需要使用某个渠道编号的 {@link #channelIdClients} + */ + private final ConcurrentMap channelCodeClients = new ConcurrentHashMap<>(); + + public SmsClientFactoryImpl() { + // 初始化 channelCodeClients 集合 + Arrays.stream(SmsChannelEnum.values()).forEach(channel -> { + // 创建一个空的 SmsChannelProperties 对象 + SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode()) + .setApiKey("default").setApiSecret("default"); + // 创建 Sms 客户端 + AbstractSmsClient smsClient = createSmsClient(properties); + channelCodeClients.put(channel.getCode(), smsClient); + }); + } + + @Override + public SmsClient getSmsClient(Long channelId) { + return channelIdClients.get(channelId); + } + + @Override + public SmsClient getSmsClient(String channelCode) { + return channelCodeClients.get(channelCode); + } + + @Override + public void createOrUpdateSmsClient(SmsChannelProperties properties) { + AbstractSmsClient client = channelIdClients.get(properties.getId()); + if (client == null) { + client = this.createSmsClient(properties); + client.init(); + channelIdClients.put(client.getId(), client); + } else { + client.refresh(properties); + } + } + + private AbstractSmsClient createSmsClient(SmsChannelProperties properties) { + SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(properties.getCode()); + Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channelEnum)); + // 创建客户端 + switch (channelEnum) { + case ALIYUN: return new AliyunSmsClient(properties); + case YUN_PIAN: return new YunpianSmsClient(properties); + case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties); + } + // 创建失败,错误日志 + 抛出异常 + log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties); + throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", properties)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java new file mode 100644 index 0000000..b47406b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java @@ -0,0 +1,212 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import com.aliyuncs.AcsRequest; +import com.aliyuncs.AcsResponse; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.profile.DefaultProfile; +import com.aliyuncs.profile.IClientProfile; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.annotations.VisibleForTesting; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +/** + * 阿里短信客户端的实现类 + * + * @author zzf + * @date 2021/1/25 14:17 + */ +@Slf4j +public class AliyunSmsClient extends AbstractSmsClient { + + /** + * REGION, 使用杭州 + */ + private static final String ENDPOINT = "cn-hangzhou"; + + /** + * 阿里云客户端 + */ + private volatile IAcsClient client; + + public AliyunSmsClient(SmsChannelProperties properties) { + super(properties, new AliyunSmsCodeMapping()); + Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); + Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); + } + + @Override + protected void doInit() { + IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); + client = new DefaultAcsClient(profile); + } + + @Override + protected SmsCommonResult doSendSms(Long sendLogId, String mobile, + String apiTemplateId, List> templateParams) { + // 构建参数 + SendSmsRequest request = new SendSmsRequest(); + request.setPhoneNumbers(mobile); + request.setSignName(properties.getSignature()); + request.setTemplateCode(apiTemplateId); + request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); + request.setOutId(String.valueOf(sendLogId)); + // 执行请求 + return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId())); + } + + @Override + protected List doParseSmsReceiveStatus(String text) throws Throwable { + List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); + return statuses.stream().map(status -> { + SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); + resp.setSuccess(status.getSuccess()); + resp.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()); + resp.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()); + resp.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId())); + return resp; + }).collect(Collectors.toList()); + } + + @Override + protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) { + // 构建参数 + QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); + request.setTemplateCode(apiTemplateId); + // 执行请求 + return invoke(request, response -> { + SmsTemplateRespDTO data = new SmsTemplateRespDTO(); + data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); + data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); + return data; + }); + } + + @VisibleForTesting + Integer convertSmsTemplateAuditStatus(Integer templateStatus) { + switch (templateStatus) { + case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); + case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); + case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); + default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); + } + } + + @VisibleForTesting + SmsCommonResult invoke(AcsRequest request, Function responseConsumer) { + try { + // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射 + T sendResult = client.getAcsResponse(request); + String code = (String) ReflectUtil.getFieldValue(sendResult, "code"); + String message = (String) ReflectUtil.getFieldValue(sendResult, "message"); + String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId"); + // 解析结果 + R data = null; + if (Objects.equals(code, "OK")) { // 请求成功的情况下 + data = responseConsumer.apply(sendResult); + } + // 拼接结果 + return SmsCommonResult.build(code, message, requestId, data, codeMapping); + } catch (ClientException ex) { + return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping); + } + } + + private static String formatResultMsg(ClientException ex) { + if (StrUtil.isEmpty(ex.getErrorDescription())) { + return ex.getErrMsg(); + } + return ex.getErrMsg() + " => " + ex.getErrorDescription(); + } + + /** + * 短信接收状态 + * + * 参见 https://help.aliyun.com/document_detail/101867.html 文档 + * + * @author 芋道源码 + */ + @Data + public static class SmsReceiveStatus { + + /** + * 手机号 + */ + @JsonProperty("phone_number") + private String phoneNumber; + /** + * 发送时间 + */ + @JsonProperty("send_time") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private Date sendTime; + /** + * 状态报告时间 + */ + @JsonProperty("report_time") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private Date reportTime; + /** + * 是否接收成功 + */ + private Boolean success; + /** + * 状态报告说明 + */ + @JsonProperty("err_msg") + private String errMsg; + /** + * 状态报告编码 + */ + @JsonProperty("err_code") + private String errCode; + /** + * 发送序列号 + */ + @JsonProperty("biz_id") + private String bizId; + /** + * 用户序列号 + * + * 这里我们传递的是 SysSmsLogDO 的日志编号 + */ + @JsonProperty("out_id") + private String outId; + /** + * 短信长度,例如说 1、2、3 + * + * 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送 + */ + @JsonProperty("sms_size") + private Integer smsSize; + + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java new file mode 100644 index 0000000..18ab0e7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java @@ -0,0 +1,43 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; + +import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; + +/** + * 阿里云的 SmsCodeMapping 实现类 + * + * 参见 https://help.aliyun.com/document_detail/101346.htm 文档 + * + * @author 芋道源码 + */ +public class AliyunSmsCodeMapping implements SmsCodeMapping { + + @Override + public ErrorCode apply(String apiCode) { + switch (apiCode) { + case "OK": return GlobalErrorCodeConstants.SUCCESS; + case "isv.ACCOUNT_NOT_EXISTS": + case "isv.ACCOUNT_ABNORMAL": + case "MissingAccessKeyId": return SMS_ACCOUNT_INVALID; + case "isp.RAM_PERMISSION_DENY": return SMS_PERMISSION_DENY; + case "isv.INVALID_JSON_PARAM": + case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR; + case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_BUSINESS_LIMIT_CONTROL; + case "isv.DAY_LIMIT_CONTROL": return SMS_SEND_DAY_LIMIT_CONTROL; + case "isv.SMS_CONTENT_ILLEGAL": return SMS_SEND_CONTENT_INVALID; + case "isv.SMS_TEMPLATE_ILLEGAL": return SMS_TEMPLATE_INVALID; + case "isv.SMS_SIGNATURE_ILLEGAL": + case "isv.SIGN_NAME_ILLEGAL": + case "isv.SMS_SIGN_ILLEGAL": return SMS_SIGN_INVALID; + case "isv.AMOUNT_NOT_ENOUGH": + case "isv.OUT_OF_SERVICE": return SMS_ACCOUNT_MONEY_NOT_ENOUGH; + case "isv.MOBILE_NUMBER_ILLEGAL": return SMS_MOBILE_INVALID; + case "isv.TEMPLATE_MISSING_PARAMETERS": return SMS_TEMPLATE_PARAM_ERROR; + } + return SMS_UNKNOWN; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java new file mode 100644 index 0000000..efd50a4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java @@ -0,0 +1,23 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.debug; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; + +import java.util.Objects; + +import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; + +/** + * 钉钉的 SmsCodeMapping 实现类 + * + * @author 芋道源码 + */ +public class DebugDingTalkCodeMapping implements SmsCodeMapping { + + @Override + public ErrorCode apply(String apiCode) { + return Objects.equals(apiCode, "0") ? GlobalErrorCodeConstants.SUCCESS : SMS_UNKNOWN; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java new file mode 100644 index 0000000..aff2e67 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java @@ -0,0 +1,96 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.debug; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; +import cn.hutool.crypto.digest.HmacAlgorithm; +import cn.hutool.http.HttpUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 基于钉钉 WebHook 实现的调试的短信客户端实现类 + * + * 考虑到省钱,我们使用钉钉 WebHook 模拟发送短信,方便调试。 + * + * @author 芋道源码 + */ +public class DebugDingTalkSmsClient extends AbstractSmsClient { + + public DebugDingTalkSmsClient(SmsChannelProperties properties) { + super(properties, new DebugDingTalkCodeMapping()); + Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); + Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); + } + + @Override + protected void doInit() { + } + + @Override + protected SmsCommonResult doSendSms(Long sendLogId, String mobile, + String apiTemplateId, List> templateParams) throws Throwable { + // 构建请求 + String url = buildUrl("robot/send"); + Map params = new HashMap<>(); + params.put("msgtype", "text"); + String content = String.format("【模拟短信】\n手机号:%s\n短信日志编号:%d\n模板参数:%s", + mobile, sendLogId, MapUtils.convertMap(templateParams)); + params.put("text", MapUtil.builder().put("content", content).build()); + // 执行请求 + String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params)); + // 解析结果 + Map responseObj = JsonUtils.parseObject(responseText, Map.class); + return SmsCommonResult.build(MapUtil.getStr(responseObj, "errcode"), MapUtil.getStr(responseObj, "errorMsg"), + null, new SmsSendRespDTO().setSerialNo(StrUtil.uuid()), codeMapping); + } + + /** + * 构建请求地址 + * + * 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档 + * + * @param path 请求路径 + * @return 请求地址 + */ + @SuppressWarnings("SameParameterValue") + private String buildUrl(String path) { + // 生成 timestamp + long timestamp = System.currentTimeMillis(); + // 生成 sign + String secret = properties.getApiSecret(); + String stringToSign = timestamp + "\n" + secret; + byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign); + String sign = Base64.encode(signData); + // 构建最终 URL + return String.format("https://oapi.dingtalk.com/%s?access_token=%s×tamp=%d&sign=%s", + path, properties.getApiKey(), timestamp, sign); + } + + @Override + protected List doParseSmsReceiveStatus(String text) throws Throwable { + throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调"); + } + + @Override + protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) { + SmsTemplateRespDTO data = new SmsTemplateRespDTO().setId(apiTemplateId).setContent("") + .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(""); + return SmsCommonResult.build("0", "success", null, data, codeMapping); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java new file mode 100644 index 0000000..7ed31c2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java @@ -0,0 +1,204 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.annotations.VisibleForTesting; +import com.yunpian.sdk.YunpianClient; +import com.yunpian.sdk.constant.YunpianConstant; +import com.yunpian.sdk.model.Result; +import com.yunpian.sdk.model.Template; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +/** + * 云片短信客户端的实现类 + * + * @author zzf + * @date 9:48 2021/3/5 + */ +@Slf4j +public class YunpianSmsClient extends AbstractSmsClient { + + /** + * 云信短信客户端 + */ + private volatile YunpianClient client; + + public YunpianSmsClient(SmsChannelProperties properties) { + super(properties, new YunpianSmsCodeMapping()); + Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); + } + + @Override + public void doInit() { + YunpianClient oldClient = client; + // 初始化新的客户端 + YunpianClient newClient = new YunpianClient(properties.getApiKey()); + newClient.init(); + this.client = newClient; + // 销毁老的客户端 + if (oldClient != null) { + oldClient.close(); + } + } + + @Override + protected SmsCommonResult doSendSms(Long sendLogId, String mobile, + String apiTemplateId, List> templateParams) throws Throwable { + return invoke(() -> { + Map request = new HashMap<>(); + request.put(YunpianConstant.MOBILE, mobile); + request.put(YunpianConstant.TPL_ID, apiTemplateId); + request.put(YunpianConstant.TPL_VALUE, formatTplValue(templateParams)); + request.put(YunpianConstant.UID, String.valueOf(sendLogId)); + request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl()); + return client.sms().tpl_single_send(request); + }, response -> new SmsSendRespDTO().setSerialNo(String.valueOf(response.getSid()))); + } + + private static String formatTplValue(List> templateParams) { + if (CollUtil.isEmpty(templateParams)) { + return ""; + } + // 参考 https://www.yunpian.com/official/document/sms/zh_cn/introduction_demos_encode_sample 格式化 + StringJoiner joiner = new StringJoiner("&"); + templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), URLUtil.encode(String.valueOf(param.getValue()))))); + return joiner.toString(); + } + + @Override + protected List doParseSmsReceiveStatus(String text) throws Throwable { + List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); + return statuses.stream().map(status -> { + SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); + resp.setSuccess(Objects.equals(status.getReportStatus(), "SUCCESS")); + resp.setErrorCode(status.getErrorMsg()).setErrorMsg(status.getErrorDetail()); + resp.setMobile(status.getMobile()).setReceiveTime(status.getUserReceiveTime()); + resp.setSerialNo(String.valueOf(status.getSid())).setLogId(status.getUid()); + return resp; + }).collect(Collectors.toList()); + } + + @Override + protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable { + return invoke(() -> { + Map request = new HashMap<>(); + request.put(YunpianConstant.APIKEY, properties.getApiKey()); + request.put(YunpianConstant.TPL_ID, apiTemplateId); + return client.tpl().get(request); + }, response -> { + Template template = response.get(0); + return new SmsTemplateRespDTO().setId(String.valueOf(template.getTpl_id())).setContent(template.getTpl_content()) + .setAuditStatus(convertSmsTemplateAuditStatus(template.getCheck_status())).setAuditReason(template.getReason()); + }); + } + + @VisibleForTesting + Integer convertSmsTemplateAuditStatus(String checkStatus) { + switch (checkStatus) { + case "CHECKING": return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); + case "SUCCESS": return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); + case "FAIL": return SmsTemplateAuditStatusEnum.FAIL.getStatus(); + default: throw new IllegalArgumentException(String.format("未知审核状态(%s)", checkStatus)); + } + } + + @VisibleForTesting + SmsCommonResult invoke(Supplier> requestConsumer, Function responseConsumer) throws Throwable { + // 执行请求 + Result result = requestConsumer.get(); + if (result.getThrowable() != null) { + throw result.getThrowable(); + } + // 解析结果 + R data = null; + if (result.getData() != null) { + data = responseConsumer.apply(result.getData()); + } + // 拼接结果 + return SmsCommonResult.build(String.valueOf(result.getCode()), formatResultMsg(result), null, data, codeMapping); + } + + private static String formatResultMsg(Result sendResult) { + if (StrUtil.isEmpty(sendResult.getDetail())) { + return sendResult.getMsg(); + } + return sendResult.getMsg() + " => " + sendResult.getDetail(); + } + + /** + * 短信接收状态 + * + * 参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档 + * + * @author 芋道源码 + */ + @Data + public static class SmsReceiveStatus { + + /** + * 接收状态 + * + * 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收 + */ + @JsonProperty("report_status") + private String reportStatus; + /** + * 接收手机号 + */ + private String mobile; + /** + * 运营商返回的代码,如:"DB:0103" + * + * 由于不同运营商信息不同,此字段仅供参考; + */ + @JsonProperty("error_msg") + private String errorMsg; + /** + * 运营商反馈代码的中文解释 + * + * 默认不推送此字段,如需推送,请联系客服 + */ + @JsonProperty("error_detail") + private String errorDetail; + /** + * 短信编号 + */ + private Long sid; + /** + * 用户自定义 id + * + * 这里我们传递的是 SysSmsLogDO 的日志编号 + */ + private Long uid; + /** + * 用户接收时间 + */ + @JsonProperty("user_receive_time") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private Date userReceiveTime; + + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java new file mode 100644 index 0000000..9261684 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java @@ -0,0 +1,45 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; +import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; +import static com.yunpian.sdk.constant.Code.*; + +/** + * 云片的 SmsCodeMapping 实现类 + * + * 参见 https://www.yunpian.com/official/document/sms/zh_CN/returnvalue_common 文档 + * + * @author 芋道源码 + */ +public class YunpianSmsCodeMapping implements SmsCodeMapping { + + @Override + public ErrorCode apply(String apiCode) { + int code = Integer.parseInt(apiCode); + switch (code) { + case OK: return SUCCESS; + case ARGUMENT_MISSING: return SMS_API_PARAM_ERROR; + case BAD_ARGUMENT_FORMAT: return SMS_TEMPLATE_PARAM_ERROR; + case TPL_NOT_FOUND: + case TPL_NOT_VALID: return SMS_TEMPLATE_INVALID; + case MONEY_NOT_ENOUGH: return SMS_ACCOUNT_MONEY_NOT_ENOUGH; + case BLACK_WORD: return SMS_SEND_CONTENT_INVALID; + case DUP_IN_SHORT_TIME: + case TOO_MANY_TIME_IN_5: + case DAY_LIMIT_PER_MOBILE: + case HOUR_LIMIT_PER_MOBILE: return SMS_SEND_BUSINESS_LIMIT_CONTROL; + case BLACK_PHONE_FILTER: return SMS_MOBILE_BLACK; + case SIGN_NOT_MATCH: + case BAD_SIGN_FORMAT: + case SIGN_NOT_VALID: return SMS_SIGN_INVALID; + case BAD_API_KEY: return SMS_ACCOUNT_INVALID; + case API_NOT_ALLOWED: return SMS_PERMISSION_DENY; + case IP_NOT_ALLOWED: return SMS_IP_DENY; + } + return SMS_UNKNOWN; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java new file mode 100644 index 0000000..ba2615d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.dashboard.framework.sms.core.enums; + +import cn.hutool.core.util.ArrayUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 短信渠道枚举 + * + * @author zzf + * @date 2021/1/25 10:56 + */ +@Getter +@AllArgsConstructor +public enum SmsChannelEnum { + + DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"), + YUN_PIAN("YUN_PIAN", "云片"), + ALIYUN("ALIYUN", "阿里云"), +// TENCENT("TENCENT", "腾讯云"), +// HUA_WEI("HUA_WEI", "华为云"), + ; + + /** + * 编码 + */ + private final String code; + /** + * 名字 + */ + private final String name; + + public static SmsChannelEnum getByCode(String code) { + return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java new file mode 100644 index 0000000..bfd77fb --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java @@ -0,0 +1,47 @@ +package cn.iocoder.dashboard.framework.sms.core.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * 短信框架的错误码枚举 + * + * 短信框架,使用 2-001-000-000 段 + * + * @author 芋道源码 + */ +public interface SmsFrameworkErrorCodeConstants { + + ErrorCode SMS_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析"); + + // ========== 权限 / 限流等相关 2001000100 ========== + + ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); + // 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信 + ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); + + // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 + ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流"); + // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 + ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流"); + + ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词"); + + // ========== 模板相关 2001000200 ========== + ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在 + ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确"); + + // ========== 签名相关 2001000300 ========== + ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用"); + + // ========== 账户相关 2001000400 ========== + ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足"); + ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在"); + + // ========== 其它相关 2001000900 开头 ========== + ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失"); + ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确"); + ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中"); + + ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常"); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java new file mode 100644 index 0000000..888b2ee --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java @@ -0,0 +1,21 @@ +package cn.iocoder.dashboard.framework.sms.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 短信模板的审核状态枚举 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum SmsTemplateAuditStatusEnum { + + CHECKING(1), + SUCCESS(2), + FAIL(3); + + private final Integer status; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java new file mode 100644 index 0000000..750f2e7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/dashboard/framework/sms/core/property/SmsChannelProperties.java @@ -0,0 +1,52 @@ +package cn.iocoder.dashboard.framework.sms.core.property; + +import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; +import lombok.Data; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 短信渠道配置类 + * + * @author zzf + * @date 2021/1/25 17:01 + */ +@Data +@Validated +public class SmsChannelProperties { + + /** + * 渠道编号 + */ + @NotNull(message = "短信渠道 ID 不能为空") + private Long id; + /** + * 短信签名 + */ + @NotEmpty(message = "短信签名不能为空") + private String signature; + /** + * 渠道编码 + * + * 枚举 {@link SmsChannelEnum} + */ + @NotEmpty(message = "渠道编码不能为空") + private String code; + /** + * 短信 API 的账号 + */ + @NotEmpty(message = "短信 API 的账号不能为空") + private String apiKey; + /** + * 短信 API 的秘钥 + */ + @NotEmpty(message = "短信 API 的秘钥不能为空") + private String apiSecret; + /** + * 短信发送回调 URL + */ + private String callbackUrl; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java new file mode 100644 index 0000000..cfef169 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java @@ -0,0 +1,224 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; + +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.dashboard.framework.BaseMockitoUnitTest; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import com.aliyuncs.AcsRequest; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; +import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.aliyuncs.exceptions.ClientException; +import com.google.common.collect.Lists; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatcher; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.List; +import java.util.function.Function; + +import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR; +import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.when; + +/** + * {@link AliyunSmsClient} 的单元测试 + * + * @author 芋道源码 + */ +public class AliyunSmsClientTest extends BaseMockitoUnitTest { + + private final SmsChannelProperties properties = new SmsChannelProperties() + .setApiKey(randomString()) // 随机一个 apiKey,避免构建报错 + .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错 + .setSignature("芋道源码"); + + @InjectMocks + private final AliyunSmsClient smsClient = new AliyunSmsClient(properties); + + @Mock + private IAcsClient client; + + @Test + public void testDoInit() { + // 准备参数 + // mock 方法 + + // 调用 + smsClient.doInit(); + // 断言 + assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "acsClient")); + } + + @Test + @SuppressWarnings("unchecked") + public void testDoSendSms() throws ClientException { + // 准备参数 + Long sendLogId = randomLongId(); + String mobile = randomString(); + String apiTemplateId = randomString(); + List> templateParams = Lists.newArrayList( + new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); + // mock 方法 + SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("OK")); + when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { + assertEquals(mobile, acsRequest.getPhoneNumbers()); + assertEquals(properties.getSignature(), acsRequest.getSignName()); + assertEquals(apiTemplateId, acsRequest.getTemplateCode()); + assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); + assertEquals(sendLogId.toString(), acsRequest.getOutId()); + return true; + }))).thenReturn(response); + + // 调用 + SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, + apiTemplateId, templateParams); + // 断言 + assertEquals(response.getCode(), result.getApiCode()); + assertEquals(response.getMessage(), result.getApiMsg()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); + assertEquals(response.getRequestId(), result.getApiRequestId()); + // 断言结果 + assertEquals(response.getBizId(), result.getData().getSerialNo()); + } + + @Test + public void testDoTParseSmsReceiveStatus() throws Throwable { + // 准备参数 + String text = "[\n" + + " {\n" + + " \"phone_number\" : \"13900000001\",\n" + + " \"send_time\" : \"2017-01-01 11:12:13\",\n" + + " \"report_time\" : \"2017-02-02 22:23:24\",\n" + + " \"success\" : true,\n" + + " \"err_code\" : \"DELIVERED\",\n" + + " \"err_msg\" : \"用户接收成功\",\n" + + " \"sms_size\" : \"1\",\n" + + " \"biz_id\" : \"12345\",\n" + + " \"out_id\" : \"67890\"\n" + + " }\n" + + "]"; + // mock 方法 + + // 调用 + List statuses = smsClient.doParseSmsReceiveStatus(text); + // 断言 + assertEquals(1, statuses.size()); + assertTrue(statuses.get(0).getSuccess()); + assertEquals("DELIVERED", statuses.get(0).getErrorCode()); + assertEquals("用户接收成功", statuses.get(0).getErrorMsg()); + assertEquals("13900000001", statuses.get(0).getMobile()); + assertEquals(DateUtils.buildTime(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime()); + assertEquals("12345", statuses.get(0).getSerialNo()); + assertEquals(67890L, statuses.get(0).getLogId()); + } + + @Test + public void testDoGetSmsTemplate() throws ClientException { + // 准备参数 + String apiTemplateId = randomString(); + // mock 方法 + QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { + o.setCode("OK"); + o.setTemplateStatus(1); // 设置模板通过 + }); + when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { + assertEquals(apiTemplateId, acsRequest.getTemplateCode()); + return true; + }))).thenReturn(response); + + // 调用 + SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId); + // 断言 + assertEquals(response.getCode(), result.getApiCode()); + assertEquals(response.getMessage(), result.getApiMsg()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); + assertEquals(response.getRequestId(), result.getApiRequestId()); + // 断言结果 + assertEquals(response.getTemplateCode(), result.getData().getId()); + assertEquals(response.getTemplateContent(), result.getData().getContent()); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); + assertEquals(response.getReason(), result.getData().getAuditReason()); + } + + @Test + public void testConvertSmsTemplateAuditStatus() { + assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), + smsClient.convertSmsTemplateAuditStatus(0)); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), + smsClient.convertSmsTemplateAuditStatus(1)); + assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), + smsClient.convertSmsTemplateAuditStatus(2)); + assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus(3), + "未知审核状态(3)"); + } + + @Test + @SuppressWarnings("unchecked") + public void testInvoke_throwable() throws ClientException { + // 准备参数 + QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); + // mock 方法 + ClientException ex = new ClientException("isv.INVALID_PARAMETERS", "参数不正确", randomString()); + when(client.getAcsResponse(any(AcsRequest.class))).thenThrow(ex); + + // 调用,并断言异常 + SmsCommonResult result = smsClient.invoke(request,null); + // 断言 + assertEquals(ex.getErrCode(), result.getApiCode()); + assertEquals(ex.getErrMsg(), result.getApiMsg()); + assertEquals(SMS_API_PARAM_ERROR.getCode(), result.getCode()); + assertEquals(SMS_API_PARAM_ERROR.getMsg(), result.getMsg()); + assertEquals(ex.getRequestId(), result.getApiRequestId()); + } + + @Test + public void testInvoke_success() throws ClientException { + // 准备参数 + QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); + Function responseConsumer = response -> { + SmsTemplateRespDTO data = new SmsTemplateRespDTO(); + data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); + data.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(response.getReason()); + return data; + }; + // mock 方法 + QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { + o.setCode("OK"); + o.setTemplateStatus(1); // 设置模板通过 + }); + when(client.getAcsResponse(any(AcsRequest.class))).thenReturn(response); + + // 调用 + SmsCommonResult result = smsClient.invoke(request, responseConsumer); + // 断言 + assertEquals(response.getCode(), result.getApiCode()); + assertEquals(response.getMessage(), result.getApiMsg()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); + assertEquals(response.getRequestId(), result.getApiRequestId()); + // 断言结果 + assertEquals(response.getTemplateCode(), result.getData().getId()); + assertEquals(response.getTemplateContent(), result.getData().getContent()); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); + assertEquals(response.getReason(), result.getData().getAuditReason()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java new file mode 100644 index 0000000..823c7ce --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java @@ -0,0 +1,43 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun; + +import cn.iocoder.dashboard.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link AliyunSmsCodeMapping} 的单元测试 + * + * @author 芋道源码 + */ +public class AliyunSmsCodeMappingTest extends BaseMockitoUnitTest { + + @InjectMocks + private AliyunSmsCodeMapping codeMapping; + + @Test + public void testApply() { + assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply("OK")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("MissingAccessKeyId")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_NOT_EXISTS")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_ABNORMAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("isv.DAY_LIMIT_CONTROL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("isv.SMS_CONTENT_ILLEGAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGN_ILLEGAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SIGN_NAME_ILLEGAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("isp.RAM_PERMISSION_DENY")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.OUT_OF_SERVICE")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.AMOUNT_NOT_ENOUGH")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("isv.SMS_TEMPLATE_ILLEGAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGNATURE_ILLEGAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_PARAMETERS")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_JSON_PARAM")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("isv.MOBILE_NUMBER_ILLEGAL")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("isv.TEMPLATE_MISSING_PARAMETERS")); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("isv.BUSINESS_LIMIT_CONTROL")); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java new file mode 100644 index 0000000..899abab --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java @@ -0,0 +1,202 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; + +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.dashboard.framework.BaseMockitoUnitTest; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import com.google.common.collect.Lists; +import com.yunpian.sdk.YunpianClient; +import com.yunpian.sdk.api.SmsApi; +import com.yunpian.sdk.api.TplApi; +import com.yunpian.sdk.constant.YunpianConstant; +import com.yunpian.sdk.model.Result; +import com.yunpian.sdk.model.SmsSingleSend; +import com.yunpian.sdk.model.Template; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +import static cn.iocoder.dashboard.framework.test.core.util.RandomUtils.*; +import static com.yunpian.sdk.constant.Code.OK; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * 对 {@link YunpianSmsClient} 的单元测试 + * + * @author 芋道源码 + */ +public class YunpianSmsClientTest extends BaseMockitoUnitTest { + + private final SmsChannelProperties properties = new SmsChannelProperties() + .setApiKey(randomString()); // 随机一个 apiKey,避免构建报错 + + @InjectMocks + private final YunpianSmsClient smsClient = new YunpianSmsClient(properties); + + @Mock + private YunpianClient client; + + @Test + public void testDoInit() { + // 准备参数 + // mock 方法 + + // 调用 + smsClient.doInit(); + // 断言 + assertNotEquals(client, ReflectUtil.getFieldValue(smsClient, "client")); + verify(client, times(1)).close(); + } + + @Test + @SuppressWarnings("unchecked") + public void testDoSendSms() throws Throwable { + // 准备参数 + Long sendLogId = randomLongId(); + String mobile = randomString(); + String apiTemplateId = randomString(); + List> templateParams = Lists.newArrayList( + new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); + // mock sms 方法 + SmsApi smsApi = mock(SmsApi.class); + when(client.sms()).thenReturn(smsApi); + // mock tpl_single_send 方法 + Map request = new HashMap<>(); + request.put(YunpianConstant.MOBILE, mobile); + request.put(YunpianConstant.TPL_ID, apiTemplateId); + request.put(YunpianConstant.TPL_VALUE, "#code#=1234&#op#=login"); + request.put(YunpianConstant.UID, String.valueOf(sendLogId)); + request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl()); + Result responseResult = randomPojo(Result.class, SmsSingleSend.class, + o -> o.setCode(OK)); // API 发送成功的 code + when(smsApi.tpl_single_send(eq(request))).thenReturn(responseResult); + + // 调用 + SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, + apiTemplateId, templateParams); + // 断言 + assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); + assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); + assertNull(result.getApiRequestId()); + // 断言结果 + assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo()); + } + + @Test + public void testDoParseSmsReceiveStatus() throws Throwable { + // 准备参数 + String text = "[{\"sid\":9527,\"uid\":1024,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"}]"; + // mock 方法 + + // 调用 + + // 断言 + // 调用 + List statuses = smsClient.doParseSmsReceiveStatus(text); + // 断言 + assertEquals(1, statuses.size()); + assertTrue(statuses.get(0).getSuccess()); + assertEquals("", statuses.get(0).getErrorCode()); + assertNull(statuses.get(0).getErrorMsg()); + assertEquals("15205201314", statuses.get(0).getMobile()); + assertEquals(DateUtils.buildTime(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime()); + assertEquals("9527", statuses.get(0).getSerialNo()); + assertEquals(1024L, statuses.get(0).getLogId()); + } + + @Test + @SuppressWarnings("unchecked") + public void testDoGetSmsTemplate() throws Throwable { + // 准备参数 + String apiTemplateId = randomString(); + // mock tpl 方法 + TplApi tplApi = mock(TplApi.class); + when(client.tpl()).thenReturn(tplApi); + // mock get 方法 + Map request = new HashMap<>(); + request.put(YunpianConstant.APIKEY, properties.getApiKey()); + request.put(YunpianConstant.TPL_ID, apiTemplateId); + Result> responseResult = randomPojo(Result.class, List.class, o -> { + o.setCode(OK); // API 发送成功的 code + o.setData(randomPojoList(Template.class, t -> t.setCheck_status("SUCCESS"))); + }); + when(tplApi.get(eq(request))).thenReturn(responseResult); + + // 调用 + SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId); + // 断言 + assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); + assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); + assertNull(result.getApiRequestId()); + // 断言结果 + Template template = responseResult.getData().get(0); + assertEquals(template.getTpl_id().toString(), result.getData().getId()); + assertEquals(template.getTpl_content(), result.getData().getContent()); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); + assertEquals(template.getReason(), result.getData().getAuditReason()); + } + + @Test + public void testConvertSmsTemplateAuditStatus() { + assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), + smsClient.convertSmsTemplateAuditStatus("CHECKING")); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), + smsClient.convertSmsTemplateAuditStatus("SUCCESS")); + assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), + smsClient.convertSmsTemplateAuditStatus("FAIL")); + assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus("test"), + "未知审核状态(test)"); + } + + @Test + public void testInvoke_throwable() { + // 准备参数 + Supplier> requestConsumer = + () -> new Result<>().setThrowable(new NullPointerException()); + // mock 方法 + + // 调用,并断言异常 + assertThrows(NullPointerException.class, + () -> smsClient.invoke(requestConsumer, null)); + } + + @Test + @SuppressWarnings("unchecked") + public void testInvoke_success() throws Throwable { + // 准备参数 + Result responseResult = randomPojo(Result.class, SmsSingleSend.class, o -> o.setCode(OK)); + Supplier> requestConsumer = () -> responseResult; + Function responseConsumer = + smsSingleSend -> new SmsSendRespDTO().setSerialNo(String.valueOf(responseResult.getData().getSid())); + // mock 方法 + + // 调用 + SmsCommonResult result = smsClient.invoke(requestConsumer, responseConsumer); + // 断言 + assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); + assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); + assertNull(result.getApiRequestId()); + assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java new file mode 100644 index 0000000..76d0796 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/dashboard/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java @@ -0,0 +1,43 @@ +package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian; + +import cn.iocoder.dashboard.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; + +import static com.yunpian.sdk.constant.Code.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link YunpianSmsCodeMapping} 的单元测试 + * + * @author 芋道源码 + */ +class YunpianSmsCodeMappingTest extends BaseMockitoUnitTest { + + @InjectMocks + private YunpianSmsCodeMapping codeMapping; + + @Test + public void testApply() { + assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(String.valueOf(OK))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply(String.valueOf(ARGUMENT_MISSING))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply(String.valueOf(BAD_ARGUMENT_FORMAT))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply(String.valueOf(MONEY_NOT_ENOUGH))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_FOUND))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_VALID))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DUP_IN_SHORT_TIME))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(TOO_MANY_TIME_IN_5))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DAY_LIMIT_PER_MOBILE))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(HOUR_LIMIT_PER_MOBILE))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply(String.valueOf(BLACK_PHONE_FILTER))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_MATCH))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_VALID))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(BAD_SIGN_FORMAT))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply(String.valueOf(BAD_API_KEY))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply(String.valueOf(API_NOT_ALLOWED))); + assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply(String.valueOf(IP_NOT_ALLOWED))); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/pom.xml b/yudao-framework/yudao-spring-boot-starter-config/pom.xml new file mode 100644 index 0000000..54dca3a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/pom.xml @@ -0,0 +1,32 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-config + jar + + ${artifactId} + 配置中心,基于 Apollo 魔改实现 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + org.springframework.boot + spring-boot-starter + + + + + com.ctrip.framework.apollo + apollo-client + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java new file mode 100644 index 0000000..8e0fe57 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/core/ConfigConsts.java @@ -0,0 +1,20 @@ +package cn.iocoder.dashboard.framework.apollo.core; + +/** + * 针对 {@link com.ctrip.framework.apollo.core.ConfigConsts} 的补充,主要增加: + * + * 1. apollo.jdbc.* 配置项的枚举 + * + * @author 芋道源码 + */ +public class ConfigConsts { + + /** + * {@link cn.iocoder.dashboard.framework.apollo.internals.ConfigFrameworkDAO} 的实现类 + */ + public static final String APOLLO_JDBC_DAO = "apollo.jdbc.dao"; + public static final String APOLLO_JDBC_URL = "apollo.jdbc.url"; + public static final String APOLLO_JDBC_USERNAME = "apollo.jdbc.username"; + public static final String APOLLO_JDBC_PASSWORD = "apollo.jdbc.password"; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java new file mode 100644 index 0000000..8f46b2d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/ConfigFrameworkDAO.java @@ -0,0 +1,32 @@ +package cn.iocoder.dashboard.framework.apollo.internals; + +import cn.iocoder.dashboard.framework.apollo.internals.dto.ConfigRespDTO; + +import java.util.Date; +import java.util.List; + +/** + * 配置 Framework DAO 接口 + * + * 注意,实现类必须提供 (String jdbcUrl, String username, String password) 构造方法 + * + * @author 芋道源码 + */ +public interface ConfigFrameworkDAO { + + /** + * 查询是否存在比 maxUpdateTime 更新记录更晚的配置 + * + * @param maxUpdateTime 最大更新时间 + * @return 是否存在 + */ + boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime); + + /** + * 查询配置列表 + * + * @return 配置列表 + */ + List selectList(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java new file mode 100644 index 0000000..97726d3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DBConfigRepository.java @@ -0,0 +1,183 @@ +package cn.iocoder.dashboard.framework.apollo.internals; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.dashboard.framework.apollo.core.ConfigConsts; +import cn.iocoder.dashboard.framework.apollo.internals.dto.ConfigRespDTO; +import com.ctrip.framework.apollo.Apollo; +import com.ctrip.framework.apollo.build.ApolloInjector; +import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; +import com.ctrip.framework.apollo.enums.ConfigSourceType; +import com.ctrip.framework.apollo.internals.AbstractConfigRepository; +import com.ctrip.framework.apollo.internals.ConfigRepository; +import com.ctrip.framework.apollo.tracer.Tracer; +import com.ctrip.framework.apollo.util.ConfigUtil; +import com.ctrip.framework.apollo.util.factory.PropertiesFactory; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Constructor; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +@Slf4j +public class DBConfigRepository extends AbstractConfigRepository { + + private final static ScheduledExecutorService m_executorService; + + private static DBConfigRepository INSTANCE; + + static { + m_executorService = Executors.newScheduledThreadPool(1, + ApolloThreadFactory.create(DBConfigRepository.class.getSimpleName(), true)); + } + + private final ConfigUtil m_configUtil; + private final PropertiesFactory propertiesFactory; + private final String m_namespace; + + /** + * 配置缓存,使用 Properties 存储 + */ + private volatile Properties m_configCache; + /** + * 缓存配置的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + private volatile Date maxUpdateTime; + + /** + * 配置读取 DAO + */ + private final ConfigFrameworkDAO configFrameworkDAO; + + public DBConfigRepository(String namespace) { + // 初始化变量 + this.m_namespace = namespace; + this.propertiesFactory = ApolloInjector.getInstance(PropertiesFactory.class); + this.m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); + // 初始化 DB + this.configFrameworkDAO = createConfigFrameworkDAO(); + + // 初始化加载 + this.trySync(); + // 初始化定时任务 + this.schedulePeriodicRefresh(); + + // 设置单例 + INSTANCE = this; + } + + @SneakyThrows + private static ConfigFrameworkDAO createConfigFrameworkDAO() { + String dao = System.getProperty(ConfigConsts.APOLLO_JDBC_DAO); + String url = System.getProperty(ConfigConsts.APOLLO_JDBC_URL); + String username = System.getProperty(ConfigConsts.APOLLO_JDBC_USERNAME); + String password = System.getProperty(ConfigConsts.APOLLO_JDBC_PASSWORD); + // 创建 DBConfigRepository 对象 + Class clazz = ClassUtil.loadClass(dao); + Constructor constructor = ReflectUtil.getConstructor(clazz, String.class, String.class, String.class); + return constructor.newInstance(url, username, password); + } + + /** + * 通知同步, + */ + public static void noticeSync() { + // 提交到线程池中,避免和 schedulePeriodicRefresh 并发问题 + m_executorService.submit(() -> { + INSTANCE.trySync(); + }); + } + + @Override + protected void sync() { + // 第一步,尝试获取配置 + List configs = this.loadConfigIfUpdate(this.maxUpdateTime); + if (CollUtil.isEmpty(configs)) { // 如果没有更新,则返回 + return; + } + + // 第二步,构建新的 Properties + Properties newProperties = this.buildProperties(configs); + this.m_configCache = newProperties; + // 第三步,获取最大的配置时间 + assert configs.size() > 0; // 断言,避免告警 + this.maxUpdateTime = configs.stream().max(Comparator.comparing(ConfigRespDTO::getUpdateTime)).get().getUpdateTime(); + // 第四部,触发配置刷新!重要!!!! + super.fireRepositoryChange(m_namespace, newProperties); + log.info("[sync][缓存配置,数量为:{}]", configs.size()); + } + + @Override + public Properties getConfig() { + // 兜底,避免可能存在配置为 null 的情况 + if (m_configCache == null) { + this.trySync(); + } + // 返回配置 + return m_configCache; + } + + @Override + public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) { + // 啥事不做 + } + + @Override + public ConfigSourceType getSourceType() { + return ConfigSourceType.REMOTE; + } + + private Properties buildProperties(List configs) { + Properties properties = propertiesFactory.getPropertiesInstance(); + configs.stream().filter(ConfigRespDTO::getDeleted) // 过滤掉被删除的配置 + .forEach(config -> properties.put(config.getKey(), config.getValue())); + return properties; + } + + // ========== 定时器相关操作 ========== + + private void schedulePeriodicRefresh() { + log.debug("Schedule periodic refresh with interval: {} {}", + m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit()); + m_executorService.scheduleAtFixedRate(() -> { + Tracer.logEvent("Apollo.ConfigService", String.format("periodicRefresh: %s", m_namespace)); + log.debug("refresh config for namespace: {}", m_namespace); + + // 执行同步. 内部已经 try catch 掉异常,无需在处理 + trySync(); + + Tracer.logEvent("Apollo.Client.Version", Apollo.VERSION); + }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(), + m_configUtil.getRefreshIntervalTimeUnit()); + } + + // ========== 数据库相关操作 ========== + + /** + * 如果配置发生变化,从数据库中获取最新的全量配置。 + * 如果未发生变化,则返回空 + * + * @param maxUpdateTime 当前配置的最大更新时间 + * @return 配置列表 + */ + private List loadConfigIfUpdate(Date maxUpdateTime) { + // 第一步,判断是否要更新。 + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 + log.info("[loadConfigIfUpdate][首次加载全量配置]"); + } else { // 判断数据库中是否有更新的配置 + if (!configFrameworkDAO.selectExistsByUpdateTimeAfter(maxUpdateTime)) { + return null; + } + log.info("[loadConfigIfUpdate][增量加载全量配置]"); + } + // 第二步,如果有更新,则从数据库加载所有配置 + return configFrameworkDAO.selectList(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java new file mode 100644 index 0000000..587a850 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/DefaultXInjector.java @@ -0,0 +1,75 @@ +package cn.iocoder.dashboard.framework.apollo.internals; + +import cn.iocoder.dashboard.framework.apollo.spi.DBConfigFactory; +import com.ctrip.framework.apollo.exceptions.ApolloConfigException; +import com.ctrip.framework.apollo.internals.*; +import com.ctrip.framework.apollo.spi.*; +import com.ctrip.framework.apollo.tracer.Tracer; +import com.ctrip.framework.apollo.util.ConfigUtil; +import com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory; +import com.ctrip.framework.apollo.util.factory.PropertiesFactory; +import com.ctrip.framework.apollo.util.http.HttpUtil; +import com.ctrip.framework.apollo.util.yaml.YamlParser; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Singleton; + +/** + * Guice injector + * + * 基于 Guice 注入器实现类 + * + * @author Jason Song(song_s@ctrip.com) + */ +public class DefaultXInjector implements Injector { + + private final com.google.inject.Injector m_injector; + + public DefaultXInjector() { + try { + m_injector = Guice.createInjector(new ApolloModule()); + } catch (Throwable ex) { + ApolloConfigException exception = new ApolloConfigException("Unable to initialize Guice Injector!", ex); + Tracer.logError(exception); + throw exception; + } + } + + @Override + public T getInstance(Class clazz) { + try { + return m_injector.getInstance(clazz); + } catch (Throwable ex) { + Tracer.logError(ex); + throw new ApolloConfigException(String.format("Unable to load instance for %s!", clazz.getName()), ex); + } + } + + @Override + public T getInstance(Class clazz, String name) { + // Guice does not support get instance by type and name + return null; + } + + private static class ApolloModule extends AbstractModule { + + @Override + protected void configure() { + bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class); + bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class); + bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class); + + // 自定义 ConfigFactory 实现,使用 DB 作为数据源 + bind(ConfigFactory.class).to(DBConfigFactory.class).in(Singleton.class); + + bind(ConfigUtil.class).in(Singleton.class); + bind(HttpUtil.class).in(Singleton.class); + bind(ConfigServiceLocator.class).in(Singleton.class); + bind(RemoteConfigLongPollService.class).in(Singleton.class); + bind(YamlParser.class).in(Singleton.class); + bind(PropertiesFactory.class).to(DefaultPropertiesFactory.class).in(Singleton.class); + } + + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java new file mode 100644 index 0000000..3945dfb --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/internals/dto/ConfigRespDTO.java @@ -0,0 +1,33 @@ +package cn.iocoder.dashboard.framework.apollo.internals.dto; + +import lombok.Data; + +import java.util.Date; + +/** + * 配置 Response DTO + * + * @author 芋道源码 + */ +@Data +public class ConfigRespDTO { + + /** + * 参数键名 + */ + private String key; + /** + * 参数键值 + */ + private String value; + + /** + * 是否删除 + */ + private Boolean deleted; + /** + * 更新时间 + */ + private Date updateTime; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java new file mode 100644 index 0000000..0330411 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/package-info.java @@ -0,0 +1,13 @@ +/** + * 配置中心客户端,基于 Apollo Client 进行简化 + * + * 差别在于,我们使用 {@link cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO} 表作为配置源。 + * 当然,功能肯定也会相对少些,满足最小化诉求。 + * + * 1. 项目初始化时,可以使用 SysConfigDO 表的配置 + * 2. 使用 Spring @Value 可以注入属性 + * 3. SysConfigDO 表的配置修改时,注入到 @Value 的属性可以刷新 + * + * 另外,整个包结构会参考 Apollo 为主,方便维护与理解 + */ +package cn.iocoder.dashboard.framework.apollo; diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java new file mode 100644 index 0000000..bfa9e53 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spi/DBConfigFactory.java @@ -0,0 +1,32 @@ +package cn.iocoder.dashboard.framework.apollo.spi; + +import cn.iocoder.dashboard.framework.apollo.internals.DBConfigRepository; +import com.ctrip.framework.apollo.Config; +import com.ctrip.framework.apollo.ConfigFile; +import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; +import com.ctrip.framework.apollo.internals.ConfigRepository; +import com.ctrip.framework.apollo.internals.DefaultConfig; +import com.ctrip.framework.apollo.spi.ConfigFactory; + +/** + * 基于 DB 的 ConfigFactory 实现类 + * + * @author 芋道源码 + */ +public class DBConfigFactory implements ConfigFactory { + + @Override + public Config create(String namespace) { + return new DefaultConfig(namespace, this.createDBConfigRepository(namespace)); + } + + @Override + public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) { + throw new UnsupportedOperationException("暂不支持 Apollo 配置文件"); + } + + private ConfigRepository createDBConfigRepository(String namespace) { + return new DBConfigRepository(namespace); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java new file mode 100644 index 0000000..47af6b5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/dashboard/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java @@ -0,0 +1,63 @@ +package cn.iocoder.dashboard.framework.apollo.spring.boot; + +import cn.iocoder.dashboard.framework.apollo.core.ConfigConsts; +import com.google.common.base.Strings; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; + +/** + * 对 {@link com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer} 的补充,目前的目的有: + * + * 1. 将自定义的 apollo.jdbc 设置到 System 变量中 + * + * @author 芋道源码 + */ +public class ApolloApplicationContextInitializer implements EnvironmentPostProcessor, Ordered { + + /** + * 优先级更高,要早于 Apollo 的 ApolloApplicationContextInitializer 的初始化 + */ + public static final int DEFAULT_ORDER = -1; + + private int order = DEFAULT_ORDER; + + private static final String[] APOLLO_SYSTEM_PROPERTIES = {ConfigConsts.APOLLO_JDBC_DAO, + ConfigConsts.APOLLO_JDBC_URL, ConfigConsts.APOLLO_JDBC_USERNAME, ConfigConsts.APOLLO_JDBC_PASSWORD}; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + initializeSystemProperty(environment); + } + + /** + * To fill system properties from environment config + */ + void initializeSystemProperty(ConfigurableEnvironment environment) { + for (String propertyName : APOLLO_SYSTEM_PROPERTIES) { + fillSystemPropertyFromEnvironment(environment, propertyName); + } + } + + private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environment, String propertyName) { + if (System.getProperty(propertyName) != null) { + return; + } + String propertyValue = environment.getProperty(propertyName); + if (Strings.isNullOrEmpty(propertyValue)) { + return; + } + System.setProperty(propertyName, propertyValue); + } + + @Override + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml new file mode 100644 index 0000000..14eaa51 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-excel + jar + + ${artifactId} + Excel 拓展 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + jakarta.servlet + jakarta.servlet-api + provided + + + + + com.alibaba + easyexcel + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/annotations/DictFormat.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/annotations/DictFormat.java new file mode 100644 index 0000000..0d898b4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/annotations/DictFormat.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.excel.core.annotations; + +import java.lang.annotation.*; + +/** + * 字典格式化 + * + * 实现将字典数据的值,格式化成字典数据的标签 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface DictFormat { + + /** + * 例如说,SysDictTypeConstants、InfDictTypeConstants + * + * @return 字典类型 + */ + String value(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java new file mode 100644 index 0000000..431d1d0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.framework.excel.core.convert; + + +import cn.hutool.core.convert.Convert; +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; +import cn.iocoder.yudao.framework.dict.core.util.DictUtils; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import lombok.extern.slf4j.Slf4j; + +/** + * Excel {@link DictDataRespDTO} 数据字典转换器 + * + * @author 芋道源码 + */ +@Slf4j +public class DictConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + // 使用字典解析 + String type = getType(contentProperty); + String label = cellData.getStringValue(); + DictDataRespDTO dictData = DictUtils.parseDictDataFromCache(type, label); + if (dictData == null) { + log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label); + return null; + } + // 将 String 的 value 转换成对应的属性 + Class fieldClazz = contentProperty.getField().getType(); + return Convert.convert(fieldClazz, dictData.getValue()); + } + + @Override + public CellData convertToExcelData(Object object, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + // 空时,返回空 + if (object == null) { + return new CellData<>(""); + } + + // 使用字典格式化 + String type = getType(contentProperty); + String value = String.valueOf(object); + DictDataRespDTO dictData = DictUtils.getDictDataFromCache(type, value); + if (dictData == null) { + log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value); + return new CellData<>(""); + } + // 生成 Excel 小表格 + return new CellData<>(dictData.getLabel()); + } + + private static String getType(ExcelContentProperty contentProperty) { + return contentProperty.getField().getAnnotation(DictFormat.class).value(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java new file mode 100644 index 0000000..f0a577c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.framework.excel.core.convert; + +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +/** + * Excel Json 转换器 + * + * @author 芋道源码 + */ +public class JsonConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public CellData convertToExcelData(Object value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + // 生成 Excel 小表格 + return new CellData<>(JsonUtils.toJsonString(value)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java new file mode 100644 index 0000000..0e9bfb4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.framework.excel.core.util; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.List; + +/** + * Excel 工具类 + * + * @author 芋道源码 + */ +public class ExcelUtils { + + /** + * 将列表以 Excel 响应给前端 + * + * @param response 响应 + * @param filename 文件名 + * @param sheetName Excel sheet 名 + * @param head Excel head 头 + * @param data 数据列表哦 + * @param 泛型,保证 head 和 data 类型的一致性 + * @throws IOException 写入失败的情况 + */ + public static void write(HttpServletResponse response, String filename, String sheetName, + Class head, List data) throws IOException { + // 输出 Excel + EasyExcel.write(response.getOutputStream(), head) + .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 + .sheet(sheetName).doWrite(data); + // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + } + + public static List raed(MultipartFile file, Class head) throws IOException { + return EasyExcel.read(file.getInputStream(), head, null) + .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 + .doReadAllSync(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java new file mode 100644 index 0000000..53bc5c0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java @@ -0,0 +1,4 @@ +/** + * 基于 EasyExcel 实现 Excel 相关的操作 + */ +package cn.iocoder.yudao.framework.excel; diff --git a/yudao-framework/yudao-spring-boot-starter-job/pom.xml b/yudao-framework/yudao-spring-boot-starter-job/pom.xml new file mode 100644 index 0000000..0fe41ea --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/pom.xml @@ -0,0 +1,26 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-job + jar + + ${artifactId} + 定时任务,基于 Quartz 拓展 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + org.springframework.boot + spring-boot-starter-quartz + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java new file mode 100644 index 0000000..30d8837 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/config/QuartzConfig.java @@ -0,0 +1,18 @@ +package cn.iocoder.dashboard.framework.quartz.config; + +import cn.iocoder.dashboard.framework.quartz.core.scheduler.SchedulerManager; +import org.quartz.Scheduler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +@Configuration +@EnableScheduling // 开启 Spring 自带的定时任务 +public class QuartzConfig { + + @Bean + public SchedulerManager schedulerManager(Scheduler scheduler) { + return new SchedulerManager(scheduler); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java new file mode 100644 index 0000000..2849d1a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/enums/JobDataKeyEnum.java @@ -0,0 +1,14 @@ +package cn.iocoder.dashboard.framework.quartz.core.enums; + +/** + * Quartz Job Data 的 key 枚举 + */ +public enum JobDataKeyEnum { + + JOB_ID, + JOB_HANDLER_NAME, + JOB_HANDLER_PARAM, + JOB_RETRY_COUNT, // 最大重试次数 + JOB_RETRY_INTERVAL, // 每次重试间隔 + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java new file mode 100644 index 0000000..bdf8a1b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandler.java @@ -0,0 +1,19 @@ +package cn.iocoder.dashboard.framework.quartz.core.handler; + +/** + * 任务处理器 + * + * @author 芋道源码 + */ +public interface JobHandler { + + /** + * 执行任务 + * + * @param param 参数 + * @return 结果 + * @throws Exception 异常 + */ + String execute(String param) throws Exception; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java new file mode 100644 index 0000000..b3aa5ed --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/handler/JobHandlerInvoker.java @@ -0,0 +1,113 @@ +package cn.iocoder.dashboard.framework.quartz.core.handler; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.thread.ThreadUtil; +import cn.iocoder.dashboard.framework.quartz.core.enums.JobDataKeyEnum; +import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService; +import lombok.extern.slf4j.Slf4j; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.PersistJobDataAfterExecution; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import javax.annotation.Resource; +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.diff; +import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCauseMessage; + +/** + * 基础 Job 调用者,负责调用 {@link JobHandler#execute(String)} 执行任务 + * + * @author 芋道源码 + */ +@DisallowConcurrentExecution +@PersistJobDataAfterExecution +@Slf4j +public class JobHandlerInvoker extends QuartzJobBean { + + @Resource + private ApplicationContext applicationContext; + + @Resource + private JobLogFrameworkService jobLogFrameworkService; + + @Override + protected void executeInternal(JobExecutionContext executionContext) throws JobExecutionException { + // 第一步,获得 Job 数据 + Long jobId = executionContext.getMergedJobDataMap().getLong(JobDataKeyEnum.JOB_ID.name()); + String jobHandlerName = executionContext.getMergedJobDataMap().getString(JobDataKeyEnum.JOB_HANDLER_NAME.name()); + String jobHandlerParam = executionContext.getMergedJobDataMap().getString(JobDataKeyEnum.JOB_HANDLER_PARAM.name()); + int refireCount = executionContext.getRefireCount(); + int retryCount = (Integer) executionContext.getMergedJobDataMap().getOrDefault(JobDataKeyEnum.JOB_RETRY_COUNT.name(), 0); + int retryInterval = (Integer) executionContext.getMergedJobDataMap().getOrDefault(JobDataKeyEnum.JOB_RETRY_INTERVAL.name(), 0); + + // 第二步,执行任务 + Long jobLogId = null; + Date startTime = new Date(); + String data = null; + Throwable exception = null; + try { + // 记录 Job 日志(初始) + jobLogId = jobLogFrameworkService.createJobLog(jobId, startTime, jobHandlerName, jobHandlerParam, refireCount + 1); + // 执行任务 + data = this.executeInternal(jobHandlerName, jobHandlerParam); + } catch (Throwable ex) { + exception = ex; + } + + // 第三步,记录执行日志 + this.updateJobLogResultAsync(jobLogId, startTime, data, exception, executionContext); + + // 第四步,处理有异常的情况 + handleException(exception, refireCount, retryCount, retryInterval); + } + + private String executeInternal(String jobHandlerName, String jobHandlerParam) throws Exception { + // 获得 JobHandler 对象 + JobHandler jobHandler = applicationContext.getBean(jobHandlerName, JobHandler.class); + Assert.notNull(jobHandler, "JobHandler 不会为空"); + // 执行任务 + return jobHandler.execute(jobHandlerParam); + } + + private void updateJobLogResultAsync(Long jobLogId, Date startTime, String data, Throwable exception, + JobExecutionContext executionContext) { + Date endTime = new Date(); + // 处理是否成功 + boolean success = exception == null; + if (!success) { + data = getRootCauseMessage(exception); + } + // 更新日志 + try { + jobLogFrameworkService.updateJobLogResultAsync(jobLogId, endTime, (int) diff(endTime, startTime), success, data); + } catch (Exception ex) { + log.error("[executeInternal][Job({}) logId({}) 记录执行日志失败({}/{})]", + executionContext.getJobDetail().getKey(), jobLogId, success, data); + } + } + + private void handleException(Throwable exception, + int refireCount, int retryCount, int retryInterval) throws JobExecutionException { + // 如果有异常,则进行重试 + if (exception == null) { + return; + } + // 情况一:如果到达重试上限,则直接抛出异常即可 + if (refireCount >= retryCount) { + throw new JobExecutionException(exception); + } + + // 情况二:如果未到达重试上限,则 sleep 一定间隔时间,然后重试 + // 这里使用 sleep 来实现,主要还是希望实现比较简单。因为,同一时间,不会存在大量失败的 Job。 + if (retryInterval > 0) { + ThreadUtil.sleep(retryInterval); + } + // 第二个参数,refireImmediately = true,表示立即重试 + throw new JobExecutionException(exception, true); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java new file mode 100644 index 0000000..e72c909 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManager.java @@ -0,0 +1,130 @@ +package cn.iocoder.dashboard.framework.quartz.core.scheduler; + +import cn.iocoder.dashboard.framework.quartz.core.enums.JobDataKeyEnum; +import cn.iocoder.dashboard.framework.quartz.core.handler.JobHandlerInvoker; +import org.quartz.*; + +/** + * {@link org.quartz.Scheduler} 的管理器,负责创建任务 + * + * 考虑到实现的简洁性,我们使用 jobHandlerName 作为唯一标识,即: + * 1. Job 的 {@link JobDetail#getKey()} + * 2. Trigger 的 {@link Trigger#getKey()} + * + * 另外,jobHandlerName 对应到 Spring Bean 的名字,直接调用 + * + * @author 芋道源码 + */ +public class SchedulerManager { + + private final Scheduler scheduler; + + public SchedulerManager(Scheduler scheduler) { + this.scheduler = scheduler; + } + + /** + * 添加 Job 到 Quartz 中 + * + * @param jobId 任务编号 + * @param jobHandlerName 任务处理器的名字 + * @param jobHandlerParam 任务处理器的参数 + * @param cronExpression CRON 表达式 + * @param retryCount 重试次数 + * @param retryInterval 重试间隔 + * @throws SchedulerException 添加异常 + */ + public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression, + Integer retryCount, Integer retryInterval) + throws SchedulerException { + // 创建 JobDetail 对象 + JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class) + .usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId) + .usingJobData(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName) + .withIdentity(jobHandlerName).build(); + // 创建 Trigger 对象 + Trigger trigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); + // 新增调度 + scheduler.scheduleJob(jobDetail, trigger); + } + + /** + * 更新 Job 到 Quartz + * + * @param jobHandlerName 任务处理器的名字 + * @param jobHandlerParam 任务处理器的参数 + * @param cronExpression CRON 表达式 + * @param retryCount 重试次数 + * @param retryInterval 重试间隔 + * @throws SchedulerException 更新异常 + */ + public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression, + Integer retryCount, Integer retryInterval) + throws SchedulerException { + // 创建新 Trigger 对象 + Trigger newTrigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); + // 修改调度 + scheduler.rescheduleJob(new TriggerKey(jobHandlerName), newTrigger); + } + + /** + * 删除 Quartz 中的 Job + * + * @param jobHandlerName 任务处理器的名字 + * @throws SchedulerException 删除异常 + */ + public void deleteJob(String jobHandlerName) throws SchedulerException { + scheduler.deleteJob(new JobKey(jobHandlerName)); + } + + /** + * 暂停 Quartz 中的 Job + * + * @param jobHandlerName 任务处理器的名字 + * @throws SchedulerException 暂停异常 + */ + public void pauseJob(String jobHandlerName) throws SchedulerException { + scheduler.pauseJob(new JobKey(jobHandlerName)); + } + + /** + * 启动 Quartz 中的 Job + * + * @param jobHandlerName 任务处理器的名字 + * @throws SchedulerException 启动异常 + */ + public void resumeJob(String jobHandlerName) throws SchedulerException { + scheduler.resumeJob(new JobKey(jobHandlerName)); + scheduler.resumeTrigger(new TriggerKey(jobHandlerName)); + } + + /** + * 立即触发一次 Quartz 中的 Job + * + * @param jobId 任务编号 + * @param jobHandlerName 任务处理器的名字 + * @param jobHandlerParam 任务处理器的参数 + * @throws SchedulerException 触发异常 + */ + public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam) + throws SchedulerException { + JobDataMap data = new JobDataMap(); // 无需重试,所以不设置 retryCount 和 retryInterval + data.put(JobDataKeyEnum.JOB_ID.name(), jobId); + data.put(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName); + data.put(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam); + // 触发任务 + scheduler.triggerJob(new JobKey(jobHandlerName), data); + } + + private Trigger buildTrigger(String jobHandlerName, String jobHandlerParam, String cronExpression, + Integer retryCount, Integer retryInterval) { + return TriggerBuilder.newTrigger() + .withIdentity(jobHandlerName) + .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) + .usingJobData(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam) + .usingJobData(JobDataKeyEnum.JOB_RETRY_COUNT.name(), retryCount) + .usingJobData(JobDataKeyEnum.JOB_RETRY_INTERVAL.name(), retryInterval) + .build(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java new file mode 100644 index 0000000..a93dfdf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/service/JobLogFrameworkService.java @@ -0,0 +1,44 @@ +package cn.iocoder.dashboard.framework.quartz.core.service; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * Job 日志 Framework Service 接口 + * + * @author 芋道源码 + */ +public interface JobLogFrameworkService { + + /** + * 创建 Job 日志 + * + * @param jobId 任务编号 + * @param beginTime 开始时间 + * @param jobHandlerName Job 处理器的名字 + * @param jobHandlerParam Job 处理器的参数 + * @param executeIndex 第几次执行 + * @return Job 日志的编号 + */ + Long createJobLog(@NotNull(message = "任务编号不能为空") Long jobId, + @NotNull(message = "开始时间") Date beginTime, + @NotEmpty(message = "Job 处理器的名字不能为空") String jobHandlerName, + String jobHandlerParam, + @NotNull(message = "第几次执行不能为空") Integer executeIndex); + + /** + * 更新 Job 日志的执行结果 + * + * @param logId 日志编号 + * @param endTime 结束时间。因为是异步,避免记录时间不准去 + * @param duration 运行时长,单位:毫秒 + * @param success 是否成功 + * @param result 成功数据 + */ + void updateJobLogResultAsync(@NotNull(message = "日志编号不能为空") Long logId, + @NotNull(message = "结束时间不能为空") Date endTime, + @NotNull(message = "运行时长不能为空") Integer duration, + boolean success, String result); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java new file mode 100644 index 0000000..62ba408 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java @@ -0,0 +1,54 @@ +package cn.iocoder.dashboard.framework.quartz.core.util; + +import org.quartz.CronExpression; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Quartz Cron 表达式的工具类 + * + * @author 芋道源码 + */ +public class CronUtils { + + /** + * 校验 CRON 表达式是否有效 + * + * @param cronExpression CRON 表达式 + * @return 是否有效 + */ + public static boolean isValid(String cronExpression) { + return CronExpression.isValidExpression(cronExpression); + } + + /** + * 基于 CRON 表达式,获得下 n 个满足执行的时间 + * + * @param cronExpression CRON 表达式 + * @param n 数量 + * @return 满足条件的执行时间 + */ + public static List getNextTimes(String cronExpression, int n) { + // 获得 CronExpression 对象 + CronExpression cron; + try { + cron = new CronExpression(cronExpression); + } catch (ParseException e) { + throw new IllegalArgumentException(e.getMessage()); + } + // 从当前开始计算,n 个满足条件的 + Date now = new Date(); + List nextTimes = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + Date nextTime = cron.getNextValidTimeAfter(now); + nextTimes.add(nextTime); + // 切换现在,为下一个触发时间; + now = nextTime; + } + return nextTimes; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java new file mode 100644 index 0000000..79d9eeb --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/dashboard/framework/quartz/package-info.java @@ -0,0 +1,5 @@ +/** + * 定时任务,采用 Quartz 实现进程内的任务执行。 + * 考虑到高可用,使用 Quartz 自带的 MySQL 集群方案。 + */ +package cn.iocoder.dashboard.framework.quartz; diff --git a/yudao-framework/yudao-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md b/yudao-framework/yudao-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md new file mode 100644 index 0000000..6564701 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml index 7f9b9f6..7b3a315 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml @@ -15,4 +15,49 @@ 服务监控,提供链路追踪、日志服务、指标收集等等功能 https://github.com/YunaiV/ruoyi-vue-pro + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + org.springframework + spring-web + provided + + + + jakarta.servlet + jakarta.servlet-api + provided + + + + + org.apache.skywalking + apm-toolkit-trace + + + org.apache.skywalking + apm-toolkit-logback-1.x + + + org.apache.skywalking + apm-toolkit-opentracing + + + + de.codecentric + spring-boot-admin-starter-client + + + diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerAutoConfiguration.java new file mode 100644 index 0000000..7209cd8 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerAutoConfiguration.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.framework.tracer.config; + +import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect; +import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter; +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; +import io.opentracing.Tracer; +import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Tracer 配置类 + * + * @author mashu + */ +@Configuration +@ConditionalOnClass({BizTraceAspect.class}) +@EnableConfigurationProperties(TracerProperties.class) +@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) +public class TracerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public TracerProperties bizTracerProperties() { + return new TracerProperties(); + } + + @Bean + @ConditionalOnMissingBean + public BizTraceAspect bizTracingAop() { + return new BizTraceAspect(); + } + + @Bean + @ConditionalOnMissingBean + public Tracer tracer() { + return new SkywalkingTracer(); + } + + /** + * 创建 TraceFilter 过滤器,响应 header 设置 traceId + */ + @Bean + public FilterRegistrationBean traceFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new TraceFilter()); + registrationBean.setOrder(WebFilterOrderEnum.TRACE_FILTER); + return registrationBean; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerProperties.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerProperties.java new file mode 100644 index 0000000..11d25a8 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/TracerProperties.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.framework.tracer.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * BizTracer配置类 + * + * @author 麻薯 + */ +@ConfigurationProperties("yudao.tracer") +@Data +public class TracerProperties { +} diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/annotation/BizTrace.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/annotation/BizTrace.java new file mode 100644 index 0000000..8b12140 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/annotation/BizTrace.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.framework.tracer.core.annotation; + +import java.lang.annotation.*; + +/** + * 打印业务编号 / 业务类型注解 + * + * 使用时,需要设置 SkyWalking OAP Server 的 application.yaml 配置文件,修改 SW_SEARCHABLE_TAG_KEYS 配置项, + * 增加 biz.type 和 biz.id 两值,然后重启 SkyWalking OAP Server 服务器。 + * + * @author 麻薯 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface BizTrace { + + /** + * 业务编号 tag 名 + */ + String ID_TAG = "biz.id"; + /** + * 业务类型 tag 名 + */ + String TYPE_TAG = "biz.type"; + + /** + * @return 操作名 + */ + String operationName() default ""; + + /** + * @return 业务编号 + */ + String id(); + + /** + * @return 业务类型 + */ + String type(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/aop/BizTraceAspect.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/aop/BizTraceAspect.java new file mode 100644 index 0000000..1bc9d18 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/aop/BizTraceAspect.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.framework.tracer.core.aop; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.tracer.core.annotation.BizTrace; +import cn.iocoder.yudao.framework.common.util.sping.SpringExpressionUtils; +import io.opentracing.Span; +import io.opentracing.Tracer; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; + +import javax.annotation.Resource; +import java.util.Map; + +import static java.util.Arrays.asList; + +/** + * {@link BizTrace} 切面,记录业务链路 + * + * @author mashu + */ +@Aspect +@Slf4j +public class BizTraceAspect { + + private static final String BIZ_OPERATION_NAME_PREFIX = "Biz/"; + + @Resource + private Tracer tracer; + + @Around(value = "@annotation(trace)") + public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable { + // 创建 span + String operationName = getOperationName(joinPoint, trace); + Span span = tracer.buildSpan(operationName).startManual(); + try { + // 执行原有方法 + return joinPoint.proceed(); + } finally { + // 设置 Span 的 biz 属性 + setBizTag(span, joinPoint, trace); + // 完成 Span + span.finish(); + } + } + + private String getOperationName(ProceedingJoinPoint joinPoint, BizTrace trace) { + // 自定义操作名 + if (StrUtil.isNotEmpty(trace.operationName())) { + return BIZ_OPERATION_NAME_PREFIX + trace.operationName(); + } + // 默认操作名,使用方法名 + return BIZ_OPERATION_NAME_PREFIX + + joinPoint.getSignature().getDeclaringType().getSimpleName() + + "/" + joinPoint.getSignature().getName(); + } + + private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) { + try { + Map result = SpringExpressionUtils.parseExpressions(joinPoint, asList(trace.type(), trace.id())); + span.setTag(BizTrace.TYPE_TAG, MapUtil.getStr(result, trace.type())); + span.setTag(BizTrace.ID_TAG, MapUtil.getStr(result, trace.id())); + } catch (Exception ex) { + log.error("[setBizTag][解析 bizType 与 bizId 发生异常]", ex); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java new file mode 100644 index 0000000..91ac30f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.framework.tracer.core.filter; + +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Trace 过滤器,打印 traceId 到 header 中返回 + * + * @author 芋道源码 + */ +public class TraceFilter extends OncePerRequestFilter { + + /** + * Header 名 - 链路追踪编号 + */ + private static final String HEADER_NAME_TRACE_ID = "trace-id"; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { + // 设置响应 traceId + response.addHeader(HEADER_NAME_TRACE_ID, TracerUtils.getTraceId()); + // 继续过滤 + chain.doFilter(request, response); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/package-info.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/package-info.java new file mode 100644 index 0000000..43ee5e4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/package-info.java @@ -0,0 +1,6 @@ +/** + * 使用 SkyWalking 组件,作为链路追踪、日志中心。 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.tracer; diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md new file mode 100644 index 0000000..ed9d4fe --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 73753ff..0daf802 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -22,8 +22,7 @@ cn.iocoder.boot - yudao-framework-all - ${revision} + yudao-common diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/JsonLongSetTypeHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/JsonLongSetTypeHandler.java index f4f3ce9..ed6d81b 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/JsonLongSetTypeHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/JsonLongSetTypeHandler.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.mybatis.core.type; -import cn.iocoder.yudao.framework.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; import com.fasterxml.jackson.core.type.TypeReference; diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml deleted file mode 100644 index 3c0486c..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - cn.iocoder.boot - yudao-framework - ${revision} - - 4.0.0 - yudao-spring-boot-starter-operatelog - jar - - ${artifactId} - 操作日志 - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - cn.iocoder.boot - yudao-spring-boot-starter-web - provided - - - - - com.google.guava - guava - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java deleted file mode 100644 index c4e784b..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.config; - -import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class YudaoOperateLogAutoConfiguration { - - @Bean - public OperateLogAspect operateLogAspect() { - return new OperateLogAspect(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java deleted file mode 100644 index 2f9ecaf..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.annotations; - -import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 操作日志注解 - * - * @author 芋道源码 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface OperateLog { - - // ========== 模块字段 ========== - - /** - * 操作模块 - * - * 为空时,会尝试读取 {@link Api#value()} 属性 - */ - String module() default ""; - /** - * 操作名 - * - * 为空时,会尝试读取 {@link ApiOperation#value()} 属性 - */ - String name() default ""; - /** - * 操作分类 - * - * 实际并不是数组,因为枚举不能设置 null 作为默认值 - */ - OperateTypeEnum[] type() default {}; - - // ========== 开关字段 ========== - - /** - * 是否记录操作日志 - */ - boolean enable() default true; - /** - * 是否记录方法参数 - */ - boolean logArgs() default true; - /** - * 是否记录方法结果的数据 - */ - boolean logResultData() default true; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java deleted file mode 100644 index b6a6cd2..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java +++ /dev/null @@ -1,354 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.aop; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; -import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.IntStream; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; - -/** - * 拦截使用 @OperateLog 注解,如果满足条件,则生成操作日志。 - * 满足如下任一条件,则会进行记录: - * 1. 使用 @ApiOperation + 非 @GetMapping - * 2. 使用 @OperateLog 注解 - * - * 但是,如果声明 @OperateLog 注解时,将 enable 属性设置为 false 时,强制不记录。 - * - * @author 芋道源码 - */ -@Aspect -@Slf4j -public class OperateLogAspect { - - /** - * 用于记录操作内容的上下文 - * - * @see OperateLogCreateReqDTO#getContent() - */ - private static final ThreadLocal CONTENT = new ThreadLocal<>(); - /** - * 用于记录拓展字段的上下文 - * - * @see OperateLogCreateReqDTO#getExts() - */ - private static final ThreadLocal> EXTS = new ThreadLocal<>(); - - @Resource - private OperateLogFrameworkService operateLogFrameworkService; - - @Around("@annotation(apiOperation)") - public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable { - // 可能也添加了 @ApiOperation 注解 - OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class); - return around0(joinPoint, operateLog, apiOperation); - } - - @Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况 - public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable { - return around0(joinPoint, operateLog, null); - } - - private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable { - // 记录开始时间 - Date startTime = new Date(); - try { - // 执行原有方法 - Object result = joinPoint.proceed(); - // 记录正常执行时的操作日志 - this.log(joinPoint, operateLog, apiOperation, startTime, result, null); - return result; - } catch (Throwable exception) { - this.log(joinPoint, operateLog, apiOperation, startTime, null, exception); - throw exception; - } finally { - clearThreadLocal(); - } - } - - public static void setContent(String content) { - CONTENT.set(content); - } - - public static void addExt(String key, Object value) { - if (EXTS.get() == null) { - EXTS.set(new HashMap<>()); - } - EXTS.get().put(key, value); - } - - private static void clearThreadLocal() { - CONTENT.remove(); - EXTS.remove(); - } - - private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, - Date startTime, Object result, Throwable exception) { - try { - // 判断不记录的情况 - if (!isLogEnable(joinPoint, operateLog)) { - return; - } - // 真正记录操作日志 - this.log0(joinPoint, operateLog, apiOperation, startTime, result, exception); - } catch (Throwable ex) { - log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) operateLog({}) apiOperation({}) result({}) exception({}) ]", - joinPoint, operateLog, apiOperation, result, exception, ex); - } - } - - private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, - Date startTime, Object result, Throwable exception) { - OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO(); - // 补全通用字段 - operateLogDTO.setTraceId(TracerUtils.getTraceId()); - operateLogDTO.setStartTime(startTime); - // 补充用户信息 - fillUserFields(operateLogDTO); - // 补全模块信息 - fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation); - // 补全请求信息 - fillRequestFields(operateLogDTO); - // 补全方法信息 - fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception); - - // 异步记录日志 - operateLogFrameworkService.createOperateLogAsync(operateLogDTO); - } - - private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { - operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId()); - } - - private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, - ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) { - // module 属性 - if (operateLog != null) { - operateLogDTO.setModule(operateLog.module()); - } - if (StrUtil.isEmpty(operateLogDTO.getModule())) { - Api api = getClassAnnotation(joinPoint, Api.class); - if (api != null) { - // 优先读取 @API 的 name 属性 - if (StrUtil.isNotEmpty(api.value())) { - operateLogDTO.setModule(api.value()); - } - // 没有的话,读取 @API 的 tags 属性 - if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) { - operateLogDTO.setModule(api.tags()[0]); - } - } - } - // name 属性 - if (operateLog != null) { - operateLogDTO.setName(operateLog.name()); - } - if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) { - operateLogDTO.setName(apiOperation.value()); - } - // type 属性 - if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) { - operateLogDTO.setType(operateLog.type()[0].getType()); - } - if (operateLogDTO.getType() == null) { - RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); - OperateTypeEnum operateLogType = convertOperateLogType(requestMethod); - operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null); - } - // content 和 exts 属性 - operateLogDTO.setContent(CONTENT.get()); - operateLogDTO.setExts(EXTS.get()); - } - - private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) { - // 获得 Request 对象 - HttpServletRequest request = ServletUtils.getRequest(); - if (request == null) { - return; - } - // 补全请求信息 - operateLogDTO.setRequestMethod(request.getMethod()); - operateLogDTO.setRequestUrl(request.getRequestURI()); - operateLogDTO.setUserIp(ServletUtil.getClientIP(request)); - operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request)); - } - - private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO, - ProceedingJoinPoint joinPoint, OperateLog operateLog, - Date startTime, Object result, Throwable exception) { - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - operateLogDTO.setJavaMethod(methodSignature.toString()); - if (operateLog == null || operateLog.logArgs()) { - operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); - } - if (operateLog == null || operateLog.logResultData()) { - operateLogDTO.setResultData(obtainResultData(result)); - } - operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); - // (正常)处理 resultCode 和 resultMsg 字段 - if (result != null) { - if (result instanceof CommonResult) { - CommonResult commonResult = (CommonResult) result; - operateLogDTO.setResultCode(commonResult.getCode()); - operateLogDTO.setResultMsg(commonResult.getMsg()); - } else { - operateLogDTO.setResultCode(SUCCESS.getCode()); - } - } - // (异常)处理 resultCode 和 resultMsg 字段 - if (exception != null) { - operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); - operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); - } - } - - private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) { - // 有 @OperateLog 注解的情况下 - if (operateLog != null) { - return operateLog.enable(); - } - // 没有 @ApiOperation 注解的情况下,只记录 POST、PUT、DELETE 的情况 - return obtainFirstLogRequestMethod(obtainRequestMethod(joinPoint)) != null; - } - - private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { - if (ArrayUtil.isEmpty(requestMethods)) { - return null; - } - return Arrays.stream(requestMethods).filter(requestMethod -> - requestMethod == RequestMethod.POST - || requestMethod == RequestMethod.PUT - || requestMethod == RequestMethod.DELETE) - .findFirst().orElse(null); - } - - private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { - if (ArrayUtil.isEmpty(requestMethods)) { - return null; - } - // 优先,匹配最优的 POST、PUT、DELETE - RequestMethod result = obtainFirstLogRequestMethod(requestMethods); - if (result != null) { - return result; - } - // 然后,匹配次优的 GET - result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) - .findFirst().orElse(null); - if (result != null) { - return result; - } - // 兜底,获得第一个 - return requestMethods[0]; - } - - private static OperateTypeEnum convertOperateLogType(RequestMethod requestMethod) { - if (requestMethod == null) { - return null; - } - switch (requestMethod) { - case GET: - return OperateTypeEnum.GET; - case POST: - return OperateTypeEnum.CREATE; - case PUT: - return OperateTypeEnum.UPDATE; - case DELETE: - return OperateTypeEnum.DELETE; - default: - return OperateTypeEnum.OTHER; - } - } - - private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { - RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 - ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); - return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; - } - - @SuppressWarnings("SameParameterValue") - private static T getMethodAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { - return ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(annotationClass); - } - - @SuppressWarnings("SameParameterValue") - private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { - return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); - } - - private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { - // TODO 提升:参数脱敏和忽略 - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - String[] argNames = methodSignature.getParameterNames(); - Object[] argValues = joinPoint.getArgs(); - // 拼接参数 - Map args = Maps.newHashMapWithExpectedSize(argValues.length); - for (int i = 0; i < argNames.length; i++) { - String argName = argNames[i]; - Object argValue = argValues[i]; - // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 - args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); - } - return JsonUtils.toJsonString(args); - } - - private static String obtainResultData(Object result) { - // TODO 提升:结果脱敏和忽略 - if (result instanceof CommonResult) { - result = ((CommonResult) result).getData(); - } - return JsonUtils.toJsonString(result); - } - - private static boolean isIgnoreArgs(Object object) { - Class clazz = object.getClass(); - // 处理数组的情况 - if (clazz.isArray()) { - return IntStream.range(0, Array.getLength(object)) - .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); - } - // 递归,处理数组、Collection、Map 的情况 - if (Collection.class.isAssignableFrom(clazz)) { - return ((Collection) object).stream() - .anyMatch((Predicate) o -> isIgnoreArgs(object)); - } - if (Map.class.isAssignableFrom(clazz)) { - return isIgnoreArgs(((Map) object).values()); - } - // obj - return object instanceof MultipartFile - || object instanceof HttpServletRequest - || object instanceof HttpServletResponse; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java deleted file mode 100644 index 8dd98d4..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java +++ /dev/null @@ -1,84 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.dto; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Date; -import java.util.Map; - -/** - * 操作日志创建 Request DTO - */ -@Data -public class OperateLogCreateReqDTO { - - @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") - @NotEmpty(message = "链路追踪编号不能为空") - private String traceId; - - @ApiModelProperty(value = "用户编号", required = true, example = "1024") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @ApiModelProperty(value = "操作模块", required = true, example = "订单") - @NotEmpty(message = "操作模块不能为空") - private String module; - - @ApiModelProperty(value = "操作名", required = true, example = "创建订单") - @NotEmpty(message = "操作名") - private String name; - - @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") - @NotNull(message = "操作分类不能为空") - private Integer type; - - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") - private String content; - - @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}") - private Map exts; - - @ApiModelProperty(value = "请求方法名", required = true, example = "GET") - @NotEmpty(message = "请求方法名不能为空") - private String requestMethod; - - @ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy") - @NotEmpty(message = "请求地址不能为空") - private String requestUrl; - - @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0") - @NotEmpty(message = "浏览器 UserAgent 不能为空") - private String userAgent; - - @ApiModelProperty(value = "Java 方法名", required = true, example = "cn.iocoder.dashboard.UserController.save(...)") - @NotEmpty(message = "Java 方法名不能为空") - private String javaMethod; - - @ApiModelProperty(value = "Java 方法的参数") - private String javaMethodArgs; - - @ApiModelProperty(value = "开始时间", required = true) - @NotNull(message = "开始时间不能为空") - private Date startTime; - - @ApiModelProperty(value = "执行时长,单位:毫秒", required = true) - @NotNull(message = "执行时长不能为空") - private Integer duration; - - @ApiModelProperty(value = "结果码", required = true) - @NotNull(message = "结果码不能为空") - private Integer resultCode; - - @ApiModelProperty(value = "结果提示") - private String resultMsg; - - @ApiModelProperty(value = "结果数据") - private String resultData; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java deleted file mode 100644 index 65ee26d..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.enums; - -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 操作日志的操作类型 - * - * @author ruoyi - */ -@Getter -@AllArgsConstructor -public enum OperateTypeEnum { - - /** - * 查询 - * - * 绝大多数情况下,不会记录查询动作,因为过于大量显得没有意义。 - * 在有需要的时候,通过声明 {@link OperateLog} 注解来记录 - */ - GET(1), - /** - * 新增 - */ - CREATE(2), - /** - * 修改 - */ - UPDATE(3), - /** - * 删除 - */ - DELETE(4), - /** - * 导出 - */ - EXPORT(5), - /** - * 导入 - */ - IMPORT(6), - /** - * 其它 - * - * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识 - */ - OTHER(0); - - /** - * 类型 - */ - private final Integer type; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java deleted file mode 100644 index 58aa3d5..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core; diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java deleted file mode 100644 index ef20e2e..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.service; - -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; - -import java.util.concurrent.Future; - -public interface OperateLogFrameworkService { - - /** - * 异步记录操作日志 - * - * @param reqVO 操作日志请求 - * @return true: 记录成功,false: 记录失败 - */ - Future createOperateLogAsync(OperateLogCreateReqDTO reqVO); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java deleted file mode 100644 index a9801e5..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.framework.operatelog.core.util; - -import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; - -/** - * 操作日志工具类 - * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 - * - * @author 芋道源码 - */ -public class OperateLogUtils { - - public static void setContent(String content) { - OperateLogAspect.setContent(content); - } - - public static void addExt(String key, Object value) { - OperateLogAspect.addExt(key, value); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java deleted file mode 100644 index d272b53..0000000 --- a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 用户操作日志:记录用户的操作,用于对用户的操作的审计与追溯,永久保存。 - * - * @author 芋道源码 - */ -package cn.iocoder.yudao.framework.operatelog; diff --git a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml index 0933bf9..16b5acf 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml @@ -15,4 +15,24 @@ 服务保证,提供分布式锁、幂等、限流、熔断等等功能 https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-spring-boot-starter-redis + provided + + + + + com.baomidou + lock4j-redisson-spring-boot-starter + + + + io.github.resilience4j + resilience4j-spring-boot2 + + + diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/IdempotentConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/IdempotentConfiguration.java new file mode 100644 index 0000000..4700379 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/IdempotentConfiguration.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.framework.idempotent.config; + +import cn.iocoder.yudao.framework.idempotent.core.aop.IdempotentAspect; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; +import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.util.List; + +@Configuration(proxyBeanMethods = false) +@AutoConfigureAfter(RedisAutoConfiguration.class) +public class IdempotentConfiguration { + + @Bean + public IdempotentAspect idempotentAspect(List keyResolvers, IdempotentRedisDAO idempotentRedisDAO) { + return new IdempotentAspect(keyResolvers, idempotentRedisDAO); + } + + @Bean + public IdempotentRedisDAO idempotentRedisDAO(StringRedisTemplate stringRedisTemplate) { + return new IdempotentRedisDAO(stringRedisTemplate); + } + + // ========== 各种 IdempotentKeyResolver Bean ========== + + @Bean + public DefaultIdempotentKeyResolver defaultIdempotentKeyResolver() { + return new DefaultIdempotentKeyResolver(); + } + + @Bean + public ExpressionIdempotentKeyResolver expressionIdempotentKeyResolver() { + return new ExpressionIdempotentKeyResolver(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/annotation/Idempotent.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/annotation/Idempotent.java new file mode 100644 index 0000000..579a07c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/annotation/Idempotent.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.framework.idempotent.core.annotation; + +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.concurrent.TimeUnit; + +/** + * 幂等注解 + * + * @author 芋道源码 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Idempotent { + + /** + * 幂等的超时时间,默认为 1 秒 + * + * 注意,如果执行时间超过它,请求还是会进来 + */ + int timeout() default 1; + /** + * 时间单位,默认为 SECONDS 秒 + */ + TimeUnit timeUnit() default TimeUnit.SECONDS; + + /** + * 提示信息,正在执行中的提示 + */ + String message() default "重复请求,请稍后重试"; + + /** + * 使用的 Key 解析器 + */ + Class keyResolver() default DefaultIdempotentKeyResolver.class; + /** + * 使用的 Key 参数 + */ + String keyArg() default ""; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/aop/IdempotentAspect.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/aop/IdempotentAspect.java new file mode 100644 index 0000000..9453444 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/aop/IdempotentAspect.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.framework.idempotent.core.aop; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; +import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.util.Assert; + +import java.util.List; +import java.util.Map; + +/** + * 拦截声明了 {@link Idempotent} 注解的方法,实现幂等操作 + * + * @author 芋道源码 + */ +@Aspect +@Slf4j +public class IdempotentAspect { + + /** + * IdempotentKeyResolver 集合 + */ + private final Map, IdempotentKeyResolver> keyResolvers; + + private final IdempotentRedisDAO idempotentRedisDAO; + + public IdempotentAspect(List keyResolvers, IdempotentRedisDAO idempotentRedisDAO) { + this.keyResolvers = CollectionUtils.convertMap(keyResolvers, IdempotentKeyResolver::getClass); + this.idempotentRedisDAO = idempotentRedisDAO; + } + + @Before("@annotation(idempotent)") + public void beforePointCut(JoinPoint joinPoint, Idempotent idempotent) { + // 获得 IdempotentKeyResolver + IdempotentKeyResolver keyResolver = keyResolvers.get(idempotent.keyResolver()); + Assert.notNull(keyResolver, "找不到对应的 IdempotentKeyResolver"); + // 解析 Key + String key = keyResolver.resolver(joinPoint, idempotent); + + // 锁定 Key。 + boolean success = idempotentRedisDAO.setIfAbsent(key, idempotent.timeout(), idempotent.timeUnit()); + // 锁定失败,抛出异常 + if (!success) { + log.info("[beforePointCut][方法({}) 参数({}) 存在重复请求]", joinPoint.getSignature().toString(), joinPoint.getArgs()); + throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), idempotent.message()); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java new file mode 100644 index 0000000..1617570 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.idempotent.core.keyresolver; + +import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent; +import org.aspectj.lang.JoinPoint; + +/** + * 幂等 Key 解析器接口 + * + * @author 芋道源码 + */ +public interface IdempotentKeyResolver { + + /** + * 解析一个 Key + * + * @param idempotent 幂等注解 + * @param joinPoint AOP 切面 + * @return Key + */ + String resolver(JoinPoint joinPoint, Idempotent idempotent); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java new file mode 100644 index 0000000..5685699 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; +import org.aspectj.lang.JoinPoint; + +/** + * 默认幂等 Key 解析器,使用方法名 + 方法参数,组装成一个 Key + * + * 为了避免 Key 过长,使用 MD5 进行“压缩” + * + * @author 芋道源码 + */ +public class DefaultIdempotentKeyResolver implements IdempotentKeyResolver { + + @Override + public String resolver(JoinPoint joinPoint, Idempotent idempotent) { + String methodName = joinPoint.getSignature().toString(); + String argsStr = StrUtil.join(",", joinPoint.getArgs()); + return SecureUtil.md5(methodName + argsStr); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java new file mode 100644 index 0000000..50b4a2c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl; + +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent; +import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import java.lang.reflect.Method; + +/** + * 基于 Spring EL 表达式, + * + * @author 芋道源码 + */ +public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver { + + private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); + private final ExpressionParser expressionParser = new SpelExpressionParser(); + + @Override + public String resolver(JoinPoint joinPoint, Idempotent idempotent) { + // 获得被拦截方法参数名列表 + Method method = getMethod(joinPoint); + Object[] args = joinPoint.getArgs(); + String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method); + // 准备 Spring EL 表达式解析的上下文 + StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + if (ArrayUtil.isNotEmpty(parameterNames)) { + for (int i = 0; i < parameterNames.length; i++) { + evaluationContext.setVariable(parameterNames[i], args[i]); + } + } + + // 解析参数 + Expression expression = expressionParser.parseExpression(idempotent.keyArg()); + return expression.getValue(evaluationContext, String.class); + } + + private static Method getMethod(JoinPoint point) { + // 处理,声明在类上的情况 + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + if (!method.getDeclaringClass().isInterface()) { + return method; + } + + // 处理,声明在接口上的情况 + try { + return point.getTarget().getClass().getDeclaredMethod( + point.getSignature().getName(), method.getParameterTypes()); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/redis/IdempotentRedisDAO.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/redis/IdempotentRedisDAO.java new file mode 100644 index 0000000..05e1c6b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/redis/IdempotentRedisDAO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.idempotent.core.redis; + +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; +import lombok.AllArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.util.concurrent.TimeUnit; + +import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; + +/** + * 幂等 Redis DAO + * + * @author 芋道源码 + */ +@AllArgsConstructor +public class IdempotentRedisDAO { + + private static final RedisKeyDefine IDEMPOTENT = new RedisKeyDefine("幂等操作", + "idempotent:%s", // 参数为 uuid + STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); + + private final StringRedisTemplate redisTemplate; + + public Boolean setIfAbsent(String key, long timeout, TimeUnit timeUnit) { + String redisKey = formatKey(key); + return redisTemplate.opsForValue().setIfAbsent(redisKey, "", timeout, timeUnit); + } + + private static String formatKey(String key) { + return String.format(IDEMPOTENT.getKeyTemplate(), key); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/package-info.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/package-info.java new file mode 100644 index 0000000..8cad5fc --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/package-info.java @@ -0,0 +1,12 @@ +/** + * 幂等组件,参考 https://github.com/it4alla/idempotent 项目实现 + * 实现原理是,相同参数的方法,一段时间内,有且仅能执行一次。通过这样的方式,保证幂等性。 + * + * 使用场景:例如说,用户快速的双击了某个按钮,前端没有禁用该按钮,导致发送了两次重复的请求。 + * + * 和 it4alla/idempotent 组件的差异点,主要体现在两点: + * 1. 我们去掉了 @Idempotent 注解的 delKey 属性。原因是,本质上 delKey 为 true 时,实现的是分布式锁的能力 + * 此时,我们偏向使用 Lock4j 组件。原则上,一个组件只提供一种单一的能力。 + * 2. 考虑到组件的通用性,我们并未像 it4alla/idempotent 组件一样使用 Redisson RMap 结构,而是直接使用 Redis 的 String 数据格式。 + */ +package cn.iocoder.yudao.framework.idempotent; diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/Lock4jConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/Lock4jConfiguration.java new file mode 100644 index 0000000..567ff69 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/Lock4jConfiguration.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.framework.lock4j.config; + +import cn.hutool.core.util.ClassUtil; +import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy; +import cn.iocoder.yudao.framework.lock4j.core.Lock4jRedisKeyConstants; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Lock4jConfiguration { + + static { + // 手动加载 Lock4jRedisKeyConstants 类,因为它不会被使用到 + // 如果不加载,会导致 Redis 监控,看到它的 Redis Key 枚举 + ClassUtil.loadClass(Lock4jRedisKeyConstants.class.getName()); + } + + @Bean + public DefaultLockFailureStrategy lockFailureStrategy() { + return new DefaultLockFailureStrategy(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java new file mode 100644 index 0000000..3af5435 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.lock4j.core; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import com.baomidou.lock.LockFailureStrategy; +import lombok.extern.slf4j.Slf4j; + +/** + * 自定义获取锁失败策略,抛出 {@link ServiceException} 异常 + */ +@Slf4j +public class DefaultLockFailureStrategy implements LockFailureStrategy { + + @Override + public void onLockFailure(String key, long acquireTimeout, int acquireCount) { + log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取超时时长:{} ms]", Thread.currentThread().getName(), key, acquireTimeout); + throw new ServiceException(GlobalErrorCodeConstants.LOCKED); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/Lock4jRedisKeyConstants.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/Lock4jRedisKeyConstants.java new file mode 100644 index 0000000..cc01a25 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/Lock4jRedisKeyConstants.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.framework.lock4j.core; + +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; +import org.redisson.api.RLock; + +import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH; + +/** + * Lock4j Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface Lock4jRedisKeyConstants { + + RedisKeyDefine LOCK4J = new RedisKeyDefine("分布式锁", + "lock4j:%s", // 参数来自 DefaultLockKeyBuilder 类 + HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/package-info.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/package-info.java new file mode 100644 index 0000000..267b951 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/package-info.java @@ -0,0 +1,4 @@ +/** + * 分布式锁组件,使用 https://gitee.com/baomidou/lock4j 开源项目 + */ +package cn.iocoder.yudao.framework.lock4j; diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/package-info.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/package-info.java new file mode 100644 index 0000000..649e8a0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/package-info.java @@ -0,0 +1,9 @@ +/** + * 使用 Resilience4j 组件,实现服务保障,包括: + * 1. 熔断器 + * 2. 限流器 + * 3. 舱壁隔离 + * 4. 重试 + * 5. 限时器 + */ +package cn.iocoder.yudao.framework.resilience4j; diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md new file mode 100644 index 0000000..8d6d033 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml new file mode 100644 index 0000000..58ab727 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml @@ -0,0 +1,31 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-redis + jar + + ${artifactId} + Redis 封装拓展 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + + + + + org.redisson + redisson-spring-boot-starter + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/RedisConfig.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/RedisConfig.java new file mode 100644 index 0000000..354cb27 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/RedisConfig.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.framework.redis.config; + +import cn.hutool.system.SystemUtil; +import cn.iocoder.yudao.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.framework.redis.core.stream.AbstractStreamMessageListener; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.stream.Consumer; +import org.springframework.data.redis.connection.stream.ObjectRecord; +import org.springframework.data.redis.connection.stream.ReadOffset; +import org.springframework.data.redis.connection.stream.StreamOffset; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.stream.StreamMessageListenerContainer; + +import java.util.List; + +/** + * Redis 配置类 + */ +@Configuration +@Slf4j +public class RedisConfig { + + /** + * 创建 RedisTemplate Bean,使用 JSON 序列化方式 + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + // 创建 RedisTemplate 对象 + RedisTemplate template = new RedisTemplate<>(); + // 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。 + template.setConnectionFactory(factory); + // 使用 String 序列化方式,序列化 KEY 。 + template.setKeySerializer(RedisSerializer.string()); + template.setHashKeySerializer(RedisSerializer.string()); + // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。 + template.setValueSerializer(RedisSerializer.json()); + template.setHashValueSerializer(RedisSerializer.json()); + return template; + } + + /** + * 创建 Redis Pub/Sub 广播消费的容器 + */ + @Bean + public RedisMessageListenerContainer redisMessageListenerContainer( + RedisConnectionFactory factory, List> listeners) { + // 创建 RedisMessageListenerContainer 对象 + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + // 设置 RedisConnection 工厂。 + container.setConnectionFactory(factory); + // 添加监听器 + listeners.forEach(listener -> { + container.addMessageListener(listener, new ChannelTopic(listener.getChannel())); + log.info("[redisMessageListenerContainer][注册 Channel({}) 对应的监听器({})]", + listener.getChannel(), listener.getClass().getName()); + }); + return container; + } + + /** + * 创建 Redis Stream 集群消费的容器 + * + * Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html + */ + @Bean(initMethod = "start", destroyMethod = "stop") + public StreamMessageListenerContainer> redisStreamMessageListenerContainer( + RedisTemplate redisTemplate, List> listeners) { + // 第一步,创建 StreamMessageListenerContainer 容器 + // 创建 options 配置 + StreamMessageListenerContainer.StreamMessageListenerContainerOptions> containerOptions = + StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder() + .batchSize(10) // 一次性最多拉取多少条消息 + .targetType(String.class) // 目标类型。统一使用 String,通过自己封装的 AbstractStreamMessageListener 去反序列化 + .build(); + // 创建 container 对象 + StreamMessageListenerContainer> container = StreamMessageListenerContainer.create( + redisTemplate.getRequiredConnectionFactory(), containerOptions); + + // 第二步,注册监听器,消费对应的 Stream 主题 + String consumerName = buildConsumerName(); +// String consumerName = "110"; + listeners.forEach(listener -> { + // 创建 listener 对应的消费者分组 + try { + redisTemplate.opsForStream().createGroup(listener.getStreamKey(), listener.getGroup()); + } catch (Exception ignore) {} + // 设置 listener 对应的 redisTemplate + listener.setRedisTemplate(redisTemplate); + // 创建 Consumer 对象 + Consumer consumer = Consumer.from(listener.getGroup(), consumerName); + // 设置 Consumer 消费进度,以最小消费进度为准 + StreamOffset streamOffset = StreamOffset.create(listener.getStreamKey(), ReadOffset.lastConsumed()); + // 设置 Consumer 监听 + StreamMessageListenerContainer.StreamReadRequestBuilder builder = StreamMessageListenerContainer.StreamReadRequest + .builder(streamOffset).consumer(consumer) + .autoAcknowledge(false) // 不自动 ack + .cancelOnError(throwable -> false); // 默认配置,发生异常就取消消费,显然不符合预期;因此,我们设置为 false + container.register(builder.build(), listener); + }); + return container; + } + + /** + * 构建消费者名字,使用本地 IP + 进程编号的方式。 + * 参考自 RocketMQ clientId 的实现 + * + * @return 消费者名字 + */ + private static String buildConsumerName() { + return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyDefine.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyDefine.java new file mode 100644 index 0000000..1167bfa --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyDefine.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.framework.redis.core; + +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; + +import java.time.Duration; + +/** + * Redis Key 定义类 + * + * @author 芋道源码 + */ +@Data +public class RedisKeyDefine { + + @Getter + @AllArgsConstructor + public enum KeyTypeEnum { + + STRING("String"), + LIST("List"), + HASH("Hash"), + SET("Set"), + ZSET("Sorted Set"), + STREAM("Stream"), + PUBSUB("Pub/Sub"); + + /** + * 类型 + */ + @JsonValue + private final String type; + + } + + @Getter + @AllArgsConstructor + public enum TimeoutTypeEnum { + + FOREVER(1), // 永不超时 + DYNAMIC(2), // 动态超时 + FIXED(3); // 固定超时 + + /** + * 类型 + */ + @JsonValue + private final Integer type; + + } + + /** + * Key 模板 + */ + private final String keyTemplate; + /** + * Key 类型的枚举 + */ + private final KeyTypeEnum keyType; + /** + * Value 类型 + * + * 如果是使用分布式锁,设置为 {@link java.util.concurrent.locks.Lock} 类型 + */ + private final Class valueType; + /** + * 超时类型 + */ + private final TimeoutTypeEnum timeoutType; + /** + * 过期时间 + */ + private final Duration timeout; + /** + * 备注 + */ + private final String memo; + + private RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class valueType, + TimeoutTypeEnum timeoutType, Duration timeout) { + this.memo = memo; + this.keyTemplate = keyTemplate; + this.keyType = keyType; + this.valueType = valueType; + this.timeout = timeout; + this.timeoutType = timeoutType; + // 添加注册表 + RedisKeyRegistry.add(this); + } + + public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class valueType, Duration timeout) { + this(memo, keyTemplate, keyType, valueType, TimeoutTypeEnum.FIXED, timeout); + } + + public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class valueType, TimeoutTypeEnum timeoutType) { + this(memo, keyTemplate, keyType, valueType, timeoutType, Duration.ZERO); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyRegistry.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyRegistry.java new file mode 100644 index 0000000..882d8d3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyRegistry.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.redis.core; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@link RedisKeyDefine} 注册表 + */ +public class RedisKeyRegistry { + + /** + * Redis RedisKeyDefine 数组 + */ + private static final List defines = new ArrayList<>(); + + public static void add(RedisKeyDefine define) { + defines.add(define); + } + + public static List list() { + return defines; + } + + public static int size() { + return defines.size(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/AbstractChannelMessageListener.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/AbstractChannelMessageListener.java new file mode 100644 index 0000000..8d3bf6f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/AbstractChannelMessageListener.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.framework.redis.core.pubsub; + +import cn.hutool.core.util.TypeUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import lombok.SneakyThrows; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; + +import java.lang.reflect.Type; + +/** + * Redis Pub/Sub 监听器抽象类,用于实现广播消费 + * + * @param 消息类型。一定要填写噢,不然会报错 + * + * @author 芋道源码 + */ +public abstract class AbstractChannelMessageListener implements MessageListener { + + /** + * 消息类型 + */ + private final Class messageType; + /** + * Redis Channel + */ + private final String channel; + + @SneakyThrows + protected AbstractChannelMessageListener() { + this.messageType = getMessageClass(); + this.channel = messageType.newInstance().getChannel(); + } + + /** + * 获得 Sub 订阅的 Redis Channel 通道 + * + * @return channel + */ + public final String getChannel() { + return channel; + } + + @Override + public final void onMessage(Message message, byte[] bytes) { + T messageObj = JsonUtils.parseObject(message.getBody(), messageType); + this.onMessage(messageObj); + } + + /** + * 处理消息 + * + * @param message 消息 + */ + public abstract void onMessage(T message); + + /** + * 通过解析类上的泛型,获得消息类型 + * + * @return 消息类型 + */ + @SuppressWarnings("unchecked") + private Class getMessageClass() { + Type type = TypeUtil.getTypeArgument(getClass(), 0); + if (type == null) { + throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); + } + return (Class) type; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/ChannelMessage.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/ChannelMessage.java new file mode 100644 index 0000000..60e5f49 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/pubsub/ChannelMessage.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.redis.core.pubsub; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Redis Channel Message 接口 + * + * @author 芋道源码 + */ +public interface ChannelMessage { + + /** + * 获得 Redis Channel + * + * @return Channel + */ + @JsonIgnore // 避免序列化 + String getChannel(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/AbstractStreamMessageListener.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/AbstractStreamMessageListener.java new file mode 100644 index 0000000..85d44f4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/AbstractStreamMessageListener.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.framework.redis.core.stream; + +import cn.hutool.core.util.TypeUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.connection.stream.ObjectRecord; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.stream.StreamListener; + +import java.lang.reflect.Type; + +/** + * Redis Stream 监听器抽象类,用于实现集群消费 + * + * @param 消息类型。一定要填写噢,不然会报错 + * + * @author 芋道源码 + */ +public abstract class AbstractStreamMessageListener + implements StreamListener> { + + /** + * 消息类型 + */ + private final Class messageType; + /** + * Redis Channel + */ + @Getter + private final String streamKey; + + /** + * Redis 消费者分组,默认使用 spring.application.name 名字 + */ + @Value("${spring.application.name}") + @Getter + private String group; + /** + * + */ + @Setter + private RedisTemplate redisTemplate; + + @SneakyThrows + protected AbstractStreamMessageListener() { + this.messageType = getMessageClass(); + this.streamKey = messageType.newInstance().getStreamKey(); + } + + @Override + public void onMessage(ObjectRecord message) { + // 消费消息 + T messageObj = JsonUtils.parseObject(message.getValue(), messageType); + this.onMessage(messageObj); + // ack 消息消费完成 + redisTemplate.opsForStream().acknowledge(group, message); + // TODO 芋艿:需要额外考虑以下几个点: + // 1. 处理异常的情况 + // 2. 发送日志;以及事务的结合 + // 3. 消费日志;以及通用的幂等性 + // 4. 消费失败的重试,https://zhuanlan.zhihu.com/p/60501638 + } + + /** + * 处理消息 + * + * @param message 消息 + */ + public abstract void onMessage(T message); + + /** + * 通过解析类上的泛型,获得消息类型 + * + * @return 消息类型 + */ + @SuppressWarnings("unchecked") + private Class getMessageClass() { + Type type = TypeUtil.getTypeArgument(getClass(), 0); + if (type == null) { + throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); + } + return (Class) type; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/StreamMessage.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/StreamMessage.java new file mode 100644 index 0000000..ecb9c74 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/stream/StreamMessage.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.redis.core.stream; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Redis Stream Message 接口 + * + * @author 芋道源码 + */ +public interface StreamMessage { + + /** + * 获得 Redis Stream Key + * + * @return Channel + */ + @JsonIgnore // 避免序列化 + String getStreamKey(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/util/RedisMessageUtils.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/util/RedisMessageUtils.java new file mode 100644 index 0000000..0d83586 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/util/RedisMessageUtils.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.framework.redis.core.util; + +import cn.iocoder.yudao.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.yudao.framework.redis.core.stream.StreamMessage; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import org.springframework.data.redis.connection.stream.RecordId; +import org.springframework.data.redis.connection.stream.StreamRecords; +import org.springframework.data.redis.core.RedisTemplate; + +/** + * Redis 消息工具类 + * + * @author 芋道源码 + */ +public class RedisMessageUtils { + + /** + * 发送 Redis 消息,基于 Redis pub/sub 实现 + * + * @param redisTemplate Redis 操作模板 + * @param message 消息 + */ + public static void sendChannelMessage(RedisTemplate redisTemplate, T message) { + redisTemplate.convertAndSend(message.getChannel(), JsonUtils.toJsonString(message)); + } + + /** + * 发送 Redis 消息,基于 Redis Stream 实现 + * + * @param redisTemplate Redis 操作模板 + * @param message 消息 + * @return 消息记录的编号对象 + */ + public static RecordId sendStreamMessage(RedisTemplate redisTemplate, T message) { + return redisTemplate.opsForStream().add(StreamRecords.newRecord() + .ofObject(JsonUtils.toJsonString(message)) // 设置内容 + .withStreamKey(message.getStreamKey())); // 设置 stream key + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/package-info.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/package-info.java new file mode 100644 index 0000000..bd8a5d3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/package-info.java @@ -0,0 +1,4 @@ +/** + * 采用 Spring Data Redis 操作 Redis,底层使用 Redisson 作为客户端 + */ +package cn.iocoder.yudao.framework.redis; diff --git a/yudao-framework/yudao-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md b/yudao-framework/yudao-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md new file mode 100644 index 0000000..80c5445 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java index cde7662..2f93433 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java index b2fd4a5..517df55 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.security.core.handler; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java index 1c71ed0..380f5b7 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.security.core.handler; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java index 3b099bf..ed61cf0 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.config.SecurityProperties; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.stereotype.Component; diff --git a/yudao-framework/yudao-spring-boot-starter-test/pom.xml b/yudao-framework/yudao-spring-boot-starter-test/pom.xml new file mode 100644 index 0000000..fccc9df --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/pom.xml @@ -0,0 +1,41 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-test + jar + + ${artifactId} + 测试组件,用于单元测试、集成测试 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + + org.springframework.boot + spring-boot-starter-test + + + + com.h2database + h2 + + + + com.github.fppt + jedis-mock + + + + uk.co.jemos.podam + podam + + + diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/BaseMockitoUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/BaseMockitoUnitTest.java new file mode 100644 index 0000000..eb1f3d4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/BaseMockitoUnitTest.java @@ -0,0 +1,13 @@ +package cn.iocoder.dashboard.framework.test.core.ut; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +/** + * 纯 Mockito 的单元测试 + * + * @author 芋道源码 + */ +@ExtendWith(MockitoExtension.class) +public class BaseMockitoUnitTest { +} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/package-info.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/package-info.java new file mode 100644 index 0000000..0f33dfb --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/ut/package-info.java @@ -0,0 +1,4 @@ +/** + * 提供单元测试 Unit Test 的基类 + */ +package cn.iocoder.dashboard.framework.test.core.ut; diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java new file mode 100644 index 0000000..9f7e501 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/AssertUtils.java @@ -0,0 +1,97 @@ +package cn.iocoder.dashboard.framework.test.core.util; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.function.Executable; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * 单元测试,assert 断言工具类 + * + * @author 芋道源码 + */ +public class AssertUtils { + + /** + * 比对两个对象的属性是否一致 + * + * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略 + * + * @param expected 期望对象 + * @param actual 实际对象 + * @param ignoreFields 忽略的属性数组 + */ + public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) { + Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); + Arrays.stream(expectedFields).forEach(expectedField -> { + // 如果是忽略的属性,则不进行比对 + if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { + return; + } + // 忽略不存在的属性 + Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); + if (actualField == null) { + return; + } + // 比对 + Assertions.assertEquals( + ReflectUtil.getFieldValue(expected, expectedField), + ReflectUtil.getFieldValue(actual, actualField), + String.format("Field(%s) 不匹配", expectedField.getName()) + ); + }); + } + + /** + * 比对两个对象的属性是否一致 + * + * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略 + * + * @param expected 期望对象 + * @param actual 实际对象 + * @param ignoreFields 忽略的属性数组 + * @return 是否一致 + */ + public static boolean isPojoEquals(Object expected, Object actual, String... ignoreFields) { + Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); + return Arrays.stream(expectedFields).allMatch(expectedField -> { + // 如果是忽略的属性,则不进行比对 + if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { + return true; + } + // 忽略不存在的属性 + Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); + if (actualField == null) { + return true; + } + return Objects.equals(ReflectUtil.getFieldValue(expected, expectedField), + ReflectUtil.getFieldValue(actual, actualField)); + }); + } + + /** + * 执行方法,校验抛出的 Service 是否符合条件 + * + * @param executable 业务异常 + * @param errorCode 错误码对象 + * @param messageParams 消息参数 + */ + public static void assertServiceException(Executable executable, ErrorCode errorCode, Object... messageParams) { + // 调用方法 + ServiceException serviceException = assertThrows(ServiceException.class, executable); + // 校验错误码 + Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配"); + String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), messageParams); + Assertions.assertEquals(message, serviceException.getMessage(), "错误提示不匹配"); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java new file mode 100644 index 0000000..7ac7b28 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/core/util/RandomUtils.java @@ -0,0 +1,100 @@ +package cn.iocoder.dashboard.framework.test.core.util; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import java.lang.reflect.Type; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 随机工具类 + * + * @author 芋道源码 + */ +public class RandomUtils { + + private static final int RANDOM_STRING_LENGTH = 10; + + private static final int RANDOM_DATE_MAX = 30; + + private static final int RANDOM_COLLECTION_LENGTH = 5; + + private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl(); + + static { + // 字符串 + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class, + (dataProviderStrategy, attributeMetadata, map) -> randomString()); + // Boolean + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { + // 如果是 deleted 的字段,返回非删除 + if (attributeMetadata.getAttributeName().equals("deleted")) { + return false; + } + return RandomUtil.randomBoolean(); + }); + } + + public static String randomString() { + return RandomUtil.randomString(RANDOM_STRING_LENGTH); + } + + public static Long randomLongId() { + return RandomUtil.randomLong(0, Long.MAX_VALUE); + } + + public static Integer randomInteger() { + return RandomUtil.randomInt(0, Integer.MAX_VALUE); + } + + public static Date randomDate() { + return RandomUtil.randomDay(0, RANDOM_DATE_MAX); + } + + public static Short randomShort() { + return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); + } + + public static Set randomSet(Class clazz) { + return Stream.iterate(0, i -> i).limit(RandomUtil.randomInt(0, RANDOM_DATE_MAX)) + .map(i -> randomPojo(clazz)).collect(Collectors.toSet()); + } + + public static Integer randomCommonStatus() { + return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); + } + + @SafeVarargs + public static T randomPojo(Class clazz, Consumer... consumers) { + T pojo = PODAM_FACTORY.manufacturePojo(clazz); + // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 + if (ArrayUtil.isNotEmpty(consumers)) { + Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo)); + } + return pojo; + } + + @SafeVarargs + public static T randomPojo(Class clazz, Type type, Consumer... consumers) { + T pojo = PODAM_FACTORY.manufacturePojo(clazz, type); + // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 + if (ArrayUtil.isNotEmpty(consumers)) { + Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo)); + } + return pojo; + } + + @SafeVarargs + public static List randomPojoList(Class clazz, Consumer... consumers) { + int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH); + return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers)) + .collect(Collectors.toList()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java new file mode 100644 index 0000000..fa02213 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/dashboard/framework/test/package-info.java @@ -0,0 +1,4 @@ +/** + * 测试组件,用于单元测试、集成测试等等 + */ +package cn.iocoder.dashboard.framework.test; diff --git a/yudao-framework/yudao-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md b/yudao-framework/yudao-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md new file mode 100644 index 0000000..c6d0e9a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 422ab7c..49f54fe 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -7,12 +7,12 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.framework.util.date.DateUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.filter.OncePerRequestFilter; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java index f21d33c..3b3fe67 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.jackson.config; import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer; import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer; -import cn.iocoder.yudao.framework.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import org.springframework.context.annotation.Bean; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java index 31b8ba1..7051fc8 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.web.core.filter; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java index 2c2e3f0..0ce793d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.web.core.filter; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import org.springframework.web.filter.OncePerRequestFilter; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java index 991cad4..25bd209 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java @@ -6,7 +6,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HTMLFilter; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index ca15c40..3616bd3 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -7,10 +7,10 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO; -import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import io.github.resilience4j.ratelimiter.RequestNotPermitted; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; -- libgit2 0.21.4