From d5cc95fefbb7dea269602b8b20d67c368d905369 Mon Sep 17 00:00:00 2001 From: RuoYi Date: Fri, 17 Jul 2020 16:56:03 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E5=8D=87=E7=BA=A7element-ui=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=88=B02.13.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/package.json | 2 +- ruoyi-ui/src/utils/index.js | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 6353e1b4f..40a0f4e35 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -44,7 +44,7 @@ "axios": "0.18.1", "clipboard": "2.0.4", "echarts": "4.2.1", - "element-ui": "2.13.0", + "element-ui": "2.13.2", "file-saver": "2.0.1", "js-beautify": "^1.10.2", "fuse.js": "3.4.4", diff --git a/ruoyi-ui/src/utils/index.js b/ruoyi-ui/src/utils/index.js index 6c3017c76..49897c990 100644 --- a/ruoyi-ui/src/utils/index.js +++ b/ruoyi-ui/src/utils/index.js @@ -124,19 +124,21 @@ export function param(json) { * @returns {Object} */ export function param2Obj(url) { - const search = url.split('?')[1] + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') if (!search) { return {} } - return JSON.parse( - '{"' + - decodeURIComponent(search) - .replace(/"/g, '\\"') - .replace(/&/g, '","') - .replace(/=/g, '":"') - .replace(/\+/g, ' ') + - '"}' - ) + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj } /** From 0d52e11e3dd739eb5a67ea645f0ca4c4be77ad91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B9=B3=E5=87=A1?= Date: Sat, 18 Jul 2020 00:03:27 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E7=A6=81=E6=AD=A2=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E5=AF=86=E6=96=87=E8=BF=94=E5=9B=9E=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ruoyi/project/system/domain/SysUser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java index 2e491ad53..8890b8dc3 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java +++ b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java @@ -196,7 +196,7 @@ public class SysUser extends BaseEntity { this.avatar = avatar; } - + @JsonIgnore @JsonProperty public String getPassword() { From 0238c4ad9210b1a45e7c626cfaf40367cb741b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B9=B3=E5=87=A1?= Date: Sat, 18 Jul 2020 00:07:17 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E5=A4=84=E7=90=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=94=9F=E6=88=90=E9=A1=B5=E9=9D=A2=E4=B8=AD=E7=9A=84=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=9D=A1=E4=BB=B6=E2=80=9C=E5=88=9B=E5=BB=BA=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E2=80=9D=E6=9C=AA=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/mybatis/tool/GenTableMapper.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml b/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml index d688599a7..0c58d720d 100644 --- a/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml +++ b/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml @@ -62,12 +62,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND lower(table_comment) like lower(concat('%', #{tableComment}, '%')) - - - - - - + + AND create_time >= to_date(#{beginTime},'yyyy-MM-dd HH24:mi:ss') + + + AND create_time <= to_date(#{endTime},'yyyy-MM-dd HH24:mi:ss') + From 11ab4b4832f8d9222646d083c92204d7b2b7f5fc Mon Sep 17 00:00:00 2001 From: RuoYi Date: Sat, 18 Jul 2020 12:32:22 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E7=BC=BA=E5=B0=91JsonIgnore=E5=8C=85?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ruoyi/project/system/domain/SysUser.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java index 8890b8dc3..65b4a6658 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java +++ b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java @@ -7,6 +7,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; @@ -196,6 +197,7 @@ public class SysUser extends BaseEntity { this.avatar = avatar; } + @JsonIgnore @JsonProperty public String getPassword() From 0d341f1aaa210119a3bad591f84438e48a7f602d Mon Sep 17 00:00:00 2001 From: RuoYi Date: Sat, 18 Jul 2020 16:24:04 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ruoyi/project/system/domain/SysUser.java | 2 +- ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java index 65b4a6658..f63f59832 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java +++ b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java @@ -197,7 +197,7 @@ public class SysUser extends BaseEntity { this.avatar = avatar; } - + @JsonIgnore @JsonProperty public String getPassword() diff --git a/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml b/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml index 0c58d720d..64a1f5e59 100644 --- a/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml +++ b/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml @@ -63,10 +63,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND lower(table_comment) like lower(concat('%', #{tableComment}, '%')) - AND create_time >= to_date(#{beginTime},'yyyy-MM-dd HH24:mi:ss') + AND date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d') - AND create_time <= to_date(#{endTime},'yyyy-MM-dd HH24:mi:ss') + AND date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') From cee572f237cb293e4a9070ef458356bc6daa2105 Mon Sep 17 00:00:00 2001 From: RuoYi Date: Sun, 19 Jul 2020 10:25:40 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E8=8B=A5=E4=BE=9D=203.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi/.gitignore => .gitignore | 0 {ruoyi/bin => bin}/clean.bat | 0 {ruoyi/bin => bin}/package.bat | 0 bin/run.bat | 14 + doc/若依环境使用手册.docx | Bin 0 -> 428430 bytes pom.xml | 234 +++ ruoyi-admin/pom.xml | 108 + .../main/java/com/ruoyi/RuoYiApplication.java | 0 .../com/ruoyi/RuoYiServletInitializer.java | 0 .../controller}/common/CaptchaController.java | 8 +- .../controller}/common/CommonController.java | 6 +- .../controller/monitor}/ServerController.java | 6 +- .../monitor}/SysLogininforController.java | 16 +- .../monitor}/SysOperlogController.java | 16 +- .../monitor}/SysUserOnlineController.java | 20 +- .../system}/SysConfigController.java | 18 +- .../controller/system}/SysDeptController.java | 14 +- .../system}/SysDictDataController.java | 18 +- .../system}/SysDictTypeController.java | 16 +- .../system}/SysLoginController.java | 20 +- .../controller/system}/SysMenuController.java | 18 +- .../system}/SysNoticeController.java | 16 +- .../controller/system}/SysPostController.java | 16 +- .../system}/SysProfileController.java | 20 +- .../controller/system}/SysRoleController.java | 18 +- .../controller/system}/SysUserController.java | 28 +- .../controller/tool/SwaggerController.java | 24 + .../web/controller/tool}/TestController.java | 6 +- .../ruoyi/web/core}/config/SwaggerConfig.java | 3 +- .../META-INF/spring-devtools.properties | 0 .../src/main/resources/application-druid.yml | 0 .../src/main/resources/application.yml | 17 +- .../src/main/resources/banner.txt | 0 .../main/resources/i18n/messages.properties | 0 .../src/main/resources/logback.xml | 0 .../main/resources/mybatis/mybatis-config.xml | 0 ruoyi-common/pom.xml | 124 ++ .../ruoyi/common}/annotation/DataScope.java | 2 +- .../ruoyi/common}/annotation/DataSource.java | 4 +- .../com/ruoyi/common}/annotation/Excel.java | 236 +-- .../com/ruoyi/common}/annotation/Excels.java | 36 +- .../com/ruoyi/common}/annotation/Log.java | 6 +- .../common}/annotation/RepeatSubmit.java | 46 +- .../com/ruoyi/common}/config/RuoYiConfig.java | 4 +- .../com/ruoyi/common/constant/Constants.java | 4 +- .../ruoyi/common/constant/GenConstants.java | 0 .../com/ruoyi/common/constant/HttpStatus.java | 0 .../common/constant/ScheduleConstants.java | 100 +- .../ruoyi/common/constant/UserConstants.java | 0 .../core}/controller/BaseController.java | 18 +- .../ruoyi/common/core}/domain/AjaxResult.java | 2 +- .../ruoyi/common/core}/domain/BaseEntity.java | 2 +- .../ruoyi/common/core}/domain/TreeEntity.java | 2 +- .../ruoyi/common/core}/domain/TreeSelect.java | 6 +- .../common/core/domain/entity}/SysDept.java | 4 +- .../core/domain/entity}/SysDictData.java | 8 +- .../core/domain/entity}/SysDictType.java | 8 +- .../common/core/domain/entity}/SysMenu.java | 4 +- .../common/core/domain/entity}/SysRole.java | 8 +- .../common/core/domain/entity}/SysUser.java | 12 +- .../common/core/domain/model}/LoginBody.java | 2 +- .../common/core/domain/model}/LoginUser.java | 4 +- .../ruoyi/common/core}/page/PageDomain.java | 5 +- .../common/core}/page/TableDataInfo.java | 4 +- .../ruoyi/common/core}/page/TableSupport.java | 2 +- .../ruoyi/common/core}/redis/RedisCache.java | 2 +- .../ruoyi/common/core/text/CharsetKit.java | 0 .../com/ruoyi/common/core/text/Convert.java | 0 .../ruoyi/common/core/text/StrFormatter.java | 0 .../ruoyi/common}/enums/BusinessStatus.java | 2 +- .../com/ruoyi/common}/enums/BusinessType.java | 2 +- .../ruoyi/common}/enums/DataSourceType.java | 2 +- .../com/ruoyi/common/enums/HttpMethod.java | 0 .../com/ruoyi/common}/enums/OperatorType.java | 2 +- .../com/ruoyi/common/enums/UserStatus.java | 0 .../ruoyi/common/exception/BaseException.java | 0 .../common/exception/CustomException.java | 0 .../common/exception/DemoModeException.java | 0 .../ruoyi/common/exception/UtilException.java | 0 .../common/exception/file/FileException.java | 0 .../FileNameLengthLimitExceededException.java | 0 .../file/FileSizeLimitExceededException.java | 0 .../file/InvalidExtensionException.java | 0 .../common/exception/job/TaskException.java | 66 +- .../exception/user/CaptchaException.java | 0 .../user/CaptchaExpireException.java | 0 .../common/exception/user/UserException.java | 0 .../user/UserPasswordNotMatchException.java | 0 .../ruoyi/common/filter/RepeatableFilter.java | 104 +- .../filter/RepeatedlyRequestWrapper.java | 144 +- .../com/ruoyi/common/filter/XssFilter.java | 0 .../filter/XssHttpServletRequestWrapper.java | 0 .../java/com/ruoyi/common/utils/Arith.java | 0 .../com/ruoyi/common/utils/DateUtils.java | 0 .../com/ruoyi/common/utils/DictUtils.java | 5 +- .../com/ruoyi/common/utils/ExceptionUtil.java | 80 +- .../java/com/ruoyi/common/utils/LogUtils.java | 0 .../com/ruoyi/common/utils/MessageUtils.java | 0 .../com/ruoyi/common/utils/SecurityUtils.java | 2 +- .../com/ruoyi/common/utils/ServletUtils.java | 0 .../com/ruoyi/common/utils/StringUtils.java | 0 .../java/com/ruoyi/common/utils/Threads.java | 0 .../ruoyi/common/utils/VerifyCodeUtils.java | 0 .../ruoyi/common/utils/bean/BeanUtils.java | 220 +-- .../common/utils/file/FileUploadUtils.java | 4 +- .../ruoyi/common/utils/file/FileUtils.java | 0 .../common/utils/file/MimeTypeUtils.java | 0 .../ruoyi/common/utils/html/EscapeUtil.java | 0 .../ruoyi/common/utils/html/HTMLFilter.java | 1136 +++++------ .../ruoyi/common/utils/http/HttpHelper.java | 110 +- .../ruoyi/common/utils/http/HttpUtils.java | 0 .../ruoyi/common/utils/ip/AddressUtils.java | 2 +- .../com/ruoyi/common/utils/ip/IpUtils.java | 0 .../com/ruoyi/common/utils/poi/ExcelUtil.java | 1748 ++++++++--------- .../common/utils/reflect/ReflectUtils.java | 812 ++++---- .../com/ruoyi/common/utils/sign/Base64.java | 0 .../com/ruoyi/common/utils/sign/Md5Utils.java | 0 .../common/utils/spring/SpringUtils.java | 0 .../com/ruoyi/common/utils/sql/SqlUtil.java | 0 .../com/ruoyi/common/utils/uuid}/IdUtils.java | 4 +- .../com/ruoyi/common/utils/uuid}/UUID.java | 2 +- ruoyi-framework/pom.xml | 62 + .../framework/aspectj/DataScopeAspect.java | 14 +- .../framework/aspectj/DataSourceAspect.java | 6 +- .../ruoyi/framework/aspectj/LogAspect.java | 12 +- .../framework/config/ApplicationConfig.java | 2 +- .../ruoyi/framework/config/DruidConfig.java | 2 +- .../config/FastJson2JsonRedisSerializer.java | 0 .../ruoyi/framework/config/FilterConfig.java | 0 .../ruoyi/framework/config/MyBatisConfig.java | 0 .../ruoyi/framework/config/RedisConfig.java | 0 .../framework/config/ResourcesConfig.java | 1 + .../framework/config/SecurityConfig.java | 0 .../ruoyi/framework/config/ServerConfig.java | 0 .../framework/config/ThreadPoolConfig.java | 0 .../config/properties/DruidProperties.java | 0 .../datasource/DynamicDataSource.java | 0 .../DynamicDataSourceContextHolder.java | 0 .../interceptor/RepeatSubmitInterceptor.java | 110 +- .../impl/SameUrlDataInterceptor.java | 214 +- .../ruoyi/framework/manager/AsyncManager.java | 0 .../framework/manager/ShutdownManager.java | 0 .../manager/factory/AsyncFactory.java | 8 +- .../filter/JwtAuthenticationTokenFilter.java | 4 +- .../handle/AuthenticationEntryPointImpl.java | 2 +- .../handle/LogoutSuccessHandlerImpl.java | 6 +- .../ruoyi/framework/web/domain/Server.java | 0 .../framework/web/domain/server/Cpu.java | 0 .../framework/web/domain/server/Jvm.java | 0 .../framework/web/domain/server/Mem.java | 0 .../framework/web/domain/server/Sys.java | 0 .../framework/web/domain/server/SysFile.java | 0 .../web/exception/GlobalExceptionHandler.java | 2 +- .../web}/service/PermissionService.java | 6 +- .../web}/service/SysLoginService.java | 6 +- .../web}/service/SysPermissionService.java | 8 +- .../framework/web}/service/TokenService.java | 8 +- .../web}/service/UserDetailsServiceImpl.java | 8 +- ruoyi-generator/pom.xml | 34 + .../ruoyi/generator}/config/GenConfig.java | 11 +- .../generator}/controller/GenController.java | 22 +- .../com/ruoyi/generator}/domain/GenTable.java | 6 +- .../generator}/domain/GenTableColumn.java | 6 +- .../mapper/GenTableColumnMapper.java | 6 +- .../generator}/mapper/GenTableMapper.java | 6 +- .../service/GenTableColumnServiceImpl.java | 8 +- .../service/GenTableServiceImpl.java | 18 +- .../service/IGenTableColumnService.java | 4 +- .../generator}/service/IGenTableService.java | 4 +- .../com/ruoyi/generator}/util/GenUtils.java | 10 +- .../generator}/util/VelocityInitializer.java | 2 +- .../ruoyi/generator}/util/VelocityUtils.java | 15 +- .../src/main/resources/generator.yml | 10 + .../generator}/GenTableColumnMapper.xml | 2 +- .../mapper/generator}/GenTableMapper.xml | 2 +- .../main/resources/vm/java/controller.java.vm | 10 +- .../src/main/resources/vm/java/domain.java.vm | 6 +- .../src/main/resources/vm/java/mapper.java.vm | 0 .../main/resources/vm/java/service.java.vm | 0 .../resources/vm/java/serviceImpl.java.vm | 0 .../src/main/resources/vm/js/api.js.vm | 0 .../src/main/resources/vm/sql/sql.vm | 0 .../main/resources/vm/vue/index-tree.vue.vm | 0 .../src/main/resources/vm/vue/index.vue.vm | 0 .../src/main/resources/vm/xml/mapper.xml.vm | 0 ruoyi-quartz/pom.xml | 40 + .../ruoyi/quartz}/config/ScheduleConfig.java | 114 +- .../quartz}/controller/SysJobController.java | 284 +-- .../controller/SysJobLogController.java | 180 +- .../java/com/ruoyi/quartz}/domain/SysJob.java | 344 ++-- .../com/ruoyi/quartz}/domain/SysJobLog.java | 310 +-- .../ruoyi/quartz}/mapper/SysJobLogMapper.java | 128 +- .../ruoyi/quartz}/mapper/SysJobMapper.java | 134 +- .../quartz}/service/ISysJobLogService.java | 112 +- .../ruoyi/quartz}/service/ISysJobService.java | 204 +- .../service/impl/SysJobLogServiceImpl.java | 174 +- .../service/impl/SysJobServiceImpl.java | 508 ++--- .../java/com/ruoyi/quartz}/task/RyTask.java | 56 +- .../ruoyi/quartz/util}/AbstractQuartzJob.java | 214 +- .../com/ruoyi/quartz/util}/CronUtils.java | 126 +- .../com/ruoyi/quartz/util}/JobInvokeUtil.java | 364 ++-- .../QuartzDisallowConcurrentExecution.java | 42 +- .../quartz/util}/QuartzJobExecution.java | 38 +- .../com/ruoyi/quartz/util}/ScheduleUtils.java | 226 +-- .../mapper/quartz}/SysJobLogMapper.xml | 184 +- .../resources/mapper/quartz}/SysJobMapper.xml | 220 +-- ruoyi-system/pom.xml | 28 + .../com/ruoyi}/system/domain/SysConfig.java | 8 +- .../ruoyi/system}/domain/SysLogininfor.java | 10 +- .../com/ruoyi}/system/domain/SysNotice.java | 4 +- .../com/ruoyi/system}/domain/SysOperLog.java | 8 +- .../com/ruoyi}/system/domain/SysPost.java | 8 +- .../com/ruoyi}/system/domain/SysRoleDept.java | 2 +- .../com/ruoyi}/system/domain/SysRoleMenu.java | 2 +- .../ruoyi/system}/domain/SysUserOnline.java | 2 +- .../com/ruoyi}/system/domain/SysUserPost.java | 2 +- .../com/ruoyi}/system/domain/SysUserRole.java | 2 +- .../com/ruoyi}/system/domain/vo/MetaVo.java | 2 +- .../com/ruoyi}/system/domain/vo/RouterVo.java | 2 +- .../ruoyi}/system/mapper/SysConfigMapper.java | 6 +- .../ruoyi}/system/mapper/SysDeptMapper.java | 4 +- .../system/mapper/SysDictDataMapper.java | 4 +- .../system/mapper/SysDictTypeMapper.java | 4 +- .../system}/mapper/SysLogininforMapper.java | 4 +- .../ruoyi}/system/mapper/SysMenuMapper.java | 4 +- .../ruoyi}/system/mapper/SysNoticeMapper.java | 6 +- .../system}/mapper/SysOperLogMapper.java | 4 +- .../ruoyi}/system/mapper/SysPostMapper.java | 4 +- .../system/mapper/SysRoleDeptMapper.java | 4 +- .../ruoyi}/system/mapper/SysRoleMapper.java | 4 +- .../system/mapper/SysRoleMenuMapper.java | 4 +- .../ruoyi}/system/mapper/SysUserMapper.java | 6 +- .../system/mapper/SysUserPostMapper.java | 4 +- .../system/mapper/SysUserRoleMapper.java | 4 +- .../system/service/ISysConfigService.java | 4 +- .../system/service/ISysDeptService.java | 6 +- .../system/service/ISysDictDataService.java | 4 +- .../system/service/ISysDictTypeService.java | 6 +- .../service/ISysLogininforService.java | 4 +- .../system/service/ISysMenuService.java | 8 +- .../system/service/ISysNoticeService.java | 4 +- .../system}/service/ISysOperLogService.java | 4 +- .../system/service/ISysPostService.java | 4 +- .../system/service/ISysRoleService.java | 4 +- .../system/service/ISysUserOnlineService.java | 6 +- .../system/service/ISysUserService.java | 4 +- .../service/impl/SysConfigServiceImpl.java | 13 +- .../service/impl/SysDeptServiceImpl.java | 12 +- .../service/impl/SysDictDataServiceImpl.java | 8 +- .../service/impl/SysDictTypeServiceImpl.java | 12 +- .../impl/SysLogininforServiceImpl.java | 8 +- .../service/impl/SysMenuServiceImpl.java | 18 +- .../service/impl/SysNoticeServiceImpl.java | 8 +- .../service/impl/SysOperLogServiceImpl.java | 8 +- .../service/impl/SysPostServiceImpl.java | 10 +- .../service/impl/SysRoleServiceImpl.java | 20 +- .../impl/SysUserOnlineServiceImpl.java | 8 +- .../service/impl/SysUserServiceImpl.java | 28 +- .../mapper}/system/SysConfigMapper.xml | 2 +- .../mapper}/system/SysDeptMapper.xml | 2 +- .../mapper}/system/SysDictDataMapper.xml | 2 +- .../mapper}/system/SysDictTypeMapper.xml | 2 +- .../mapper/system}/SysLogininforMapper.xml | 2 +- .../mapper}/system/SysMenuMapper.xml | 2 +- .../mapper}/system/SysNoticeMapper.xml | 2 +- .../mapper/system}/SysOperLogMapper.xml | 2 +- .../mapper}/system/SysPostMapper.xml | 2 +- .../mapper}/system/SysRoleDeptMapper.xml | 2 +- .../mapper}/system/SysRoleMapper.xml | 2 +- .../mapper}/system/SysRoleMenuMapper.xml | 2 +- .../mapper}/system/SysUserMapper.xml | 2 +- .../mapper}/system/SysUserPostMapper.xml | 2 +- .../mapper}/system/SysUserRoleMapper.xml | 2 +- ruoyi-ui/package.json | 2 +- ruoyi/bin/run-tomcat.bat | 14 - ruoyi/pom.xml | 287 --- ruoyi/ry.sh => ry.sh | 2 +- {ruoyi/sql => sql}/quartz.sql | 338 ++-- {ruoyi/sql => sql}/ry_20200629.sql | 0 279 files changed, 5935 insertions(+), 5542 deletions(-) rename ruoyi/.gitignore => .gitignore (100%) rename {ruoyi/bin => bin}/clean.bat (100%) rename {ruoyi/bin => bin}/package.bat (100%) create mode 100644 bin/run.bat create mode 100644 doc/若依环境使用手册.docx create mode 100644 pom.xml create mode 100644 ruoyi-admin/pom.xml rename {ruoyi => ruoyi-admin}/src/main/java/com/ruoyi/RuoYiApplication.java (100%) rename {ruoyi => ruoyi-admin}/src/main/java/com/ruoyi/RuoYiServletInitializer.java (100%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-admin/src/main/java/com/ruoyi/web/controller}/common/CaptchaController.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-admin/src/main/java/com/ruoyi/web/controller}/common/CommonController.java (93%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor}/ServerController.java (79%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor}/SysLogininforController.java (80%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor}/SysOperlogController.java (79%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor}/SysUserOnlineController.java (82%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysConfigController.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysDeptController.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysDictDataController.java (85%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysDictTypeController.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysLoginController.java (79%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysMenuController.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysNoticeController.java (83%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysPostController.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysProfileController.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysRoleController.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/system/controller => ruoyi-admin/src/main/java/com/ruoyi/web/controller/system}/SysUserController.java (88%) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java rename {ruoyi/src/main/java/com/ruoyi/project/tool/swagger => ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool}/TestController.java (93%) rename {ruoyi/src/main/java/com/ruoyi/framework => ruoyi-admin/src/main/java/com/ruoyi/web/core}/config/SwaggerConfig.java (95%) rename {ruoyi => ruoyi-admin}/src/main/resources/META-INF/spring-devtools.properties (100%) rename {ruoyi => ruoyi-admin}/src/main/resources/application-druid.yml (100%) rename {ruoyi => ruoyi-admin}/src/main/resources/application.yml (80%) rename {ruoyi => ruoyi-admin}/src/main/resources/banner.txt (100%) rename {ruoyi => ruoyi-admin}/src/main/resources/i18n/messages.properties (100%) rename {ruoyi => ruoyi-admin}/src/main/resources/logback.xml (100%) rename {ruoyi => ruoyi-admin}/src/main/resources/mybatis/mybatis-config.xml (100%) create mode 100644 ruoyi-common/pom.xml rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/annotation/DataScope.java (86%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/annotation/DataSource.java (82%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/annotation/Excel.java (93%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/annotation/Excels.java (84%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/annotation/Log.java (78%) rename {ruoyi/src/main/java/com/ruoyi/framework/interceptor => ruoyi-common/src/main/java/com/ruoyi/common}/annotation/RepeatSubmit.java (87%) rename {ruoyi/src/main/java/com/ruoyi/framework => ruoyi-common/src/main/java/com/ruoyi/common}/config/RuoYiConfig.java (93%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/constant/Constants.java (91%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/constant/GenConstants.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/constant/HttpStatus.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java (95%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/constant/UserConstants.java (100%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/controller/BaseController.java (82%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/domain/AjaxResult.java (94%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/domain/BaseEntity.java (93%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/domain/TreeEntity.java (91%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/domain/TreeSelect.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project/system/domain => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity}/SysDept.java (93%) rename {ruoyi/src/main/java/com/ruoyi/project/system/domain => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity}/SysDictData.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project/system/domain => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity}/SysDictType.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project/system/domain => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity}/SysMenu.java (93%) rename {ruoyi/src/main/java/com/ruoyi/project/system/domain => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity}/SysRole.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project/system/domain => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity}/SysUser.java (91%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model}/LoginBody.java (89%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model}/LoginUser.java (91%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/page/PageDomain.java (91%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/page/TableDataInfo.java (91%) rename {ruoyi/src/main/java/com/ruoyi/framework/web => ruoyi-common/src/main/java/com/ruoyi/common/core}/page/TableSupport.java (92%) rename {ruoyi/src/main/java/com/ruoyi/framework => ruoyi-common/src/main/java/com/ruoyi/common/core}/redis/RedisCache.java (95%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/core/text/CharsetKit.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/core/text/Convert.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/core/text/StrFormatter.java (100%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/enums/BusinessStatus.java (70%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/enums/BusinessType.java (83%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/enums/DataSourceType.java (70%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/enums/HttpMethod.java (100%) rename {ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang => ruoyi-common/src/main/java/com/ruoyi/common}/enums/OperatorType.java (75%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/enums/UserStatus.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/BaseException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/CustomException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/DemoModeException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/UtilException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/file/FileException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/job/TaskException.java (95%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/user/UserException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java (96%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java (96%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/filter/XssFilter.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/Arith.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/DateUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/DictUtils.java (90%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java (95%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/LogUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/MessageUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/SecurityUtils.java (93%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/ServletUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/StringUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/Threads.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java (96%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java (95%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/file/FileUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java (97%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java (88%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java (93%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java (95%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java (97%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/sign/Base64.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java (100%) rename {ruoyi => ruoyi-common}/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java (100%) rename {ruoyi/src/main/java/com/ruoyi/common/utils => ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid}/IdUtils.java (87%) rename {ruoyi/src/main/java/com/ruoyi/common/core/lang => ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid}/UUID.java (96%) create mode 100644 ruoyi-framework/pom.xml rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java (89%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java (86%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java (92%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java (92%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/DruidConfig.java (96%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/FilterConfig.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/RedisConfig.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java (94%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/SecurityConfig.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/ServerConfig.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java (92%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java (95%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/manager/AsyncManager.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java (91%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java (92%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java (93%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java (89%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/domain/Server.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java (100%) rename {ruoyi => ruoyi-framework}/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java (95%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-framework/src/main/java/com/ruoyi/framework/web}/service/PermissionService.java (93%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-framework/src/main/java/com/ruoyi/framework/web}/service/SysLoginService.java (93%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-framework/src/main/java/com/ruoyi/framework/web}/service/SysPermissionService.java (83%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-framework/src/main/java/com/ruoyi/framework/web}/service/TokenService.java (93%) rename {ruoyi/src/main/java/com/ruoyi/framework/security => ruoyi-framework/src/main/java/com/ruoyi/framework/web}/service/UserDetailsServiceImpl.java (88%) create mode 100644 ruoyi-generator/pom.xml rename {ruoyi/src/main/java/com/ruoyi/framework => ruoyi-generator/src/main/java/com/ruoyi/generator}/config/GenConfig.java (73%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/controller/GenController.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/domain/GenTable.java (93%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/domain/GenTableColumn.java (94%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/mapper/GenTableColumnMapper.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/mapper/GenTableMapper.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/service/GenTableColumnServiceImpl.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/service/GenTableServiceImpl.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/service/IGenTableColumnService.java (85%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/service/IGenTableService.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/util/GenUtils.java (94%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/util/VelocityInitializer.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project/tool/gen => ruoyi-generator/src/main/java/com/ruoyi/generator}/util/VelocityUtils.java (95%) create mode 100644 ruoyi-generator/src/main/resources/generator.yml rename {ruoyi/src/main/resources/mybatis/tool => ruoyi-generator/src/main/resources/mapper/generator}/GenTableColumnMapper.xml (97%) rename {ruoyi/src/main/resources/mybatis/tool => ruoyi-generator/src/main/resources/mapper/generator}/GenTableMapper.xml (97%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/java/controller.java.vm (90%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/java/domain.java.vm (90%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/java/mapper.java.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/java/service.java.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/java/serviceImpl.java.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/js/api.js.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/sql/sql.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/vue/index-tree.vue.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/vue/index.vue.vm (100%) rename {ruoyi => ruoyi-generator}/src/main/resources/vm/xml/mapper.xml.vm (100%) create mode 100644 ruoyi-quartz/pom.xml rename {ruoyi/src/main/java/com/ruoyi/framework => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/config/ScheduleConfig.java (96%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/controller/SysJobController.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/controller/SysJobLogController.java (84%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/domain/SysJob.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/domain/SysJobLog.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/mapper/SysJobLogMapper.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/mapper/SysJobMapper.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/service/ISysJobLogService.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/service/ISysJobService.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/service/impl/SysJobLogServiceImpl.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/service/impl/SysJobServiceImpl.java (92%) rename {ruoyi/src/main/java/com/ruoyi/framework => ruoyi-quartz/src/main/java/com/ruoyi/quartz}/task/RyTask.java (91%) rename {ruoyi/src/main/java/com/ruoyi/common/utils/job => ruoyi-quartz/src/main/java/com/ruoyi/quartz/util}/AbstractQuartzJob.java (92%) rename {ruoyi/src/main/java/com/ruoyi/common/utils/job => ruoyi-quartz/src/main/java/com/ruoyi/quartz/util}/CronUtils.java (94%) rename {ruoyi/src/main/java/com/ruoyi/common/utils/job => ruoyi-quartz/src/main/java/com/ruoyi/quartz/util}/JobInvokeUtil.java (95%) rename {ruoyi/src/main/java/com/ruoyi/common/utils/job => ruoyi-quartz/src/main/java/com/ruoyi/quartz/util}/QuartzDisallowConcurrentExecution.java (82%) rename {ruoyi/src/main/java/com/ruoyi/common/utils/job => ruoyi-quartz/src/main/java/com/ruoyi/quartz/util}/QuartzJobExecution.java (79%) rename {ruoyi/src/main/java/com/ruoyi/common/utils/job => ruoyi-quartz/src/main/java/com/ruoyi/quartz/util}/ScheduleUtils.java (95%) rename {ruoyi/src/main/resources/mybatis/system => ruoyi-quartz/src/main/resources/mapper/quartz}/SysJobLogMapper.xml (95%) rename {ruoyi/src/main/resources/mybatis/system => ruoyi-quartz/src/main/resources/mapper/quartz}/SysJobMapper.xml (96%) create mode 100644 ruoyi-system/pom.xml rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysConfig.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/domain/SysLogininfor.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysNotice.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/domain/SysOperLog.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysPost.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysRoleDept.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysRoleMenu.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/domain/SysUserOnline.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysUserPost.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/SysUserRole.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/vo/MetaVo.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/domain/vo/RouterVo.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysConfigMapper.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysDeptMapper.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysDictDataMapper.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysDictTypeMapper.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/mapper/SysLogininforMapper.java (85%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysMenuMapper.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysNoticeMapper.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/mapper/SysOperLogMapper.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysPostMapper.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysRoleDeptMapper.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysRoleMapper.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysRoleMenuMapper.java (83%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysUserMapper.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysUserPostMapper.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/mapper/SysUserRoleMapper.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysConfigService.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysDeptService.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysDictDataService.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysDictTypeService.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/service/ISysLogininforService.java (85%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysMenuService.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysNoticeService.java (87%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/service/ISysOperLogService.java (86%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysPostService.java (91%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysRoleService.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysUserOnlineService.java (84%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/ISysUserService.java (93%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysConfigServiceImpl.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysDeptServiceImpl.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysDictDataServiceImpl.java (88%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysDictTypeServiceImpl.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/service/impl/SysLogininforServiceImpl.java (82%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysMenuServiceImpl.java (92%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysNoticeServiceImpl.java (85%) rename {ruoyi/src/main/java/com/ruoyi/project/monitor => ruoyi-system/src/main/java/com/ruoyi/system}/service/impl/SysOperLogServiceImpl.java (83%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysPostServiceImpl.java (90%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysRoleServiceImpl.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysUserOnlineServiceImpl.java (89%) rename {ruoyi/src/main/java/com/ruoyi/project => ruoyi-system/src/main/java/com/ruoyi}/system/service/impl/SysUserServiceImpl.java (90%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysConfigMapper.xml (96%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysDeptMapper.xml (96%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysDictDataMapper.xml (96%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysDictTypeMapper.xml (95%) rename {ruoyi/src/main/resources/mybatis/monitor => ruoyi-system/src/main/resources/mapper/system}/SysLogininforMapper.xml (94%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysMenuMapper.xml (97%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysNoticeMapper.xml (96%) rename {ruoyi/src/main/resources/mybatis/monitor => ruoyi-system/src/main/resources/mapper/system}/SysOperLogMapper.xml (95%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysPostMapper.xml (96%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysRoleDeptMapper.xml (90%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysRoleMapper.xml (96%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysRoleMenuMapper.xml (89%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysUserMapper.xml (97%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysUserPostMapper.xml (90%) rename {ruoyi/src/main/resources/mybatis => ruoyi-system/src/main/resources/mapper}/system/SysUserRoleMapper.xml (92%) delete mode 100644 ruoyi/bin/run-tomcat.bat delete mode 100644 ruoyi/pom.xml rename ruoyi/ry.sh => ry.sh (93%) rename {ruoyi/sql => sql}/quartz.sql (97%) rename {ruoyi/sql => sql}/ry_20200629.sql (100%) diff --git a/ruoyi/.gitignore b/.gitignore similarity index 100% rename from ruoyi/.gitignore rename to .gitignore diff --git a/ruoyi/bin/clean.bat b/bin/clean.bat similarity index 100% rename from ruoyi/bin/clean.bat rename to bin/clean.bat diff --git a/ruoyi/bin/package.bat b/bin/package.bat similarity index 100% rename from ruoyi/bin/package.bat rename to bin/package.bat diff --git a/bin/run.bat b/bin/run.bat new file mode 100644 index 000000000..e5fb6a6b2 --- /dev/null +++ b/bin/run.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] Web̡ +echo. + +cd %~dp0 +cd ../ruoyi-admin/target + +set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -jar %JAVA_OPTS% ruoyi-admin.jar + +cd bin +pause \ No newline at end of file diff --git a/doc/若依环境使用手册.docx b/doc/若依环境使用手册.docx new file mode 100644 index 0000000000000000000000000000000000000000..9e4daef4d9be2e445419109a02eaf321cd4d537e GIT binary patch literal 428430 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¾twym7CDwF0ZTRbgtZ;w&J#5V!jdB+^ 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%0AY2VEvQRzM9!H4$A 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

R( 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%0A58**rmk*;6Nc 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

-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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..cb9ecfbb2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,234 @@ + + + 4.0.0 + + com.ruoyi + ruoyi + 3.0.0 + + ruoyi + http://www.ruoyi.vip + 若依管理系统 + + + 3.0.0 + UTF-8 + UTF-8 + 1.8 + 1.3.2 + 1.1.14 + 1.19 + 2.9.2 + 1.2.5 + 1.2.70 + 3.9.1 + 2.5 + 1.3.3 + 3.17 + 1.7 + 0.9.0 + + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.1.RELEASE + pom + import + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + eu.bitwalker + UserAgentUtils + ${bitwalker.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.boot.version} + + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + + io.springfox + springfox-swagger2 + ${swagger.version} + + + io.swagger + swagger-annotations + + + io.swagger + swagger-models + + + + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + + commons-io + commons-io + ${commons.io.version} + + + + + commons-fileupload + commons-fileupload + ${commons.fileupload.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity + ${velocity.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + + com.ruoyi + ruoyi-quartz + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-generator + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-framework + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-system + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-common + ${ruoyi.version} + + + + + + + ruoyi-admin + ruoyi-framework + ruoyi-system + ruoyi-quartz + ruoyi-generator + ruoyi-common + + pom + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + + \ No newline at end of file diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml new file mode 100644 index 000000000..1ed741f4f --- /dev/null +++ b/ruoyi-admin/pom.xml @@ -0,0 +1,108 @@ + + + + ruoyi + com.ruoyi + 3.0.0 + + 4.0.0 + jar + ruoyi-admin + + + web服务入口 + + + + + + + org.springframework.boot + spring-boot-devtools + true + + + + + io.springfox + springfox-swagger2 + + + + + io.swagger + swagger-annotations + 1.5.21 + + + + io.swagger + swagger-models + 1.5.21 + + + + + io.springfox + springfox-swagger-ui + + + + + mysql + mysql-connector-java + + + + + com.ruoyi + ruoyi-framework + + + + + com.ruoyi + ruoyi-quartz + + + + + com.ruoyi + ruoyi-generator + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.1.RELEASE + + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + false + ${project.artifactId} + + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/RuoYiApplication.java rename to ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java diff --git a/ruoyi/src/main/java/com/ruoyi/RuoYiServletInitializer.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/RuoYiServletInitializer.java rename to ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java diff --git a/ruoyi/src/main/java/com/ruoyi/project/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/common/CaptchaController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java index 9a3af208b..a4ee00ff6 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/common/CaptchaController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.common; +package com.ruoyi.web.controller.common; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -8,11 +8,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.IdUtils; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.VerifyCodeUtils; import com.ruoyi.common.utils.sign.Base64; -import com.ruoyi.framework.redis.RedisCache; -import com.ruoyi.framework.web.domain.AjaxResult; +import com.ruoyi.common.utils.uuid.IdUtils; /** * 验证码操作处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/project/common/CommonController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java index b59fb29c0..9cba04dca 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/common/CommonController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.common; +package com.ruoyi.web.controller.common; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -9,13 +9,13 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUtils; -import com.ruoyi.framework.config.RuoYiConfig; import com.ruoyi.framework.config.ServerConfig; -import com.ruoyi.framework.web.domain.AjaxResult; /** * 通用请求处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java similarity index 79% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java index a69222615..2f0c86e73 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/ServerController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java @@ -1,11 +1,11 @@ -package com.ruoyi.project.monitor.controller; +package com.ruoyi.web.controller.monitor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.framework.web.domain.Server; /** diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java similarity index 80% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java index ecda07647..560c4b585 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.monitor.controller; +package com.ruoyi.web.controller.monitor; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -8,14 +8,14 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.monitor.domain.SysLogininfor; -import com.ruoyi.project.monitor.service.ISysLogininforService; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.service.ISysLogininforService; /** * 系统访问记录 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java similarity index 79% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java index d0d5c340b..194285613 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.monitor.controller; +package com.ruoyi.web.controller.monitor; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -8,14 +8,14 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.monitor.domain.SysOperLog; -import com.ruoyi.project.monitor.service.ISysOperLogService; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.service.ISysOperLogService; /** * 操作日志记录 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java similarity index 82% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java index 5a7301912..7f73813a0 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.monitor.controller; +package com.ruoyi.web.controller.monitor; import java.util.ArrayList; import java.util.Collection; @@ -11,17 +11,17 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.redis.RedisCache; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.monitor.domain.SysUserOnline; -import com.ruoyi.project.system.service.ISysUserOnlineService; +import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.service.ISysUserOnlineService; /** * 在线用户监控 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java index 9a832cb59..41b82098e 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,16 +12,17 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysConfig; -import com.ruoyi.project.system.service.ISysConfigService; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.service.ISysConfigService; /** * 参数配置 信息操作处理 @@ -82,6 +83,7 @@ public class SysConfigController extends BaseController @PreAuthorize("@ss.hasPermi('system:config:add')") @Log(title = "参数管理", businessType = BusinessType.INSERT) @PostMapping + @RepeatSubmit public AjaxResult add(@Validated @RequestBody SysConfig config) { if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java index e549a4324..60bd1a5b5 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.Iterator; import java.util.List; @@ -14,15 +14,15 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.project.system.domain.SysDept; -import com.ruoyi.project.system.service.ISysDeptService; +import com.ruoyi.system.service.ISysDeptService; /** * 部门信息 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java similarity index 85% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java index 8b3b394e5..58cf43d22 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,16 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysDictData; -import com.ruoyi.project.system.service.ISysDictDataService; -import com.ruoyi.project.system.service.ISysDictTypeService; +import com.ruoyi.system.service.ISysDictDataService; +import com.ruoyi.system.service.ISysDictTypeService; /** * 数据字典信息 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java index 816d5438a..efde2d49f 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,16 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictType; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysDictType; -import com.ruoyi.project.system.service.ISysDictTypeService; +import com.ruoyi.system.service.ISysDictTypeService; /** * 数据字典信息 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java similarity index 79% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index 73aaa71c4..4ade9f683 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import java.util.Set; @@ -8,16 +8,16 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.framework.security.LoginBody; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.SysLoginService; -import com.ruoyi.framework.security.service.SysPermissionService; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.project.system.domain.SysMenu; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.service.ISysMenuService; +import com.ruoyi.framework.web.service.SysLoginService; +import com.ruoyi.framework.web.service.SysPermissionService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.ISysMenuService; /** * 登录验证 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java index a958f62c0..8bdfe9169 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,19 +12,19 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.project.system.domain.SysMenu; -import com.ruoyi.project.system.service.ISysMenuService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.ISysMenuService; /** * 菜单信息 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java similarity index 83% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java index 9f003927d..029ee385b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,14 +12,14 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysNotice; -import com.ruoyi.project.system.service.ISysNoticeService; +import com.ruoyi.system.domain.SysNotice; +import com.ruoyi.system.service.ISysNoticeService; /** * 公告 信息操作处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java index 0c30ef798..67d76ee0b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,16 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysPost; -import com.ruoyi.project.system.service.ISysPostService; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.service.ISysPostService; /** * 岗位信息操作处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java index 8b0b38e1a..bfedddfdd 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.io.IOException; import org.springframework.beans.factory.annotation.Autowired; @@ -10,18 +10,18 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.file.FileUploadUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.config.RuoYiConfig; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.service.ISysUserService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.ISysUserService; /** * 个人信息 业务处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java index 62ab85842..927a6c283 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -12,16 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysRole; -import com.ruoyi.project.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysRoleService; /** * 角色信息 @@ -151,4 +151,4 @@ public class SysRoleController extends BaseController { return AjaxResult.success(roleService.selectRoleAll()); } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java index 5c6857008..946df4d60 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.controller; +package com.ruoyi.web.controller.system; import java.util.List; import java.util.stream.Collectors; @@ -14,23 +14,23 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.system.domain.SysRole; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.service.ISysPostService; -import com.ruoyi.project.system.service.ISysRoleService; -import com.ruoyi.project.system.service.ISysUserService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.ISysPostService; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysUserService; /** * 用户信息 @@ -198,4 +198,4 @@ public class SysUserController extends BaseController user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.updateUserStatus(user)); } -} \ No newline at end of file +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java new file mode 100644 index 000000000..e901fedd7 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java @@ -0,0 +1,24 @@ +package com.ruoyi.web.controller.tool; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import com.ruoyi.common.core.controller.BaseController; + +/** + * swagger 接口 + * + * @author ruoyi + */ +@Controller +@RequestMapping("/tool/swagger") +public class SwaggerController extends BaseController +{ + @PreAuthorize("@ss.hasPermi('tool:swagger:view')") + @GetMapping() + public String index() + { + return redirect("/swagger-ui.html"); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/swagger/TestController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/project/tool/swagger/TestController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java index 17f4c31e7..2ae0c54ac 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/swagger/TestController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.tool.swagger; +package com.ruoyi.web.controller.tool; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -11,9 +11,9 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiModel; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java index 969268565..86acc3f0b 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.config; +package com.ruoyi.web.core.config; import java.util.ArrayList; import java.util.List; @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import com.ruoyi.common.config.RuoYiConfig; import io.swagger.annotations.ApiOperation; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; diff --git a/ruoyi/src/main/resources/META-INF/spring-devtools.properties b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties similarity index 100% rename from ruoyi/src/main/resources/META-INF/spring-devtools.properties rename to ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties diff --git a/ruoyi/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml similarity index 100% rename from ruoyi/src/main/resources/application-druid.yml rename to ruoyi-admin/src/main/resources/application-druid.yml diff --git a/ruoyi/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml similarity index 80% rename from ruoyi/src/main/resources/application.yml rename to ruoyi-admin/src/main/resources/application.yml index cf23b8e06..c87725a42 100644 --- a/ruoyi/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -3,7 +3,7 @@ ruoyi: # 名称 name: RuoYi # 版本 - version: 2.3.0 + version: 3.0.0 # 版权年份 copyrightYear: 2019 # 实例演示开关 @@ -87,9 +87,9 @@ token: # MyBatis配置 mybatis: # 搜索指定包别名 - typeAliasesPackage: com.ruoyi.project.**.domain + typeAliasesPackage: com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 - mapperLocations: classpath*:mybatis/**/*Mapper.xml + mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml @@ -115,14 +115,3 @@ xss: excludes: /system/notice/* # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* - -# 代码生成 -gen: - # 作者 - author: ruoyi - # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool - packageName: com.ruoyi.project.system - # 自动去除表前缀,默认是true - autoRemovePre: false - # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) - tablePrefix: sys_ \ No newline at end of file diff --git a/ruoyi/src/main/resources/banner.txt b/ruoyi-admin/src/main/resources/banner.txt similarity index 100% rename from ruoyi/src/main/resources/banner.txt rename to ruoyi-admin/src/main/resources/banner.txt diff --git a/ruoyi/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties similarity index 100% rename from ruoyi/src/main/resources/i18n/messages.properties rename to ruoyi-admin/src/main/resources/i18n/messages.properties diff --git a/ruoyi/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml similarity index 100% rename from ruoyi/src/main/resources/logback.xml rename to ruoyi-admin/src/main/resources/logback.xml diff --git a/ruoyi/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml similarity index 100% rename from ruoyi/src/main/resources/mybatis/mybatis-config.xml rename to ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml new file mode 100644 index 000000000..e4c677a2a --- /dev/null +++ b/ruoyi-common/pom.xml @@ -0,0 +1,124 @@ + + + + ruoyi + com.ruoyi + 3.0.0 + + 4.0.0 + + ruoyi-common + + + common通用工具 + + + + + + + org.springframework + spring-context-support + + + + + org.springframework + spring-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + + javax.validation + validation-api + + + + + org.apache.commons + commons-lang3 + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.alibaba + fastjson + + + + + commons-io + commons-io + + + + + commons-fileupload + commons-fileupload + + + + + org.apache.poi + poi-ooxml + + + + + org.yaml + snakeyaml + + + + + io.jsonwebtoken + jjwt + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + + eu.bitwalker + UserAgentUtils + + + + + javax.servlet + javax.servlet-api + + + + + \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java rename to ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java index 5e4cc9c2d..fe5a01f55 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.aspectj.lang.annotation; +package com.ruoyi.common.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java similarity index 82% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataSource.java rename to ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java index 15a1d82eb..6b41ee739 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataSource.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.aspectj.lang.annotation; +package com.ruoyi.common.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -6,7 +6,7 @@ import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.ruoyi.framework.aspectj.lang.enums.DataSourceType; +import com.ruoyi.common.enums.DataSourceType; /** * 自定义多数据源切换注解 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excel.java rename to ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java index de25b1cf5..351979176 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excel.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java @@ -1,118 +1,118 @@ -package com.ruoyi.framework.aspectj.lang.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 自定义导出Excel数据注解 - * - * @author ruoyi - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface Excel -{ - /** - * 导出时在excel中排序 - */ - public int sort() default Integer.MAX_VALUE; - - /** - * 导出到Excel中的名字. - */ - public String name() default ""; - - /** - * 日期格式, 如: yyyy-MM-dd - */ - public String dateFormat() default ""; - - /** - * 读取内容转表达式 (如: 0=男,1=女,2=未知) - */ - public String readConverterExp() default ""; - - /** - * 导出类型(0数字 1字符串) - */ - public ColumnType cellType() default ColumnType.STRING; - - /** - * 导出时在excel中每个列的高度 单位为字符 - */ - public double height() default 14; - - /** - * 导出时在excel中每个列的宽 单位为字符 - */ - public double width() default 16; - - /** - * 文字后缀,如% 90 变成90% - */ - public String suffix() default ""; - - /** - * 当值为空时,字段的默认值 - */ - public String defaultValue() default ""; - - /** - * 提示信息 - */ - public String prompt() default ""; - - /** - * 设置只能选择不能输入的列内容. - */ - public String[] combo() default {}; - - /** - * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. - */ - public boolean isExport() default true; - - /** - * 另一个类中的属性名称,支持多级获取,以小数点隔开 - */ - public String targetAttr() default ""; - - /** - * 字段类型(0:导出导入;1:仅导出;2:仅导入) - */ - Type type() default Type.ALL; - - public enum Type - { - ALL(0), EXPORT(1), IMPORT(2); - private final int value; - - Type(int value) - { - this.value = value; - } - - public int value() - { - return this.value; - } - } - - public enum ColumnType - { - NUMERIC(0), STRING(1); - private final int value; - - ColumnType(int value) - { - this.value = value; - } - - public int value() - { - return this.value; - } - } -} \ No newline at end of file +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义导出Excel数据注解 + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Excel +{ + /** + * 导出时在excel中排序 + */ + public int sort() default Integer.MAX_VALUE; + + /** + * 导出到Excel中的名字. + */ + public String name() default ""; + + /** + * 日期格式, 如: yyyy-MM-dd + */ + public String dateFormat() default ""; + + /** + * 读取内容转表达式 (如: 0=男,1=女,2=未知) + */ + public String readConverterExp() default ""; + + /** + * 导出类型(0数字 1字符串) + */ + public ColumnType cellType() default ColumnType.STRING; + + /** + * 导出时在excel中每个列的高度 单位为字符 + */ + public double height() default 14; + + /** + * 导出时在excel中每个列的宽 单位为字符 + */ + public double width() default 16; + + /** + * 文字后缀,如% 90 变成90% + */ + public String suffix() default ""; + + /** + * 当值为空时,字段的默认值 + */ + public String defaultValue() default ""; + + /** + * 提示信息 + */ + public String prompt() default ""; + + /** + * 设置只能选择不能输入的列内容. + */ + public String[] combo() default {}; + + /** + * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. + */ + public boolean isExport() default true; + + /** + * 另一个类中的属性名称,支持多级获取,以小数点隔开 + */ + public String targetAttr() default ""; + + /** + * 字段类型(0:导出导入;1:仅导出;2:仅导入) + */ + Type type() default Type.ALL; + + public enum Type + { + ALL(0), EXPORT(1), IMPORT(2); + private final int value; + + Type(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + public enum ColumnType + { + NUMERIC(0), STRING(1); + private final int value; + + ColumnType(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excels.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java similarity index 84% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excels.java rename to ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java index ff2280201..940763f06 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excels.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java @@ -1,18 +1,18 @@ -package com.ruoyi.framework.aspectj.lang.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Excel注解集 - * - * @author ruoyi - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Excels -{ - Excel[] value(); -} \ No newline at end of file +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Excel注解集 + * + * @author ruoyi + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Excels +{ + Excel[] value(); +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java similarity index 78% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Log.java rename to ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java index 548eaced3..3458c882d 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Log.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java @@ -1,12 +1,12 @@ -package com.ruoyi.framework.aspectj.lang.annotation; +package com.ruoyi.common.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.aspectj.lang.enums.OperatorType; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.enums.OperatorType; /** * 自定义操作日志记录注解 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java rename to ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java index 0fbd73b68..628eef1ef 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java @@ -1,23 +1,23 @@ -package com.ruoyi.framework.interceptor.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 自定义注解防止表单重复提交 - * - * @author ruoyi - * - */ -@Inherited -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RepeatSubmit -{ - -} \ No newline at end of file +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义注解防止表单重复提交 + * + * @author ruoyi + * + */ +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RepeatSubmit +{ + +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/config/RuoYiConfig.java rename to ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java index 1f6e20ad1..c64ce71d6 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/RuoYiConfig.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.config; +package com.ruoyi.common.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -113,4 +113,4 @@ public class RuoYiConfig { return getProfile() + "/upload"; } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java rename to ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index fe8afc003..9ee27077a 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -1,7 +1,5 @@ package com.ruoyi.common.constant; -import io.jsonwebtoken.Claims; - /** * 通用常量信息 * @@ -92,7 +90,7 @@ public class Constants /** * 用户名称 */ - public static final String JWT_USERNAME = Claims.SUBJECT; + public static final String JWT_USERNAME = "sub"; /** * 用户头像 diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/constant/GenConstants.java rename to ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/constant/HttpStatus.java rename to ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java rename to ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java index 62ad81545..8318b8f5f 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java @@ -1,50 +1,50 @@ -package com.ruoyi.common.constant; - -/** - * 任务调度通用常量 - * - * @author ruoyi - */ -public class ScheduleConstants -{ - public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; - - /** 执行目标key */ - public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; - - /** 默认 */ - public static final String MISFIRE_DEFAULT = "0"; - - /** 立即触发执行 */ - public static final String MISFIRE_IGNORE_MISFIRES = "1"; - - /** 触发一次执行 */ - public static final String MISFIRE_FIRE_AND_PROCEED = "2"; - - /** 不触发立即执行 */ - public static final String MISFIRE_DO_NOTHING = "3"; - - public enum Status - { - /** - * 正常 - */ - NORMAL("0"), - /** - * 暂停 - */ - PAUSE("1"); - - private String value; - - private Status(String value) - { - this.value = value; - } - - public String getValue() - { - return value; - } - } -} +package com.ruoyi.common.constant; + +/** + * 任务调度通用常量 + * + * @author ruoyi + */ +public class ScheduleConstants +{ + public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; + + /** 执行目标key */ + public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; + + /** 默认 */ + public static final String MISFIRE_DEFAULT = "0"; + + /** 立即触发执行 */ + public static final String MISFIRE_IGNORE_MISFIRES = "1"; + + /** 触发一次执行 */ + public static final String MISFIRE_FIRE_AND_PROCEED = "2"; + + /** 不触发立即执行 */ + public static final String MISFIRE_DO_NOTHING = "3"; + + public enum Status + { + /** + * 正常 + */ + NORMAL("0"), + /** + * 暂停 + */ + PAUSE("1"); + + private String value; + + private Status(String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java rename to ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java similarity index 82% rename from ruoyi/src/main/java/com/ruoyi/framework/web/controller/BaseController.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java index cb9b7d0c5..ab78abdad 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/controller/BaseController.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.controller; +package com.ruoyi.common.core.controller; import java.beans.PropertyEditorSupport; import java.util.Date; @@ -10,13 +10,13 @@ import org.springframework.web.bind.annotation.InitBinder; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.PageDomain; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.page.TableSupport; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.sql.SqlUtil; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.PageDomain; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.framework.web.page.TableSupport; /** * web层通用数据处理 @@ -83,4 +83,12 @@ public class BaseController { return rows > 0 ? AjaxResult.success() : AjaxResult.error(); } + + /** + * 页面跳转 + */ + public String redirect(String url) + { + return StringUtils.format("redirect:{}", url); + } } diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java similarity index 94% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java index 5c551bd7b..b26e066ab 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.domain; +package com.ruoyi.common.core.domain; import java.util.HashMap; import com.ruoyi.common.constant.HttpStatus; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java index 08f4f9027..a8c51a7b6 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.domain; +package com.ruoyi.common.core.domain; import java.io.Serializable; import java.util.Date; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeEntity.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java index af8643736..171f04c9b 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeEntity.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.domain; +package com.ruoyi.common.core.domain; import java.util.ArrayList; import java.util.List; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeSelect.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java index 2ace4e9c1..4a59e402a 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/TreeSelect.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java @@ -1,11 +1,11 @@ -package com.ruoyi.framework.web.domain; +package com.ruoyi.common.core.domain; import java.io.Serializable; import java.util.List; import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonInclude; -import com.ruoyi.project.system.domain.SysDept; -import com.ruoyi.project.system.domain.SysMenu; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysMenu; /** * Treeselect树结构实体类 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDept.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java index ba12f1549..423ef6852 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDept.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.common.core.domain.entity; import java.util.ArrayList; import java.util.List; @@ -7,7 +7,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.core.domain.BaseEntity; /** * 部门表 sys_dept diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDictData.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java index 8f7ec6140..4fa5f0bd8 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDictData.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java @@ -1,13 +1,13 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.common.core.domain.entity; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.core.domain.BaseEntity; /** * 字典数据表 sys_dict_data diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDictType.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java index a800f6904..6683c9194 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysDictType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.common.core.domain.entity; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; /** * 字典类型表 sys_dict_type diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysMenu.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java index 24990c072..b8ad1f389 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysMenu.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.common.core.domain.entity; import java.util.ArrayList; import java.util.List; @@ -6,7 +6,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.core.domain.BaseEntity; /** * 菜单权限表 sys_menu diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java index 677c2e461..9330f8ea9 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.common.core.domain.entity; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; /** * 角色表 sys_role diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java index f63f59832..f7e68e7b0 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.common.core.domain.entity; import java.util.Date; import java.util.List; @@ -9,11 +9,11 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type; -import com.ruoyi.framework.aspectj.lang.annotation.Excels; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.core.domain.BaseEntity; /** * 用户对象 sys_user diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/framework/security/LoginBody.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java index 59860537a..a1f8b8337 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/LoginBody.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.security; +package com.ruoyi.common.core.domain.model; /** * 用户登录对象 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/framework/security/LoginUser.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java index 6b2ff0940..a8b112692 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/LoginUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java @@ -1,11 +1,11 @@ -package com.ruoyi.framework.security; +package com.ruoyi.common.core.domain.model; import java.util.Collection; import java.util.Set; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.ruoyi.project.system.domain.SysUser; +import com.ruoyi.common.core.domain.entity.SysUser; /** * 登录用户身份权限 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/framework/web/page/PageDomain.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java index 7e50472d6..e6dd98e22 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/page/PageDomain.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.page; +package com.ruoyi.common.core.page; import com.ruoyi.common.utils.StringUtils; @@ -11,10 +11,13 @@ public class PageDomain { /** 当前记录起始索引 */ private Integer pageNum; + /** 每页显示记录数 */ private Integer pageSize; + /** 排序列 */ private String orderByColumn; + /** 排序的方向 "desc" 或者 "asc". */ private String isAsc; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java index e8b24ffe5..a3487b8ed 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.page; +package com.ruoyi.common.core.page; import java.io.Serializable; import java.util.List; @@ -82,4 +82,4 @@ public class TableDataInfo implements Serializable { this.msg = msg; } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/page/TableSupport.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/framework/web/page/TableSupport.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java index fa6a9ee38..511e24b8d 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/page/TableSupport.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.web.page; +package com.ruoyi.common.core.page; import com.ruoyi.common.utils.ServletUtils; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/framework/redis/RedisCache.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java index 2905a3834..530dcd9f7 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/redis/RedisCache.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.redis; +package com.ruoyi.common.core.redis; import java.util.Collection; import java.util.List; diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/core/text/CharsetKit.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/core/text/Convert.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/core/text/StrFormatter.java rename to ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java similarity index 70% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessStatus.java rename to ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java index 7e27f2ecb..78188fc16 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessStatus.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.aspectj.lang.enums; +package com.ruoyi.common.enums; /** * 操作状态 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java similarity index 83% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessType.java rename to ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java index d974a6489..2bbeaf7d3 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.aspectj.lang.enums; +package com.ruoyi.common.enums; /** * 业务操作类型 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java similarity index 70% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/DataSourceType.java rename to ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java index 274dd3497..4b5341d19 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/DataSourceType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.aspectj.lang.enums; +package com.ruoyi.common.enums; /** * 数据源 diff --git a/ruoyi/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/enums/HttpMethod.java rename to ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java similarity index 75% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/OperatorType.java rename to ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java index 98685a61d..06532af8f 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/lang/enums/OperatorType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.aspectj.lang.enums; +package com.ruoyi.common.enums; /** * 操作人类别 diff --git a/ruoyi/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/enums/UserStatus.java rename to ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/BaseException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/BaseException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/BaseException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/CustomException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/CustomException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/CustomException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/DemoModeException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/UtilException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/file/FileException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/exception/job/TaskException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java index a567b408b..14b2361d0 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/exception/job/TaskException.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java @@ -1,34 +1,34 @@ -package com.ruoyi.common.exception.job; - -/** - * 计划策略异常 - * - * @author ruoyi - */ -public class TaskException extends Exception -{ - private static final long serialVersionUID = 1L; - - private Code code; - - public TaskException(String msg, Code code) - { - this(msg, code, null); - } - - public TaskException(String msg, Code code, Exception nestedEx) - { - super(msg, nestedEx); - this.code = code; - } - - public Code getCode() - { - return code; - } - - public enum Code - { - TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE - } +package com.ruoyi.common.exception.job; + +/** + * 计划策略异常 + * + * @author ruoyi + */ +public class TaskException extends Exception +{ + private static final long serialVersionUID = 1L; + + private Code code; + + public TaskException(String msg, Code code) + { + this(msg, code, null); + } + + public TaskException(String msg, Code code, Exception nestedEx) + { + super(msg, nestedEx); + this.code = code; + } + + public Code getCode() + { + return code; + } + + public enum Code + { + TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE + } } \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/user/UserException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java rename to ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java similarity index 96% rename from ruoyi/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java rename to ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java index 6e3edfcee..15a6804f2 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java @@ -1,52 +1,52 @@ -package com.ruoyi.common.filter; - -import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import org.springframework.http.MediaType; -import com.ruoyi.common.utils.StringUtils; - -/** - * Repeatable 过滤器 - * - * @author ruoyi - */ -public class RepeatableFilter implements Filter -{ - @Override - public void init(FilterConfig filterConfig) throws ServletException - { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException - { - ServletRequest requestWrapper = null; - if (request instanceof HttpServletRequest && StringUtils.equalsAnyIgnoreCase(request.getContentType(), - MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE)) - { - requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); - } - if (null == requestWrapper) - { - chain.doFilter(request, response); - } - else - { - chain.doFilter(requestWrapper, response); - } - } - - @Override - public void destroy() - { - - } -} +package com.ruoyi.common.filter; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.springframework.http.MediaType; +import com.ruoyi.common.utils.StringUtils; + +/** + * Repeatable 过滤器 + * + * @author ruoyi + */ +public class RepeatableFilter implements Filter +{ + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + ServletRequest requestWrapper = null; + if (request instanceof HttpServletRequest && StringUtils.equalsAnyIgnoreCase(request.getContentType(), + MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE)) + { + requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); + } + if (null == requestWrapper) + { + chain.doFilter(request, response); + } + else + { + chain.doFilter(requestWrapper, response); + } + } + + @Override + public void destroy() + { + + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java similarity index 96% rename from ruoyi/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java rename to ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java index bd7097f53..9ad6f4940 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java @@ -1,72 +1,72 @@ -package com.ruoyi.common.filter; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import com.ruoyi.common.utils.http.HttpHelper; - -/** - * 构建可重复读取inputStream的request - * - * @author ruoyi - */ -public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper -{ - private final byte[] body; - - public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException - { - super(request); - request.setCharacterEncoding("UTF-8"); - response.setCharacterEncoding("UTF-8"); - - body = HttpHelper.getBodyString(request).getBytes("UTF-8"); - } - - @Override - public BufferedReader getReader() throws IOException - { - return new BufferedReader(new InputStreamReader(getInputStream())); - } - - @Override - public ServletInputStream getInputStream() throws IOException - { - - final ByteArrayInputStream bais = new ByteArrayInputStream(body); - - return new ServletInputStream() - { - - @Override - public int read() throws IOException - { - return bais.read(); - } - - @Override - public boolean isFinished() - { - return false; - } - - @Override - public boolean isReady() - { - return false; - } - - @Override - public void setReadListener(ReadListener readListener) - { - - } - }; - } -} +package com.ruoyi.common.filter; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import com.ruoyi.common.utils.http.HttpHelper; + +/** + * 构建可重复读取inputStream的request + * + * @author ruoyi + */ +public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper +{ + private final byte[] body; + + public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException + { + super(request); + request.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding("UTF-8"); + + body = HttpHelper.getBodyString(request).getBytes("UTF-8"); + } + + @Override + public BufferedReader getReader() throws IOException + { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + + return new ServletInputStream() + { + + @Override + public int read() throws IOException + { + return bais.read(); + } + + @Override + public boolean isFinished() + { + return false; + } + + @Override + public boolean isReady() + { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) + { + + } + }; + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/filter/XssFilter.java rename to ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java rename to ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/Arith.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/Arith.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/DateUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java index 0c1ee5dba..6fb6289c4 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java @@ -2,10 +2,11 @@ package com.ruoyi.common.utils; import java.util.Collection; import java.util.List; + import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.redis.RedisCache; -import com.ruoyi.project.system.domain.SysDictData; /** * 字典工具类 diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java index ad57439b7..4ca52838a 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java @@ -1,40 +1,40 @@ -package com.ruoyi.common.utils; - -import java.io.PrintWriter; -import java.io.StringWriter; -import org.apache.commons.lang3.exception.ExceptionUtils; - -/** - * 错误信息处理类。 - * - * @author ruoyi - */ -public class ExceptionUtil -{ - /** - * 获取exception的详细错误信息。 - */ - public static String getExceptionMessage(Throwable e) - { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw, true)); - String str = sw.toString(); - return str; - } - - public static String getRootErrorMseeage(Exception e) - { - Throwable root = ExceptionUtils.getRootCause(e); - root = (root == null ? e : root); - if (root == null) - { - return ""; - } - String msg = root.getMessage(); - if (msg == null) - { - return "null"; - } - return StringUtils.defaultString(msg); - } -} +package com.ruoyi.common.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import org.apache.commons.lang3.exception.ExceptionUtils; + +/** + * 错误信息处理类。 + * + * @author ruoyi + */ +public class ExceptionUtil +{ + /** + * 获取exception的详细错误信息。 + */ + public static String getExceptionMessage(Throwable e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + String str = sw.toString(); + return str; + } + + public static String getRootErrorMseeage(Exception e) + { + Throwable root = ExceptionUtils.getRootCause(e); + root = (root == null ? e : root); + if (root == null) + { + return ""; + } + String msg = root.getMessage(); + if (msg == null) + { + return "null"; + } + return StringUtils.defaultString(msg); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/LogUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/LogUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/MessageUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/common/utils/SecurityUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java index c8d1783e6..ce7f3b64f 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/SecurityUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java @@ -4,8 +4,8 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.exception.CustomException; -import com.ruoyi.framework.security.LoginUser; /** * 安全服务工具类 diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/ServletUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/Threads.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/Threads.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java similarity index 96% rename from ruoyi/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java index 4463662d4..51cdc2fb1 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java @@ -1,110 +1,110 @@ -package com.ruoyi.common.utils.bean; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Bean 工具类 - * - * @author ruoyi - */ -public class BeanUtils extends org.springframework.beans.BeanUtils -{ - /** Bean方法名中属性名开始的下标 */ - private static final int BEAN_METHOD_PROP_INDEX = 3; - - /** * 匹配getter方法的正则表达式 */ - private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); - - /** * 匹配setter方法的正则表达式 */ - private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); - - /** - * Bean属性复制工具方法。 - * - * @param dest 目标对象 - * @param src 源对象 - */ - public static void copyBeanProp(Object dest, Object src) - { - try - { - copyProperties(src, dest); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * 获取对象的setter方法。 - * - * @param obj 对象 - * @return 对象的setter方法列表 - */ - public static List getSetterMethods(Object obj) - { - // setter方法列表 - List setterMethods = new ArrayList(); - - // 获取所有方法 - Method[] methods = obj.getClass().getMethods(); - - // 查找setter方法 - - for (Method method : methods) - { - Matcher m = SET_PATTERN.matcher(method.getName()); - if (m.matches() && (method.getParameterTypes().length == 1)) - { - setterMethods.add(method); - } - } - // 返回setter方法列表 - return setterMethods; - } - - /** - * 获取对象的getter方法。 - * - * @param obj 对象 - * @return 对象的getter方法列表 - */ - - public static List getGetterMethods(Object obj) - { - // getter方法列表 - List getterMethods = new ArrayList(); - // 获取所有方法 - Method[] methods = obj.getClass().getMethods(); - // 查找getter方法 - for (Method method : methods) - { - Matcher m = GET_PATTERN.matcher(method.getName()); - if (m.matches() && (method.getParameterTypes().length == 0)) - { - getterMethods.add(method); - } - } - // 返回getter方法列表 - return getterMethods; - } - - /** - * 检查Bean方法名中的属性名是否相等。
- * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 - * - * @param m1 方法名1 - * @param m2 方法名2 - * @return 属性名一样返回true,否则返回false - */ - - public static boolean isMethodPropEquals(String m1, String m2) - { - return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); - } -} +package com.ruoyi.common.utils.bean; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Bean 工具类 + * + * @author ruoyi + */ +public class BeanUtils extends org.springframework.beans.BeanUtils +{ + /** Bean方法名中属性名开始的下标 */ + private static final int BEAN_METHOD_PROP_INDEX = 3; + + /** * 匹配getter方法的正则表达式 */ + private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); + + /** * 匹配setter方法的正则表达式 */ + private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); + + /** + * Bean属性复制工具方法。 + * + * @param dest 目标对象 + * @param src 源对象 + */ + public static void copyBeanProp(Object dest, Object src) + { + try + { + copyProperties(src, dest); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * 获取对象的setter方法。 + * + * @param obj 对象 + * @return 对象的setter方法列表 + */ + public static List getSetterMethods(Object obj) + { + // setter方法列表 + List setterMethods = new ArrayList(); + + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + + // 查找setter方法 + + for (Method method : methods) + { + Matcher m = SET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 1)) + { + setterMethods.add(method); + } + } + // 返回setter方法列表 + return setterMethods; + } + + /** + * 获取对象的getter方法。 + * + * @param obj 对象 + * @return 对象的getter方法列表 + */ + + public static List getGetterMethods(Object obj) + { + // getter方法列表 + List getterMethods = new ArrayList(); + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + // 查找getter方法 + for (Method method : methods) + { + Matcher m = GET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 0)) + { + getterMethods.add(method); + } + } + // 返回getter方法列表 + return getterMethods; + } + + /** + * 检查Bean方法名中的属性名是否相等。
+ * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 + * + * @param m1 方法名1 + * @param m2 方法名2 + * @return 属性名一样返回true,否则返回false + */ + + public static boolean isMethodPropEquals(String m1, String m2) + { + return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java index 5b356e294..183f91867 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java @@ -4,14 +4,14 @@ import java.io.File; import java.io.IOException; import org.apache.commons.io.FilenameUtils; import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; import com.ruoyi.common.exception.file.FileSizeLimitExceededException; import com.ruoyi.common.exception.file.InvalidExtensionException; import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.IdUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.config.RuoYiConfig; +import com.ruoyi.common.utils.uuid.IdUtils; /** * 文件上传工具类 diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/file/FileUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java similarity index 97% rename from ruoyi/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java index 6244cd57b..41739569d 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java @@ -1,569 +1,569 @@ -package com.ruoyi.common.utils.html; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * HTML过滤器,用于去除XSS漏洞隐患。 - * - * @author ruoyi - */ -public final class HTMLFilter -{ - /** - * regex flag union representing /si modifiers in php - **/ - private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; - private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); - private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); - private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); - private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); - private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); - private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); - private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); - private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); - private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); - private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); - private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); - private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); - private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); - private static final Pattern P_END_ARROW = Pattern.compile("^>"); - private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); - private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); - private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); - private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); - private static final Pattern P_AMP = Pattern.compile("&"); - private static final Pattern P_QUOTE = Pattern.compile("\""); - private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); - private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); - private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); - - // @xxx could grow large... maybe use sesat's ReferenceMap - private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); - private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); - - /** - * set of allowed html elements, along with allowed attributes for each element - **/ - private final Map> vAllowed; - /** - * counts of open tags for each (allowable) html element - **/ - private final Map vTagCounts = new HashMap<>(); - - /** - * html elements which must always be self-closing (e.g. "") - **/ - private final String[] vSelfClosingTags; - /** - * html elements which must always have separate opening and closing tags (e.g. "") - **/ - private final String[] vNeedClosingTags; - /** - * set of disallowed html elements - **/ - private final String[] vDisallowed; - /** - * attributes which should be checked for valid protocols - **/ - private final String[] vProtocolAtts; - /** - * allowed protocols - **/ - private final String[] vAllowedProtocols; - /** - * tags which should be removed if they contain no content (e.g. "" or "") - **/ - private final String[] vRemoveBlanks; - /** - * entities allowed within html markup - **/ - private final String[] vAllowedEntities; - /** - * flag determining whether comments are allowed in input String. - */ - private final boolean stripComment; - private final boolean encodeQuotes; - /** - * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" - * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. - */ - private final boolean alwaysMakeTags; - - /** - * Default constructor. - */ - public HTMLFilter() - { - vAllowed = new HashMap<>(); - - final ArrayList a_atts = new ArrayList<>(); - a_atts.add("href"); - a_atts.add("target"); - vAllowed.put("a", a_atts); - - final ArrayList img_atts = new ArrayList<>(); - img_atts.add("src"); - img_atts.add("width"); - img_atts.add("height"); - img_atts.add("alt"); - vAllowed.put("img", img_atts); - - final ArrayList no_atts = new ArrayList<>(); - vAllowed.put("b", no_atts); - vAllowed.put("strong", no_atts); - vAllowed.put("i", no_atts); - vAllowed.put("em", no_atts); - - vSelfClosingTags = new String[] { "img" }; - vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; - vDisallowed = new String[] {}; - vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. - vProtocolAtts = new String[] { "src", "href" }; - vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; - vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; - stripComment = true; - encodeQuotes = true; - alwaysMakeTags = true; - } - - /** - * Map-parameter configurable constructor. - * - * @param conf map containing configuration. keys match field names. - */ - @SuppressWarnings("unchecked") - public HTMLFilter(final Map conf) - { - - assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; - assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; - assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; - assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; - assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; - assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; - assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; - assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; - - vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); - vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); - vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); - vDisallowed = (String[]) conf.get("vDisallowed"); - vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); - vProtocolAtts = (String[]) conf.get("vProtocolAtts"); - vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); - vAllowedEntities = (String[]) conf.get("vAllowedEntities"); - stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; - encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; - alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; - } - - private void reset() - { - vTagCounts.clear(); - } - - // --------------------------------------------------------------- - // my versions of some PHP library functions - public static String chr(final int decimal) - { - return String.valueOf((char) decimal); - } - - public static String htmlSpecialChars(final String s) - { - String result = s; - result = regexReplace(P_AMP, "&", result); - result = regexReplace(P_QUOTE, """, result); - result = regexReplace(P_LEFT_ARROW, "<", result); - result = regexReplace(P_RIGHT_ARROW, ">", result); - return result; - } - - // --------------------------------------------------------------- - - /** - * given a user submitted input String, filter out any invalid or restricted html. - * - * @param input text (i.e. submitted by a user) than may contain html - * @return "clean" version of input, with only valid, whitelisted html elements allowed - */ - public String filter(final String input) - { - reset(); - String s = input; - - s = escapeComments(s); - - s = balanceHTML(s); - - s = checkTags(s); - - s = processRemoveBlanks(s); - - s = validateEntities(s); - - return s; - } - - public boolean isAlwaysMakeTags() - { - return alwaysMakeTags; - } - - public boolean isStripComments() - { - return stripComment; - } - - private String escapeComments(final String s) - { - final Matcher m = P_COMMENTS.matcher(s); - final StringBuffer buf = new StringBuffer(); - if (m.find()) - { - final String match = m.group(1); // (.*?) - m.appendReplacement(buf, Matcher.quoteReplacement("")); - } - m.appendTail(buf); - - return buf.toString(); - } - - private String balanceHTML(String s) - { - if (alwaysMakeTags) - { - // - // try and form html - // - s = regexReplace(P_END_ARROW, "", s); - s = regexReplace(P_BODY_TO_END, "<$1>", s); - s = regexReplace(P_XML_CONTENT, "$1<$2", s); - - } - else - { - // - // escape stray brackets - // - s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); - s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); - - // - // the last regexp causes '<>' entities to appear - // (we need to do a lookahead assertion so that the last bracket can - // be used in the next pass of the regexp) - // - s = regexReplace(P_BOTH_ARROWS, "", s); - } - - return s; - } - - private String checkTags(String s) - { - Matcher m = P_TAGS.matcher(s); - - final StringBuffer buf = new StringBuffer(); - while (m.find()) - { - String replaceStr = m.group(1); - replaceStr = processTag(replaceStr); - m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); - } - m.appendTail(buf); - - // these get tallied in processTag - // (remember to reset before subsequent calls to filter method) - final StringBuilder sBuilder = new StringBuilder(buf.toString()); - for (String key : vTagCounts.keySet()) - { - for (int ii = 0; ii < vTagCounts.get(key); ii++) - { - sBuilder.append(""); - } - } - s = sBuilder.toString(); - - return s; - } - - private String processRemoveBlanks(final String s) - { - String result = s; - for (String tag : vRemoveBlanks) - { - if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) - { - P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); - } - result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); - if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) - { - P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); - } - result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); - } - - return result; - } - - private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) - { - Matcher m = regex_pattern.matcher(s); - return m.replaceAll(replacement); - } - - private String processTag(final String s) - { - // ending tags - Matcher m = P_END_TAG.matcher(s); - if (m.find()) - { - final String name = m.group(1).toLowerCase(); - if (allowed(name)) - { - if (false == inArray(name, vSelfClosingTags)) - { - if (vTagCounts.containsKey(name)) - { - vTagCounts.put(name, vTagCounts.get(name) - 1); - return ""; - } - } - } - } - - // starting tags - m = P_START_TAG.matcher(s); - if (m.find()) - { - final String name = m.group(1).toLowerCase(); - final String body = m.group(2); - String ending = m.group(3); - - // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); - if (allowed(name)) - { - final StringBuilder params = new StringBuilder(); - - final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); - final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); - final List paramNames = new ArrayList<>(); - final List paramValues = new ArrayList<>(); - while (m2.find()) - { - paramNames.add(m2.group(1)); // ([a-z0-9]+) - paramValues.add(m2.group(3)); // (.*?) - } - while (m3.find()) - { - paramNames.add(m3.group(1)); // ([a-z0-9]+) - paramValues.add(m3.group(3)); // ([^\"\\s']+) - } - - String paramName, paramValue; - for (int ii = 0; ii < paramNames.size(); ii++) - { - paramName = paramNames.get(ii).toLowerCase(); - paramValue = paramValues.get(ii); - - // debug( "paramName='" + paramName + "'" ); - // debug( "paramValue='" + paramValue + "'" ); - // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); - - if (allowedAttribute(name, paramName)) - { - if (inArray(paramName, vProtocolAtts)) - { - paramValue = processParamProtocol(paramValue); - } - params.append(' ').append(paramName).append("=\"").append(paramValue).append("\""); - } - } - - if (inArray(name, vSelfClosingTags)) - { - ending = " /"; - } - - if (inArray(name, vNeedClosingTags)) - { - ending = ""; - } - - if (ending == null || ending.length() < 1) - { - if (vTagCounts.containsKey(name)) - { - vTagCounts.put(name, vTagCounts.get(name) + 1); - } - else - { - vTagCounts.put(name, 1); - } - } - else - { - ending = " /"; - } - return "<" + name + params + ending + ">"; - } - else - { - return ""; - } - } - - // comments - m = P_COMMENT.matcher(s); - if (!stripComment && m.find()) - { - return "<" + m.group() + ">"; - } - - return ""; - } - - private String processParamProtocol(String s) - { - s = decodeEntities(s); - final Matcher m = P_PROTOCOL.matcher(s); - if (m.find()) - { - final String protocol = m.group(1); - if (!inArray(protocol, vAllowedProtocols)) - { - // bad protocol, turn into local anchor link instead - s = "#" + s.substring(protocol.length() + 1); - if (s.startsWith("#//")) - { - s = "#" + s.substring(3); - } - } - } - - return s; - } - - private String decodeEntities(String s) - { - StringBuffer buf = new StringBuffer(); - - Matcher m = P_ENTITY.matcher(s); - while (m.find()) - { - final String match = m.group(1); - final int decimal = Integer.decode(match).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENTITY_UNICODE.matcher(s); - while (m.find()) - { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENCODE.matcher(s); - while (m.find()) - { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - s = validateEntities(s); - return s; - } - - private String validateEntities(final String s) - { - StringBuffer buf = new StringBuffer(); - - // validate entities throughout the string - Matcher m = P_VALID_ENTITIES.matcher(s); - while (m.find()) - { - final String one = m.group(1); // ([^&;]*) - final String two = m.group(2); // (?=(;|&|$)) - m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); - } - m.appendTail(buf); - - return encodeQuotes(buf.toString()); - } - - private String encodeQuotes(final String s) - { - if (encodeQuotes) - { - StringBuffer buf = new StringBuffer(); - Matcher m = P_VALID_QUOTES.matcher(s); - while (m.find()) - { - final String one = m.group(1); // (>|^) - final String two = m.group(2); // ([^<]+?) - final String three = m.group(3); // (<|$) - // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) - m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); - } - m.appendTail(buf); - return buf.toString(); - } - else - { - return s; - } - } - - private String checkEntity(final String preamble, final String term) - { - - return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; - } - - private boolean isValidEntity(final String entity) - { - return inArray(entity, vAllowedEntities); - } - - private static boolean inArray(final String s, final String[] array) - { - for (String item : array) - { - if (item != null && item.equals(s)) - { - return true; - } - } - return false; - } - - private boolean allowed(final String name) - { - return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); - } - - private boolean allowedAttribute(final String name, final String paramName) - { - return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); - } +package com.ruoyi.common.utils.html; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * HTML过滤器,用于去除XSS漏洞隐患。 + * + * @author ruoyi + */ +public final class HTMLFilter +{ + /** + * regex flag union representing /si modifiers in php + **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); + + /** + * set of allowed html elements, along with allowed attributes for each element + **/ + private final Map> vAllowed; + /** + * counts of open tags for each (allowable) html element + **/ + private final Map vTagCounts = new HashMap<>(); + + /** + * html elements which must always be self-closing (e.g. "") + **/ + private final String[] vSelfClosingTags; + /** + * html elements which must always have separate opening and closing tags (e.g. "") + **/ + private final String[] vNeedClosingTags; + /** + * set of disallowed html elements + **/ + private final String[] vDisallowed; + /** + * attributes which should be checked for valid protocols + **/ + private final String[] vProtocolAtts; + /** + * allowed protocols + **/ + private final String[] vAllowedProtocols; + /** + * tags which should be removed if they contain no content (e.g. "" or "") + **/ + private final String[] vRemoveBlanks; + /** + * entities allowed within html markup + **/ + private final String[] vAllowedEntities; + /** + * flag determining whether comments are allowed in input String. + */ + private final boolean stripComment; + private final boolean encodeQuotes; + /** + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" + * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** + * Default constructor. + */ + public HTMLFilter() + { + vAllowed = new HashMap<>(); + + final ArrayList a_atts = new ArrayList<>(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList<>(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList<>(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[] { "img" }; + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; + vDisallowed = new String[] {}; + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. + vProtocolAtts = new String[] { "src", "href" }; + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = true; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) + { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() + { + vTagCounts.clear(); + } + + // --------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) + { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) + { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + // --------------------------------------------------------------- + + /** + * given a user submitted input String, filter out any invalid or restricted html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) + { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHTML(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + s = validateEntities(s); + + return s; + } + + public boolean isAlwaysMakeTags() + { + return alwaysMakeTags; + } + + public boolean isStripComments() + { + return stripComment; + } + + private String escapeComments(final String s) + { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) + { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) + { + if (alwaysMakeTags) + { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } + else + { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) + { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) + { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) + { + for (int ii = 0; ii < vTagCounts.get(key); ii++) + { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) + { + String result = s; + for (String tag : vRemoveBlanks) + { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) + { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) + { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) + { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) + { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) + { + if (false == inArray(name, vSelfClosingTags)) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) + { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) + { + paramNames.add(m2.group(1)); // ([a-z0-9]+) + paramValues.add(m2.group(3)); // (.*?) + } + while (m3.find()) + { + paramNames.add(m3.group(1)); // ([a-z0-9]+) + paramValues.add(m3.group(3)); // ([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) + { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + // debug( "paramName='" + paramName + "'" ); + // debug( "paramValue='" + paramValue + "'" ); + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) + { + if (inArray(paramName, vProtocolAtts)) + { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\"").append(paramValue).append("\""); + } + } + + if (inArray(name, vSelfClosingTags)) + { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) + { + ending = ""; + } + + if (ending == null || ending.length() < 1) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } + else + { + vTagCounts.put(name, 1); + } + } + else + { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } + else + { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) + { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) + { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) + { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) + { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) + { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) + { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) + { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) + { + if (encodeQuotes) + { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // (>|^) + final String two = m.group(2); // ([^<]+?) + final String three = m.group(3); // (<|$) + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } + else + { + return s; + } + } + + private String checkEntity(final String preamble, final String term) + { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) + { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) + { + for (String item : array) + { + if (item != null && item.equals(s)) + { + return true; + } + } + return false; + } + + private boolean allowed(final String name) + { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) + { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } } \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java index dcf1b8f53..e34fa5ae6 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java @@ -1,55 +1,55 @@ -package com.ruoyi.common.utils.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import javax.servlet.ServletRequest; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 通用http工具封装 - * - * @author ruoyi - */ -public class HttpHelper -{ - private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); - - public static String getBodyString(ServletRequest request) - { - StringBuilder sb = new StringBuilder(); - BufferedReader reader = null; - try (InputStream inputStream = request.getInputStream()) - { - reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); - String line = ""; - while ((line = reader.readLine()) != null) - { - sb.append(line); - } - } - catch (IOException e) - { - LOGGER.warn("getBodyString出现问题!"); - } - finally - { - if (reader != null) - { - try - { - reader.close(); - } - catch (IOException e) - { - LOGGER.error(ExceptionUtils.getFullStackTrace(e)); - } - } - } - return sb.toString(); - } -} +package com.ruoyi.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import javax.servlet.ServletRequest; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http工具封装 + * + * @author ruoyi + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题!"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java index c36431f99..11faa3236 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java @@ -3,10 +3,10 @@ package com.ruoyi.common.utils.ip; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtils; -import com.ruoyi.framework.config.RuoYiConfig; /** * 获取地址类 diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java index 3211ac551..f4947e0c6 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -1,875 +1,875 @@ -package com.ruoyi.common.utils.poi; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; -import org.apache.poi.hssf.usermodel.HSSFDateUtil; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationConstraint; -import org.apache.poi.ss.usermodel.DataValidationHelper; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFDataValidation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.core.text.Convert; -import com.ruoyi.common.exception.CustomException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.reflect.ReflectUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type; -import com.ruoyi.framework.aspectj.lang.annotation.Excels; -import com.ruoyi.framework.config.RuoYiConfig; -import com.ruoyi.framework.web.domain.AjaxResult; - -/** - * Excel相关处理 - * - * @author ruoyi - */ -public class ExcelUtil -{ - private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); - - /** - * Excel sheet最大行数,默认65536 - */ - public static final int sheetSize = 65536; - - /** - * 工作表名称 - */ - private String sheetName; - - /** - * 导出类型(EXPORT:导出数据;IMPORT:导入模板) - */ - private Type type; - - /** - * 工作薄对象 - */ - private Workbook wb; - - /** - * 工作表对象 - */ - private Sheet sheet; - - /** - * 样式列表 - */ - private Map styles; - - /** - * 导入导出数据列表 - */ - private List list; - - /** - * 注解列表 - */ - private List fields; - - /** - * 实体对象 - */ - public Class clazz; - - public ExcelUtil(Class clazz) - { - this.clazz = clazz; - } - - public void init(List list, String sheetName, Type type) - { - if (list == null) - { - list = new ArrayList(); - } - this.list = list; - this.sheetName = sheetName; - this.type = type; - createExcelField(); - createWorkbook(); - } - - /** - * 对excel表单默认第一个索引名转换成list - * - * @param is 输入流 - * @return 转换后集合 - */ - public List importExcel(InputStream is) throws Exception - { - return importExcel(StringUtils.EMPTY, is); - } - - /** - * 对excel表单指定表格索引名转换成list - * - * @param sheetName 表格索引名 - * @param is 输入流 - * @return 转换后集合 - */ - public List importExcel(String sheetName, InputStream is) throws Exception - { - this.type = Type.IMPORT; - this.wb = WorkbookFactory.create(is); - List list = new ArrayList(); - Sheet sheet = null; - if (StringUtils.isNotEmpty(sheetName)) - { - // 如果指定sheet名,则取指定sheet中的内容. - sheet = wb.getSheet(sheetName); - } - else - { - // 如果传入的sheet名不存在则默认指向第1个sheet. - sheet = wb.getSheetAt(0); - } - - if (sheet == null) - { - throw new IOException("文件sheet不存在"); - } - - int rows = sheet.getPhysicalNumberOfRows(); - - if (rows > 0) - { - // 定义一个map用于存放excel列的序号和field. - Map cellMap = new HashMap(); - // 获取表头 - Row heard = sheet.getRow(0); - for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) - { - Cell cell = heard.getCell(i); - if (StringUtils.isNotNull(cell)) - { - String value = this.getCellValue(heard, i).toString(); - cellMap.put(value, i); - } - else - { - cellMap.put(null, i); - } - } - // 有数据时才处理 得到类的所有field. - Field[] allFields = clazz.getDeclaredFields(); - // 定义一个map用于存放列的序号和field. - Map fieldsMap = new HashMap(); - for (int col = 0; col < allFields.length; col++) - { - Field field = allFields[col]; - Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - // 设置类的私有字段属性可访问. - field.setAccessible(true); - Integer column = cellMap.get(attr.name()); - fieldsMap.put(column, field); - } - } - for (int i = 1; i < rows; i++) - { - // 从第2行开始取数据,默认第一行是表头. - Row row = sheet.getRow(i); - T entity = null; - for (Map.Entry entry : fieldsMap.entrySet()) - { - Object val = this.getCellValue(row, entry.getKey()); - - // 如果不存在实例则新建. - entity = (entity == null ? clazz.newInstance() : entity); - // 从map中得到对应列的field. - Field field = fieldsMap.get(entry.getKey()); - // 取得类型,并根据对象类型设置值. - Class fieldType = field.getType(); - if (String.class == fieldType) - { - String s = Convert.toStr(val); - if (StringUtils.endsWith(s, ".0")) - { - val = StringUtils.substringBefore(s, ".0"); - } - else - { - val = Convert.toStr(val); - } - } - else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) - { - val = Convert.toInt(val); - } - else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) - { - val = Convert.toLong(val); - } - else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) - { - val = Convert.toDouble(val); - } - else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) - { - val = Convert.toFloat(val); - } - else if (BigDecimal.class == fieldType) - { - val = Convert.toBigDecimal(val); - } - else if (Date.class == fieldType) - { - if (val instanceof String) - { - val = DateUtils.parseDate(val); - } - else if (val instanceof Double) - { - val = DateUtil.getJavaDate((Double) val); - } - } - if (StringUtils.isNotNull(fieldType)) - { - Excel attr = field.getAnnotation(Excel.class); - String propertyName = field.getName(); - if (StringUtils.isNotEmpty(attr.targetAttr())) - { - propertyName = field.getName() + "." + attr.targetAttr(); - } - else if (StringUtils.isNotEmpty(attr.readConverterExp())) - { - val = reverseByExp(String.valueOf(val), attr.readConverterExp()); - } - ReflectUtils.invokeSetter(entity, propertyName, val); - } - } - list.add(entity); - } - } - return list; - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @return 结果 - */ - public AjaxResult exportExcel(List list, String sheetName) - { - this.init(list, sheetName, Type.EXPORT); - return exportExcel(); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param sheetName 工作表的名称 - * @return 结果 - */ - public AjaxResult importTemplateExcel(String sheetName) - { - this.init(null, sheetName, Type.IMPORT); - return exportExcel(); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @return 结果 - */ - public AjaxResult exportExcel() - { - OutputStream out = null; - try - { - // 取出一共有多少个sheet. - double sheetNo = Math.ceil(list.size() / sheetSize); - for (int index = 0; index <= sheetNo; index++) - { - createSheet(sheetNo, index); - - // 产生一行 - Row row = sheet.createRow(0); - int column = 0; - // 写入各个字段的列头名称 - for (Object[] os : fields) - { - Excel excel = (Excel) os[1]; - this.createCell(excel, row, column++); - } - if (Type.EXPORT.equals(type)) - { - fillExcelData(index, row); - } - } - String filename = encodingFilename(sheetName); - out = new FileOutputStream(getAbsoluteFile(filename)); - wb.write(out); - return AjaxResult.success(filename); - } - catch (Exception e) - { - log.error("导出Excel异常{}", e.getMessage()); - throw new CustomException("导出Excel失败,请联系网站管理员!"); - } - finally - { - if (wb != null) - { - try - { - wb.close(); - } - catch (IOException e1) - { - e1.printStackTrace(); - } - } - if (out != null) - { - try - { - out.close(); - } - catch (IOException e1) - { - e1.printStackTrace(); - } - } - } - } - - /** - * 填充excel数据 - * - * @param index 序号 - * @param row 单元格行 - */ - public void fillExcelData(int index, Row row) - { - int startNo = index * sheetSize; - int endNo = Math.min(startNo + sheetSize, list.size()); - for (int i = startNo; i < endNo; i++) - { - row = sheet.createRow(i + 1 - startNo); - // 得到导出对象. - T vo = (T) list.get(i); - int column = 0; - for (Object[] os : fields) - { - Field field = (Field) os[0]; - Excel excel = (Excel) os[1]; - // 设置实体类私有属性可访问 - field.setAccessible(true); - this.addCell(excel, row, vo, field, column++); - } - } - } - - /** - * 创建表格样式 - * - * @param wb 工作薄对象 - * @return 样式列表 - */ - private Map createStyles(Workbook wb) - { - // 写入各条记录,每条记录对应excel表中的一行 - Map styles = new HashMap(); - CellStyle style = wb.createCellStyle(); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setBorderRight(BorderStyle.THIN); - style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderLeft(BorderStyle.THIN); - style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderTop(BorderStyle.THIN); - style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderBottom(BorderStyle.THIN); - style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - Font dataFont = wb.createFont(); - dataFont.setFontName("Arial"); - dataFont.setFontHeightInPoints((short) 10); - style.setFont(dataFont); - styles.put("data", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setFillPattern(FillPatternType.SOLID_FOREGROUND); - Font headerFont = wb.createFont(); - headerFont.setFontName("Arial"); - headerFont.setFontHeightInPoints((short) 10); - headerFont.setBold(true); - headerFont.setColor(IndexedColors.WHITE.getIndex()); - style.setFont(headerFont); - styles.put("header", style); - - return styles; - } - - /** - * 创建单元格 - */ - public Cell createCell(Excel attr, Row row, int column) - { - // 创建列 - Cell cell = row.createCell(column); - // 写入列信息 - cell.setCellValue(attr.name()); - setDataValidation(attr, row, column); - cell.setCellStyle(styles.get("header")); - return cell; - } - - /** - * 设置单元格信息 - * - * @param value 单元格值 - * @param attr 注解相关 - * @param cell 单元格信息 - */ - public void setCellVo(Object value, Excel attr, Cell cell) - { - if (ColumnType.STRING == attr.cellType()) - { - cell.setCellType(CellType.NUMERIC); - cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix()); - } - else if (ColumnType.NUMERIC == attr.cellType()) - { - cell.setCellType(CellType.NUMERIC); - cell.setCellValue(Integer.parseInt(value + "")); - } - } - - /** - * 创建表格样式 - */ - public void setDataValidation(Excel attr, Row row, int column) - { - if (attr.name().indexOf("注:") >= 0) - { - sheet.setColumnWidth(column, 6000); - } - else - { - // 设置列宽 - sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); - row.setHeight((short) (attr.height() * 20)); - } - // 如果设置了提示信息则鼠标放上去提示. - if (StringUtils.isNotEmpty(attr.prompt())) - { - // 这里默认设了2-101列提示. - setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); - } - // 如果设置了combo属性则本列只能选择不能输入 - if (attr.combo().length > 0) - { - // 这里默认设了2-101列只能选择不能输入. - setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); - } - } - - /** - * 添加单元格 - */ - public Cell addCell(Excel attr, Row row, T vo, Field field, int column) - { - Cell cell = null; - try - { - // 设置行高 - row.setHeight((short) (attr.height() * 20)); - // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. - if (attr.isExport()) - { - // 创建cell - cell = row.createCell(column); - cell.setCellStyle(styles.get("data")); - - // 用于读取对象中的属性 - Object value = getTargetValue(vo, field, attr); - String dateFormat = attr.dateFormat(); - String readConverterExp = attr.readConverterExp(); - if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) - { - cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); - } - else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) - { - cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp)); - } - else - { - // 设置列类型 - setCellVo(value, attr, cell); - } - } - } - catch (Exception e) - { - log.error("导出Excel失败{}", e); - } - return cell; - } - - /** - * 设置 POI XSSFSheet 单元格提示 - * - * @param sheet 表单 - * @param promptTitle 提示标题 - * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 - */ - public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, - int firstCol, int endCol) - { - DataValidationHelper helper = sheet.getDataValidationHelper(); - DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); - CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); - DataValidation dataValidation = helper.createValidation(constraint, regions); - dataValidation.createPromptBox(promptTitle, promptContent); - dataValidation.setShowPromptBox(true); - sheet.addValidationData(dataValidation); - } - - /** - * 设置某些列的值只能输入预制的数据,显示下拉框. - * - * @param sheet 要设置的sheet. - * @param textlist 下拉框显示的内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 - * @return 设置好的sheet. - */ - public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) - { - DataValidationHelper helper = sheet.getDataValidationHelper(); - // 加载下拉列表内容 - DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); - // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 - CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); - // 数据有效性对象 - DataValidation dataValidation = helper.createValidation(constraint, regions); - // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { - dataValidation.setSuppressDropDownArrow(true); - dataValidation.setShowErrorBox(true); - } - else - { - dataValidation.setSuppressDropDownArrow(false); - } - - sheet.addValidationData(dataValidation); - } - - /** - * 解析导出值 0=男,1=女,2=未知 - * - * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @return 解析后值 - * @throws Exception - */ - public static String convertByExp(String propertyValue, String converterExp) throws Exception - { - try - { - String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { - String[] itemArray = item.split("="); - if (itemArray[0].equals(propertyValue)) - { - return itemArray[1]; - } - } - } - catch (Exception e) - { - throw e; - } - return propertyValue; - } - - /** - * 反向解析值 男=0,女=1,未知=2 - * - * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @return 解析后值 - * @throws Exception - */ - public static String reverseByExp(String propertyValue, String converterExp) throws Exception - { - try - { - String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { - String[] itemArray = item.split("="); - if (itemArray[1].equals(propertyValue)) - { - return itemArray[0]; - } - } - } - catch (Exception e) - { - throw e; - } - return propertyValue; - } - - /** - * 编码文件名 - */ - public String encodingFilename(String filename) - { - filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; - return filename; - } - - /** - * 获取下载路径 - * - * @param filename 文件名称 - */ - public String getAbsoluteFile(String filename) - { - String downloadPath = RuoYiConfig.getDownloadPath() + filename; - File desc = new File(downloadPath); - if (!desc.getParentFile().exists()) - { - desc.getParentFile().mkdirs(); - } - return downloadPath; - } - - /** - * 获取bean中的属性值 - * - * @param vo 实体对象 - * @param field 字段 - * @param excel 注解 - * @return 最终的属性值 - * @throws Exception - */ - private Object getTargetValue(T vo, Field field, Excel excel) throws Exception - { - Object o = field.get(vo); - if (StringUtils.isNotEmpty(excel.targetAttr())) - { - String target = excel.targetAttr(); - if (target.indexOf(".") > -1) - { - String[] targets = target.split("[.]"); - for (String name : targets) - { - o = getValue(o, name); - } - } - else - { - o = getValue(o, target); - } - } - return o; - } - - /** - * 以类的属性的get方法方法形式获取值 - * - * @param o - * @param name - * @return value - * @throws Exception - */ - private Object getValue(Object o, String name) throws Exception - { - if (StringUtils.isNotEmpty(name)) - { - Class clazz = o.getClass(); - String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); - Method method = clazz.getMethod(methodName); - o = method.invoke(o); - } - return o; - } - - /** - * 得到所有定义字段 - */ - private void createExcelField() - { - this.fields = new ArrayList(); - List tempFields = new ArrayList<>(); - tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); - tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - for (Field field : tempFields) - { - // 单注解 - if (field.isAnnotationPresent(Excel.class)) - { - putToField(field, field.getAnnotation(Excel.class)); - } - - // 多注解 - if (field.isAnnotationPresent(Excels.class)) - { - Excels attrs = field.getAnnotation(Excels.class); - Excel[] excels = attrs.value(); - for (Excel excel : excels) - { - putToField(field, excel); - } - } - } - this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); - } - - /** - * 放到字段集合中 - */ - private void putToField(Field field, Excel attr) - { - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - this.fields.add(new Object[] { field, attr }); - } - } - - /** - * 创建一个工作簿 - */ - public void createWorkbook() - { - this.wb = new SXSSFWorkbook(500); - } - - /** - * 创建工作表 - * - * @param sheetNo sheet数量 - * @param index 序号 - */ - public void createSheet(double sheetNo, int index) - { - this.sheet = wb.createSheet(); - this.styles = createStyles(wb); - // 设置工作表的名称. - if (sheetNo == 0) - { - wb.setSheetName(index, sheetName); - } - else - { - wb.setSheetName(index, sheetName + index); - } - } - - /** - * 获取单元格值 - * - * @param row 获取的行 - * @param column 获取单元格列号 - * @return 单元格值 - */ - public Object getCellValue(Row row, int column) - { - if (row == null) - { - return row; - } - Object val = ""; - try - { - Cell cell = row.getCell(column); - if (StringUtils.isNotNull(cell)) - { - if (cell.getCellTypeEnum() == CellType.NUMERIC || cell.getCellTypeEnum() == CellType.FORMULA) - { - val = cell.getNumericCellValue(); - if (HSSFDateUtil.isCellDateFormatted(cell)) - { - val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 - } - else - { - if ((Double) val % 1 > 0) - { - val = new DecimalFormat("0.00").format(val); - } - else - { - val = new DecimalFormat("0").format(val); - } - } - } - else if (cell.getCellTypeEnum() == CellType.STRING) - { - val = cell.getStringCellValue(); - } - else if (cell.getCellTypeEnum() == CellType.BOOLEAN) - { - val = cell.getBooleanCellValue(); - } - else if (cell.getCellTypeEnum() == CellType.ERROR) - { - val = cell.getErrorCellValue(); - } - - } - } - catch (Exception e) - { - return val; - } - return val; - } +package com.ruoyi.common.utils.poi; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import org.apache.poi.hssf.usermodel.HSSFDateUtil; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.exception.CustomException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.reflect.ReflectUtils; + +/** + * Excel相关处理 + * + * @author ruoyi + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + private Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 实体对象 + */ + public Class clazz; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + public void init(List list, String sheetName, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + createExcelField(); + createWorkbook(); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(StringUtils.EMPTY, is); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + Sheet sheet = null; + if (StringUtils.isNotEmpty(sheetName)) + { + // 如果指定sheet名,则取指定sheet中的内容. + sheet = wb.getSheet(sheetName); + } + else + { + // 如果传入的sheet名不存在则默认指向第1个sheet. + sheet = wb.getSheetAt(0); + } + + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + + int rows = sheet.getPhysicalNumberOfRows(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(0); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + Field[] allFields = clazz.getDeclaredFields(); + // 定义一个map用于存放列的序号和field. + Map fieldsMap = new HashMap(); + for (int col = 0; col < allFields.length; col++) + { + Field field = allFields[col]; + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + // 设置类的私有字段属性可访问. + field.setAccessible(true); + Integer column = cellMap.get(attr.name()); + fieldsMap.put(column, field); + } + } + for (int i = 1; i < rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = fieldsMap.get(entry.getKey()); + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + val = Convert.toStr(val); + } + } + else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) + { + val = Convert.toInt(val); + } + else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) + { + val = Convert.toLong(val); + } + else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) + { + val = Convert.toDouble(val); + } + else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + if (StringUtils.isNotNull(fieldType)) + { + Excel attr = field.getAnnotation(Excel.class); + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(String.valueOf(val), attr.readConverterExp()); + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName) + { + this.init(list, sheetName, Type.EXPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + this.init(null, sheetName, Type.IMPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public AjaxResult exportExcel() + { + OutputStream out = null; + try + { + // 取出一共有多少个sheet. + double sheetNo = Math.ceil(list.size() / sheetSize); + for (int index = 0; index <= sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(0); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + this.createCell(excel, row, column++); + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + } + } + String filename = encodingFilename(sheetName); + out = new FileOutputStream(getAbsoluteFile(filename)); + wb.write(out); + return AjaxResult.success(filename); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + throw new CustomException("导出Excel失败,请联系网站管理员!"); + } + finally + { + if (wb != null) + { + try + { + wb.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + if (out != null) + { + try + { + out.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + for (int i = startNo; i < endNo; i++) + { + row = sheet.createRow(i + 1 - startNo); + // 得到导出对象. + T vo = (T) list.get(i); + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + // 设置实体类私有属性可访问 + field.setAccessible(true); + this.addCell(excel, row, vo, field, column++); + } + } + } + + /** + * 创建表格样式 + * + * @param wb 工作薄对象 + * @return 样式列表 + */ + private Map createStyles(Workbook wb) + { + // 写入各条记录,每条记录对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(IndexedColors.WHITE.getIndex()); + style.setFont(headerFont); + styles.put("header", style); + + return styles; + } + + /** + * 创建单元格 + */ + public Cell createCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get("header")); + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + cell.setCellType(CellType.NUMERIC); + cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix()); + } + else if (ColumnType.NUMERIC == attr.cellType()) + { + cell.setCellType(CellType.NUMERIC); + cell.setCellValue(Integer.parseInt(value + "")); + } + } + + /** + * 创建表格样式 + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + row.setHeight((short) (attr.height() * 20)); + } + // 如果设置了提示信息则鼠标放上去提示. + if (StringUtils.isNotEmpty(attr.prompt())) + { + // 这里默认设了2-101列提示. + setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); + } + // 如果设置了combo属性则本列只能选择不能输入 + if (attr.combo().length > 0) + { + // 这里默认设了2-101列只能选择不能输入. + setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); + } + } + + /** + * 添加单元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight((short) (attr.height() * 20)); + // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + cell.setCellStyle(styles.get("data")); + + // 用于读取对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) + { + cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); + } + else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp)); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet 单元格提示 + * + * @param sheet 表单 + * @param promptTitle 提示标题 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + dataValidation.createPromptBox(promptTitle, promptContent); + dataValidation.setShowPromptBox(true); + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框. + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + * @return 设置好的sheet. + */ + public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @return 解析后值 + * @throws Exception + */ + public static String convertByExp(String propertyValue, String converterExp) throws Exception + { + try + { + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + catch (Exception e) + { + throw e; + } + return propertyValue; + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @return 解析后值 + * @throws Exception + */ + public static String reverseByExp(String propertyValue, String converterExp) throws Exception + { + try + { + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + catch (Exception e) + { + throw e; + } + return propertyValue; + } + + /** + * 编码文件名 + */ + public String encodingFilename(String filename) + { + filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; + return filename; + } + + /** + * 获取下载路径 + * + * @param filename 文件名称 + */ + public String getAbsoluteFile(String filename) + { + String downloadPath = RuoYiConfig.getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + /** + * 获取bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (StringUtils.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.indexOf(".") > -1) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形式获取值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (StringUtils.isNotEmpty(name)) + { + Class clazz = o.getClass(); + String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); + Method method = clazz.getMethod(methodName); + o = method.invoke(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + putToField(field, field.getAnnotation(Excel.class)); + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel excel : excels) + { + putToField(field, excel); + } + } + } + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + } + + /** + * 放到字段集合中 + */ + private void putToField(Field field, Excel attr) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + this.fields.add(new Object[] { field, attr }); + } + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(double sheetNo, int index) + { + this.sheet = wb.createSheet(); + this.styles = createStyles(wb); + // 设置工作表的名称. + if (sheetNo == 0) + { + wb.setSheetName(index, sheetName); + } + else + { + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (StringUtils.isNotNull(cell)) + { + if (cell.getCellTypeEnum() == CellType.NUMERIC || cell.getCellTypeEnum() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (HSSFDateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 > 0) + { + val = new DecimalFormat("0.00").format(val); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellTypeEnum() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellTypeEnum() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellTypeEnum() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } } \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java similarity index 97% rename from ruoyi/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java index b78e53e10..5241101be 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java @@ -1,406 +1,406 @@ -package com.ruoyi.common.utils.reflect; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Date; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.Validate; -import org.apache.poi.ss.usermodel.DateUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.core.text.Convert; -import com.ruoyi.common.utils.DateUtils; - -/** - * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. - * - * @author ruoyi - */ -@SuppressWarnings("rawtypes") -public class ReflectUtils -{ - private static final String SETTER_PREFIX = "set"; - - private static final String GETTER_PREFIX = "get"; - - private static final String CGLIB_CLASS_SEPARATOR = "$$"; - - private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); - - /** - * 调用Getter方法. - * 支持多级,如:对象名.对象名.方法 - */ - @SuppressWarnings("unchecked") - public static E invokeGetter(Object obj, String propertyName) - { - Object object = obj; - for (String name : StringUtils.split(propertyName, ".")) - { - String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); - object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); - } - return (E) object; - } - - /** - * 调用Setter方法, 仅匹配方法名。 - * 支持多级,如:对象名.对象名.方法 - */ - public static void invokeSetter(Object obj, String propertyName, E value) - { - Object object = obj; - String[] names = StringUtils.split(propertyName, "."); - for (int i = 0; i < names.length; i++) - { - if (i < names.length - 1) - { - String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); - object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); - } - else - { - String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); - invokeMethodByName(object, setterMethodName, new Object[] { value }); - } - } - } - - /** - * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. - */ - @SuppressWarnings("unchecked") - public static E getFieldValue(final Object obj, final String fieldName) - { - Field field = getAccessibleField(obj, fieldName); - if (field == null) - { - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); - return null; - } - E result = null; - try - { - result = (E) field.get(obj); - } - catch (IllegalAccessException e) - { - logger.error("不可能抛出的异常{}", e.getMessage()); - } - return result; - } - - /** - * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. - */ - public static void setFieldValue(final Object obj, final String fieldName, final E value) - { - Field field = getAccessibleField(obj, fieldName); - if (field == null) - { - // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); - return; - } - try - { - field.set(obj, value); - } - catch (IllegalAccessException e) - { - logger.error("不可能抛出的异常: {}", e.getMessage()); - } - } - - /** - * 直接调用对象方法, 无视private/protected修饰符. - * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. - * 同时匹配方法名+参数类型, - */ - @SuppressWarnings("unchecked") - public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, - final Object[] args) - { - if (obj == null || methodName == null) - { - return null; - } - Method method = getAccessibleMethod(obj, methodName, parameterTypes); - if (method == null) - { - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); - return null; - } - try - { - return (E) method.invoke(obj, args); - } - catch (Exception e) - { - String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; - throw convertReflectionExceptionToUnchecked(msg, e); - } - } - - /** - * 直接调用对象方法, 无视private/protected修饰符, - * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. - * 只匹配函数名,如果有多个同名函数调用第一个。 - */ - @SuppressWarnings("unchecked") - public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) - { - Method method = getAccessibleMethodByName(obj, methodName, args.length); - if (method == null) - { - // 如果为空不报错,直接返回空。 - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); - return null; - } - try - { - // 类型转换(将参数数据类型转换为目标方法参数类型) - Class[] cs = method.getParameterTypes(); - for (int i = 0; i < cs.length; i++) - { - if (args[i] != null && !args[i].getClass().equals(cs[i])) - { - if (cs[i] == String.class) - { - args[i] = Convert.toStr(args[i]); - if (StringUtils.endsWith((String) args[i], ".0")) - { - args[i] = StringUtils.substringBefore((String) args[i], ".0"); - } - } - else if (cs[i] == Integer.class) - { - args[i] = Convert.toInt(args[i]); - } - else if (cs[i] == Long.class) - { - args[i] = Convert.toLong(args[i]); - } - else if (cs[i] == Double.class) - { - args[i] = Convert.toDouble(args[i]); - } - else if (cs[i] == Float.class) - { - args[i] = Convert.toFloat(args[i]); - } - else if (cs[i] == Date.class) - { - if (args[i] instanceof String) - { - args[i] = DateUtils.parseDate(args[i]); - } - else - { - args[i] = DateUtil.getJavaDate((Double) args[i]); - } - } - } - } - return (E) method.invoke(obj, args); - } - catch (Exception e) - { - String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; - throw convertReflectionExceptionToUnchecked(msg, e); - } - } - - /** - * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. - * 如向上转型到Object仍无法找到, 返回null. - */ - public static Field getAccessibleField(final Object obj, final String fieldName) - { - // 为空不报错。直接返回 null - if (obj == null) - { - return null; - } - Validate.notBlank(fieldName, "fieldName can't be blank"); - for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) - { - try - { - Field field = superClass.getDeclaredField(fieldName); - makeAccessible(field); - return field; - } - catch (NoSuchFieldException e) - { - continue; - } - } - return null; - } - - /** - * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. - * 如向上转型到Object仍无法找到, 返回null. - * 匹配函数名+参数类型。 - * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) - */ - public static Method getAccessibleMethod(final Object obj, final String methodName, - final Class... parameterTypes) - { - // 为空不报错。直接返回 null - if (obj == null) - { - return null; - } - Validate.notBlank(methodName, "methodName can't be blank"); - for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) - { - try - { - Method method = searchType.getDeclaredMethod(methodName, parameterTypes); - makeAccessible(method); - return method; - } - catch (NoSuchMethodException e) - { - continue; - } - } - return null; - } - - /** - * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. - * 如向上转型到Object仍无法找到, 返回null. - * 只匹配函数名。 - * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) - */ - public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) - { - // 为空不报错。直接返回 null - if (obj == null) - { - return null; - } - Validate.notBlank(methodName, "methodName can't be blank"); - for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) - { - Method[] methods = searchType.getDeclaredMethods(); - for (Method method : methods) - { - if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) - { - makeAccessible(method); - return method; - } - } - } - return null; - } - - /** - * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 - */ - public static void makeAccessible(Method method) - { - if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) - && !method.isAccessible()) - { - method.setAccessible(true); - } - } - - /** - * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 - */ - public static void makeAccessible(Field field) - { - if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) - || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) - { - field.setAccessible(true); - } - } - - /** - * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 - * 如无法找到, 返回Object.class. - */ - @SuppressWarnings("unchecked") - public static Class getClassGenricType(final Class clazz) - { - return getClassGenricType(clazz, 0); - } - - /** - * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. - * 如无法找到, 返回Object.class. - */ - public static Class getClassGenricType(final Class clazz, final int index) - { - Type genType = clazz.getGenericSuperclass(); - - if (!(genType instanceof ParameterizedType)) - { - logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); - return Object.class; - } - - Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); - - if (index >= params.length || index < 0) - { - logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " - + params.length); - return Object.class; - } - if (!(params[index] instanceof Class)) - { - logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); - return Object.class; - } - - return (Class) params[index]; - } - - public static Class getUserClass(Object instance) - { - if (instance == null) - { - throw new RuntimeException("Instance must not be null"); - } - Class clazz = instance.getClass(); - if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) - { - Class superClass = clazz.getSuperclass(); - if (superClass != null && !Object.class.equals(superClass)) - { - return superClass; - } - } - return clazz; - - } - - /** - * 将反射时的checked exception转换为unchecked exception. - */ - public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) - { - if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException - || e instanceof NoSuchMethodException) - { - return new IllegalArgumentException(msg, e); - } - else if (e instanceof InvocationTargetException) - { - return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); - } - return new RuntimeException(msg, e); - } -} +package com.ruoyi.common.utils.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Date; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.apache.poi.ss.usermodel.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.DateUtils; + +/** + * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. + * + * @author ruoyi + */ +@SuppressWarnings("rawtypes") +public class ReflectUtils +{ + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + @SuppressWarnings("unchecked") + public static E invokeGetter(Object obj, String propertyName) + { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return (E) object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter(Object obj, String propertyName, E value) + { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i = 0; i < names.length; i++) + { + if (i < names.length - 1) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + else + { + String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); + invokeMethodByName(object, setterMethodName, new Object[] { value }); + } + } + } + + /** + * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. + */ + @SuppressWarnings("unchecked") + public static E getFieldValue(final Object obj, final String fieldName) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return null; + } + E result = null; + try + { + result = (E) field.get(obj); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常{}", e.getMessage()); + } + return result; + } + + /** + * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. + */ + public static void setFieldValue(final Object obj, final String fieldName, final E value) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return; + } + try + { + field.set(obj, value); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常: {}", e.getMessage()); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符. + * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. + * 同时匹配方法名+参数类型, + */ + @SuppressWarnings("unchecked") + public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, + final Object[] args) + { + if (obj == null || methodName == null) + { + return null; + } + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + @SuppressWarnings("unchecked") + public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) + { + Method method = getAccessibleMethodByName(obj, methodName, args.length); + if (method == null) + { + // 如果为空不报错,直接返回空。 + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + // 类型转换(将参数数据类型转换为目标方法参数类型) + Class[] cs = method.getParameterTypes(); + for (int i = 0; i < cs.length; i++) + { + if (args[i] != null && !args[i].getClass().equals(cs[i])) + { + if (cs[i] == String.class) + { + args[i] = Convert.toStr(args[i]); + if (StringUtils.endsWith((String) args[i], ".0")) + { + args[i] = StringUtils.substringBefore((String) args[i], ".0"); + } + } + else if (cs[i] == Integer.class) + { + args[i] = Convert.toInt(args[i]); + } + else if (cs[i] == Long.class) + { + args[i] = Convert.toLong(args[i]); + } + else if (cs[i] == Double.class) + { + args[i] = Convert.toDouble(args[i]); + } + else if (cs[i] == Float.class) + { + args[i] = Convert.toFloat(args[i]); + } + else if (cs[i] == Date.class) + { + if (args[i] instanceof String) + { + args[i] = DateUtils.parseDate(args[i]); + } + else + { + args[i] = DateUtil.getJavaDate((Double) args[i]); + } + } + } + } + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) + { + try + { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } + catch (NoSuchFieldException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class... parameterTypes) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + try + { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } + catch (NoSuchMethodException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) + { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) + { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !method.isAccessible()) + { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) + { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) + || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) + { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) + { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + */ + public static Class getClassGenricType(final Class clazz, final int index) + { + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) + { + logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) + { + logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) + { + logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class getUserClass(Object instance) + { + if (instance == null) + { + throw new RuntimeException("Instance must not be null"); + } + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) + { + Class superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) + { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) + { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) + { + return new IllegalArgumentException(msg, e); + } + else if (e instanceof InvocationTargetException) + { + return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(msg, e); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/sign/Base64.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/sign/Base64.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/IdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/common/utils/IdUtils.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java index 45d8ac91a..eb78f6fed 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/IdUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java @@ -1,6 +1,6 @@ -package com.ruoyi.common.utils; +package com.ruoyi.common.utils.uuid; -import com.ruoyi.common.core.lang.UUID; +import com.ruoyi.common.utils.uuid.UUID; /** * ID生成器工具类 diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java similarity index 96% rename from ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java index fa7429774..eef72ee0b 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java @@ -1,4 +1,4 @@ -package com.ruoyi.common.core.lang; +package com.ruoyi.common.utils.uuid; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml new file mode 100644 index 000000000..4d93d31a7 --- /dev/null +++ b/ruoyi-framework/pom.xml @@ -0,0 +1,62 @@ + + + + ruoyi + com.ruoyi + 3.0.0 + + 4.0.0 + + ruoyi-framework + + + framework框架核心 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + com.alibaba + druid-spring-boot-starter + + + + + com.github.oshi + oshi-core + + + + net.java.dev.jna + jna + + + + net.java.dev.jna + jna-platform + + + + + com.ruoyi + ruoyi-system + + + + + \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java index e28e9680c..58040b6dc 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -8,15 +8,15 @@ import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.DataScope; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.framework.web.domain.BaseEntity; -import com.ruoyi.project.system.domain.SysRole; -import com.ruoyi.project.system.domain.SysUser; +import com.ruoyi.framework.web.service.TokenService; /** * 数据过滤处理 @@ -58,7 +58,7 @@ public class DataScopeAspect public static final String DATA_SCOPE = "dataScope"; // 配置织入点 - @Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.DataScope)") + @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") public void dataScopePointCut() { } diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java index bc850732f..4648fcd3c 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java @@ -11,8 +11,8 @@ import org.slf4j.LoggerFactory; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.DataSource; import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; /** @@ -27,8 +27,8 @@ public class DataSourceAspect { protected Logger logger = LoggerFactory.getLogger(getClass()); - @Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.DataSource)" - + "|| @within(com.ruoyi.framework.aspectj.lang.annotation.DataSource)") + @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" + + "|| @within(com.ruoyi.common.annotation.DataSource)") public void dsPointCut() { diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java index 29a1c97e6..51a7cd2bf 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java @@ -17,18 +17,18 @@ import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.HandlerMapping; import com.alibaba.fastjson.JSON; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessStatus; import com.ruoyi.common.enums.HttpMethod; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessStatus; import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.project.monitor.domain.SysOperLog; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.domain.SysOperLog; /** * 操作日志记录处理 @@ -42,7 +42,7 @@ public class LogAspect private static final Logger log = LoggerFactory.getLogger(LogAspect.class); // 配置织入点 - @Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)") + @Pointcut("@annotation(com.ruoyi.common.annotation.Log)") public void logPointCut() { } diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java index 5a6da111c..66a00e7cb 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java @@ -16,7 +16,7 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy; // 表示通过aop框架暴露该代理对象,AopContext能够访问 @EnableAspectJAutoProxy(exposeProxy = true) // 指定要扫描的Mapper类的包的路径 -@MapperScan("com.ruoyi.project.**.mapper") +@MapperScan("com.ruoyi.**.mapper") public class ApplicationConfig { /** diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java similarity index 96% rename from ruoyi/src/main/java/com/ruoyi/framework/config/DruidConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java index f0519d5ac..f671b3a30 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/DruidConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java @@ -19,8 +19,8 @@ import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; import com.alibaba.druid.util.Utils; +import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.aspectj.lang.enums.DataSourceType; import com.ruoyi.framework.config.properties.DruidProperties; import com.ruoyi.framework.datasource.DynamicDataSource; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/RedisConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java similarity index 94% rename from ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java index 8c19564b1..2e120aab8 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.Constants; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/SecurityConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/ServerConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java index 088798d55..bce2f3fe1 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java @@ -1,55 +1,55 @@ -package com.ruoyi.framework.interceptor; - -import java.lang.reflect.Method; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.framework.interceptor.annotation.RepeatSubmit; -import com.ruoyi.framework.web.domain.AjaxResult; - -/** - * 防止重复提交拦截器 - * - * @author ruoyi - */ -@Component -public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter -{ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception - { - if (handler instanceof HandlerMethod) - { - HandlerMethod handlerMethod = (HandlerMethod) handler; - Method method = handlerMethod.getMethod(); - RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); - if (annotation != null) - { - if (this.isRepeatSubmit(request)) - { - AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试"); - ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult)); - return false; - } - } - return true; - } - else - { - return super.preHandle(request, response, handler); - } - } - - /** - * 验证是否重复提交由子类实现具体的防重复提交的规则 - * - * @param httpServletRequest - * @return - * @throws Exception - */ - public abstract boolean isRepeatSubmit(HttpServletRequest request); -} +package com.ruoyi.framework.interceptor; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; + +/** + * 防止重复提交拦截器 + * + * @author ruoyi + */ +@Component +public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter +{ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception + { + if (handler instanceof HandlerMethod) + { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) + { + if (this.isRepeatSubmit(request)) + { + AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试"); + ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult)); + return false; + } + } + return true; + } + else + { + return super.preHandle(request, response, handler); + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * + * @param httpServletRequest + * @return + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request); +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java index 05f59ee00..5f78380b9 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java @@ -1,107 +1,107 @@ -package com.ruoyi.framework.interceptor.impl; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import javax.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.filter.RepeatedlyRequestWrapper; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.http.HttpHelper; -import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; -import com.ruoyi.framework.redis.RedisCache; - -/** - * 判断请求url和数据是否和上一次相同, - * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 - * - * @author ruoyi - */ -@Component -public class SameUrlDataInterceptor extends RepeatSubmitInterceptor -{ - public final String REPEAT_PARAMS = "repeatParams"; - - public final String REPEAT_TIME = "repeatTime"; - - public final String CACHE_REPEAT_KEY = "repeatData"; - - @Autowired - private RedisCache redisCache; - - /** - * 间隔时间,单位:秒 默认10秒 - * - * 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据 - */ - private int intervalTime = 10; - - public void setIntervalTime(int intervalTime) - { - this.intervalTime = intervalTime; - } - - @SuppressWarnings("unchecked") - @Override - public boolean isRepeatSubmit(HttpServletRequest request) - { - RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; - String nowParams = HttpHelper.getBodyString(repeatedlyRequest); - - // body参数为空,获取Parameter的数据 - if (StringUtils.isEmpty(nowParams)) - { - nowParams = JSONObject.toJSONString(request.getParameterMap()); - } - Map nowDataMap = new HashMap(); - nowDataMap.put(REPEAT_PARAMS, nowParams); - nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); - - // 请求地址(作为存放cache的key值) - String url = request.getRequestURI(); - - Object sessionObj = redisCache.getCacheObject(CACHE_REPEAT_KEY); - if (sessionObj != null) - { - Map sessionMap = (Map) sessionObj; - if (sessionMap.containsKey(url)) - { - Map preDataMap = (Map) sessionMap.get(url); - if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) - { - return true; - } - } - } - Map cacheMap = new HashMap(); - cacheMap.put(url, nowDataMap); - redisCache.setCacheObject(CACHE_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS); - return false; - } - - /** - * 判断参数是否相同 - */ - private boolean compareParams(Map nowMap, Map preMap) - { - String nowParams = (String) nowMap.get(REPEAT_PARAMS); - String preParams = (String) preMap.get(REPEAT_PARAMS); - return nowParams.equals(preParams); - } - - /** - * 判断两次间隔时间 - */ - private boolean compareTime(Map nowMap, Map preMap) - { - long time1 = (Long) nowMap.get(REPEAT_TIME); - long time2 = (Long) preMap.get(REPEAT_TIME); - if ((time1 - time2) < (this.intervalTime * 1000)) - { - return true; - } - return false; - } -} +package com.ruoyi.framework.interceptor.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.filter.RepeatedlyRequestWrapper; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.http.HttpHelper; +import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 判断请求url和数据是否和上一次相同, + * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 + * + * @author ruoyi + */ +@Component +public class SameUrlDataInterceptor extends RepeatSubmitInterceptor +{ + public final String REPEAT_PARAMS = "repeatParams"; + + public final String REPEAT_TIME = "repeatTime"; + + public final String CACHE_REPEAT_KEY = "repeatData"; + + @Autowired + private RedisCache redisCache; + + /** + * 间隔时间,单位:秒 默认10秒 + * + * 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据 + */ + private int intervalTime = 10; + + public void setIntervalTime(int intervalTime) + { + this.intervalTime = intervalTime; + } + + @SuppressWarnings("unchecked") + @Override + public boolean isRepeatSubmit(HttpServletRequest request) + { + RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; + String nowParams = HttpHelper.getBodyString(repeatedlyRequest); + + // body参数为空,获取Parameter的数据 + if (StringUtils.isEmpty(nowParams)) + { + nowParams = JSONObject.toJSONString(request.getParameterMap()); + } + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + + // 请求地址(作为存放cache的key值) + String url = request.getRequestURI(); + + Object sessionObj = redisCache.getCacheObject(CACHE_REPEAT_KEY); + if (sessionObj != null) + { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) + { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) + { + return true; + } + } + } + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); + redisCache.setCacheObject(CACHE_REPEAT_KEY, cacheMap, intervalTime, TimeUnit.SECONDS); + return false; + } + + /** + * 判断参数是否相同 + */ + private boolean compareParams(Map nowMap, Map preMap) + { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap) + { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < (this.intervalTime * 1000)) + { + return true; + } + return false; + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/manager/AsyncManager.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java index 0be7a3073..3d6cef9f0 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java @@ -9,10 +9,10 @@ import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.project.monitor.domain.SysLogininfor; -import com.ruoyi.project.monitor.domain.SysOperLog; -import com.ruoyi.project.monitor.service.ISysLogininforService; -import com.ruoyi.project.monitor.service.ISysOperLogService; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.service.ISysLogininforService; +import com.ruoyi.system.service.ISysOperLogService; import eu.bitwalker.useragentutils.UserAgent; /** diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java index ede50befd..75fd00d16 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java @@ -11,10 +11,10 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; +import com.ruoyi.framework.web.service.TokenService; /** * token过滤器 验证token有效性 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java index 995b1f36a..bf9965d31 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java @@ -9,9 +9,9 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSON; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.domain.AjaxResult; /** * 认证失败处理类 返回未授权 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java index c2cc60baa..1d5b1f9c6 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java @@ -11,13 +11,13 @@ import org.springframework.security.web.authentication.logout.LogoutSuccessHandl import com.alibaba.fastjson.JSON; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.framework.security.service.TokenService; -import com.ruoyi.framework.web.domain.AjaxResult; +import com.ruoyi.framework.web.service.TokenService; /** * 自定义退出处理类 返回成功 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/Server.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/Server.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java similarity index 100% rename from ruoyi/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java index 12b4358df..300fe9d29 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java @@ -11,11 +11,11 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.NoHandlerFoundException; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.exception.BaseException; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.DemoModeException; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.domain.AjaxResult; /** * 全局异常处理器 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/service/PermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/security/service/PermissionService.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java index c0b40a67d..2b7ad7ebb 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/service/PermissionService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java @@ -1,13 +1,13 @@ -package com.ruoyi.framework.security.service; +package com.ruoyi.framework.web.service; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.project.system.domain.SysRole; /** * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java index 67b6b4949..020831036 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.security.service; +package com.ruoyi.framework.web.service; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; @@ -8,6 +8,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaExpireException; @@ -15,8 +17,6 @@ import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.framework.redis.RedisCache; -import com.ruoyi.framework.security.LoginUser; /** * 登录校验方法 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java similarity index 83% rename from ruoyi/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java index 021e9a5b6..19c4a5158 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java @@ -1,12 +1,12 @@ -package com.ruoyi.framework.security.service; +package com.ruoyi.framework.web.service; import java.util.HashSet; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.service.ISysMenuService; -import com.ruoyi.project.system.service.ISysRoleService; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.system.service.ISysMenuService; +import com.ruoyi.system.service.ISysRoleService; /** * 用户权限处理 diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/framework/security/service/TokenService.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java index 7637ed88d..66885afdc 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/service/TokenService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.security.service; +package com.ruoyi.framework.web.service; import java.util.HashMap; import java.util.Map; @@ -8,13 +8,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.IdUtils; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.framework.redis.RedisCache; -import com.ruoyi.framework.security.LoginUser; +import com.ruoyi.common.utils.uuid.IdUtils; import eu.bitwalker.useragentutils.UserAgent; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; diff --git a/ruoyi/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java index 2a8c69272..a78f2c753 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.framework.security.service; +package com.ruoyi.framework.web.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,12 +7,12 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.UserStatus; import com.ruoyi.common.exception.BaseException; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.service.ISysUserService; +import com.ruoyi.system.service.ISysUserService; /** * 用户验证处理 diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml new file mode 100644 index 000000000..5929f4dd8 --- /dev/null +++ b/ruoyi-generator/pom.xml @@ -0,0 +1,34 @@ + + + + ruoyi + com.ruoyi + 3.0.0 + + 4.0.0 + + ruoyi-generator + + + generator代码生成 + + + + + + + org.apache.velocity + velocity + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/GenConfig.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java similarity index 73% rename from ruoyi/src/main/java/com/ruoyi/framework/config/GenConfig.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java index a74e2c38e..1b144deb9 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/GenConfig.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java @@ -1,6 +1,8 @@ -package com.ruoyi.framework.config; +package com.ruoyi.generator.config; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; /** @@ -10,6 +12,7 @@ import org.springframework.stereotype.Component; */ @Component @ConfigurationProperties(prefix = "gen") +@PropertySource(value = { "classpath:generator.yml" }) public class GenConfig { /** 作者 */ @@ -18,7 +21,7 @@ public class GenConfig /** 生成包路径 */ public static String packageName; - /** 自动去除表前缀,默认是true */ + /** 自动去除表前缀,默认是false */ public static boolean autoRemovePre; /** 表前缀(类名不会包含表前缀) */ @@ -29,6 +32,7 @@ public class GenConfig return author; } + @Value("${author}") public void setAuthor(String author) { GenConfig.author = author; @@ -39,6 +43,7 @@ public class GenConfig return packageName; } + @Value("${packageName}") public void setPackageName(String packageName) { GenConfig.packageName = packageName; @@ -49,6 +54,7 @@ public class GenConfig return autoRemovePre; } + @Value("${autoRemovePre}") public void setAutoRemovePre(boolean autoRemovePre) { GenConfig.autoRemovePre = autoRemovePre; @@ -59,6 +65,7 @@ public class GenConfig return tablePrefix; } + @Value("${tablePrefix}") public void setTablePrefix(String tablePrefix) { GenConfig.tablePrefix = tablePrefix; diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java index 05f9414e9..816ce1422 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.tool.gen.controller; +package com.ruoyi.generator.controller; import java.io.IOException; import java.util.HashMap; @@ -17,16 +17,16 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.text.Convert; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.tool.gen.domain.GenTable; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; -import com.ruoyi.project.tool.gen.service.IGenTableColumnService; -import com.ruoyi.project.tool.gen.service.IGenTableService; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.service.IGenTableColumnService; +import com.ruoyi.generator.service.IGenTableService; /** * 代码生成 操作处理 @@ -183,4 +183,4 @@ public class GenController extends BaseController response.setContentType("application/octet-stream; charset=UTF-8"); IOUtils.write(data, response.getOutputStream()); } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java index 039af5eb2..5123165e3 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.tool.gen.domain; +package com.ruoyi.generator.domain; import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import org.apache.commons.lang3.ArrayUtils; import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.domain.BaseEntity; /** * 业务表 gen_table @@ -268,4 +268,4 @@ public class GenTable extends BaseEntity } return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY); } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java similarity index 94% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java index 303575f55..bee9ae12b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.tool.gen.domain; +package com.ruoyi.generator.domain; import javax.validation.constraints.NotBlank; +import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.domain.BaseEntity; /** * 代码生成业务字段表 gen_table_column @@ -365,4 +365,4 @@ public class GenTableColumn extends BaseEntity return this.columnComment; } } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableColumnMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableColumnMapper.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java index dfd8ddd09..1366453c8 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableColumnMapper.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.tool.gen.mapper; +package com.ruoyi.generator.mapper; import java.util.List; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; +import com.ruoyi.generator.domain.GenTableColumn; /** * 业务字段 数据层 @@ -49,4 +49,4 @@ public interface GenTableColumnMapper * @return 结果 */ public int deleteGenTableColumnByIds(Long[] ids); -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableMapper.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java index eae10e485..4288d889b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableMapper.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.tool.gen.mapper; +package com.ruoyi.generator.mapper; import java.util.List; -import com.ruoyi.project.tool.gen.domain.GenTable; +import com.ruoyi.generator.domain.GenTable; /** * 业务 数据层 @@ -73,4 +73,4 @@ public interface GenTableMapper * @return 结果 */ public int deleteGenTableByIds(Long[] ids); -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java index 61ae55e3a..3a2d66a59 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java @@ -1,11 +1,11 @@ -package com.ruoyi.project.tool.gen.service; +package com.ruoyi.generator.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.common.core.text.Convert; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; -import com.ruoyi.project.tool.gen.mapper.GenTableColumnMapper; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.mapper.GenTableColumnMapper; /** * 业务字段 服务层实现 @@ -65,4 +65,4 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService { return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids)); } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java index b10c54946..955960f54 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.tool.gen.service; +package com.ruoyi.generator.service; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -24,13 +24,13 @@ import com.ruoyi.common.constant.GenConstants; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.project.tool.gen.domain.GenTable; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; -import com.ruoyi.project.tool.gen.mapper.GenTableColumnMapper; -import com.ruoyi.project.tool.gen.mapper.GenTableMapper; -import com.ruoyi.project.tool.gen.util.GenUtils; -import com.ruoyi.project.tool.gen.util.VelocityInitializer; -import com.ruoyi.project.tool.gen.util.VelocityUtils; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.mapper.GenTableColumnMapper; +import com.ruoyi.generator.mapper.GenTableMapper; +import com.ruoyi.generator.util.GenUtils; +import com.ruoyi.generator.util.VelocityInitializer; +import com.ruoyi.generator.util.VelocityUtils; /** * 业务 服务层实现 @@ -342,4 +342,4 @@ public class GenTableServiceImpl implements IGenTableService genTable.setTreeName(treeName); } } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java similarity index 85% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java index a2c7fc288..2130d0431 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.tool.gen.service; +package com.ruoyi.generator.service; import java.util.List; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; +import com.ruoyi.generator.domain.GenTableColumn; /** * 业务字段 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableService.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java index 73093fe5e..2bff5976c 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableService.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.tool.gen.service; +package com.ruoyi.generator.service; import java.util.List; import java.util.Map; -import com.ruoyi.project.tool.gen.domain.GenTable; +import com.ruoyi.generator.domain.GenTable; /** * 业务 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java similarity index 94% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java index 29a840dd6..e141dffa7 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.tool.gen.util; +package com.ruoyi.generator.util; import java.util.Arrays; import org.apache.commons.lang3.RegExUtils; import com.ruoyi.common.constant.GenConstants; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.config.GenConfig; -import com.ruoyi.project.tool.gen.domain.GenTable; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; +import com.ruoyi.generator.config.GenConfig; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; /** * 代码生成器 工具类 @@ -239,4 +239,4 @@ public class GenUtils return 0; } } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityInitializer.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java index 7f932fc3b..8f9ee07b8 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityInitializer.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.tool.gen.util; +package com.ruoyi.generator.util; import java.util.Properties; import org.apache.velocity.app.Velocity; diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityUtils.java rename to ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java index f3e38a87f..9ec14c33c 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/VelocityUtils.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.tool.gen.util; +package com.ruoyi.generator.util; import java.util.ArrayList; import java.util.HashSet; @@ -8,16 +8,21 @@ import com.alibaba.fastjson.JSONObject; import com.ruoyi.common.constant.GenConstants; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.project.tool.gen.domain.GenTable; -import com.ruoyi.project.tool.gen.domain.GenTableColumn; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +/** + * 代码生成模板处理 + * + * @author ruoyi + */ public class VelocityUtils { /** 项目空间路径 */ private static final String PROJECT_PATH = "main/java"; /** mybatis空间路径 */ - private static final String MYBATIS_PATH = "main/resources/mybatis"; + private static final String MYBATIS_PATH = "main/resources/mapper"; /** * 设置模板变量信息 @@ -290,4 +295,4 @@ public class VelocityUtils } return num; } -} \ No newline at end of file +} diff --git a/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-generator/src/main/resources/generator.yml new file mode 100644 index 000000000..4544c8c24 --- /dev/null +++ b/ruoyi-generator/src/main/resources/generator.yml @@ -0,0 +1,10 @@ +# 代码生成 +gen: + # 作者 + author: ruoyi + # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool + packageName: com.ruoyi.system + # 自动去除表前缀,默认是false + autoRemovePre: false + # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) + tablePrefix: sys_ \ No newline at end of file diff --git a/ruoyi/src/main/resources/mybatis/tool/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml similarity index 97% rename from ruoyi/src/main/resources/mybatis/tool/GenTableColumnMapper.xml rename to ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml index c936fe07f..513275653 100644 --- a/ruoyi/src/main/resources/mybatis/tool/GenTableColumnMapper.xml +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml similarity index 97% rename from ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml rename to ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml index 64a1f5e59..503bb15c9 100644 --- a/ruoyi/src/main/resources/mybatis/tool/GenTableMapper.xml +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm similarity index 90% rename from ruoyi/src/main/resources/vm/java/controller.java.vm rename to ruoyi-generator/src/main/resources/vm/java/controller.java.vm index c45ba6699..6c349df1e 100644 --- a/ruoyi/src/main/resources/vm/java/controller.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -11,15 +11,15 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; import ${packageName}.domain.${ClassName}; import ${packageName}.service.I${ClassName}Service; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.common.utils.poi.ExcelUtil; #if($table.crud) -import com.ruoyi.framework.web.page.TableDataInfo; +import com.ruoyi.common.core.page.TableDataInfo; #elseif($table.tree) #end diff --git a/ruoyi/src/main/resources/vm/java/domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm similarity index 90% rename from ruoyi/src/main/resources/vm/java/domain.java.vm rename to ruoyi-generator/src/main/resources/vm/java/domain.java.vm index c943c1b21..9dd824786 100644 --- a/ruoyi/src/main/resources/vm/java/domain.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm @@ -5,11 +5,11 @@ import ${import}; #end import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; +import com.ruoyi.common.annotation.Excel; #if($table.crud) -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.core.domain.BaseEntity; #elseif($table.tree) -import com.ruoyi.framework.web.domain.TreeEntity; +import com.ruoyi.common.core.domain.TreeEntity; #end /** diff --git a/ruoyi/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm similarity index 100% rename from ruoyi/src/main/resources/vm/java/mapper.java.vm rename to ruoyi-generator/src/main/resources/vm/java/mapper.java.vm diff --git a/ruoyi/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm similarity index 100% rename from ruoyi/src/main/resources/vm/java/service.java.vm rename to ruoyi-generator/src/main/resources/vm/java/service.java.vm diff --git a/ruoyi/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm similarity index 100% rename from ruoyi/src/main/resources/vm/java/serviceImpl.java.vm rename to ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm diff --git a/ruoyi/src/main/resources/vm/js/api.js.vm b/ruoyi-generator/src/main/resources/vm/js/api.js.vm similarity index 100% rename from ruoyi/src/main/resources/vm/js/api.js.vm rename to ruoyi-generator/src/main/resources/vm/js/api.js.vm diff --git a/ruoyi/src/main/resources/vm/sql/sql.vm b/ruoyi-generator/src/main/resources/vm/sql/sql.vm similarity index 100% rename from ruoyi/src/main/resources/vm/sql/sql.vm rename to ruoyi-generator/src/main/resources/vm/sql/sql.vm diff --git a/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm similarity index 100% rename from ruoyi/src/main/resources/vm/vue/index-tree.vue.vm rename to ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm diff --git a/ruoyi/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm similarity index 100% rename from ruoyi/src/main/resources/vm/vue/index.vue.vm rename to ruoyi-generator/src/main/resources/vm/vue/index.vue.vm diff --git a/ruoyi/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm similarity index 100% rename from ruoyi/src/main/resources/vm/xml/mapper.xml.vm rename to ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm diff --git a/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml new file mode 100644 index 000000000..b62c7f7f0 --- /dev/null +++ b/ruoyi-quartz/pom.xml @@ -0,0 +1,40 @@ + + + + ruoyi + com.ruoyi + 3.0.0 + + 4.0.0 + + ruoyi-quartz + + + quartz定时任务 + + + + + + + org.quartz-scheduler + quartz + + + com.mchange + c3p0 + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java similarity index 96% rename from ruoyi/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java index a607e85f7..e466ed057 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java @@ -1,57 +1,57 @@ -package com.ruoyi.framework.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.quartz.SchedulerFactoryBean; -import javax.sql.DataSource; -import java.util.Properties; - -/** - * 定时任务配置 - * - * @author ruoyi - */ -@Configuration -public class ScheduleConfig -{ - @Bean - public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) - { - SchedulerFactoryBean factory = new SchedulerFactoryBean(); - factory.setDataSource(dataSource); - - // quartz参数 - Properties prop = new Properties(); - prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); - prop.put("org.quartz.scheduler.instanceId", "AUTO"); - // 线程池配置 - prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); - prop.put("org.quartz.threadPool.threadCount", "20"); - prop.put("org.quartz.threadPool.threadPriority", "5"); - // JobStore配置 - prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); - // 集群配置 - prop.put("org.quartz.jobStore.isClustered", "true"); - prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); - prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); - prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); - - // sqlserver 启用 - // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); - prop.put("org.quartz.jobStore.misfireThreshold", "12000"); - prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); - factory.setQuartzProperties(prop); - - factory.setSchedulerName("RuoyiScheduler"); - // 延时启动 - factory.setStartupDelay(1); - factory.setApplicationContextSchedulerContextKey("applicationContextKey"); - // 可选,QuartzScheduler - // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 - factory.setOverwriteExistingJobs(true); - // 设置自动启动,默认为true - factory.setAutoStartup(true); - - return factory; - } -} +package com.ruoyi.quartz.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import javax.sql.DataSource; +import java.util.Properties; + +/** + * 定时任务配置 + * + * @author ruoyi + */ +@Configuration +public class ScheduleConfig +{ + @Bean + public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) + { + SchedulerFactoryBean factory = new SchedulerFactoryBean(); + factory.setDataSource(dataSource); + + // quartz参数 + Properties prop = new Properties(); + prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); + prop.put("org.quartz.scheduler.instanceId", "AUTO"); + // 线程池配置 + prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); + prop.put("org.quartz.threadPool.threadCount", "20"); + prop.put("org.quartz.threadPool.threadPriority", "5"); + // JobStore配置 + prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); + // 集群配置 + prop.put("org.quartz.jobStore.isClustered", "true"); + prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); + prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); + prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); + + // sqlserver 启用 + // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); + prop.put("org.quartz.jobStore.misfireThreshold", "12000"); + prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); + factory.setQuartzProperties(prop); + + factory.setSchedulerName("RuoyiScheduler"); + // 延时启动 + factory.setStartupDelay(1); + factory.setApplicationContextSchedulerContextKey("applicationContextKey"); + // 可选,QuartzScheduler + // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 + factory.setOverwriteExistingJobs(true); + // 设置自动启动,默认为true + factory.setAutoStartup(true); + + return factory; + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java index 742d281c0..f770a7d8f 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java @@ -1,142 +1,142 @@ -package com.ruoyi.project.monitor.controller; - -import java.util.List; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.job.CronUtils; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.framework.web.page.TableDataInfo; -import com.ruoyi.project.monitor.domain.SysJob; -import com.ruoyi.project.monitor.service.ISysJobService; - -/** - * 调度任务信息操作处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/job") -public class SysJobController extends BaseController -{ - @Autowired - private ISysJobService jobService; - - /** - * 查询定时任务列表 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:list')") - @GetMapping("/list") - public TableDataInfo list(SysJob sysJob) - { - startPage(); - List list = jobService.selectJobList(sysJob); - return getDataTable(list); - } - - /** - * 导出定时任务列表 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:export')") - @Log(title = "定时任务", businessType = BusinessType.EXPORT) - @GetMapping("/export") - public AjaxResult export(SysJob sysJob) - { - List list = jobService.selectJobList(sysJob); - ExcelUtil util = new ExcelUtil(SysJob.class); - return util.exportExcel(list, "定时任务"); - } - - /** - * 获取定时任务详细信息 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:query')") - @GetMapping(value = "/{jobId}") - public AjaxResult getInfo(@PathVariable("jobId") Long jobId) - { - return AjaxResult.success(jobService.selectJobById(jobId)); - } - - /** - * 新增定时任务 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:add')") - @Log(title = "定时任务", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException - { - if (!CronUtils.isValid(sysJob.getCronExpression())) - { - return AjaxResult.error("cron表达式不正确"); - } - sysJob.setCreateBy(SecurityUtils.getUsername()); - return toAjax(jobService.insertJob(sysJob)); - } - - /** - * 修改定时任务 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:edit')") - @Log(title = "定时任务", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException - { - if (!CronUtils.isValid(sysJob.getCronExpression())) - { - return AjaxResult.error("cron表达式不正确"); - } - sysJob.setUpdateBy(SecurityUtils.getUsername()); - return toAjax(jobService.updateJob(sysJob)); - } - - /** - * 定时任务状态修改 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") - @Log(title = "定时任务", businessType = BusinessType.UPDATE) - @PutMapping("/changeStatus") - public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException - { - SysJob newJob = jobService.selectJobById(job.getJobId()); - newJob.setStatus(job.getStatus()); - return toAjax(jobService.changeStatus(newJob)); - } - - /** - * 定时任务立即执行一次 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") - @Log(title = "定时任务", businessType = BusinessType.UPDATE) - @PutMapping("/run") - public AjaxResult run(@RequestBody SysJob job) throws SchedulerException - { - jobService.run(job); - return AjaxResult.success(); - } - - /** - * 删除定时任务 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:remove')") - @Log(title = "定时任务", businessType = BusinessType.DELETE) - @DeleteMapping("/{jobIds}") - public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException - { - jobService.deleteJobByIds(jobIds); - return AjaxResult.success(); - } -} +package com.ruoyi.quartz.controller; + +import java.util.List; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.service.ISysJobService; +import com.ruoyi.quartz.util.CronUtils; + +/** + * 调度任务信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/job") +public class SysJobController extends BaseController +{ + @Autowired + private ISysJobService jobService; + + /** + * 查询定时任务列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:list')") + @GetMapping("/list") + public TableDataInfo list(SysJob sysJob) + { + startPage(); + List list = jobService.selectJobList(sysJob); + return getDataTable(list); + } + + /** + * 导出定时任务列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:export')") + @Log(title = "定时任务", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SysJob sysJob) + { + List list = jobService.selectJobList(sysJob); + ExcelUtil util = new ExcelUtil(SysJob.class); + return util.exportExcel(list, "定时任务"); + } + + /** + * 获取定时任务详细信息 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{jobId}") + public AjaxResult getInfo(@PathVariable("jobId") Long jobId) + { + return AjaxResult.success(jobService.selectJobById(jobId)); + } + + /** + * 新增定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:add')") + @Log(title = "定时任务", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysJob sysJob) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(sysJob.getCronExpression())) + { + return AjaxResult.error("cron表达式不正确"); + } + sysJob.setCreateBy(SecurityUtils.getUsername()); + return toAjax(jobService.insertJob(sysJob)); + } + + /** + * 修改定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:edit')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysJob sysJob) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(sysJob.getCronExpression())) + { + return AjaxResult.error("cron表达式不正确"); + } + sysJob.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(jobService.updateJob(sysJob)); + } + + /** + * 定时任务状态修改 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException + { + SysJob newJob = jobService.selectJobById(job.getJobId()); + newJob.setStatus(job.getStatus()); + return toAjax(jobService.changeStatus(newJob)); + } + + /** + * 定时任务立即执行一次 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/run") + public AjaxResult run(@RequestBody SysJob job) throws SchedulerException + { + jobService.run(job); + return AjaxResult.success(); + } + + /** + * 删除定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "定时任务", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobIds}") + public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException + { + jobService.deleteJobByIds(jobIds); + return AjaxResult.success(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java similarity index 84% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java index ba1181649..10a842b6d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java @@ -1,90 +1,90 @@ -package com.ruoyi.project.monitor.controller; - -import java.util.List; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.framework.aspectj.lang.annotation.Log; -import com.ruoyi.framework.aspectj.lang.enums.BusinessType; -import com.ruoyi.project.monitor.domain.SysJobLog; -import com.ruoyi.project.monitor.service.ISysJobLogService; -import com.ruoyi.framework.web.controller.BaseController; -import com.ruoyi.framework.web.domain.AjaxResult; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.web.page.TableDataInfo; - -/** - * 调度日志操作处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/jobLog") -public class SysJobLogController extends BaseController -{ - @Autowired - private ISysJobLogService jobLogService; - - /** - * 查询定时任务调度日志列表 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:list')") - @GetMapping("/list") - public TableDataInfo list(SysJobLog sysJobLog) - { - startPage(); - List list = jobLogService.selectJobLogList(sysJobLog); - return getDataTable(list); - } - - /** - * 导出定时任务调度日志列表 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:export')") - @Log(title = "任务调度日志", businessType = BusinessType.EXPORT) - @GetMapping("/export") - public AjaxResult export(SysJobLog sysJobLog) - { - List list = jobLogService.selectJobLogList(sysJobLog); - ExcelUtil util = new ExcelUtil(SysJobLog.class); - return util.exportExcel(list, "调度日志"); - } - - /** - * 根据调度编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:query')") - @GetMapping(value = "/{configId}") - public AjaxResult getInfo(@PathVariable Long jobLogId) - { - return AjaxResult.success(jobLogService.selectJobLogById(jobLogId)); - } - - - /** - * 删除定时任务调度日志 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:remove')") - @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE) - @DeleteMapping("/{jobLogIds}") - public AjaxResult remove(@PathVariable Long[] jobLogIds) - { - return toAjax(jobLogService.deleteJobLogByIds(jobLogIds)); - } - - /** - * 清空定时任务调度日志 - */ - @PreAuthorize("@ss.hasPermi('monitor:job:remove')") - @Log(title = "调度日志", businessType = BusinessType.CLEAN) - @DeleteMapping("/clean") - public AjaxResult clean() - { - jobLogService.cleanJobLog(); - return AjaxResult.success(); - } -} +package com.ruoyi.quartz.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 调度日志操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/jobLog") +public class SysJobLogController extends BaseController +{ + @Autowired + private ISysJobLogService jobLogService; + + /** + * 查询定时任务调度日志列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:list')") + @GetMapping("/list") + public TableDataInfo list(SysJobLog sysJobLog) + { + startPage(); + List list = jobLogService.selectJobLogList(sysJobLog); + return getDataTable(list); + } + + /** + * 导出定时任务调度日志列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:export')") + @Log(title = "任务调度日志", businessType = BusinessType.EXPORT) + @GetMapping("/export") + public AjaxResult export(SysJobLog sysJobLog) + { + List list = jobLogService.selectJobLogList(sysJobLog); + ExcelUtil util = new ExcelUtil(SysJobLog.class); + return util.exportExcel(list, "调度日志"); + } + + /** + * 根据调度编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long jobLogId) + { + return AjaxResult.success(jobLogService.selectJobLogById(jobLogId)); + } + + + /** + * 删除定时任务调度日志 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobLogIds}") + public AjaxResult remove(@PathVariable Long[] jobLogIds) + { + return toAjax(jobLogService.deleteJobLogByIds(jobLogIds)); + } + + /** + * 清空定时任务调度日志 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "调度日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + jobLogService.cleanJobLog(); + return AjaxResult.success(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java index 126be47f3..8e0048bec 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java @@ -1,172 +1,172 @@ -package com.ruoyi.project.monitor.domain; - -import java.io.Serializable; -import java.util.Date; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.job.CronUtils; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; - -/** - * 定时任务调度表 sys_job - * - * @author ruoyi - */ -public class SysJob extends BaseEntity implements Serializable -{ - private static final long serialVersionUID = 1L; - - /** 任务ID */ - @Excel(name = "任务序号", cellType = ColumnType.NUMERIC) - private Long jobId; - - /** 任务名称 */ - @Excel(name = "任务名称") - private String jobName; - - /** 任务组名 */ - @Excel(name = "任务组名") - private String jobGroup; - - /** 调用目标字符串 */ - @Excel(name = "调用目标字符串") - private String invokeTarget; - - /** cron执行表达式 */ - @Excel(name = "执行表达式 ") - private String cronExpression; - - /** cron计划策略 */ - @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行") - private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT; - - /** 是否并发执行(0允许 1禁止) */ - @Excel(name = "并发执行", readConverterExp = "0=允许,1=禁止") - private String concurrent; - - /** 任务状态(0正常 1暂停) */ - @Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停") - private String status; - - public Long getJobId() - { - return jobId; - } - - public void setJobId(Long jobId) - { - this.jobId = jobId; - } - - @NotBlank(message = "任务名称不能为空") - @Size(min = 0, max = 64, message = "任务名称不能超过64个字符") - public String getJobName() - { - return jobName; - } - - public void setJobName(String jobName) - { - this.jobName = jobName; - } - - public String getJobGroup() - { - return jobGroup; - } - - public void setJobGroup(String jobGroup) - { - this.jobGroup = jobGroup; - } - - @NotBlank(message = "调用目标字符串不能为空") - @Size(min = 0, max = 1000, message = "调用目标字符串长度不能超过500个字符") - public String getInvokeTarget() - { - return invokeTarget; - } - - public void setInvokeTarget(String invokeTarget) - { - this.invokeTarget = invokeTarget; - } - - @NotBlank(message = "Cron执行表达式不能为空") - @Size(min = 0, max = 255, message = "Cron执行表达式不能超过255个字符") - public String getCronExpression() - { - return cronExpression; - } - - public void setCronExpression(String cronExpression) - { - this.cronExpression = cronExpression; - } - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - public Date getNextValidTime() - { - if (StringUtils.isNotEmpty(cronExpression)) - { - return CronUtils.getNextExecution(cronExpression); - } - return null; - } - - public String getMisfirePolicy() - { - return misfirePolicy; - } - - public void setMisfirePolicy(String misfirePolicy) - { - this.misfirePolicy = misfirePolicy; - } - - public String getConcurrent() - { - return concurrent; - } - - public void setConcurrent(String concurrent) - { - this.concurrent = concurrent; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("jobId", getJobId()) - .append("jobName", getJobName()) - .append("jobGroup", getJobGroup()) - .append("cronExpression", getCronExpression()) - .append("nextValidTime", getNextValidTime()) - .append("misfirePolicy", getMisfirePolicy()) - .append("concurrent", getConcurrent()) - .append("status", getStatus()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} \ No newline at end of file +package com.ruoyi.quartz.domain; + +import java.io.Serializable; +import java.util.Date; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.quartz.util.CronUtils; + +/** + * 定时任务调度表 sys_job + * + * @author ruoyi + */ +public class SysJob extends BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 任务ID */ + @Excel(name = "任务序号", cellType = ColumnType.NUMERIC) + private Long jobId; + + /** 任务名称 */ + @Excel(name = "任务名称") + private String jobName; + + /** 任务组名 */ + @Excel(name = "任务组名") + private String jobGroup; + + /** 调用目标字符串 */ + @Excel(name = "调用目标字符串") + private String invokeTarget; + + /** cron执行表达式 */ + @Excel(name = "执行表达式 ") + private String cronExpression; + + /** cron计划策略 */ + @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行") + private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT; + + /** 是否并发执行(0允许 1禁止) */ + @Excel(name = "并发执行", readConverterExp = "0=允许,1=禁止") + private String concurrent; + + /** 任务状态(0正常 1暂停) */ + @Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停") + private String status; + + public Long getJobId() + { + return jobId; + } + + public void setJobId(Long jobId) + { + this.jobId = jobId; + } + + @NotBlank(message = "任务名称不能为空") + @Size(min = 0, max = 64, message = "任务名称不能超过64个字符") + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + @NotBlank(message = "调用目标字符串不能为空") + @Size(min = 0, max = 1000, message = "调用目标字符串长度不能超过500个字符") + public String getInvokeTarget() + { + return invokeTarget; + } + + public void setInvokeTarget(String invokeTarget) + { + this.invokeTarget = invokeTarget; + } + + @NotBlank(message = "Cron执行表达式不能为空") + @Size(min = 0, max = 255, message = "Cron执行表达式不能超过255个字符") + public String getCronExpression() + { + return cronExpression; + } + + public void setCronExpression(String cronExpression) + { + this.cronExpression = cronExpression; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getNextValidTime() + { + if (StringUtils.isNotEmpty(cronExpression)) + { + return CronUtils.getNextExecution(cronExpression); + } + return null; + } + + public String getMisfirePolicy() + { + return misfirePolicy; + } + + public void setMisfirePolicy(String misfirePolicy) + { + this.misfirePolicy = misfirePolicy; + } + + public String getConcurrent() + { + return concurrent; + } + + public void setConcurrent(String concurrent) + { + this.concurrent = concurrent; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobId", getJobId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("cronExpression", getCronExpression()) + .append("nextValidTime", getNextValidTime()) + .append("misfirePolicy", getMisfirePolicy()) + .append("concurrent", getConcurrent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysJobLog.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysJobLog.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java index c7a3cd229..63c4cd69d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysJobLog.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java @@ -1,155 +1,155 @@ -package com.ruoyi.project.monitor.domain; - -import java.util.Date; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.web.domain.BaseEntity; - -/** - * 定时任务调度日志表 sys_job_log - * - * @author ruoyi - */ -public class SysJobLog extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** ID */ - @Excel(name = "日志序号") - private Long jobLogId; - - /** 任务名称 */ - @Excel(name = "任务名称") - private String jobName; - - /** 任务组名 */ - @Excel(name = "任务组名") - private String jobGroup; - - /** 调用目标字符串 */ - @Excel(name = "调用目标字符串") - private String invokeTarget; - - /** 日志信息 */ - @Excel(name = "日志信息") - private String jobMessage; - - /** 执行状态(0正常 1失败) */ - @Excel(name = "执行状态", readConverterExp = "0=正常,1=失败") - private String status; - - /** 异常信息 */ - @Excel(name = "异常信息") - private String exceptionInfo; - - /** 开始时间 */ - private Date startTime; - - /** 停止时间 */ - private Date stopTime; - - public Long getJobLogId() - { - return jobLogId; - } - - public void setJobLogId(Long jobLogId) - { - this.jobLogId = jobLogId; - } - - public String getJobName() - { - return jobName; - } - - public void setJobName(String jobName) - { - this.jobName = jobName; - } - - public String getJobGroup() - { - return jobGroup; - } - - public void setJobGroup(String jobGroup) - { - this.jobGroup = jobGroup; - } - - public String getInvokeTarget() - { - return invokeTarget; - } - - public void setInvokeTarget(String invokeTarget) - { - this.invokeTarget = invokeTarget; - } - - public String getJobMessage() - { - return jobMessage; - } - - public void setJobMessage(String jobMessage) - { - this.jobMessage = jobMessage; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - public String getExceptionInfo() - { - return exceptionInfo; - } - - public void setExceptionInfo(String exceptionInfo) - { - this.exceptionInfo = exceptionInfo; - } - - public Date getStartTime() - { - return startTime; - } - - public void setStartTime(Date startTime) - { - this.startTime = startTime; - } - - public Date getStopTime() - { - return stopTime; - } - - public void setStopTime(Date stopTime) - { - this.stopTime = stopTime; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("jobLogId", getJobLogId()) - .append("jobName", getJobName()) - .append("jobGroup", getJobGroup()) - .append("jobMessage", getJobMessage()) - .append("status", getStatus()) - .append("exceptionInfo", getExceptionInfo()) - .append("startTime", getStartTime()) - .append("stopTime", getStopTime()) - .toString(); - } -} +package com.ruoyi.quartz.domain; + +import java.util.Date; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 定时任务调度日志表 sys_job_log + * + * @author ruoyi + */ +public class SysJobLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "日志序号") + private Long jobLogId; + + /** 任务名称 */ + @Excel(name = "任务名称") + private String jobName; + + /** 任务组名 */ + @Excel(name = "任务组名") + private String jobGroup; + + /** 调用目标字符串 */ + @Excel(name = "调用目标字符串") + private String invokeTarget; + + /** 日志信息 */ + @Excel(name = "日志信息") + private String jobMessage; + + /** 执行状态(0正常 1失败) */ + @Excel(name = "执行状态", readConverterExp = "0=正常,1=失败") + private String status; + + /** 异常信息 */ + @Excel(name = "异常信息") + private String exceptionInfo; + + /** 开始时间 */ + private Date startTime; + + /** 停止时间 */ + private Date stopTime; + + public Long getJobLogId() + { + return jobLogId; + } + + public void setJobLogId(Long jobLogId) + { + this.jobLogId = jobLogId; + } + + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + public String getInvokeTarget() + { + return invokeTarget; + } + + public void setInvokeTarget(String invokeTarget) + { + this.invokeTarget = invokeTarget; + } + + public String getJobMessage() + { + return jobMessage; + } + + public void setJobMessage(String jobMessage) + { + this.jobMessage = jobMessage; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getExceptionInfo() + { + return exceptionInfo; + } + + public void setExceptionInfo(String exceptionInfo) + { + this.exceptionInfo = exceptionInfo; + } + + public Date getStartTime() + { + return startTime; + } + + public void setStartTime(Date startTime) + { + this.startTime = startTime; + } + + public Date getStopTime() + { + return stopTime; + } + + public void setStopTime(Date stopTime) + { + this.stopTime = stopTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobLogId", getJobLogId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("jobMessage", getJobMessage()) + .append("status", getStatus()) + .append("exceptionInfo", getExceptionInfo()) + .append("startTime", getStartTime()) + .append("stopTime", getStopTime()) + .toString(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysJobLogMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysJobLogMapper.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java index 39137dd85..ed01ef72e 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysJobLogMapper.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java @@ -1,64 +1,64 @@ -package com.ruoyi.project.monitor.mapper; - -import java.util.List; -import com.ruoyi.project.monitor.domain.SysJobLog; - -/** - * 调度任务日志信息 数据层 - * - * @author ruoyi - */ -public interface SysJobLogMapper -{ - /** - * 获取quartz调度器日志的计划任务 - * - * @param jobLog 调度日志信息 - * @return 调度任务日志集合 - */ - public List selectJobLogList(SysJobLog jobLog); - - /** - * 查询所有调度任务日志 - * - * @return 调度任务日志列表 - */ - public List selectJobLogAll(); - - /** - * 通过调度任务日志ID查询调度信息 - * - * @param jobLogId 调度任务日志ID - * @return 调度任务日志对象信息 - */ - public SysJobLog selectJobLogById(Long jobLogId); - - /** - * 新增任务日志 - * - * @param jobLog 调度日志信息 - * @return 结果 - */ - public int insertJobLog(SysJobLog jobLog); - - /** - * 批量删除调度日志信息 - * - * @param logIds 需要删除的数据ID - * @return 结果 - */ - public int deleteJobLogByIds(Long[] logIds); - - /** - * 删除任务日志 - * - * @param jobId 调度日志ID - * @return 结果 - */ - public int deleteJobLogById(Long jobId); - - /** - * 清空任务日志 - */ - public void cleanJobLog(); -} +package com.ruoyi.quartz.mapper; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJobLog; + +/** + * 调度任务日志信息 数据层 + * + * @author ruoyi + */ +public interface SysJobLogMapper +{ + /** + * 获取quartz调度器日志的计划任务 + * + * @param jobLog 调度日志信息 + * @return 调度任务日志集合 + */ + public List selectJobLogList(SysJobLog jobLog); + + /** + * 查询所有调度任务日志 + * + * @return 调度任务日志列表 + */ + public List selectJobLogAll(); + + /** + * 通过调度任务日志ID查询调度信息 + * + * @param jobLogId 调度任务日志ID + * @return 调度任务日志对象信息 + */ + public SysJobLog selectJobLogById(Long jobLogId); + + /** + * 新增任务日志 + * + * @param jobLog 调度日志信息 + * @return 结果 + */ + public int insertJobLog(SysJobLog jobLog); + + /** + * 批量删除调度日志信息 + * + * @param logIds 需要删除的数据ID + * @return 结果 + */ + public int deleteJobLogByIds(Long[] logIds); + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + * @return 结果 + */ + public int deleteJobLogById(Long jobId); + + /** + * 清空任务日志 + */ + public void cleanJobLog(); +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysJobMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysJobMapper.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java index ab1146188..f481ea12e 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysJobMapper.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java @@ -1,67 +1,67 @@ -package com.ruoyi.project.monitor.mapper; - -import java.util.List; -import com.ruoyi.project.monitor.domain.SysJob; - -/** - * 调度任务信息 数据层 - * - * @author ruoyi - */ -public interface SysJobMapper -{ - /** - * 查询调度任务日志集合 - * - * @param job 调度信息 - * @return 操作日志集合 - */ - public List selectJobList(SysJob job); - - /** - * 查询所有调度任务 - * - * @return 调度任务列表 - */ - public List selectJobAll(); - - /** - * 通过调度ID查询调度任务信息 - * - * @param jobId 调度ID - * @return 角色对象信息 - */ - public SysJob selectJobById(Long jobId); - - /** - * 通过调度ID删除调度任务信息 - * - * @param jobId 调度ID - * @return 结果 - */ - public int deleteJobById(Long jobId); - - /** - * 批量删除调度任务信息 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - public int deleteJobByIds(Long[] ids); - - /** - * 修改调度任务信息 - * - * @param job 调度任务信息 - * @return 结果 - */ - public int updateJob(SysJob job); - - /** - * 新增调度任务信息 - * - * @param job 调度任务信息 - * @return 结果 - */ - public int insertJob(SysJob job); -} +package com.ruoyi.quartz.mapper; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 调度任务信息 数据层 + * + * @author ruoyi + */ +public interface SysJobMapper +{ + /** + * 查询调度任务日志集合 + * + * @param job 调度信息 + * @return 操作日志集合 + */ + public List selectJobList(SysJob job); + + /** + * 查询所有调度任务 + * + * @return 调度任务列表 + */ + public List selectJobAll(); + + /** + * 通过调度ID查询调度任务信息 + * + * @param jobId 调度ID + * @return 角色对象信息 + */ + public SysJob selectJobById(Long jobId); + + /** + * 通过调度ID删除调度任务信息 + * + * @param jobId 调度ID + * @return 结果 + */ + public int deleteJobById(Long jobId); + + /** + * 批量删除调度任务信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteJobByIds(Long[] ids); + + /** + * 修改调度任务信息 + * + * @param job 调度任务信息 + * @return 结果 + */ + public int updateJob(SysJob job); + + /** + * 新增调度任务信息 + * + * @param job 调度任务信息 + * @return 结果 + */ + public int insertJob(SysJob job); +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysJobLogService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysJobLogService.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java index 85561e766..5291a63ac 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysJobLogService.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java @@ -1,56 +1,56 @@ -package com.ruoyi.project.monitor.service; - -import java.util.List; -import com.ruoyi.project.monitor.domain.SysJobLog; - -/** - * 定时任务调度日志信息信息 服务层 - * - * @author ruoyi - */ -public interface ISysJobLogService -{ - /** - * 获取quartz调度器日志的计划任务 - * - * @param jobLog 调度日志信息 - * @return 调度任务日志集合 - */ - public List selectJobLogList(SysJobLog jobLog); - - /** - * 通过调度任务日志ID查询调度信息 - * - * @param jobLogId 调度任务日志ID - * @return 调度任务日志对象信息 - */ - public SysJobLog selectJobLogById(Long jobLogId); - - /** - * 新增任务日志 - * - * @param jobLog 调度日志信息 - */ - public void addJobLog(SysJobLog jobLog); - - /** - * 批量删除调度日志信息 - * - * @param logIds 需要删除的日志ID - * @return 结果 - */ - public int deleteJobLogByIds(Long[] logIds); - - /** - * 删除任务日志 - * - * @param jobId 调度日志ID - * @return 结果 - */ - public int deleteJobLogById(Long jobId); - - /** - * 清空任务日志 - */ - public void cleanJobLog(); -} +package com.ruoyi.quartz.service; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJobLog; + +/** + * 定时任务调度日志信息信息 服务层 + * + * @author ruoyi + */ +public interface ISysJobLogService +{ + /** + * 获取quartz调度器日志的计划任务 + * + * @param jobLog 调度日志信息 + * @return 调度任务日志集合 + */ + public List selectJobLogList(SysJobLog jobLog); + + /** + * 通过调度任务日志ID查询调度信息 + * + * @param jobLogId 调度任务日志ID + * @return 调度任务日志对象信息 + */ + public SysJobLog selectJobLogById(Long jobLogId); + + /** + * 新增任务日志 + * + * @param jobLog 调度日志信息 + */ + public void addJobLog(SysJobLog jobLog); + + /** + * 批量删除调度日志信息 + * + * @param logIds 需要删除的日志ID + * @return 结果 + */ + public int deleteJobLogByIds(Long[] logIds); + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + * @return 结果 + */ + public int deleteJobLogById(Long jobId); + + /** + * 清空任务日志 + */ + public void cleanJobLog(); +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysJobService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysJobService.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java index f7da1ac62..53f098956 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysJobService.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java @@ -1,102 +1,102 @@ -package com.ruoyi.project.monitor.service; - -import java.util.List; -import org.quartz.SchedulerException; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.project.monitor.domain.SysJob; - -/** - * 定时任务调度信息信息 服务层 - * - * @author ruoyi - */ -public interface ISysJobService -{ - /** - * 获取quartz调度器的计划任务 - * - * @param job 调度信息 - * @return 调度任务集合 - */ - public List selectJobList(SysJob job); - - /** - * 通过调度任务ID查询调度信息 - * - * @param jobId 调度任务ID - * @return 调度任务对象信息 - */ - public SysJob selectJobById(Long jobId); - - /** - * 暂停任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int pauseJob(SysJob job) throws SchedulerException; - - /** - * 恢复任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int resumeJob(SysJob job) throws SchedulerException; - - /** - * 删除任务后,所对应的trigger也将被删除 - * - * @param job 调度信息 - * @return 结果 - */ - public int deleteJob(SysJob job) throws SchedulerException; - - /** - * 批量删除调度信息 - * - * @param jobIds 需要删除的任务ID - * @return 结果 - */ - public void deleteJobByIds(Long[] jobIds) throws SchedulerException; - - /** - * 任务调度状态修改 - * - * @param job 调度信息 - * @return 结果 - */ - public int changeStatus(SysJob job) throws SchedulerException; - - /** - * 立即运行任务 - * - * @param job 调度信息 - * @return 结果 - */ - public void run(SysJob job) throws SchedulerException; - - /** - * 新增任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int insertJob(SysJob job) throws SchedulerException, TaskException; - - /** - * 更新任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int updateJob(SysJob job) throws SchedulerException, TaskException; - - /** - * 校验cron表达式是否有效 - * - * @param cronExpression 表达式 - * @return 结果 - */ - public boolean checkCronExpressionIsValid(String cronExpression); -} \ No newline at end of file +package com.ruoyi.quartz.service; + +import java.util.List; +import org.quartz.SchedulerException; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务调度信息信息 服务层 + * + * @author ruoyi + */ +public interface ISysJobService +{ + /** + * 获取quartz调度器的计划任务 + * + * @param job 调度信息 + * @return 调度任务集合 + */ + public List selectJobList(SysJob job); + + /** + * 通过调度任务ID查询调度信息 + * + * @param jobId 调度任务ID + * @return 调度任务对象信息 + */ + public SysJob selectJobById(Long jobId); + + /** + * 暂停任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int pauseJob(SysJob job) throws SchedulerException; + + /** + * 恢复任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int resumeJob(SysJob job) throws SchedulerException; + + /** + * 删除任务后,所对应的trigger也将被删除 + * + * @param job 调度信息 + * @return 结果 + */ + public int deleteJob(SysJob job) throws SchedulerException; + + /** + * 批量删除调度信息 + * + * @param jobIds 需要删除的任务ID + * @return 结果 + */ + public void deleteJobByIds(Long[] jobIds) throws SchedulerException; + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + * @return 结果 + */ + public int changeStatus(SysJob job) throws SchedulerException; + + /** + * 立即运行任务 + * + * @param job 调度信息 + * @return 结果 + */ + public void run(SysJob job) throws SchedulerException; + + /** + * 新增任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int insertJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 更新任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int updateJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 校验cron表达式是否有效 + * + * @param cronExpression 表达式 + * @return 结果 + */ + public boolean checkCronExpressionIsValid(String cronExpression); +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java index 991cf813f..f68a5482b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java @@ -1,87 +1,87 @@ -package com.ruoyi.project.monitor.service.impl; - -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.project.monitor.domain.SysJobLog; -import com.ruoyi.project.monitor.mapper.SysJobLogMapper; -import com.ruoyi.project.monitor.service.ISysJobLogService; - -/** - * 定时任务调度日志信息 服务层 - * - * @author ruoyi - */ -@Service -public class SysJobLogServiceImpl implements ISysJobLogService -{ - @Autowired - private SysJobLogMapper jobLogMapper; - - /** - * 获取quartz调度器日志的计划任务 - * - * @param jobLog 调度日志信息 - * @return 调度任务日志集合 - */ - @Override - public List selectJobLogList(SysJobLog jobLog) - { - return jobLogMapper.selectJobLogList(jobLog); - } - - /** - * 通过调度任务日志ID查询调度信息 - * - * @param jobLogId 调度任务日志ID - * @return 调度任务日志对象信息 - */ - @Override - public SysJobLog selectJobLogById(Long jobLogId) - { - return jobLogMapper.selectJobLogById(jobLogId); - } - - /** - * 新增任务日志 - * - * @param jobLog 调度日志信息 - */ - @Override - public void addJobLog(SysJobLog jobLog) - { - jobLogMapper.insertJobLog(jobLog); - } - - /** - * 批量删除调度日志信息 - * - * @param logIds 需要删除的数据ID - * @return 结果 - */ - @Override - public int deleteJobLogByIds(Long[] logIds) - { - return jobLogMapper.deleteJobLogByIds(logIds); - } - - /** - * 删除任务日志 - * - * @param jobId 调度日志ID - */ - @Override - public int deleteJobLogById(Long jobId) - { - return jobLogMapper.deleteJobLogById(jobId); - } - - /** - * 清空任务日志 - */ - @Override - public void cleanJobLog() - { - jobLogMapper.cleanJobLog(); - } -} +package com.ruoyi.quartz.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.mapper.SysJobLogMapper; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 定时任务调度日志信息 服务层 + * + * @author ruoyi + */ +@Service +public class SysJobLogServiceImpl implements ISysJobLogService +{ + @Autowired + private SysJobLogMapper jobLogMapper; + + /** + * 获取quartz调度器日志的计划任务 + * + * @param jobLog 调度日志信息 + * @return 调度任务日志集合 + */ + @Override + public List selectJobLogList(SysJobLog jobLog) + { + return jobLogMapper.selectJobLogList(jobLog); + } + + /** + * 通过调度任务日志ID查询调度信息 + * + * @param jobLogId 调度任务日志ID + * @return 调度任务日志对象信息 + */ + @Override + public SysJobLog selectJobLogById(Long jobLogId) + { + return jobLogMapper.selectJobLogById(jobLogId); + } + + /** + * 新增任务日志 + * + * @param jobLog 调度日志信息 + */ + @Override + public void addJobLog(SysJobLog jobLog) + { + jobLogMapper.insertJobLog(jobLog); + } + + /** + * 批量删除调度日志信息 + * + * @param logIds 需要删除的数据ID + * @return 结果 + */ + @Override + public int deleteJobLogByIds(Long[] logIds) + { + return jobLogMapper.deleteJobLogByIds(logIds); + } + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + */ + @Override + public int deleteJobLogById(Long jobId) + { + return jobLogMapper.deleteJobLogById(jobId); + } + + /** + * 清空任务日志 + */ + @Override + public void cleanJobLog() + { + jobLogMapper.cleanJobLog(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java index c53cd3c91..d7bc6c984 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java @@ -1,254 +1,254 @@ -package com.ruoyi.project.monitor.service.impl; - -import java.util.List; -import javax.annotation.PostConstruct; -import org.quartz.JobDataMap; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.common.utils.job.CronUtils; -import com.ruoyi.common.utils.job.ScheduleUtils; -import com.ruoyi.project.monitor.domain.SysJob; -import com.ruoyi.project.monitor.mapper.SysJobMapper; -import com.ruoyi.project.monitor.service.ISysJobService; - -/** - * 定时任务调度信息 服务层 - * - * @author ruoyi - */ -@Service -public class SysJobServiceImpl implements ISysJobService -{ - @Autowired - private Scheduler scheduler; - - @Autowired - private SysJobMapper jobMapper; - - /** - * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) - */ - @PostConstruct - public void init() throws SchedulerException, TaskException - { - scheduler.clear(); - List jobList = jobMapper.selectJobAll(); - for (SysJob job : jobList) - { - ScheduleUtils.createScheduleJob(scheduler, job); - } - } - - /** - * 获取quartz调度器的计划任务列表 - * - * @param job 调度信息 - * @return - */ - @Override - public List selectJobList(SysJob job) - { - return jobMapper.selectJobList(job); - } - - /** - * 通过调度任务ID查询调度信息 - * - * @param jobId 调度任务ID - * @return 调度任务对象信息 - */ - @Override - public SysJob selectJobById(Long jobId) - { - return jobMapper.selectJobById(jobId); - } - - /** - * 暂停任务 - * - * @param job 调度信息 - */ - @Override - @Transactional - public int pauseJob(SysJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); - int rows = jobMapper.updateJob(job); - if (rows > 0) - { - scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - return rows; - } - - /** - * 恢复任务 - * - * @param job 调度信息 - */ - @Override - @Transactional - public int resumeJob(SysJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); - int rows = jobMapper.updateJob(job); - if (rows > 0) - { - scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - return rows; - } - - /** - * 删除任务后,所对应的trigger也将被删除 - * - * @param job 调度信息 - */ - @Override - @Transactional - public int deleteJob(SysJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - int rows = jobMapper.deleteJobById(jobId); - if (rows > 0) - { - scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - return rows; - } - - /** - * 批量删除调度信息 - * - * @param jobIds 需要删除的任务ID - * @return 结果 - */ - @Override - @Transactional - public void deleteJobByIds(Long[] jobIds) throws SchedulerException - { - for (Long jobId : jobIds) - { - SysJob job = jobMapper.selectJobById(jobId); - deleteJob(job); - } - } - - /** - * 任务调度状态修改 - * - * @param job 调度信息 - */ - @Override - @Transactional - public int changeStatus(SysJob job) throws SchedulerException - { - int rows = 0; - String status = job.getStatus(); - if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) - { - rows = resumeJob(job); - } - else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) - { - rows = pauseJob(job); - } - return rows; - } - - /** - * 立即运行任务 - * - * @param job 调度信息 - */ - @Override - @Transactional - public void run(SysJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - SysJob properties = selectJobById(job.getJobId()); - // 参数 - JobDataMap dataMap = new JobDataMap(); - dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); - scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap); - } - - /** - * 新增任务 - * - * @param job 调度信息 调度信息 - */ - @Override - @Transactional - public int insertJob(SysJob job) throws SchedulerException, TaskException - { - job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); - int rows = jobMapper.insertJob(job); - if (rows > 0) - { - ScheduleUtils.createScheduleJob(scheduler, job); - } - return rows; - } - - /** - * 更新任务的时间表达式 - * - * @param job 调度信息 - */ - @Override - @Transactional - public int updateJob(SysJob job) throws SchedulerException, TaskException - { - SysJob properties = selectJobById(job.getJobId()); - int rows = jobMapper.updateJob(job); - if (rows > 0) - { - updateSchedulerJob(job, properties.getJobGroup()); - } - return rows; - } - - /** - * 更新任务 - * - * @param job 任务对象 - * @param jobGroup 任务组名 - */ - public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException - { - Long jobId = job.getJobId(); - // 判断是否存在 - JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); - if (scheduler.checkExists(jobKey)) - { - // 防止创建时存在数据问题 先移除,然后在执行创建操作 - scheduler.deleteJob(jobKey); - } - ScheduleUtils.createScheduleJob(scheduler, job); - } - - /** - * 校验cron表达式是否有效 - * - * @param cronExpression 表达式 - * @return 结果 - */ - @Override - public boolean checkCronExpressionIsValid(String cronExpression) - { - return CronUtils.isValid(cronExpression); - } -} \ No newline at end of file +package com.ruoyi.quartz.service.impl; + +import java.util.List; +import javax.annotation.PostConstruct; +import org.quartz.JobDataMap; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.mapper.SysJobMapper; +import com.ruoyi.quartz.service.ISysJobService; +import com.ruoyi.quartz.util.CronUtils; +import com.ruoyi.quartz.util.ScheduleUtils; + +/** + * 定时任务调度信息 服务层 + * + * @author ruoyi + */ +@Service +public class SysJobServiceImpl implements ISysJobService +{ + @Autowired + private Scheduler scheduler; + + @Autowired + private SysJobMapper jobMapper; + + /** + * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) + */ + @PostConstruct + public void init() throws SchedulerException, TaskException + { + scheduler.clear(); + List jobList = jobMapper.selectJobAll(); + for (SysJob job : jobList) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + } + + /** + * 获取quartz调度器的计划任务列表 + * + * @param job 调度信息 + * @return + */ + @Override + public List selectJobList(SysJob job) + { + return jobMapper.selectJobList(job); + } + + /** + * 通过调度任务ID查询调度信息 + * + * @param jobId 调度任务ID + * @return 调度任务对象信息 + */ + @Override + public SysJob selectJobById(Long jobId) + { + return jobMapper.selectJobById(jobId); + } + + /** + * 暂停任务 + * + * @param job 调度信息 + */ + @Override + @Transactional + public int pauseJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 恢复任务 + * + * @param job 调度信息 + */ + @Override + @Transactional + public int resumeJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 删除任务后,所对应的trigger也将被删除 + * + * @param job 调度信息 + */ + @Override + @Transactional + public int deleteJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + int rows = jobMapper.deleteJobById(jobId); + if (rows > 0) + { + scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 批量删除调度信息 + * + * @param jobIds 需要删除的任务ID + * @return 结果 + */ + @Override + @Transactional + public void deleteJobByIds(Long[] jobIds) throws SchedulerException + { + for (Long jobId : jobIds) + { + SysJob job = jobMapper.selectJobById(jobId); + deleteJob(job); + } + } + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + */ + @Override + @Transactional + public int changeStatus(SysJob job) throws SchedulerException + { + int rows = 0; + String status = job.getStatus(); + if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) + { + rows = resumeJob(job); + } + else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) + { + rows = pauseJob(job); + } + return rows; + } + + /** + * 立即运行任务 + * + * @param job 调度信息 + */ + @Override + @Transactional + public void run(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + SysJob properties = selectJobById(job.getJobId()); + // 参数 + JobDataMap dataMap = new JobDataMap(); + dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); + scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap); + } + + /** + * 新增任务 + * + * @param job 调度信息 调度信息 + */ + @Override + @Transactional + public int insertJob(SysJob job) throws SchedulerException, TaskException + { + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.insertJob(job); + if (rows > 0) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + return rows; + } + + /** + * 更新任务的时间表达式 + * + * @param job 调度信息 + */ + @Override + @Transactional + public int updateJob(SysJob job) throws SchedulerException, TaskException + { + SysJob properties = selectJobById(job.getJobId()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + updateSchedulerJob(job, properties.getJobGroup()); + } + return rows; + } + + /** + * 更新任务 + * + * @param job 任务对象 + * @param jobGroup 任务组名 + */ + public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException + { + Long jobId = job.getJobId(); + // 判断是否存在 + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(jobKey); + } + ScheduleUtils.createScheduleJob(scheduler, job); + } + + /** + * 校验cron表达式是否有效 + * + * @param cronExpression 表达式 + * @return 结果 + */ + @Override + public boolean checkCronExpressionIsValid(String cronExpression) + { + return CronUtils.isValid(cronExpression); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/framework/task/RyTask.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java index eb7f5b9a4..25d1ddd02 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/task/RyTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java @@ -1,28 +1,28 @@ -package com.ruoyi.framework.task; - -import org.springframework.stereotype.Component; -import com.ruoyi.common.utils.StringUtils; - -/** - * 定时任务调度测试 - * - * @author ruoyi - */ -@Component("ryTask") -public class RyTask -{ - public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) - { - System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); - } - - public void ryParams(String params) - { - System.out.println("执行有参方法:" + params); - } - - public void ryNoParams() - { - System.out.println("执行无参方法"); - } -} +package com.ruoyi.quartz.task; + +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.StringUtils; + +/** + * 定时任务调度测试 + * + * @author ruoyi + */ +@Component("ryTask") +public class RyTask +{ + public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) + { + System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); + } + + public void ryParams(String params) + { + System.out.println("执行有参方法:" + params); + } + + public void ryNoParams() + { + System.out.println("执行无参方法"); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/job/AbstractQuartzJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/common/utils/job/AbstractQuartzJob.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java index ec7e62216..a0aadb689 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/job/AbstractQuartzJob.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java @@ -1,107 +1,107 @@ -package com.ruoyi.common.utils.job; - -import java.util.Date; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.utils.ExceptionUtil; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.bean.BeanUtils; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.project.monitor.domain.SysJob; -import com.ruoyi.project.monitor.domain.SysJobLog; -import com.ruoyi.project.monitor.service.ISysJobLogService; - -/** - * 抽象quartz调用 - * - * @author ruoyi - */ -public abstract class AbstractQuartzJob implements Job -{ - private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class); - - /** - * 线程本地变量 - */ - private static ThreadLocal threadLocal = new ThreadLocal<>(); - - @Override - public void execute(JobExecutionContext context) throws JobExecutionException - { - SysJob sysJob = new SysJob(); - BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); - try - { - before(context, sysJob); - if (sysJob != null) - { - doExecute(context, sysJob); - } - after(context, sysJob, null); - } - catch (Exception e) - { - log.error("任务执行异常 - :", e); - after(context, sysJob, e); - } - } - - /** - * 执行前 - * - * @param context 工作执行上下文对象 - * @param sysJob 系统计划任务 - */ - protected void before(JobExecutionContext context, SysJob sysJob) - { - threadLocal.set(new Date()); - } - - /** - * 执行后 - * - * @param context 工作执行上下文对象 - * @param sysScheduleJob 系统计划任务 - */ - protected void after(JobExecutionContext context, SysJob sysJob, Exception e) - { - Date startTime = threadLocal.get(); - threadLocal.remove(); - - final SysJobLog sysJobLog = new SysJobLog(); - sysJobLog.setJobName(sysJob.getJobName()); - sysJobLog.setJobGroup(sysJob.getJobGroup()); - sysJobLog.setInvokeTarget(sysJob.getInvokeTarget()); - sysJobLog.setStartTime(startTime); - sysJobLog.setStopTime(new Date()); - long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime(); - sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒"); - if (e != null) - { - sysJobLog.setStatus(Constants.FAIL); - String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000); - sysJobLog.setExceptionInfo(errorMsg); - } - else - { - sysJobLog.setStatus(Constants.SUCCESS); - } - - // 写入数据库当中 - SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog); - } - - /** - * 执行方法,由子类重载 - * - * @param context 工作执行上下文对象 - * @param sysJob 系统计划任务 - * @throws Exception 执行过程中的异常 - */ - protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception; -} +package com.ruoyi.quartz.util; + +import java.util.Date; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.utils.ExceptionUtil; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 抽象quartz调用 + * + * @author ruoyi + */ +public abstract class AbstractQuartzJob implements Job +{ + private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class); + + /** + * 线程本地变量 + */ + private static ThreadLocal threadLocal = new ThreadLocal<>(); + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException + { + SysJob sysJob = new SysJob(); + BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); + try + { + before(context, sysJob); + if (sysJob != null) + { + doExecute(context, sysJob); + } + after(context, sysJob, null); + } + catch (Exception e) + { + log.error("任务执行异常 - :", e); + after(context, sysJob, e); + } + } + + /** + * 执行前 + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + */ + protected void before(JobExecutionContext context, SysJob sysJob) + { + threadLocal.set(new Date()); + } + + /** + * 执行后 + * + * @param context 工作执行上下文对象 + * @param sysScheduleJob 系统计划任务 + */ + protected void after(JobExecutionContext context, SysJob sysJob, Exception e) + { + Date startTime = threadLocal.get(); + threadLocal.remove(); + + final SysJobLog sysJobLog = new SysJobLog(); + sysJobLog.setJobName(sysJob.getJobName()); + sysJobLog.setJobGroup(sysJob.getJobGroup()); + sysJobLog.setInvokeTarget(sysJob.getInvokeTarget()); + sysJobLog.setStartTime(startTime); + sysJobLog.setStopTime(new Date()); + long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime(); + sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒"); + if (e != null) + { + sysJobLog.setStatus(Constants.FAIL); + String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000); + sysJobLog.setExceptionInfo(errorMsg); + } + else + { + sysJobLog.setStatus(Constants.SUCCESS); + } + + // 写入数据库当中 + SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog); + } + + /** + * 执行方法,由子类重载 + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + * @throws Exception 执行过程中的异常 + */ + protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception; +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/job/CronUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java similarity index 94% rename from ruoyi/src/main/java/com/ruoyi/common/utils/job/CronUtils.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java index 0763a8d0f..6826787a6 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/job/CronUtils.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java @@ -1,63 +1,63 @@ -package com.ruoyi.common.utils.job; - -import java.text.ParseException; -import java.util.Date; -import org.quartz.CronExpression; - -/** - * cron表达式工具类 - * - * @author ruoyi - * - */ -public class CronUtils -{ - /** - * 返回一个布尔值代表一个给定的Cron表达式的有效性 - * - * @param cronExpression Cron表达式 - * @return boolean 表达式是否有效 - */ - public static boolean isValid(String cronExpression) - { - return CronExpression.isValidExpression(cronExpression); - } - - /** - * 返回一个字符串值,表示该消息无效Cron表达式给出有效性 - * - * @param cronExpression Cron表达式 - * @return String 无效时返回表达式错误描述,如果有效返回null - */ - public static String getInvalidMessage(String cronExpression) - { - try - { - new CronExpression(cronExpression); - return null; - } - catch (ParseException pe) - { - return pe.getMessage(); - } - } - - /** - * 返回下一个执行时间根据给定的Cron表达式 - * - * @param cronExpression Cron表达式 - * @return Date 下次Cron表达式执行时间 - */ - public static Date getNextExecution(String cronExpression) - { - try - { - CronExpression cron = new CronExpression(cronExpression); - return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis())); - } - catch (ParseException e) - { - throw new IllegalArgumentException(e.getMessage()); - } - } -} +package com.ruoyi.quartz.util; + +import java.text.ParseException; +import java.util.Date; +import org.quartz.CronExpression; + +/** + * cron表达式工具类 + * + * @author ruoyi + * + */ +public class CronUtils +{ + /** + * 返回一个布尔值代表一个给定的Cron表达式的有效性 + * + * @param cronExpression Cron表达式 + * @return boolean 表达式是否有效 + */ + public static boolean isValid(String cronExpression) + { + return CronExpression.isValidExpression(cronExpression); + } + + /** + * 返回一个字符串值,表示该消息无效Cron表达式给出有效性 + * + * @param cronExpression Cron表达式 + * @return String 无效时返回表达式错误描述,如果有效返回null + */ + public static String getInvalidMessage(String cronExpression) + { + try + { + new CronExpression(cronExpression); + return null; + } + catch (ParseException pe) + { + return pe.getMessage(); + } + } + + /** + * 返回下一个执行时间根据给定的Cron表达式 + * + * @param cronExpression Cron表达式 + * @return Date 下次Cron表达式执行时间 + */ + public static Date getNextExecution(String cronExpression) + { + try + { + CronExpression cron = new CronExpression(cronExpression); + return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis())); + } + catch (ParseException e) + { + throw new IllegalArgumentException(e.getMessage()); + } + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/job/JobInvokeUtil.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/utils/job/JobInvokeUtil.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java index 1670ee536..5519c672f 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/job/JobInvokeUtil.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java @@ -1,182 +1,182 @@ -package com.ruoyi.common.utils.job; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.LinkedList; -import java.util.List; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.project.monitor.domain.SysJob; - -/** - * 任务执行工具 - * - * @author ruoyi - */ -public class JobInvokeUtil -{ - /** - * 执行方法 - * - * @param sysJob 系统任务 - */ - public static void invokeMethod(SysJob sysJob) throws Exception - { - String invokeTarget = sysJob.getInvokeTarget(); - String beanName = getBeanName(invokeTarget); - String methodName = getMethodName(invokeTarget); - List methodParams = getMethodParams(invokeTarget); - - if (!isValidClassName(beanName)) - { - Object bean = SpringUtils.getBean(beanName); - invokeMethod(bean, methodName, methodParams); - } - else - { - Object bean = Class.forName(beanName).newInstance(); - invokeMethod(bean, methodName, methodParams); - } - } - - /** - * 调用任务方法 - * - * @param bean 目标对象 - * @param methodName 方法名称 - * @param methodParams 方法参数 - */ - private static void invokeMethod(Object bean, String methodName, List methodParams) - throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException - { - if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) - { - Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams)); - method.invoke(bean, getMethodParamsValue(methodParams)); - } - else - { - Method method = bean.getClass().getDeclaredMethod(methodName); - method.invoke(bean); - } - } - - /** - * 校验是否为为class包名 - * - * @param str 名称 - * @return true是 false否 - */ - public static boolean isValidClassName(String invokeTarget) - { - return StringUtils.countMatches(invokeTarget, ".") > 1; - } - - /** - * 获取bean名称 - * - * @param invokeTarget 目标字符串 - * @return bean名称 - */ - public static String getBeanName(String invokeTarget) - { - String beanName = StringUtils.substringBefore(invokeTarget, "("); - return StringUtils.substringBeforeLast(beanName, "."); - } - - /** - * 获取bean方法 - * - * @param invokeTarget 目标字符串 - * @return method方法 - */ - public static String getMethodName(String invokeTarget) - { - String methodName = StringUtils.substringBefore(invokeTarget, "("); - return StringUtils.substringAfterLast(methodName, "."); - } - - /** - * 获取method方法参数相关列表 - * - * @param invokeTarget 目标字符串 - * @return method方法相关参数列表 - */ - public static List getMethodParams(String invokeTarget) - { - String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); - if (StringUtils.isEmpty(methodStr)) - { - return null; - } - String[] methodParams = methodStr.split(","); - List classs = new LinkedList<>(); - for (int i = 0; i < methodParams.length; i++) - { - String str = StringUtils.trimToEmpty(methodParams[i]); - // String字符串类型,包含' - if (StringUtils.contains(str, "'")) - { - classs.add(new Object[] { StringUtils.replace(str, "'", ""), String.class }); - } - // boolean布尔类型,等于true或者false - else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false")) - { - classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); - } - // long长整形,包含L - else if (StringUtils.containsIgnoreCase(str, "L")) - { - classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class }); - } - // double浮点类型,包含D - else if (StringUtils.containsIgnoreCase(str, "D")) - { - classs.add(new Object[] { Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), Double.class }); - } - // 其他类型归类为整形 - else - { - classs.add(new Object[] { Integer.valueOf(str), Integer.class }); - } - } - return classs; - } - - /** - * 获取参数类型 - * - * @param methodParams 参数相关列表 - * @return 参数类型列表 - */ - public static Class[] getMethodParamsType(List methodParams) - { - Class[] classs = new Class[methodParams.size()]; - int index = 0; - for (Object[] os : methodParams) - { - classs[index] = (Class) os[1]; - index++; - } - return classs; - } - - /** - * 获取参数值 - * - * @param methodParams 参数相关列表 - * @return 参数值列表 - */ - public static Object[] getMethodParamsValue(List methodParams) - { - Object[] classs = new Object[methodParams.size()]; - int index = 0; - for (Object[] os : methodParams) - { - classs[index] = (Object) os[0]; - index++; - } - return classs; - } -} +package com.ruoyi.quartz.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 任务执行工具 + * + * @author ruoyi + */ +public class JobInvokeUtil +{ + /** + * 执行方法 + * + * @param sysJob 系统任务 + */ + public static void invokeMethod(SysJob sysJob) throws Exception + { + String invokeTarget = sysJob.getInvokeTarget(); + String beanName = getBeanName(invokeTarget); + String methodName = getMethodName(invokeTarget); + List methodParams = getMethodParams(invokeTarget); + + if (!isValidClassName(beanName)) + { + Object bean = SpringUtils.getBean(beanName); + invokeMethod(bean, methodName, methodParams); + } + else + { + Object bean = Class.forName(beanName).newInstance(); + invokeMethod(bean, methodName, methodParams); + } + } + + /** + * 调用任务方法 + * + * @param bean 目标对象 + * @param methodName 方法名称 + * @param methodParams 方法参数 + */ + private static void invokeMethod(Object bean, String methodName, List methodParams) + throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) + { + Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams)); + method.invoke(bean, getMethodParamsValue(methodParams)); + } + else + { + Method method = bean.getClass().getDeclaredMethod(methodName); + method.invoke(bean); + } + } + + /** + * 校验是否为为class包名 + * + * @param str 名称 + * @return true是 false否 + */ + public static boolean isValidClassName(String invokeTarget) + { + return StringUtils.countMatches(invokeTarget, ".") > 1; + } + + /** + * 获取bean名称 + * + * @param invokeTarget 目标字符串 + * @return bean名称 + */ + public static String getBeanName(String invokeTarget) + { + String beanName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringBeforeLast(beanName, "."); + } + + /** + * 获取bean方法 + * + * @param invokeTarget 目标字符串 + * @return method方法 + */ + public static String getMethodName(String invokeTarget) + { + String methodName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringAfterLast(methodName, "."); + } + + /** + * 获取method方法参数相关列表 + * + * @param invokeTarget 目标字符串 + * @return method方法相关参数列表 + */ + public static List getMethodParams(String invokeTarget) + { + String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); + if (StringUtils.isEmpty(methodStr)) + { + return null; + } + String[] methodParams = methodStr.split(","); + List classs = new LinkedList<>(); + for (int i = 0; i < methodParams.length; i++) + { + String str = StringUtils.trimToEmpty(methodParams[i]); + // String字符串类型,包含' + if (StringUtils.contains(str, "'")) + { + classs.add(new Object[] { StringUtils.replace(str, "'", ""), String.class }); + } + // boolean布尔类型,等于true或者false + else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false")) + { + classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); + } + // long长整形,包含L + else if (StringUtils.containsIgnoreCase(str, "L")) + { + classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class }); + } + // double浮点类型,包含D + else if (StringUtils.containsIgnoreCase(str, "D")) + { + classs.add(new Object[] { Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), Double.class }); + } + // 其他类型归类为整形 + else + { + classs.add(new Object[] { Integer.valueOf(str), Integer.class }); + } + } + return classs; + } + + /** + * 获取参数类型 + * + * @param methodParams 参数相关列表 + * @return 参数类型列表 + */ + public static Class[] getMethodParamsType(List methodParams) + { + Class[] classs = new Class[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Class) os[1]; + index++; + } + return classs; + } + + /** + * 获取参数值 + * + * @param methodParams 参数相关列表 + * @return 参数值列表 + */ + public static Object[] getMethodParamsValue(List methodParams) + { + Object[] classs = new Object[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Object) os[0]; + index++; + } + return classs; + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/job/QuartzDisallowConcurrentExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java similarity index 82% rename from ruoyi/src/main/java/com/ruoyi/common/utils/job/QuartzDisallowConcurrentExecution.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java index 709708839..96a6dcf8e 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/job/QuartzDisallowConcurrentExecution.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java @@ -1,21 +1,21 @@ -package com.ruoyi.common.utils.job; - -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import com.ruoyi.project.monitor.domain.SysJob; - -/** - * 定时任务处理(禁止并发执行) - * - * @author ruoyi - * - */ -@DisallowConcurrentExecution -public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob -{ - @Override - protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception - { - JobInvokeUtil.invokeMethod(sysJob); - } -} +package com.ruoyi.quartz.util; + +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务处理(禁止并发执行) + * + * @author ruoyi + * + */ +@DisallowConcurrentExecution +public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/job/QuartzJobExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java similarity index 79% rename from ruoyi/src/main/java/com/ruoyi/common/utils/job/QuartzJobExecution.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java index 55aa7e040..87a06bc13 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/job/QuartzJobExecution.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java @@ -1,19 +1,19 @@ -package com.ruoyi.common.utils.job; - -import org.quartz.JobExecutionContext; -import com.ruoyi.project.monitor.domain.SysJob; - -/** - * 定时任务处理(允许并发执行) - * - * @author ruoyi - * - */ -public class QuartzJobExecution extends AbstractQuartzJob -{ - @Override - protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception - { - JobInvokeUtil.invokeMethod(sysJob); - } -} +package com.ruoyi.quartz.util; + +import org.quartz.JobExecutionContext; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务处理(允许并发执行) + * + * @author ruoyi + * + */ +public class QuartzJobExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/job/ScheduleUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java similarity index 95% rename from ruoyi/src/main/java/com/ruoyi/common/utils/job/ScheduleUtils.java rename to ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java index 3e107c695..37fe72e04 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/utils/job/ScheduleUtils.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java @@ -1,113 +1,113 @@ -package com.ruoyi.common.utils.job; - -import org.quartz.CronScheduleBuilder; -import org.quartz.CronTrigger; -import org.quartz.Job; -import org.quartz.JobBuilder; -import org.quartz.JobDetail; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.TriggerBuilder; -import org.quartz.TriggerKey; -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.common.exception.job.TaskException.Code; -import com.ruoyi.project.monitor.domain.SysJob; - -/** - * 定时任务工具类 - * - * @author ruoyi - * - */ -public class ScheduleUtils -{ - /** - * 得到quartz任务类 - * - * @param sysJob 执行计划 - * @return 具体执行任务类 - */ - private static Class getQuartzJobClass(SysJob sysJob) - { - boolean isConcurrent = "0".equals(sysJob.getConcurrent()); - return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; - } - - /** - * 构建任务触发对象 - */ - public static TriggerKey getTriggerKey(Long jobId, String jobGroup) - { - return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); - } - - /** - * 构建任务键对象 - */ - public static JobKey getJobKey(Long jobId, String jobGroup) - { - return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); - } - - /** - * 创建定时任务 - */ - public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException - { - Class jobClass = getQuartzJobClass(job); - // 构建job信息 - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); - - // 表达式调度构建器 - CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); - cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); - - // 按新的cronExpression表达式构建一个新的trigger - CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) - .withSchedule(cronScheduleBuilder).build(); - - // 放入参数,运行时的方法可以获取 - jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); - - // 判断是否存在 - if (scheduler.checkExists(getJobKey(jobId, jobGroup))) - { - // 防止创建时存在数据问题 先移除,然后在执行创建操作 - scheduler.deleteJob(getJobKey(jobId, jobGroup)); - } - - scheduler.scheduleJob(jobDetail, trigger); - - // 暂停任务 - if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) - { - scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - } - - /** - * 设置定时任务策略 - */ - public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb) - throws TaskException - { - switch (job.getMisfirePolicy()) - { - case ScheduleConstants.MISFIRE_DEFAULT: - return cb; - case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: - return cb.withMisfireHandlingInstructionIgnoreMisfires(); - case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: - return cb.withMisfireHandlingInstructionFireAndProceed(); - case ScheduleConstants.MISFIRE_DO_NOTHING: - return cb.withMisfireHandlingInstructionDoNothing(); - default: - throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() - + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); - } - } -} \ No newline at end of file +package com.ruoyi.quartz.util; + +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.Job; +import org.quartz.JobBuilder; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.exception.job.TaskException.Code; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务工具类 + * + * @author ruoyi + * + */ +public class ScheduleUtils +{ + /** + * 得到quartz任务类 + * + * @param sysJob 执行计划 + * @return 具体执行任务类 + */ + private static Class getQuartzJobClass(SysJob sysJob) + { + boolean isConcurrent = "0".equals(sysJob.getConcurrent()); + return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; + } + + /** + * 构建任务触发对象 + */ + public static TriggerKey getTriggerKey(Long jobId, String jobGroup) + { + return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 构建任务键对象 + */ + public static JobKey getJobKey(Long jobId, String jobGroup) + { + return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 创建定时任务 + */ + public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException + { + Class jobClass = getQuartzJobClass(job); + // 构建job信息 + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); + + // 表达式调度构建器 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); + cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); + + // 按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) + .withSchedule(cronScheduleBuilder).build(); + + // 放入参数,运行时的方法可以获取 + jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); + + // 判断是否存在 + if (scheduler.checkExists(getJobKey(jobId, jobGroup))) + { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(getJobKey(jobId, jobGroup)); + } + + scheduler.scheduleJob(jobDetail, trigger); + + // 暂停任务 + if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + } + + /** + * 设置定时任务策略 + */ + public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb) + throws TaskException + { + switch (job.getMisfirePolicy()) + { + case ScheduleConstants.MISFIRE_DEFAULT: + return cb; + case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: + return cb.withMisfireHandlingInstructionIgnoreMisfires(); + case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: + return cb.withMisfireHandlingInstructionFireAndProceed(); + case ScheduleConstants.MISFIRE_DO_NOTHING: + return cb.withMisfireHandlingInstructionDoNothing(); + default: + throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); + } + } +} diff --git a/ruoyi/src/main/resources/mybatis/system/SysJobLogMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml similarity index 95% rename from ruoyi/src/main/resources/mybatis/system/SysJobLogMapper.xml rename to ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml index bf8157543..7601e63d9 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysJobLogMapper.xml +++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml @@ -1,93 +1,93 @@ - - - - - - - - - - - - - - - - - select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time - from sys_job_log - - - - - - - - - - delete from sys_job_log where job_log_id = #{jobLogId} - - - - delete from sys_job_log where job_log_id in - - #{jobLogId} - - - - - truncate table sys_job_log - - - - insert into sys_job_log( - job_log_id, - job_name, - job_group, - invoke_target, - job_message, - status, - exception_info, - create_time - )values( - #{jobLogId}, - #{jobName}, - #{jobGroup}, - #{invokeTarget}, - #{jobMessage}, - #{status}, - #{exceptionInfo}, - sysdate() - ) - - + + + + + + + + + + + + + + + + + select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time + from sys_job_log + + + + + + + + + + delete from sys_job_log where job_log_id = #{jobLogId} + + + + delete from sys_job_log where job_log_id in + + #{jobLogId} + + + + + truncate table sys_job_log + + + + insert into sys_job_log( + job_log_id, + job_name, + job_group, + invoke_target, + job_message, + status, + exception_info, + create_time + )values( + #{jobLogId}, + #{jobName}, + #{jobGroup}, + #{invokeTarget}, + #{jobMessage}, + #{status}, + #{exceptionInfo}, + sysdate() + ) + + \ No newline at end of file diff --git a/ruoyi/src/main/resources/mybatis/system/SysJobMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysJobMapper.xml rename to ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml index 47f61c964..69233bdf7 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysJobMapper.xml +++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml @@ -1,111 +1,111 @@ - - - - - - - - - - - - - - - - - - - - - - select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark - from sys_job - - - - - - - - - - delete from sys_job where job_id = #{jobId} - - - - delete from sys_job where job_id in - - #{jobId} - - - - - update sys_job - - job_name = #{jobName}, - job_group = #{jobGroup}, - invoke_target = #{invokeTarget}, - cron_expression = #{cronExpression}, - misfire_policy = #{misfirePolicy}, - concurrent = #{concurrent}, - status = #{status}, - remark = #{remark}, - update_by = #{updateBy}, - update_time = sysdate() - - where job_id = #{jobId} - - - - insert into sys_job( - job_id, - job_name, - job_group, - invoke_target, - cron_expression, - misfire_policy, - concurrent, - status, - remark, - create_by, - create_time - )values( - #{jobId}, - #{jobName}, - #{jobGroup}, - #{invokeTarget}, - #{cronExpression}, - #{misfirePolicy}, - #{concurrent}, - #{status}, - #{remark}, - #{createBy}, - sysdate() - ) - - + + + + + + + + + + + + + + + + + + + + + + select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark + from sys_job + + + + + + + + + + delete from sys_job where job_id = #{jobId} + + + + delete from sys_job where job_id in + + #{jobId} + + + + + update sys_job + + job_name = #{jobName}, + job_group = #{jobGroup}, + invoke_target = #{invokeTarget}, + cron_expression = #{cronExpression}, + misfire_policy = #{misfirePolicy}, + concurrent = #{concurrent}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where job_id = #{jobId} + + + + insert into sys_job( + job_id, + job_name, + job_group, + invoke_target, + cron_expression, + misfire_policy, + concurrent, + status, + remark, + create_by, + create_time + )values( + #{jobId}, + #{jobName}, + #{jobGroup}, + #{invokeTarget}, + #{cronExpression}, + #{misfirePolicy}, + #{concurrent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + \ No newline at end of file diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml new file mode 100644 index 000000000..ebcee00c6 --- /dev/null +++ b/ruoyi-system/pom.xml @@ -0,0 +1,28 @@ + + + + ruoyi + com.ruoyi + 3.0.0 + + 4.0.0 + + ruoyi-system + + + system系统模块 + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysConfig.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java index ba1c0220b..676a8916b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysConfig.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; /** * 参数配置表 sys_config diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysLogininfor.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java index cea9373d4..02a7fb5c0 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysLogininfor.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java @@ -1,10 +1,10 @@ -package com.ruoyi.project.monitor.domain; +package com.ruoyi.system.domain; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; /** * 系统访问记录表 sys_logininfor @@ -141,4 +141,4 @@ public class SysLogininfor extends BaseEntity { this.loginTime = loginTime; } -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysNotice.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java index 916fd320f..cb739dc41 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysNotice.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java @@ -1,10 +1,10 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.core.domain.BaseEntity; /** * 通知公告表 sys_notice diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysOperLog.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java index 71d77fa83..4110b8aca 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysOperLog.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java @@ -1,10 +1,10 @@ -package com.ruoyi.project.monitor.domain; +package com.ruoyi.system.domain; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; /** * 操作日志记录表 oper_log diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysPost.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java index ebafe7d9b..1e7556b8d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysPost.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.framework.aspectj.lang.annotation.Excel; -import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; -import com.ruoyi.framework.web.domain.BaseEntity; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; /** * 岗位表 sys_post diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRoleDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRoleDept.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java index f3dbd03c8..8ed8e473e 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRoleDept.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRoleMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRoleMenu.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java index 54452296f..59d286999 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRoleMenu.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysUserOnline.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysUserOnline.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java index 843148b4e..e1495aaa7 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/domain/SysUserOnline.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.monitor.domain; +package com.ruoyi.system.domain; /** * 当前在线会话 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUserPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUserPost.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java index 1ac4bfc4b..07ceb85cc 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUserPost.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUserRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUserRole.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java index e951bf3de..ce2af2bda 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUserRole.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain; +package com.ruoyi.system.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/vo/MetaVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/vo/MetaVo.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java index 118d2fa41..e83ef10c0 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/vo/MetaVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain.vo; +package com.ruoyi.system.domain.vo; /** * 路由显示信息 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/vo/RouterVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/domain/vo/RouterVo.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java index f81fc0bb0..21ff6b59a 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/vo/RouterVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.domain.vo; +package com.ruoyi.system.domain.vo; import com.fasterxml.jackson.annotation.JsonInclude; import java.util.List; diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysConfigMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java index eea48d60e..0c395f65b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysConfigMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysConfig; +import com.ruoyi.system.domain.SysConfig; /** * 参数配置 数据层 @@ -65,4 +65,4 @@ public interface SysConfigMapper * @return 结果 */ public int deleteConfigByIds(Long[] configIds); -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java index 113db2963..6261a873a 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; -import com.ruoyi.project.system.domain.SysDept; +import com.ruoyi.common.core.domain.entity.SysDept; /** * 部门管理 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDictDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDictDataMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java index c938d884f..92f799e55 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDictDataMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; -import com.ruoyi.project.system.domain.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictData; /** * 字典表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDictTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDictTypeMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java index 8a71574fd..81bc78090 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysDictTypeMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; import org.apache.ibatis.annotations.Mapper; -import com.ruoyi.project.system.domain.SysDictType; +import com.ruoyi.common.core.domain.entity.SysDictType; /** * 字典表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysLogininforMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java similarity index 85% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysLogininforMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java index 707fed1fc..480dd9ff6 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysLogininforMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.monitor.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.monitor.domain.SysLogininfor; +import com.ruoyi.system.domain.SysLogininfor; /** * 系统访问日志情况信息 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java index fc4608526..907c613f2 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; -import com.ruoyi.project.system.domain.SysMenu; +import com.ruoyi.common.core.domain.entity.SysMenu; /** * 菜单表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysNoticeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysNoticeMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java index 3a9370fd9..cc267ac0c 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysNoticeMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysNotice; +import com.ruoyi.system.domain.SysNotice; /** * 通知公告表 数据层 @@ -57,4 +57,4 @@ public interface SysNoticeMapper * @return 结果 */ public int deleteNoticeByIds(Long[] noticeIds); -} \ No newline at end of file +} diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysOperLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysOperLogMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java index 25b1904ab..3bf69bb8e 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/mapper/SysOperLogMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.monitor.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.monitor.domain.SysOperLog; +import com.ruoyi.system.domain.SysOperLog; /** * 操作日志 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysPostMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java index 2cb34f788..a98326f8b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysPostMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysPost; +import com.ruoyi.system.domain.SysPost; /** * 岗位信息 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleDeptMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java index fd4d6bd5c..a4ad4de24 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleDeptMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysRoleDept; +import com.ruoyi.system.domain.SysRoleDept; /** * 角色与部门关联表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java index 200bb1ebe..e4379c97b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysRole; +import com.ruoyi.common.core.domain.entity.SysRole; /** * 角色表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java similarity index 83% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleMenuMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java index 8d2e37682..99de1dece 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysRoleMenuMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysRoleMenu; +import com.ruoyi.system.domain.SysRoleMenu; /** * 角色与菜单关联表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java index bb073350f..b9937f399 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java @@ -1,10 +1,8 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; - import org.apache.ibatis.annotations.Param; - -import com.ruoyi.project.system.domain.SysUser; +import com.ruoyi.common.core.domain.entity.SysUser; /** * 用户表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserPostMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java index d67f4032e..9c33e546d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserPostMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; -import com.ruoyi.project.system.domain.SysUserPost; +import com.ruoyi.system.domain.SysUserPost; /** * 用户与岗位关联表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserRoleMapper.java rename to ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java index 614538db4..ad3fe62c1 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/mapper/SysUserRoleMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.mapper; +package com.ruoyi.system.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; -import com.ruoyi.project.system.domain.SysUserRole; +import com.ruoyi.system.domain.SysUserRole; /** * 用户与角色关联表 数据层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java index 4d95ee7e9..a937e8308 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.system.domain.SysConfig; +import com.ruoyi.system.domain.SysConfig; /** * 参数配置 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java index 5f59b8ad5..e3850cf22 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.framework.web.domain.TreeSelect; -import com.ruoyi.project.system.domain.SysDept; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; /** * 部门管理 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java index 65693d119..5fe8956be 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.system.domain.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictData; /** * 字典 业务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java index c6708d32e..3603d896d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.system.domain.SysDictData; -import com.ruoyi.project.system.domain.SysDictType; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; /** * 字典 业务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysLogininforService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java similarity index 85% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysLogininforService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java index f46dddfad..f77aaa7e1 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysLogininforService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.monitor.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.monitor.domain.SysLogininfor; +import com.ruoyi.system.domain.SysLogininfor; /** * 系统访问日志情况信息 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java index 95f49aea1..78553d59d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java @@ -1,10 +1,10 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; import java.util.Set; -import com.ruoyi.framework.web.domain.TreeSelect; -import com.ruoyi.project.system.domain.SysMenu; -import com.ruoyi.project.system.domain.vo.RouterVo; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.system.domain.vo.RouterVo; /** * 菜单 业务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java similarity index 87% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java index 98bd8902e..fb1e420fd 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.system.domain.SysNotice; +import com.ruoyi.system.domain.SysNotice; /** * 公告 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysOperLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java similarity index 86% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysOperLogService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java index 3e062acde..241f121ae 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/ISysOperLogService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.monitor.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.monitor.domain.SysOperLog; +import com.ruoyi.system.domain.SysOperLog; /** * 操作日志 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java similarity index 91% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysPostService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java index 5696e0835..2fb9a540d 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysPostService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.system.domain.SysPost; +import com.ruoyi.system.domain.SysPost; /** * 岗位信息 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysRoleService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java index fbd561728..4a4bee261 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysRoleService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -1,8 +1,8 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; import java.util.Set; -import com.ruoyi.project.system.domain.SysRole; +import com.ruoyi.common.core.domain.entity.SysRole; /** * 角色业务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserOnlineService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java similarity index 84% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserOnlineService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java index 63a4a3a12..12095ff5e 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserOnlineService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.project.monitor.domain.SysUserOnline; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.system.domain.SysUserOnline; /** * 在线用户 服务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java similarity index 93% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserService.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index 3b79a1d9a..00afa0011 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -1,7 +1,7 @@ -package com.ruoyi.project.system.service; +package com.ruoyi.system.service; import java.util.List; -import com.ruoyi.project.system.domain.SysUser; +import com.ruoyi.common.core.domain.entity.SysUser; /** * 用户 业务层 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index 88f5475d6..1c113fa92 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -1,18 +1,20 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.Collection; import java.util.List; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.redis.RedisCache; -import com.ruoyi.project.system.domain.SysConfig; -import com.ruoyi.project.system.mapper.SysConfigMapper; -import com.ruoyi.project.system.service.ISysConfigService; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.mapper.SysConfigMapper; +import com.ruoyi.system.service.ISysConfigService; /** * 参数配置 服务层实现 @@ -48,6 +50,7 @@ public class SysConfigServiceImpl implements ISysConfigService * @return 参数配置信息 */ @Override + @DataSource(DataSourceType.MASTER) public SysConfig selectConfigById(Long configId) { SysConfig config = new SysConfig(); diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java index 4e0ef4a2d..ec8113ec1 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.ArrayList; import java.util.Iterator; @@ -6,14 +6,14 @@ import java.util.List; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.DataScope; -import com.ruoyi.framework.web.domain.TreeSelect; -import com.ruoyi.project.system.domain.SysDept; -import com.ruoyi.project.system.mapper.SysDeptMapper; -import com.ruoyi.project.system.service.ISysDeptService; +import com.ruoyi.system.mapper.SysDeptMapper; +import com.ruoyi.system.service.ISysDeptService; /** * 部门管理 服务实现 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java similarity index 88% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java index 065a2ce80..39d950531 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java @@ -1,12 +1,12 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.utils.DictUtils; -import com.ruoyi.project.system.domain.SysDictData; -import com.ruoyi.project.system.mapper.SysDictDataMapper; -import com.ruoyi.project.system.service.ISysDictDataService; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.service.ISysDictDataService; /** * 字典 业务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java index 10fe23bcb..c38951bc4 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.List; import javax.annotation.PostConstruct; @@ -6,14 +6,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.project.system.domain.SysDictData; -import com.ruoyi.project.system.domain.SysDictType; -import com.ruoyi.project.system.mapper.SysDictDataMapper; -import com.ruoyi.project.system.mapper.SysDictTypeMapper; -import com.ruoyi.project.system.service.ISysDictTypeService; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.mapper.SysDictTypeMapper; +import com.ruoyi.system.service.ISysDictTypeService; /** * 字典 业务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java similarity index 82% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java index 5195bb3f7..f69fd1aff 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java @@ -1,11 +1,11 @@ -package com.ruoyi.project.monitor.service.impl; +package com.ruoyi.system.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ruoyi.project.monitor.domain.SysLogininfor; -import com.ruoyi.project.monitor.mapper.SysLogininforMapper; -import com.ruoyi.project.monitor.service.ISysLogininforService; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.mapper.SysLogininforMapper; +import com.ruoyi.system.service.ISysLogininforService; /** * 系统访问日志情况信息 服务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java similarity index 92% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index e5dda00f9..d3fb074ba 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.ArrayList; import java.util.Arrays; @@ -11,16 +11,16 @@ import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.domain.TreeSelect; -import com.ruoyi.project.system.domain.SysMenu; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.domain.vo.MetaVo; -import com.ruoyi.project.system.domain.vo.RouterVo; -import com.ruoyi.project.system.mapper.SysMenuMapper; -import com.ruoyi.project.system.mapper.SysRoleMenuMapper; -import com.ruoyi.project.system.service.ISysMenuService; +import com.ruoyi.system.domain.vo.MetaVo; +import com.ruoyi.system.domain.vo.RouterVo; +import com.ruoyi.system.mapper.SysMenuMapper; +import com.ruoyi.system.mapper.SysRoleMenuMapper; +import com.ruoyi.system.service.ISysMenuService; /** * 菜单 业务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java similarity index 85% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java index 2b0191d4a..8bebd9c69 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java @@ -1,11 +1,11 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ruoyi.project.system.domain.SysNotice; -import com.ruoyi.project.system.mapper.SysNoticeMapper; -import com.ruoyi.project.system.service.ISysNoticeService; +import com.ruoyi.system.domain.SysNotice; +import com.ruoyi.system.mapper.SysNoticeMapper; +import com.ruoyi.system.service.ISysNoticeService; /** * 公告 服务层实现 diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java similarity index 83% rename from ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java index 954bc08f7..785ee1ed7 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java @@ -1,11 +1,11 @@ -package com.ruoyi.project.monitor.service.impl; +package com.ruoyi.system.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ruoyi.project.monitor.domain.SysOperLog; -import com.ruoyi.project.monitor.mapper.SysOperLogMapper; -import com.ruoyi.project.monitor.service.ISysOperLogService; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.mapper.SysOperLogMapper; +import com.ruoyi.system.service.ISysOperLogService; /** * 操作日志 服务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java index b013cbb2e..127ed3fbd 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -6,10 +6,10 @@ import org.springframework.stereotype.Service; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.project.system.domain.SysPost; -import com.ruoyi.project.system.mapper.SysPostMapper; -import com.ruoyi.project.system.mapper.SysUserPostMapper; -import com.ruoyi.project.system.service.ISysPostService; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.mapper.SysPostMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.system.service.ISysPostService; /** * 岗位信息 服务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index 71f3c6684..8bfc5a410 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.ArrayList; import java.util.Arrays; @@ -8,19 +8,19 @@ import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.DataScope; -import com.ruoyi.project.system.domain.SysRole; -import com.ruoyi.project.system.domain.SysRoleDept; -import com.ruoyi.project.system.domain.SysRoleMenu; -import com.ruoyi.project.system.mapper.SysRoleDeptMapper; -import com.ruoyi.project.system.mapper.SysRoleMapper; -import com.ruoyi.project.system.mapper.SysRoleMenuMapper; -import com.ruoyi.project.system.mapper.SysUserRoleMapper; -import com.ruoyi.project.system.service.ISysRoleService; +import com.ruoyi.system.domain.SysRoleDept; +import com.ruoyi.system.domain.SysRoleMenu; +import com.ruoyi.system.mapper.SysRoleDeptMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysRoleMenuMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.system.service.ISysRoleService; /** * 角色 业务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java similarity index 89% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java index fb45b8017..2747f6a8b 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java @@ -1,10 +1,10 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.security.LoginUser; -import com.ruoyi.project.monitor.domain.SysUserOnline; -import com.ruoyi.project.system.service.ISysUserOnlineService; +import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.service.ISysUserOnlineService; /** * 在线用户 服务层处理 diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java similarity index 90% rename from ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java rename to ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index b6842e9c3..9c77dd8d1 100644 --- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -1,4 +1,4 @@ -package com.ruoyi.project.system.service.impl; +package com.ruoyi.system.service.impl; import java.util.ArrayList; import java.util.List; @@ -7,23 +7,23 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.aspectj.lang.annotation.DataScope; -import com.ruoyi.project.system.domain.SysPost; -import com.ruoyi.project.system.domain.SysRole; -import com.ruoyi.project.system.domain.SysUser; -import com.ruoyi.project.system.domain.SysUserPost; -import com.ruoyi.project.system.domain.SysUserRole; -import com.ruoyi.project.system.mapper.SysPostMapper; -import com.ruoyi.project.system.mapper.SysRoleMapper; -import com.ruoyi.project.system.mapper.SysUserMapper; -import com.ruoyi.project.system.mapper.SysUserPostMapper; -import com.ruoyi.project.system.mapper.SysUserRoleMapper; -import com.ruoyi.project.system.service.ISysConfigService; -import com.ruoyi.project.system.service.ISysUserService; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.domain.SysUserPost; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.SysPostMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; /** * 用户 业务层处理 diff --git a/ruoyi/src/main/resources/mybatis/system/SysConfigMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysConfigMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml index daf736a76..2f0c8be86 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysConfigMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml index 333804636..d78d7da25 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml index cc15a5141..75d80a157 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysDictTypeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml similarity index 95% rename from ruoyi/src/main/resources/mybatis/system/SysDictTypeMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml index 378e9616e..cf7fc06a3 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysDictTypeMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/monitor/SysLogininforMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml similarity index 94% rename from ruoyi/src/main/resources/mybatis/monitor/SysLogininforMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml index ba3194dc6..6f0a24115 100644 --- a/ruoyi/src/main/resources/mybatis/monitor/SysLogininforMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml similarity index 97% rename from ruoyi/src/main/resources/mybatis/system/SysMenuMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml index ac3a9c507..7c97ff5e0 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysMenuMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysNoticeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysNoticeMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml index c12816a2c..76caf2d2c 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysNoticeMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/monitor/SysOperLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml similarity index 95% rename from ruoyi/src/main/resources/mybatis/monitor/SysOperLogMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml index 34669145b..e70b7bff3 100644 --- a/ruoyi/src/main/resources/mybatis/monitor/SysOperLogMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysPostMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml index 1fb6f4580..e845b0a51 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysPostMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysRoleDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml similarity index 90% rename from ruoyi/src/main/resources/mybatis/system/SysRoleDeptMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml index acda24591..700671e15 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysRoleDeptMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml similarity index 96% rename from ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml index 82524b823..8958c6bad 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysRoleMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml similarity index 89% rename from ruoyi/src/main/resources/mybatis/system/SysRoleMenuMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml index b7c5b6b20..5f6c047a5 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysRoleMenuMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml similarity index 97% rename from ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml index 99c0d50e0..a6aeb6280 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysUserPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml similarity index 90% rename from ruoyi/src/main/resources/mybatis/system/SysUserPostMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml index d634c8b30..21c40981b 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysUserPostMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi/src/main/resources/mybatis/system/SysUserRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml similarity index 92% rename from ruoyi/src/main/resources/mybatis/system/SysUserRoleMapper.xml rename to ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml index 3422b1cfd..95e07adb1 100644 --- a/ruoyi/src/main/resources/mybatis/system/SysUserRoleMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml @@ -2,7 +2,7 @@ - + diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 40a0f4e35..9f0db892b 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,6 +1,6 @@ { "name": "ruoyi", - "version": "2.3.0", + "version": "3.0.0", "description": "若依管理系统", "author": "若依", "license": "MIT", diff --git a/ruoyi/bin/run-tomcat.bat b/ruoyi/bin/run-tomcat.bat deleted file mode 100644 index 5d38ad0e3..000000000 --- a/ruoyi/bin/run-tomcat.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off -echo. -echo [Ϣ] ʹ Spring Boot Tomcat Web ̡ -echo. - -%~d0 -cd %~dp0 - -cd .. -title %cd% -set MAVEN_OPTS=%MAVEN_OPTS% -Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -call mvn clean spring-boot:run -Dmaven.test.skip=true -U - -pause \ No newline at end of file diff --git a/ruoyi/pom.xml b/ruoyi/pom.xml deleted file mode 100644 index bd9af4845..000000000 --- a/ruoyi/pom.xml +++ /dev/null @@ -1,287 +0,0 @@ - - - 4.0.0 - - com.ruoyi - ruoyi - 2.3.0 - jar - - ruoyi - http://www.ruoyi.vip - 若依管理系统 - - - org.springframework.boot - spring-boot-starter-parent - 2.1.1.RELEASE - - - - - UTF-8 - UTF-8 - 1.8 - 1.3.2 - 1.2.5 - 1.2.70 - 1.1.14 - 2.5 - 1.3.3 - 1.19 - 0.9.0 - 2.9.2 - 3.17 - 3.9.1 - 1.7 - - - - - - - org.springframework.boot - spring-boot-starter - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - org.springframework.boot - spring-boot-starter-web - - - - - org.springframework.boot - spring-boot-devtools - true - - - - - org.springframework.boot - spring-boot-starter-security - - - - - org.springframework.boot - spring-boot-starter-data-redis - - - - - org.apache.commons - commons-pool2 - - - - - mysql - mysql-connector-java - runtime - - - - - org.mybatis.spring.boot - mybatis-spring-boot-starter - ${mybatis.spring.boot.starter.version} - - - - - com.github.pagehelper - pagehelper-spring-boot-starter - ${pagehelper.spring.boot.starter.version} - - - - - com.alibaba - druid-spring-boot-starter - ${druid.version} - - - - - org.apache.commons - commons-lang3 - - - - - commons-io - commons-io - ${commons.io.version} - - - - - commons-fileupload - commons-fileupload - ${commons.fileupload.version} - - - - - eu.bitwalker - UserAgentUtils - ${bitwalker.version} - - - - - com.alibaba - fastjson - ${fastjson.version} - - - - - org.springframework - spring-context-support - - - - - io.jsonwebtoken - jjwt - ${jwt.version} - - - - - io.springfox - springfox-swagger2 - ${swagger.version} - - - io.swagger - swagger-annotations - - - io.swagger - swagger-models - - - - - - - io.swagger - swagger-annotations - 1.5.21 - - - - io.swagger - swagger-models - 1.5.21 - - - - - io.springfox - springfox-swagger-ui - ${swagger.version} - - - - - com.github.oshi - oshi-core - ${oshi.version} - - - - net.java.dev.jna - jna - - - - net.java.dev.jna - jna-platform - - - - - org.apache.poi - poi-ooxml - ${poi.version} - - - - - org.apache.velocity - velocity - ${velocity.version} - - - - - org.quartz-scheduler - quartz - - - com.mchange - c3p0 - - - - - - - - ${project.artifactId} - - - org.springframework.boot - spring-boot-maven-plugin - - true - - - - - - - - public - aliyun nexus - http://maven.aliyun.com/nexus/content/groups/public/ - - true - - - - - - - public - aliyun nexus - http://maven.aliyun.com/nexus/content/groups/public/ - - true - - - false - - - - - \ No newline at end of file diff --git a/ruoyi/ry.sh b/ry.sh similarity index 93% rename from ruoyi/ry.sh rename to ry.sh index 52f80bd24..6558b9785 100644 --- a/ruoyi/ry.sh +++ b/ry.sh @@ -1,6 +1,6 @@ #!/bin/bash -AppName=ruoyi.jar +AppName=ruoyi-admin.jar #JVM参数 JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" diff --git a/ruoyi/sql/quartz.sql b/sql/quartz.sql similarity index 97% rename from ruoyi/sql/quartz.sql rename to sql/quartz.sql index 55665e2b9..52b6a0926 100644 --- a/ruoyi/sql/quartz.sql +++ b/sql/quartz.sql @@ -1,170 +1,170 @@ --- ---------------------------- --- 1、存储每一个已配置的 jobDetail 的详细信息 --- ---------------------------- -drop table if exists QRTZ_JOB_DETAILS; -create table QRTZ_JOB_DETAILS ( - sched_name varchar(120) not null, - job_name varchar(200) not null, - job_group varchar(200) not null, - description varchar(250) null, - job_class_name varchar(250) not null, - is_durable varchar(1) not null, - is_nonconcurrent varchar(1) not null, - is_update_data varchar(1) not null, - requests_recovery varchar(1) not null, - job_data blob null, - primary key (sched_name,job_name,job_group) -) engine=innodb; - --- ---------------------------- --- 2、 存储已配置的 Trigger 的信息 --- ---------------------------- -drop table if exists QRTZ_TRIGGERS; -create table QRTZ_TRIGGERS ( - sched_name varchar(120) not null, - trigger_name varchar(200) not null, - trigger_group varchar(200) not null, - job_name varchar(200) not null, - job_group varchar(200) not null, - description varchar(250) null, - next_fire_time bigint(13) null, - prev_fire_time bigint(13) null, - priority integer null, - trigger_state varchar(16) not null, - trigger_type varchar(8) not null, - start_time bigint(13) not null, - end_time bigint(13) null, - calendar_name varchar(200) null, - misfire_instr smallint(2) null, - job_data blob null, - primary key (sched_name,trigger_name,trigger_group), - foreign key (sched_name,job_name,job_group) references QRTZ_JOB_DETAILS(sched_name,job_name,job_group) -) engine=innodb; - --- ---------------------------- --- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数 --- ---------------------------- -drop table if exists QRTZ_SIMPLE_TRIGGERS; -create table QRTZ_SIMPLE_TRIGGERS ( - sched_name varchar(120) not null, - trigger_name varchar(200) not null, - trigger_group varchar(200) not null, - repeat_count bigint(7) not null, - repeat_interval bigint(12) not null, - times_triggered bigint(10) not null, - primary key (sched_name,trigger_name,trigger_group), - foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) -) engine=innodb; - --- ---------------------------- --- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息 --- ---------------------------- -drop table if exists QRTZ_CRON_TRIGGERS; -create table QRTZ_CRON_TRIGGERS ( - sched_name varchar(120) not null, - trigger_name varchar(200) not null, - trigger_group varchar(200) not null, - cron_expression varchar(200) not null, - time_zone_id varchar(80), - primary key (sched_name,trigger_name,trigger_group), - foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) -) engine=innodb; - --- ---------------------------- --- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) --- ---------------------------- -drop table if exists QRTZ_BLOB_TRIGGERS; -create table QRTZ_BLOB_TRIGGERS ( - sched_name varchar(120) not null, - trigger_name varchar(200) not null, - trigger_group varchar(200) not null, - blob_data blob null, - primary key (sched_name,trigger_name,trigger_group), - foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) -) engine=innodb; - --- ---------------------------- --- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围 --- ---------------------------- -drop table if exists QRTZ_CALENDARS; -create table QRTZ_CALENDARS ( - sched_name varchar(120) not null, - calendar_name varchar(200) not null, - calendar blob not null, - primary key (sched_name,calendar_name) -) engine=innodb; - --- ---------------------------- --- 7、 存储已暂停的 Trigger 组的信息 --- ---------------------------- -drop table if exists QRTZ_PAUSED_TRIGGER_GRPS; -create table QRTZ_PAUSED_TRIGGER_GRPS ( - sched_name varchar(120) not null, - trigger_group varchar(200) not null, - primary key (sched_name,trigger_group) -) engine=innodb; - --- ---------------------------- --- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息 --- ---------------------------- -drop table if exists QRTZ_FIRED_TRIGGERS; -create table QRTZ_FIRED_TRIGGERS ( - sched_name varchar(120) not null, - entry_id varchar(95) not null, - trigger_name varchar(200) not null, - trigger_group varchar(200) not null, - instance_name varchar(200) not null, - fired_time bigint(13) not null, - sched_time bigint(13) not null, - priority integer not null, - state varchar(16) not null, - job_name varchar(200) null, - job_group varchar(200) null, - is_nonconcurrent varchar(1) null, - requests_recovery varchar(1) null, - primary key (sched_name,entry_id) -) engine=innodb; - --- ---------------------------- --- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例 --- ---------------------------- -drop table if exists QRTZ_SCHEDULER_STATE; -create table QRTZ_SCHEDULER_STATE ( - sched_name varchar(120) not null, - instance_name varchar(200) not null, - last_checkin_time bigint(13) not null, - checkin_interval bigint(13) not null, - primary key (sched_name,instance_name) -) engine=innodb; - --- ---------------------------- --- 10、 存储程序的悲观锁的信息(假如使用了悲观锁) --- ---------------------------- -drop table if exists QRTZ_LOCKS; -create table QRTZ_LOCKS ( - sched_name varchar(120) not null, - lock_name varchar(40) not null, - primary key (sched_name,lock_name) -) engine=innodb; - -drop table if exists QRTZ_SIMPROP_TRIGGERS; -create table QRTZ_SIMPROP_TRIGGERS ( - sched_name varchar(120) not null, - trigger_name varchar(200) not null, - trigger_group varchar(200) not null, - str_prop_1 varchar(512) null, - str_prop_2 varchar(512) null, - str_prop_3 varchar(512) null, - int_prop_1 int null, - int_prop_2 int null, - long_prop_1 bigint null, - long_prop_2 bigint null, - dec_prop_1 numeric(13,4) null, - dec_prop_2 numeric(13,4) null, - bool_prop_1 varchar(1) null, - bool_prop_2 varchar(1) null, - primary key (sched_name,trigger_name,trigger_group), - foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) -) engine=innodb; - +-- ---------------------------- +-- 1、存储每一个已配置的 jobDetail 的详细信息 +-- ---------------------------- +drop table if exists QRTZ_JOB_DETAILS; +create table QRTZ_JOB_DETAILS ( + sched_name varchar(120) not null, + job_name varchar(200) not null, + job_group varchar(200) not null, + description varchar(250) null, + job_class_name varchar(250) not null, + is_durable varchar(1) not null, + is_nonconcurrent varchar(1) not null, + is_update_data varchar(1) not null, + requests_recovery varchar(1) not null, + job_data blob null, + primary key (sched_name,job_name,job_group) +) engine=innodb; + +-- ---------------------------- +-- 2、 存储已配置的 Trigger 的信息 +-- ---------------------------- +drop table if exists QRTZ_TRIGGERS; +create table QRTZ_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + job_name varchar(200) not null, + job_group varchar(200) not null, + description varchar(250) null, + next_fire_time bigint(13) null, + prev_fire_time bigint(13) null, + priority integer null, + trigger_state varchar(16) not null, + trigger_type varchar(8) not null, + start_time bigint(13) not null, + end_time bigint(13) null, + calendar_name varchar(200) null, + misfire_instr smallint(2) null, + job_data blob null, + primary key (sched_name,trigger_name,trigger_group), + foreign key (sched_name,job_name,job_group) references QRTZ_JOB_DETAILS(sched_name,job_name,job_group) +) engine=innodb; + +-- ---------------------------- +-- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数 +-- ---------------------------- +drop table if exists QRTZ_SIMPLE_TRIGGERS; +create table QRTZ_SIMPLE_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + repeat_count bigint(7) not null, + repeat_interval bigint(12) not null, + times_triggered bigint(10) not null, + primary key (sched_name,trigger_name,trigger_group), + foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) +) engine=innodb; + +-- ---------------------------- +-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息 +-- ---------------------------- +drop table if exists QRTZ_CRON_TRIGGERS; +create table QRTZ_CRON_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + cron_expression varchar(200) not null, + time_zone_id varchar(80), + primary key (sched_name,trigger_name,trigger_group), + foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) +) engine=innodb; + +-- ---------------------------- +-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) +-- ---------------------------- +drop table if exists QRTZ_BLOB_TRIGGERS; +create table QRTZ_BLOB_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + blob_data blob null, + primary key (sched_name,trigger_name,trigger_group), + foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) +) engine=innodb; + +-- ---------------------------- +-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围 +-- ---------------------------- +drop table if exists QRTZ_CALENDARS; +create table QRTZ_CALENDARS ( + sched_name varchar(120) not null, + calendar_name varchar(200) not null, + calendar blob not null, + primary key (sched_name,calendar_name) +) engine=innodb; + +-- ---------------------------- +-- 7、 存储已暂停的 Trigger 组的信息 +-- ---------------------------- +drop table if exists QRTZ_PAUSED_TRIGGER_GRPS; +create table QRTZ_PAUSED_TRIGGER_GRPS ( + sched_name varchar(120) not null, + trigger_group varchar(200) not null, + primary key (sched_name,trigger_group) +) engine=innodb; + +-- ---------------------------- +-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息 +-- ---------------------------- +drop table if exists QRTZ_FIRED_TRIGGERS; +create table QRTZ_FIRED_TRIGGERS ( + sched_name varchar(120) not null, + entry_id varchar(95) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + instance_name varchar(200) not null, + fired_time bigint(13) not null, + sched_time bigint(13) not null, + priority integer not null, + state varchar(16) not null, + job_name varchar(200) null, + job_group varchar(200) null, + is_nonconcurrent varchar(1) null, + requests_recovery varchar(1) null, + primary key (sched_name,entry_id) +) engine=innodb; + +-- ---------------------------- +-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例 +-- ---------------------------- +drop table if exists QRTZ_SCHEDULER_STATE; +create table QRTZ_SCHEDULER_STATE ( + sched_name varchar(120) not null, + instance_name varchar(200) not null, + last_checkin_time bigint(13) not null, + checkin_interval bigint(13) not null, + primary key (sched_name,instance_name) +) engine=innodb; + +-- ---------------------------- +-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁) +-- ---------------------------- +drop table if exists QRTZ_LOCKS; +create table QRTZ_LOCKS ( + sched_name varchar(120) not null, + lock_name varchar(40) not null, + primary key (sched_name,lock_name) +) engine=innodb; + +drop table if exists QRTZ_SIMPROP_TRIGGERS; +create table QRTZ_SIMPROP_TRIGGERS ( + sched_name varchar(120) not null, + trigger_name varchar(200) not null, + trigger_group varchar(200) not null, + str_prop_1 varchar(512) null, + str_prop_2 varchar(512) null, + str_prop_3 varchar(512) null, + int_prop_1 int null, + int_prop_2 int null, + long_prop_1 bigint null, + long_prop_2 bigint null, + dec_prop_1 numeric(13,4) null, + dec_prop_2 numeric(13,4) null, + bool_prop_1 varchar(1) null, + bool_prop_2 varchar(1) null, + primary key (sched_name,trigger_name,trigger_group), + foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) +) engine=innodb; + commit; \ No newline at end of file diff --git a/ruoyi/sql/ry_20200629.sql b/sql/ry_20200629.sql similarity index 100% rename from ruoyi/sql/ry_20200629.sql rename to sql/ry_20200629.sql