wujian
2024-02-22 268beb4ebc1e5b8d4ad715b71cd64a0944073a87
first commit
已添加824个文件
95127 ■■■■■ 文件已修改
.gitignore 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LICENSE 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/clean.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/package.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/run.bat 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/╚⌠╥└╗╖╛│╩╣╙├╩╓▓ß.docx 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/pom.xml 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/MesApplication.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/MesServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/common/CaptchaController.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/common/CommonController.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/CacheController.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/ServerController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysLogininforController.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysOperlogController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysUserOnlineController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysConfigController.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDeptController.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictDataController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictTypeController.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysIndexController.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysLoginController.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysMenuController.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysNoticeController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysPostController.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysProfileController.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRegisterController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRoleController.java 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysUserController.java 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/controller/tool/TestController.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/java/com/jcdm/web/core/config/SwaggerConfig.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/META-INF/spring-devtools.properties 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/application-druid.yml 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/application.yml 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/banner.txt 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/i18n/messages.properties 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/logback.xml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-admin/src/main/resources/mybatis/mybatis-config.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/pom.xml 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/Anonymous.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/DataScope.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/DataSource.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/Excel.java 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/Excels.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/Log.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/RateLimiter.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/annotation/RepeatSubmit.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/config/MesConfig.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/constant/CacheConstants.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/constant/Constants.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/constant/GenConstants.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/constant/HttpStatus.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/constant/ScheduleConstants.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/constant/UserConstants.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/controller/BaseController.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/AjaxResult.java 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/BaseEntity.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/R.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeEntity.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeSelect.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDept.java 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictData.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictType.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysMenu.java 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysRole.java 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysUser.java 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginBody.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginUser.java 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/domain/model/RegisterBody.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/page/PageDomain.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/page/TableDataInfo.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/page/TableSupport.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/redis/MyCache.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/redis/RedisCache.java 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/text/CharsetKit.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/text/Convert.java 1006 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/core/text/StrFormatter.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/BusinessStatus.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/BusinessType.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/DataSourceType.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/HttpMethod.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/LimitType.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/OperatorType.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/enums/UserStatus.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/DemoModeException.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/GlobalException.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/ServiceException.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/UtilException.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/base/BaseException.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileException.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileNameLengthLimitExceededException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileSizeLimitExceededException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileUploadException.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/file/InvalidExtensionException.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/job/TaskException.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/BlackListException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaExpireException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserException.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserNotExistsException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordNotMatchException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordRetryLimitExceedException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/filter/PropertyPreExcludeFilter.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/filter/RepeatableFilter.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/filter/RepeatedlyRequestWrapper.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/filter/XssFilter.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/filter/XssHttpServletRequestWrapper.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/Arith.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/DateUtils.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/DictUtils.java 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/ExceptionUtil.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/LogUtils.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/MessageUtils.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/PageUtils.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/SecurityUtils.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/ServletUtils.java 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/StringUtils.java 638 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/Threads.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanUtils.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanValidators.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/file/FileTypeUtils.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUploadUtils.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUtils.java 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/file/ImageUtils.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/file/MimeTypeUtils.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/html/EscapeUtil.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/html/HTMLFilter.java 570 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpHelper.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpUtils.java 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/ip/AddressUtils.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/ip/IpUtils.java 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelHandlerAdapter.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelUtil.java 1758 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/reflect/ReflectUtils.java 410 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/sign/Base64.java 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/sign/Md5Utils.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/spring/SpringUtils.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/sql/SqlUtil.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/uuid/IdUtils.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/uuid/Seq.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/utils/uuid/UUID.java 484 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/xss/Xss.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-common/src/main/java/com/jcdm/common/xss/XssValidator.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/pom.xml 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataScopeAspect.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataSourceAspect.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/LogAspect.java 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/RateLimiterAspect.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/ApplicationConfig.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/CaptchaConfig.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/DruidConfig.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/FastJson2JsonRedisSerializer.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/FilterConfig.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/KaptchaTextCreator.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/MyBatisConfig.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/RedisConfig.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/ResourcesConfig.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/SecurityConfig.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/ServerConfig.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/ThreadPoolConfig.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/properties/DruidProperties.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/config/properties/PermitAllUrlProperties.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSource.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSourceContextHolder.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/interceptor/RepeatSubmitInterceptor.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/interceptor/impl/SameUrlDataInterceptor.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/manager/AsyncManager.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/manager/ShutdownManager.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/manager/factory/AsyncFactory.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/security/context/AuthenticationContextHolder.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/security/context/PermissionContextHolder.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/security/filter/JwtAuthenticationTokenFilter.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/security/handle/AuthenticationEntryPointImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/security/handle/LogoutSuccessHandlerImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/domain/Server.java 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Cpu.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Jvm.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Mem.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Sys.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/SysFile.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/exception/GlobalExceptionHandler.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/PermissionService.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysLoginService.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPasswordService.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPermissionService.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysRegisterService.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/TokenService.java 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/web/service/UserDetailsServiceImpl.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/websocket/PostController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/websocket/SemaphoreUtils.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketConfig.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketServer.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketUsers.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/pom.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/config/GenConfig.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/controller/GenController.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTable.java 385 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTableColumn.java 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableColumnMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableMapper.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableColumnServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableServiceImpl.java 521 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableColumnService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableService.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/util/GenUtils.java 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityInitializer.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityUtils.java 408 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/generator.yml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/mapper/generator/GenTableMapper.xml 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/java/controller.java.vm 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/java/domain.java.vm 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/java/mapper.java.vm 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/java/service.java.vm 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/java/serviceImpl.java.vm 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/java/sub-domain.java.vm 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/js/api.js.vm 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/sql/sql.vm 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/vue/index-tree.vue.vm 505 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/vue/index.vue.vm 615 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm 474 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/vue/v3/index.vue.vm 590 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-generator/src/main/resources/vm/xml/mapper.xml.vm 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/pom.xml 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/controller/BsBeatSettingController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/domain/BsBeatSetting.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/mapper/BsBeatSettingMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/IBsBeatSettingService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/impl/BsBeatSettingServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formula/controller/BsFormulaInfoController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formula/domain/BsFormulaInfo.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formula/mapper/BsFormulaInfoMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/IBsFormulaInfoService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/impl/BsFormulaInfoServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/controller/BsFormulaChildInfoController.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/domain/BsFormulaChildInfo.java 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/mapper/BsFormulaChildInfoMapper.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/IBsFormulaChildInfoService.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/impl/BsFormulaChildInfoServiceImpl.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/controller/BsLineInfoController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/domain/BsLineInfo.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/mapper/BsLineInfoMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/IBsLineInfoService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/impl/BsLineInfoServiceImpl.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/material/controller/BsMaterialInfoController.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/material/domain/BsMaterialInfo.java 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/material/mapper/BsMaterialInfoMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/material/service/IBsMaterialInfoService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/material/service/impl/BsMaterialInfoServiceImpl.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processFile/controller/BsProcessFileController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processFile/domain/BsProcessFile.java 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processFile/mapper/BsProcessFileMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/IBsProcessFileService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/impl/BsProcessFileServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processes/controller/BsProcessesInfoController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processes/domain/BsProcessesInfo.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processes/mapper/BsProcessesInfoMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/IBsProcessesInfoService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/impl/BsProcessesInfoServiceImpl.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBom/controller/BsProductBomInfoController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBom/domain/BsProductBomInfo.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBom/mapper/BsProductBomInfoMapper.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/IBsProductBomInfoService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/impl/BsProductBomInfoServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/controller/BsProductBomChildInfoController.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/domain/BsProductBomChildInfo.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/mapper/BsProductBomChildInfoMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/IBsProductBomChildInfoService.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/impl/BsProductBomChildInfoServiceImpl.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/controller/BsTechnologyRouteInfoController.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/domain/BsTechnologyRouteInfo.java 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/mapper/BsTechnologyRouteInfoMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/IBsTechnologyRouteInfoService.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/impl/BsTechnologyRouteInfoServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/controller/BsTechnologyRouteChildInfoController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/domain/BsTechnologyRouteChildInfo.java 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/mapper/BsTechnologyRouteChildInfoMapper.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/IBsTechnologyRouteChildInfoService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/impl/BsTechnologyRouteChildInfoServiceImpl.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/workshop/controller/BsWorkshopInfoController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/workshop/domain/BsWorkshopInfo.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/workshop/mapper/BsWorkshopInfoMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/IBsWorkshopInfoService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/impl/BsWorkshopInfoServiceImpl.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/controller/DaCollectionParamConfController.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/domain/DaCollectionParamConf.java 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/mapper/DaCollectionParamConfMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/IDaCollectionParamConfService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/impl/DaCollectionParamConfServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/KeyStoreLoader.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/MethodName.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientHandler.java 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientRunner.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/controller/DaOpcuaConfigController.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/DaOpcuaConfig.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/NodeEntity.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/BeanUtils.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/OpcusConfigInit.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/Properties.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/mapper/DaOpcuaConfigMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/IDaOpcuaConfigService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/impl/DaOpcuaConfigServiceImpl.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/controller/DaParamCollectionController.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/domain/DaParamCollection.java 317 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/mapper/DaParamCollectionMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/IDaParamCollectionService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/impl/DaParamCollectionServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/common/Constants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/controller/DaPassingStationCollectionController.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/domain/DaPassingStationCollection.java 302 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/mapper/DaPassingStationCollectionMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/IDaPassingStationCollectionService.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/impl/DaPassingStationCollectionServiceImpl.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/controller/EmEquipmentAlarmController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/domain/EmEquipmentAlarm.java 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/mapper/EmEquipmentAlarmMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/IEmEquipmentAlarmService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/impl/EmEquipmentAlarmServiceImpl.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/controller/EmEquipmentArchivesController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/domain/EmEquipmentArchives.java 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/mapper/EmEquipmentArchivesMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/IEmEquipmentArchivesService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/impl/EmEquipmentArchivesServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/controller/EmEquipmentStatusController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/domain/EmEquipmentStatus.java 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/mapper/EmEquipmentStatusMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/IEmEquipmentStatusService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/impl/EmEquipmentStatusServiceImpl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/controller/OmProductionOrdeInfoController.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/domain/OmProductionOrdeInfo.java 557 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/mapper/OmProductionOrdeInfoMapper.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/IOmProductionOrdeInfoService.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/impl/OmProductionOrdeInfoServiceImpl.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/workReport/controller/OmWorkReportController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/workReport/domain/OmWorkReport.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/workReport/mapper/OmWorkReportMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/IOmWorkReportService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/impl/OmWorkReportServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairData/controller/RmRepairDataController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairData/domain/RmRepairData.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairData/mapper/RmRepairDataMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/IRmRepairDataService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/impl/RmRepairDataServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/controller/RmRepairRecordController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/domain/RmRepairRecord.java 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/mapper/RmRepairRecordMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/IRmRepairRecordService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/impl/RmRepairRecordServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/controller/ScStationConfController.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/domain/ScStationConf.java 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/mapper/ScStationConfMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/IScStationConfService.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/impl/ScStationConfServiceImpl.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/util/IpInfoUtils.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/webservice/Item.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/webservice/ItemList.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/java/com/jcdm/main/webservice/test.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/beatSetting/BsBeatSettingMapper.xml 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/formula/BsFormulaInfoMapper.xml 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/formulaChild/BsFormulaChildInfoMapper.xml 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/lineInfo/BsLineInfoMapper.xml 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/material/BsMaterialInfoMapper.xml 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/processFile/BsProcessFileMapper.xml 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/processes/BsProcessesInfoMapper.xml 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/productBom/BsProductBomInfoMapper.xml 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/productBomChild/BsProductBomChildInfoMapper.xml 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/technologyRoute/BsTechnologyRouteInfoMapper.xml 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/technologyRouteChild/BsTechnologyRouteChildInfoMapper.xml 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/bs/workshop/BsWorkshopInfoMapper.xml 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/da/collectionParamConf/DaCollectionParamConfMapper.xml 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/da/opcuaconfig/DaOpcuaConfigMapper.xml 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/da/paramCollection/DaParamCollectionMapper.xml 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/da/passingStationCollection/DaPassingStationCollectionMapper.xml 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/em/equipmentAlarm/EmEquipmentAlarmMapper.xml 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/em/equipmentArchives/EmEquipmentArchivesMapper.xml 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/em/equipmentStatus/EmEquipmentStatusMapper.xml 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/om/productionOrde/OmProductionOrdeInfoMapper.xml 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/om/workReport/OmWorkReportMapper.xml 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/rm/repairData/RmRepairDataMapper.xml 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/rm/repairRecord/RmRepairRecordMapper.xml 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/mapper/sc/stationConf/ScStationConfMapper.xml 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-main/src/main/resources/opcua.properties 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/pom.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/config/ScheduleConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobController.java 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobLogController.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJob.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJobLog.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobLogMapper.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobMapper.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobLogService.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobLogServiceImpl.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobServiceImpl.java 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/task/RyTask.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/util/AbstractQuartzJob.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/util/CronUtils.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/util/JobInvokeUtil.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzDisallowConcurrentExecution.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzJobExecution.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/java/com/jcdm/quartz/util/ScheduleUtils.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/pom.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysCache.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysConfig.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysLogininfor.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysNotice.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysOperLog.java 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysPost.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleDept.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleMenu.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysUserOnline.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysUserPost.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/SysUserRole.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/vo/MetaVo.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/domain/vo/RouterVo.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysConfigMapper.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysDeptMapper.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictDataMapper.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictTypeMapper.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysLogininforMapper.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysMenuMapper.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysNoticeMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysOperLogMapper.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysPostMapper.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleDeptMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMapper.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMenuMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserMapper.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserPostMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserRoleMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysConfigService.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysDeptService.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysDictDataService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysDictTypeService.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysLogininforService.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysMenuService.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysNoticeService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysOperLogService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysPostService.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysRoleService.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysUserOnlineService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/ISysUserService.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysConfigServiceImpl.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDeptServiceImpl.java 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictDataServiceImpl.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictTypeServiceImpl.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysLogininforServiceImpl.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysMenuServiceImpl.java 531 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysNoticeServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysOperLogServiceImpl.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysPostServiceImpl.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysRoleServiceImpl.java 424 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserOnlineServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserServiceImpl.java 544 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysConfigMapper.xml 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysDeptMapper.xml 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysDictDataMapper.xml 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysDictTypeMapper.xml 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysLogininforMapper.xml 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysMenuMapper.xml 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysNoticeMapper.xml 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysOperLogMapper.xml 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysPostMapper.xml 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysRoleMapper.xml 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysUserMapper.xml 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysUserPostMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-system/src/main/resources/mapper/system/SysUserRoleMapper.xml 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.editorconfig 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.env.development 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.env.production 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.env.staging 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.eslintignore 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.eslintrc.js 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/.gitignore 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/README.md 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/babel.config.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/bin/build.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/bin/package.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/bin/run-web.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/build/index.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/dist.rar 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/package.json 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/public/html/ie.html 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/public/index.html 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/public/robots.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/App.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/login.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/ProductBom/ProductBom.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/ProductBomChild/ProductBomChild.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/beatSetting/beatSetting.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/formula/formula.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/formulaChild/formulaChild.js 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/lineInfo/lineInfo.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/material/material.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/processFile/processFile.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/processes/processes.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/technologyRoute/technologyRoute.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/technologyRouteChild/technologyRouteChild.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/bs/workshop/workshop.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/da/collectionParamConf/collectionParamConf.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/da/opcuaconfig/opcuaconfig.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/da/paramCollection/paramCollection.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/da/passingStationCollection/passingStationCollection.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/em/equipmentAlarm/equipmentAlarm.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/em/equipmentArchives/equipmentArchives.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/em/equipmentStatus/equipmentStatus.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/om/productionOrde/productionOrde.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/om/workReport/workReport.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/rm/repairData/repairData.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/rm/repairRecord/repairRecord.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/main/sc/stationConf.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/menu.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/cache.js 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/job.js 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/jobLog.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/logininfor.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/online.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/operlog.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/monitor/server.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/config.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/dept.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/dict/data.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/dict/type.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/menu.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/notice.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/post.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/role.js 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/system/user.js 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/api/tool/gen.js 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/401_images/401.gif 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/404_images/404.png 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/404_images/404_cloud.png 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/index.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/404.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/bug.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/build.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/button.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/cascader.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/chart.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/checkbox.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/clipboard.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/code.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/color.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/component.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/dashboard.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/date-range.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/date.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/dict.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/documentation.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/download.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/drag.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/druid.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/edit.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/education.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/email.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/example.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/excel.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/exit-fullscreen.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/eye-open.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/eye.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/form.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/fullscreen.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/github.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/guide.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/icon.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/input.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/international.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/job.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/language.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/link.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/list.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/lock.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/log.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/logininfor.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/message.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/money.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/monitor.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/nested.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/number.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/online.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/password.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/pdf.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/people.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/peoples.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/phone.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/post.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/qq.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/question.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/radio.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/rate.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/redis-list.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/redis.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/row.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/search.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/select.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/server.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/shopping.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/size.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/skill.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/slider.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/star.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/swagger.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/switch.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/system.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/tab.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/table.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/textarea.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/theme.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/time-range.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/time.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/tool.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/tree-table.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/tree.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/upload.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/user.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/validCode.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/wechat.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svg/zip.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/icons/svgo.yml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/dark.svg 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/light.svg 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/login-background.jpg 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/login-background.png 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/login-background1.png 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/pay.png 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/images/profile.jpg 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/logo/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/btn.scss 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/element-ui.scss 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/element-variables.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/index.scss 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/mixin.scss 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/ruoyi.scss 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/sidebar.scss 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/transition.scss 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/assets/styles/variables.scss 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Breadcrumb/index.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/day.vue 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/hour.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/index.vue 430 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/min.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/month.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/result.vue 559 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/second.vue 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/week.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Crontab/year.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/DictData/index.js 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/DictTag/index.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Editor/index.vue 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/FileUpload/index.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Hamburger/index.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/HeaderSearch/index.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/IconSelect/index.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/IconSelect/requireIcons.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/ImagePreview/index.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/ImageUpload/index.vue 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Pagination/index.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/PanThumb/index.vue 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/ParentView/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/RightPanel/index.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/RightToolbar/index.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/RuoYi/Doc/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/RuoYi/Git/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/Screenfull/index.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/SizeSelect/index.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/SvgIcon/index.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/ThemePicker/index.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/TopNav/index.vue 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/iFrame/index.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/itemSelect/index.vue 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/components/itemSelect/single.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/dialog/drag.js 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/dialog/dragHeight.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/dialog/dragWidth.js 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/index.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/module/clipboard.js 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/permission/hasPermi.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/directive/permission/hasRole.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/AppMain.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/IframeToggle/index.vue 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/InnerLink/index.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Navbar.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Settings/index.vue 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Sidebar/FixiOSBug.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Sidebar/Item.vue 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Sidebar/Link.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Sidebar/Logo.vue 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Sidebar/SidebarItem.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/Sidebar/index.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/TagsView/ScrollPane.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/TagsView/index.vue 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/components/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/index.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/layout/mixin/ResizeHandler.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/main.js 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/permission.js 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/plugins/auth.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/plugins/cache.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/plugins/download.js 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/plugins/index.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/plugins/modal.js 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/plugins/tab.js 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/router/directives.js 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/router/index.js 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/settings.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/getters.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/index.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/modules/app.js 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/modules/dict.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/modules/permission.js 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/modules/settings.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/modules/tagsView.js 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/store/modules/user.js 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/auth.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/dict/Dict.js 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/dict/DictConverter.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/dict/DictData.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/dict/DictMeta.js 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/dict/DictOptions.js 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/dict/index.js 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/errorCode.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/config.js 438 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/css.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/drawingDefault.js 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/html.js 359 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/icon.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/js.js 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/generator/render.js 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/index.js 390 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/jsencrypt.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/permission.js 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/request.js 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/ruoyi.js 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/scroll-to.js 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/utils/validate.js 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/components/icons/element-icons.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/components/icons/index.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/components/icons/svg-icons.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/dashboard/BarChart.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/dashboard/LineChart.vue 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/dashboard/PanelGroup.vue 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/dashboard/PieChart.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/dashboard/RaddarChart.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/dashboard/mixins/resize.js 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/error/401.vue 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/error/404.vue 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/index.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/index_v1.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/login.vue 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/ProductBom/index.vue 391 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/ProductBomChild/index.vue 457 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/beatSetting/index.vue 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/formula/index.vue 353 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/formulaChild/index.vue 474 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/lineInfo/index.vue 413 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/material/index.vue 413 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/processFile/index.vue 506 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/processes/index.vue 358 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/technologyRoute/index.vue 367 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/technologyRouteChild/index.vue 459 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/bs/workshop/index.vue 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/cfkb/Instructions/index.vue 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/da/collectionParamConf/index.vue 443 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/da/opcuaconfig/index.vue 426 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/da/paramCollection/index.vue 374 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/da/passingStationCollection/index.vue 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/em/equipmentAlarm/index.vue 377 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/em/equipmentArchives/index.vue 436 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/em/equipmentStatus/index.vue 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/kb/stationTerminal/index.vue 445 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/om/productionOrde/index.vue 656 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/om/workReport/index.vue 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/rm/repairData/index.vue 398 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/rm/repairRecord/index.vue 337 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/main/sc/stationConf/index.vue 342 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/cache/index.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/cache/list.vue 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/druid/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/job/index.vue 513 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/job/log.vue 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/logininfor/index.vue 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/online/index.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/operlog/index.vue 323 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/monitor/server/index.vue 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/redirect.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/register.vue 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/config/index.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/dept/index.vue 340 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/dict/data.vue 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/dict/index.vue 347 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/menu/index.vue 452 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/notice/index.vue 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/post/index.vue 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/role/authUser.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/role/index.vue 605 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/role/selectUser.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/user/authRole.vue 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/user/index.vue 670 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/user/profile/index.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/user/profile/resetPwd.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/user/profile/userAvatar.vue 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/system/user/profile/userInfo.vue 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/build/CodeTypeDialog.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/build/DraggableItem.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/build/IconsDialog.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/build/RightPanel.vue 946 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/build/TreeNodeDialog.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/build/index.vue 768 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/gen/basicInfoForm.vue 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/gen/editTable.vue 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/gen/genInfoForm.vue 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/gen/importTable.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/gen/index.vue 337 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/src/views/tool/swagger/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jcdm-ui/vue.config.js 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/quartz.sql 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/ry_20231130.sql 700 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
######################################################################
# Build Tools
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
LICENSE
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 Jcdm
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bin/clean.bat
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
@echo off
echo.
echo [信息] æ¸…理工程target生成路径。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean
pause
bin/package.bat
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
@echo off
echo.
echo [信息] æ‰“包Web工程,生成war/jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package -Dmaven.test.skip=true
pause
bin/run.bat
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] ä½¿ç”¨Jar命令运行Web工程。
echo.
cd %~dp0
cd ../jcdm-admin/target
set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -jar %JAVA_OPTS% jcdm-admin.jar
cd bin
pause
doc/¨^?¨i©¸¨[¨Z¨_©¦¨m¨g¨]©À¨m¨W¨ˆ?.docx
Binary files differ
jcdm-admin/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>jcdm</artifactId>
        <groupId>com.jcdm</groupId>
        <version>3.8.6</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>jcdm-admin</artifactId>
    <description>
        web服务入口
    </description>
    <dependencies>
        <!-- spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- è¡¨ç¤ºä¾èµ–不会传递 -->
        </dependency>
        <!-- swagger3-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
        </dependency>
        <!-- é˜²æ­¢è¿›å…¥swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.6.2</version>
        </dependency>
         <!-- Mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--sqlserver数据库配置-->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
        </dependency>
        <!-- æ ¸å¿ƒæ¨¡å—-->
        <dependency>
            <groupId>com.jcdm</groupId>
            <artifactId>jcdm-framework</artifactId>
        </dependency>
        <!-- å®šæ—¶ä»»åŠ¡-->
        <dependency>
            <groupId>com.jcdm</groupId>
            <artifactId>jcdm-quartz</artifactId>
        </dependency>
        <!-- ä»£ç ç”Ÿæˆ-->
        <dependency>
            <groupId>com.jcdm</groupId>
            <artifactId>jcdm-generator</artifactId>
        </dependency>
        <!-- JCDM模块-->
        <dependency>
            <groupId>com.jcdm</groupId>
            <artifactId>jcdm-main</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.15</version>
                <configuration>
                    <fork>true</fork> <!-- å¦‚果没有该配置,devtools不会生效 -->
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <warName>${project.artifactId}</warName>
                </configuration>
           </plugin>
        </plugins>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>
jcdm-admin/src/main/java/com/jcdm/MesApplication.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.jcdm;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
 * å¯åŠ¨ç¨‹åº
 *
 * @author jc
 */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MesApplication
{
    public static void main(String[] args)
    {
        // System.setProperty("spring.devtools.restart.enabled", "false");
        SpringApplication.run(MesApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  ç³»ç»Ÿå¯åŠ¨æˆåŠŸ   áƒš(´ڡ`ლ)゙  \n" /*+
                " .-------.       ____     __        \n" +
                " |  _ _   \\      \\   \\   /  /    \n" +
                " | ( ' )  |       \\  _. /  '       \n" +
                " |(_ o _) /        _( )_ .'         \n" +
                " | (_,_).' __  ___(_ o _)'          \n" +
                " |  |\\ \\  |  ||   |(_,_)'         \n" +
                " |  | \\ `'   /|   `-'  /           \n" +
                " |  |  \\    /  \\      /           \n" +
                " ''-'   `'-'    `-..-'              " */
                );
    }
}
jcdm-admin/src/main/java/com/jcdm/MesServletInitializer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.jcdm;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
 * web容器中进行部署
 *
 * @author jc
 */
public class MesServletInitializer extends SpringBootServletInitializer
{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
    {
        return application.sources(MesApplication.class);
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/common/CaptchaController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.jcdm.web.controller.common;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.constant.CacheConstants;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.redis.RedisCache;
import com.jcdm.common.utils.sign.Base64;
import com.jcdm.common.utils.uuid.IdUtils;
import com.jcdm.system.service.ISysConfigService;
/**
 * éªŒè¯ç æ“ä½œå¤„理
 *
 * @author jc
 */
@RestController
public class CaptchaController
{
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysConfigService configService;
    /**
     * ç”ŸæˆéªŒè¯ç 
     */
    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException
    {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        ajax.put("captchaEnabled", captchaEnabled);
        if (!captchaEnabled)
        {
            return ajax;
        }
        // ä¿å­˜éªŒè¯ç ä¿¡æ¯
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        String capStr = null, code = null;
        BufferedImage image = null;
        // ç”ŸæˆéªŒè¯ç 
        String captchaType = MesConfig.getCaptchaType();
        if ("math".equals(captchaType))
        {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        }
        else if ("char".equals(captchaType))
        {
            capStr = code = captchaProducer.createText();
            image = captchaProducer.createImage(capStr);
        }
        redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // è½¬æ¢æµä¿¡æ¯å†™å‡º
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try
        {
            ImageIO.write(image, "jpg", os);
        }
        catch (IOException e)
        {
            return AjaxResult.error(e.getMessage());
        }
        ajax.put("uuid", uuid);
        ajax.put("img", Base64.encode(os.toByteArray()));
        return ajax;
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/common/CommonController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,163 @@
package com.jcdm.web.controller.common;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.file.FileUploadUtils;
import com.jcdm.common.utils.file.FileUtils;
import com.jcdm.framework.config.ServerConfig;
/**
 * é€šç”¨è¯·æ±‚处理
 *
 * @author jc
 */
@RestController
@RequestMapping("/common")
public class CommonController
{
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);
    @Autowired
    private ServerConfig serverConfig;
    private static final String FILE_DELIMETER = ",";
    /**
     * é€šç”¨ä¸‹è½½è¯·æ±‚
     *
     * @param fileName æ–‡ä»¶åç§°
     * @param delete æ˜¯å¦åˆ é™¤
     */
    @GetMapping("/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
    {
        try
        {
            if (!FileUtils.checkAllowDownload(fileName))
            {
                throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = MesConfig.getDownloadPath() + fileName;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete)
            {
                FileUtils.deleteFile(filePath);
            }
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚(单个)
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception
    {
        try
        {
            // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
            String filePath = MesConfig.getUploadPath();
            // ä¸Šä¼ å¹¶è¿”回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚(多个)
     */
    @PostMapping("/uploads")
    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
    {
        try
        {
            // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
            String filePath = MesConfig.getUploadPath();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files)
            {
                // ä¸Šä¼ å¹¶è¿”回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = serverConfig.getUrl() + fileName;
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(FileUtils.getName(fileName));
                originalFilenames.add(file.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }
    /**
     * æœ¬åœ°èµ„源通用下载
     */
    @GetMapping("/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
            }
            // æœ¬åœ°èµ„源路径
            String localPath = MesConfig.getProfile();
            // æ•°æ®åº“资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // ä¸‹è½½åç§°
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/CacheController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
package com.jcdm.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
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.jcdm.common.constant.CacheConstants;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.system.domain.SysCache;
/**
 * ç¼“存监控
 *
 * @author jc
 */
@RestController
@RequestMapping("/monitor/cache")
public class CacheController
{
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private final static List<SysCache> caches = new ArrayList<SysCache>();
    {
        caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
        caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"));
        caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"));
        caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
        caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
        caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
        caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping()
    public AjaxResult getInfo() throws Exception
    {
        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
        Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
        Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
        Map<String, Object> result = new HashMap<>(3);
        result.put("info", info);
        result.put("dbSize", dbSize);
        List<Map<String, String>> pieList = new ArrayList<>();
        commandStats.stringPropertyNames().forEach(key -> {
            Map<String, String> data = new HashMap<>(2);
            String property = commandStats.getProperty(key);
            data.put("name", StringUtils.removeStart(key, "cmdstat_"));
            data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
            pieList.add(data);
        });
        result.put("commandStats", pieList);
        return AjaxResult.success(result);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getNames")
    public AjaxResult cache()
    {
        return AjaxResult.success(caches);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getKeys/{cacheName}")
    public AjaxResult getCacheKeys(@PathVariable String cacheName)
    {
        Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
        return AjaxResult.success(cacheKeys);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getValue/{cacheName}/{cacheKey}")
    public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
    {
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
        return AjaxResult.success(sysCache);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheName/{cacheName}")
    public AjaxResult clearCacheName(@PathVariable String cacheName)
    {
        Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
        redisTemplate.delete(cacheKeys);
        return AjaxResult.success();
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheKey/{cacheKey}")
    public AjaxResult clearCacheKey(@PathVariable String cacheKey)
    {
        redisTemplate.delete(cacheKey);
        return AjaxResult.success();
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheAll")
    public AjaxResult clearCacheAll()
    {
        Collection<String> cacheKeys = redisTemplate.keys("*");
        redisTemplate.delete(cacheKeys);
        return AjaxResult.success();
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/ServerController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.jcdm.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.jcdm.common.core.domain.AjaxResult;
import com.jcdm.framework.web.domain.Server;
/**
 * æœåŠ¡å™¨ç›‘控
 *
 * @author jc
 */
@RestController
@RequestMapping("/monitor/server")
public class ServerController
{
    @PreAuthorize("@ss.hasPermi('monitor:server:list')")
    @GetMapping()
    public AjaxResult getInfo() throws Exception
    {
        Server server = new Server();
        server.copyTo();
        return AjaxResult.success(server);
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysLogininforController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
package com.jcdm.web.controller.monitor;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.framework.web.service.SysPasswordService;
import com.jcdm.system.domain.SysLogininfor;
import com.jcdm.system.service.ISysLogininforService;
/**
 * ç³»ç»Ÿè®¿é—®è®°å½•
 *
 * @author jc
 */
@RestController
@RequestMapping("/monitor/logininfor")
public class SysLogininforController extends BaseController
{
    @Autowired
    private ISysLogininforService logininforService;
    @Autowired
    private SysPasswordService passwordService;
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysLogininfor logininfor)
    {
        startPage();
        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
        return getDataTable(list);
    }
    @Log(title = "登录日志", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysLogininfor logininfor)
    {
        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
        ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
        util.exportExcel(response, list, "登录日志");
    }
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
    @Log(title = "登录日志", businessType = BusinessType.DELETE)
    @DeleteMapping("/{infoIds}")
    public AjaxResult remove(@PathVariable Long[] infoIds)
    {
        return toAjax(logininforService.deleteLogininforByIds(infoIds));
    }
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
    @Log(title = "登录日志", businessType = BusinessType.CLEAN)
    @DeleteMapping("/clean")
    public AjaxResult clean()
    {
        logininforService.cleanLogininfor();
        return success();
    }
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
    @Log(title = "账户解锁", businessType = BusinessType.OTHER)
    @GetMapping("/unlock/{userName}")
    public AjaxResult unlock(@PathVariable("userName") String userName)
    {
        passwordService.clearLoginRecordCache(userName);
        return success();
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysOperlogController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.jcdm.web.controller.monitor;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.system.domain.SysOperLog;
import com.jcdm.system.service.ISysOperLogService;
/**
 * æ“ä½œæ—¥å¿—记录
 *
 * @author jc
 */
@RestController
@RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController
{
    @Autowired
    private ISysOperLogService operLogService;
    @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysOperLog operLog)
    {
        startPage();
        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
        return getDataTable(list);
    }
    @Log(title = "操作日志", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysOperLog operLog)
    {
        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
        ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
        util.exportExcel(response, list, "操作日志");
    }
    @Log(title = "操作日志", businessType = BusinessType.DELETE)
    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
    @DeleteMapping("/{operIds}")
    public AjaxResult remove(@PathVariable Long[] operIds)
    {
        return toAjax(operLogService.deleteOperLogByIds(operIds));
    }
    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
    @DeleteMapping("/clean")
    public AjaxResult clean()
    {
        operLogService.cleanOperLog();
        return success();
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/monitor/SysUserOnlineController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
package com.jcdm.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
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.jcdm.common.annotation.Log;
import com.jcdm.common.constant.CacheConstants;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.core.redis.RedisCache;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.system.domain.SysUserOnline;
import com.jcdm.system.service.ISysUserOnlineService;
/**
 * åœ¨çº¿ç”¨æˆ·ç›‘控
 *
 * @author jc
 */
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController
{
    @Autowired
    private ISysUserOnlineService userOnlineService;
    @Autowired
    private RedisCache redisCache;
    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
    @GetMapping("/list")
    public TableDataInfo list(String ipaddr, String userName)
    {
        Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
        for (String key : keys)
        {
            LoginUser user = redisCache.getCacheObject(key);
            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
            {
                userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
            }
            else if (StringUtils.isNotEmpty(ipaddr))
            {
                userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
            }
            else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
            {
                userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
            }
            else
            {
                userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
            }
        }
        Collections.reverse(userOnlineList);
        userOnlineList.removeAll(Collections.singleton(null));
        return getDataTable(userOnlineList);
    }
    /**
     * å¼ºé€€ç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("/{tokenId}")
    public AjaxResult forceLogout(@PathVariable String tokenId)
    {
        redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
        return success();
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysConfigController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,133 @@
package com.jcdm.web.controller.system;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.system.domain.SysConfig;
import com.jcdm.system.service.ISysConfigService;
/**
 * å‚数配置 ä¿¡æ¯æ“ä½œå¤„理
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/config")
public class SysConfigController extends BaseController
{
    @Autowired
    private ISysConfigService configService;
    /**
     * èŽ·å–参数配置列表
     */
    @PreAuthorize("@ss.hasPermi('system:config:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysConfig config)
    {
        startPage();
        List<SysConfig> list = configService.selectConfigList(config);
        return getDataTable(list);
    }
    @Log(title = "参数管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:config:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysConfig config)
    {
        List<SysConfig> list = configService.selectConfigList(config);
        ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
        util.exportExcel(response, list, "参数数据");
    }
    /**
     * æ ¹æ®å‚数编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:config:query')")
    @GetMapping(value = "/{configId}")
    public AjaxResult getInfo(@PathVariable Long configId)
    {
        return success(configService.selectConfigById(configId));
    }
    /**
     * æ ¹æ®å‚数键名查询参数值
     */
    @GetMapping(value = "/configKey/{configKey}")
    public AjaxResult getConfigKey(@PathVariable String configKey)
    {
        return success(configService.selectConfigByKey(configKey));
    }
    /**
     * æ–°å¢žå‚数配置
     */
    @PreAuthorize("@ss.hasPermi('system:config:add')")
    @Log(title = "参数管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysConfig config)
    {
        if (!configService.checkConfigKeyUnique(config))
        {
            return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
        }
        config.setCreateBy(getUsername());
        return toAjax(configService.insertConfig(config));
    }
    /**
     * ä¿®æ”¹å‚数配置
     */
    @PreAuthorize("@ss.hasPermi('system:config:edit')")
    @Log(title = "参数管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysConfig config)
    {
        if (!configService.checkConfigKeyUnique(config))
        {
            return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
        }
        config.setUpdateBy(getUsername());
        return toAjax(configService.updateConfig(config));
    }
    /**
     * åˆ é™¤å‚数配置
     */
    @PreAuthorize("@ss.hasPermi('system:config:remove')")
    @Log(title = "参数管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{configIds}")
    public AjaxResult remove(@PathVariable Long[] configIds)
    {
        configService.deleteConfigByIds(configIds);
        return success();
    }
    /**
     * åˆ·æ–°å‚数缓存
     */
    @PreAuthorize("@ss.hasPermi('system:config:remove')")
    @Log(title = "参数管理", businessType = BusinessType.CLEAN)
    @DeleteMapping("/refreshCache")
    public AjaxResult refreshCache()
    {
        configService.resetConfigCache();
        return success();
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDeptController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,132 @@
package com.jcdm.web.controller.system;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.constant.UserConstants;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysDept;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.system.service.ISysDeptService;
/**
 * éƒ¨é—¨ä¿¡æ¯
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController
{
    @Autowired
    private ISysDeptService deptService;
    /**
     * èŽ·å–部门列表
     */
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list")
    public AjaxResult list(SysDept dept)
    {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return success(depts);
    }
    /**
     * æŸ¥è¯¢éƒ¨é—¨åˆ—表(排除节点)
     */
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list/exclude/{deptId}")
    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
    {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return success(depts);
    }
    /**
     * æ ¹æ®éƒ¨é—¨ç¼–号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:dept:query')")
    @GetMapping(value = "/{deptId}")
    public AjaxResult getInfo(@PathVariable Long deptId)
    {
        deptService.checkDeptDataScope(deptId);
        return success(deptService.selectDeptById(deptId));
    }
    /**
     * æ–°å¢žéƒ¨é—¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:add')")
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDept dept)
    {
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
        }
        dept.setCreateBy(getUsername());
        return toAjax(deptService.insertDept(dept));
    }
    /**
     * ä¿®æ”¹éƒ¨é—¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDept dept)
    {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
        }
        else if (dept.getParentId().equals(deptId))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
        }
        else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
        {
            return error("该部门包含未停用的子部门!");
        }
        dept.setUpdateBy(getUsername());
        return toAjax(deptService.updateDept(dept));
    }
    /**
     * åˆ é™¤éƒ¨é—¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:remove')")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable Long deptId)
    {
        if (deptService.hasChildByDeptId(deptId))
        {
            return warn("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId))
        {
            return warn("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        return toAjax(deptService.deleteDeptById(deptId));
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictDataController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
package com.jcdm.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysDictData;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.system.service.ISysDictDataService;
import com.jcdm.system.service.ISysDictTypeService;
/**
 * æ•°æ®å­—典信息
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/dict/data")
public class SysDictDataController extends BaseController
{
    @Autowired
    private ISysDictDataService dictDataService;
    @Autowired
    private ISysDictTypeService dictTypeService;
    @PreAuthorize("@ss.hasPermi('system:dict:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysDictData dictData)
    {
        startPage();
        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
        return getDataTable(list);
    }
    @Log(title = "字典数据", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:dict:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysDictData dictData)
    {
        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
        ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
        util.exportExcel(response, list, "字典数据");
    }
    /**
     * æŸ¥è¯¢å­—典数据详细
     */
    @PreAuthorize("@ss.hasPermi('system:dict:query')")
    @GetMapping(value = "/{dictCode}")
    public AjaxResult getInfo(@PathVariable Long dictCode)
    {
        return success(dictDataService.selectDictDataById(dictCode));
    }
    /**
     * æ ¹æ®å­—典类型查询字典数据信息
     */
    @GetMapping(value = "/type/{dictType}")
    public AjaxResult dictType(@PathVariable String dictType)
    {
        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
        if (StringUtils.isNull(data))
        {
            data = new ArrayList<SysDictData>();
        }
        return success(data);
    }
    /**
     * æ–°å¢žå­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:add')")
    @Log(title = "字典数据", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDictData dict)
    {
        dict.setCreateBy(getUsername());
        return toAjax(dictDataService.insertDictData(dict));
    }
    /**
     * ä¿®æ”¹ä¿å­˜å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
    @Log(title = "字典数据", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDictData dict)
    {
        dict.setUpdateBy(getUsername());
        return toAjax(dictDataService.updateDictData(dict));
    }
    /**
     * åˆ é™¤å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{dictCodes}")
    public AjaxResult remove(@PathVariable Long[] dictCodes)
    {
        dictDataService.deleteDictDataByIds(dictCodes);
        return success();
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysDictTypeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,131 @@
package com.jcdm.web.controller.system;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysDictType;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.system.service.ISysDictTypeService;
/**
 * æ•°æ®å­—典信息
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/dict/type")
public class SysDictTypeController extends BaseController
{
    @Autowired
    private ISysDictTypeService dictTypeService;
    @PreAuthorize("@ss.hasPermi('system:dict:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysDictType dictType)
    {
        startPage();
        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
        return getDataTable(list);
    }
    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:dict:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysDictType dictType)
    {
        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
        ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
        util.exportExcel(response, list, "字典类型");
    }
    /**
     * æŸ¥è¯¢å­—典类型详细
     */
    @PreAuthorize("@ss.hasPermi('system:dict:query')")
    @GetMapping(value = "/{dictId}")
    public AjaxResult getInfo(@PathVariable Long dictId)
    {
        return success(dictTypeService.selectDictTypeById(dictId));
    }
    /**
     * æ–°å¢žå­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:add')")
    @Log(title = "字典类型", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDictType dict)
    {
        if (!dictTypeService.checkDictTypeUnique(dict))
        {
            return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
        }
        dict.setCreateBy(getUsername());
        return toAjax(dictTypeService.insertDictType(dict));
    }
    /**
     * ä¿®æ”¹å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDictType dict)
    {
        if (!dictTypeService.checkDictTypeUnique(dict))
        {
            return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
        }
        dict.setUpdateBy(getUsername());
        return toAjax(dictTypeService.updateDictType(dict));
    }
    /**
     * åˆ é™¤å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{dictIds}")
    public AjaxResult remove(@PathVariable Long[] dictIds)
    {
        dictTypeService.deleteDictTypeByIds(dictIds);
        return success();
    }
    /**
     * åˆ·æ–°å­—典缓存
     */
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
    @DeleteMapping("/refreshCache")
    public AjaxResult refreshCache()
    {
        dictTypeService.resetDictCache();
        return success();
    }
    /**
     * èŽ·å–字典选择框列表
     */
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
        return success(dictTypes);
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysIndexController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.jcdm.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.utils.StringUtils;
/**
 * é¦–页
 *
 * @author jc
 */
@RestController
public class SysIndexController
{
    /** ç³»ç»ŸåŸºç¡€é…ç½® */
    @Autowired
    private MesConfig mesConfig;
    /**
     * è®¿é—®é¦–页,提示语
     */
    @RequestMapping("/")
    public String index()
    {
        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", mesConfig.getName(), mesConfig.getVersion());
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysLoginController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.jcdm.web.controller.system;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysMenu;
import com.jcdm.common.core.domain.entity.SysUser;
import com.jcdm.common.core.domain.model.LoginBody;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.framework.web.service.SysLoginService;
import com.jcdm.framework.web.service.SysPermissionService;
import com.jcdm.system.service.ISysMenuService;
/**
 * ç™»å½•éªŒè¯
 *
 * @author jc
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private SysPermissionService permissionService;
    /**
     * ç™»å½•æ–¹æ³•
     *
     * @param loginBody ç™»å½•ä¿¡æ¯
     * @return ç»“æžœ
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // ç”Ÿæˆä»¤ç‰Œ
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }
    /**
     * èŽ·å–用户信息
     *
     * @return ç”¨æˆ·ä¿¡æ¯
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // è§’色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // æƒé™é›†åˆ
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }
    /**
     * èŽ·å–路由信息
     *
     * @return è·¯ç”±ä¿¡æ¯
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysMenuController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,142 @@
package com.jcdm.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.constant.UserConstants;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysMenu;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.system.service.ISysMenuService;
/**
 * èœå•ä¿¡æ¯
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/menu")
public class SysMenuController extends BaseController
{
    @Autowired
    private ISysMenuService menuService;
    /**
     * èŽ·å–菜单列表
     */
    @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @GetMapping("/list")
    public AjaxResult list(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return success(menus);
    }
    /**
     * æ ¹æ®èœå•ç¼–号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:menu:query')")
    @GetMapping(value = "/{menuId}")
    public AjaxResult getInfo(@PathVariable Long menuId)
    {
        return success(menuService.selectMenuById(menuId));
    }
    /**
     * èŽ·å–菜单下拉树列表
     */
    @GetMapping("/treeselect")
    public AjaxResult treeselect(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return success(menuService.buildMenuTreeSelect(menus));
    }
    /**
     * åŠ è½½å¯¹åº”角色菜单列表树
     */
    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
    {
        List<SysMenu> menus = menuService.selectMenuList(getUserId());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
        return ajax;
    }
    /**
     * æ–°å¢žèœå•
     */
    @PreAuthorize("@ss.hasPermi('system:menu:add')")
    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysMenu menu)
    {
        if (!menuService.checkMenuNameUnique(menu))
        {
            return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
        }
        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
        {
            return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
        }
        menu.setCreateBy(getUsername());
        return toAjax(menuService.insertMenu(menu));
    }
    /**
     * ä¿®æ”¹èœå•
     */
    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
    @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysMenu menu)
    {
        if (!menuService.checkMenuNameUnique(menu))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
        }
        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
        }
        else if (menu.getMenuId().equals(menu.getParentId()))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
        }
        menu.setUpdateBy(getUsername());
        return toAjax(menuService.updateMenu(menu));
    }
    /**
     * åˆ é™¤èœå•
     */
    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{menuId}")
    public AjaxResult remove(@PathVariable("menuId") Long menuId)
    {
        if (menuService.hasChildByMenuId(menuId))
        {
            return warn("存在子菜单,不允许删除");
        }
        if (menuService.checkMenuExistRole(menuId))
        {
            return warn("菜单已分配,不允许删除");
        }
        return toAjax(menuService.deleteMenuById(menuId));
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysNoticeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
package com.jcdm.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.system.domain.SysNotice;
import com.jcdm.system.service.ISysNoticeService;
/**
 * å…¬å‘Š ä¿¡æ¯æ“ä½œå¤„理
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController
{
    @Autowired
    private ISysNoticeService noticeService;
    /**
     * èŽ·å–通知公告列表
     */
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysNotice notice)
    {
        startPage();
        List<SysNotice> list = noticeService.selectNoticeList(notice);
        return getDataTable(list);
    }
    /**
     * æ ¹æ®é€šçŸ¥å…¬å‘Šç¼–号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:notice:query')")
    @GetMapping(value = "/{noticeId}")
    public AjaxResult getInfo(@PathVariable Long noticeId)
    {
        return success(noticeService.selectNoticeById(noticeId));
    }
    /**
     * æ–°å¢žé€šçŸ¥å…¬å‘Š
     */
    @PreAuthorize("@ss.hasPermi('system:notice:add')")
    @Log(title = "通知公告", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysNotice notice)
    {
        notice.setCreateBy(getUsername());
        return toAjax(noticeService.insertNotice(notice));
    }
    /**
     * ä¿®æ”¹é€šçŸ¥å…¬å‘Š
     */
    @PreAuthorize("@ss.hasPermi('system:notice:edit')")
    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysNotice notice)
    {
        notice.setUpdateBy(getUsername());
        return toAjax(noticeService.updateNotice(notice));
    }
    /**
     * åˆ é™¤é€šçŸ¥å…¬å‘Š
     */
    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/{noticeIds}")
    public AjaxResult remove(@PathVariable Long[] noticeIds)
    {
        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysPostController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
package com.jcdm.web.controller.system;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.system.domain.SysPost;
import com.jcdm.system.service.ISysPostService;
/**
 * å²—位信息操作处理
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/post")
public class SysPostController extends BaseController
{
    @Autowired
    private ISysPostService postService;
    /**
     * èŽ·å–岗位列表
     */
    @PreAuthorize("@ss.hasPermi('system:post:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysPost post)
    {
        startPage();
        List<SysPost> list = postService.selectPostList(post);
        return getDataTable(list);
    }
    @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:post:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysPost post)
    {
        List<SysPost> list = postService.selectPostList(post);
        ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
        util.exportExcel(response, list, "岗位数据");
    }
    /**
     * æ ¹æ®å²—位编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:post:query')")
    @GetMapping(value = "/{postId}")
    public AjaxResult getInfo(@PathVariable Long postId)
    {
        return success(postService.selectPostById(postId));
    }
    /**
     * æ–°å¢žå²—位
     */
    @PreAuthorize("@ss.hasPermi('system:post:add')")
    @Log(title = "岗位管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysPost post)
    {
        if (!postService.checkPostNameUnique(post))
        {
            return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
        }
        else if (!postService.checkPostCodeUnique(post))
        {
            return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
        }
        post.setCreateBy(getUsername());
        return toAjax(postService.insertPost(post));
    }
    /**
     * ä¿®æ”¹å²—位
     */
    @PreAuthorize("@ss.hasPermi('system:post:edit')")
    @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysPost post)
    {
        if (!postService.checkPostNameUnique(post))
        {
            return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
        }
        else if (!postService.checkPostCodeUnique(post))
        {
            return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
        }
        post.setUpdateBy(getUsername());
        return toAjax(postService.updatePost(post));
    }
    /**
     * åˆ é™¤å²—位
     */
    @PreAuthorize("@ss.hasPermi('system:post:remove')")
    @Log(title = "岗位管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{postIds}")
    public AjaxResult remove(@PathVariable Long[] postIds)
    {
        return toAjax(postService.deletePostByIds(postIds));
    }
    /**
     * èŽ·å–岗位选择框列表
     */
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        List<SysPost> posts = postService.selectPostAll();
        return success(posts);
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysProfileController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
package com.jcdm.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.jcdm.common.annotation.Log;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysUser;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.file.FileUploadUtils;
import com.jcdm.common.utils.file.MimeTypeUtils;
import com.jcdm.framework.web.service.TokenService;
import com.jcdm.system.service.ISysUserService;
/**
 * ä¸ªäººä¿¡æ¯ ä¸šåŠ¡å¤„理
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/user/profile")
public class SysProfileController extends BaseController
{
    @Autowired
    private ISysUserService userService;
    @Autowired
    private TokenService tokenService;
    /**
     * ä¸ªäººä¿¡æ¯
     */
    @GetMapping
    public AjaxResult profile()
    {
        LoginUser loginUser = getLoginUser();
        SysUser user = loginUser.getUser();
        AjaxResult ajax = AjaxResult.success(user);
        ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
        ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
        return ajax;
    }
    /**
     * ä¿®æ”¹ç”¨æˆ·
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult updateProfile(@RequestBody SysUser user)
    {
        LoginUser loginUser = getLoginUser();
        SysUser currentUser = loginUser.getUser();
        currentUser.setNickName(user.getNickName());
        currentUser.setEmail(user.getEmail());
        currentUser.setPhonenumber(user.getPhonenumber());
        currentUser.setSex(user.getSex());
        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
        {
            return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
        }
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
        {
            return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
        }
        if (userService.updateUserProfile(currentUser) > 0)
        {
            // æ›´æ–°ç¼“存用户信息
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改个人信息异常,请联系管理员");
    }
    /**
     * é‡ç½®å¯†ç 
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/updatePwd")
    public AjaxResult updatePwd(String oldPassword, String newPassword)
    {
        LoginUser loginUser = getLoginUser();
        String userName = loginUser.getUsername();
        String password = loginUser.getPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password))
        {
            return error("修改密码失败,旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password))
        {
            return error("新密码不能与旧密码相同");
        }
        newPassword = SecurityUtils.encryptPassword(newPassword);
        if (userService.resetUserPwd(userName, newPassword) > 0)
        {
            // æ›´æ–°ç¼“存用户密码
            loginUser.getUser().setPassword(newPassword);
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改密码异常,请联系管理员");
    }
    /**
     * å¤´åƒä¸Šä¼ 
     */
    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
    @PostMapping("/avatar")
    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
    {
        if (!file.isEmpty())
        {
            LoginUser loginUser = getLoginUser();
            String avatar = FileUploadUtils.upload(MesConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
            {
                AjaxResult ajax = AjaxResult.success();
                ajax.put("imgUrl", avatar);
                // æ›´æ–°ç¼“存用户头像
                loginUser.getUser().setAvatar(avatar);
                tokenService.setLoginUser(loginUser);
                return ajax;
            }
        }
        return error("上传图片异常,请联系管理员");
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRegisterController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package com.jcdm.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.model.RegisterBody;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.framework.web.service.SysRegisterService;
import com.jcdm.system.service.ISysConfigService;
/**
 * æ³¨å†ŒéªŒè¯
 *
 * @author JC
 */
@RestController
public class SysRegisterController extends BaseController
{
    @Autowired
    private SysRegisterService registerService;
    @Autowired
    private ISysConfigService configService;
    @PostMapping("/register")
    public AjaxResult register(@RequestBody RegisterBody user)
    {
        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
        {
            return error("当前系统没有开启注册功能!");
        }
        String msg = registerService.register(user);
        return StringUtils.isEmpty(msg) ? success() : error(msg);
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysRoleController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,262 @@
package com.jcdm.web.controller.system;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysDept;
import com.jcdm.common.core.domain.entity.SysRole;
import com.jcdm.common.core.domain.entity.SysUser;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.framework.web.service.SysPermissionService;
import com.jcdm.framework.web.service.TokenService;
import com.jcdm.system.domain.SysUserRole;
import com.jcdm.system.service.ISysDeptService;
import com.jcdm.system.service.ISysRoleService;
import com.jcdm.system.service.ISysUserService;
/**
 * è§’色信息
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/role")
public class SysRoleController extends BaseController
{
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysDeptService deptService;
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysRole role)
    {
        startPage();
        List<SysRole> list = roleService.selectRoleList(role);
        return getDataTable(list);
    }
    @Log(title = "角色管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:role:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysRole role)
    {
        List<SysRole> list = roleService.selectRoleList(role);
        ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
        util.exportExcel(response, list, "角色数据");
    }
    /**
     * æ ¹æ®è§’色编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping(value = "/{roleId}")
    public AjaxResult getInfo(@PathVariable Long roleId)
    {
        roleService.checkRoleDataScope(roleId);
        return success(roleService.selectRoleById(roleId));
    }
    /**
     * æ–°å¢žè§’色
     */
    @PreAuthorize("@ss.hasPermi('system:role:add')")
    @Log(title = "角色管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysRole role)
    {
        if (!roleService.checkRoleNameUnique(role))
        {
            return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
        }
        else if (!roleService.checkRoleKeyUnique(role))
        {
            return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
        }
        role.setCreateBy(getUsername());
        return toAjax(roleService.insertRole(role));
    }
    /**
     * ä¿®æ”¹ä¿å­˜è§’色
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysRole role)
    {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        if (!roleService.checkRoleNameUnique(role))
        {
            return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
        }
        else if (!roleService.checkRoleKeyUnique(role))
        {
            return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
        }
        role.setUpdateBy(getUsername());
        if (roleService.updateRole(role) > 0)
        {
            // æ›´æ–°ç¼“存用户权限
            LoginUser loginUser = getLoginUser();
            if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
            {
                loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
                loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
                tokenService.setLoginUser(loginUser);
            }
            return success();
        }
        return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
    }
    /**
     * ä¿®æ”¹ä¿å­˜æ•°æ®æƒé™
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping("/dataScope")
    public AjaxResult dataScope(@RequestBody SysRole role)
    {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        return toAjax(roleService.authDataScope(role));
    }
    /**
     * çŠ¶æ€ä¿®æ”¹
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysRole role)
    {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        role.setUpdateBy(getUsername());
        return toAjax(roleService.updateRoleStatus(role));
    }
    /**
     * åˆ é™¤è§’色
     */
    @PreAuthorize("@ss.hasPermi('system:role:remove')")
    @Log(title = "角色管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{roleIds}")
    public AjaxResult remove(@PathVariable Long[] roleIds)
    {
        return toAjax(roleService.deleteRoleByIds(roleIds));
    }
    /**
     * èŽ·å–角色选择框列表
     */
    @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        return success(roleService.selectRoleAll());
    }
    /**
     * æŸ¥è¯¢å·²åˆ†é…ç”¨æˆ·è§’色列表
     */
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/allocatedList")
    public TableDataInfo allocatedList(SysUser user)
    {
        startPage();
        List<SysUser> list = userService.selectAllocatedList(user);
        return getDataTable(list);
    }
    /**
     * æŸ¥è¯¢æœªåˆ†é…ç”¨æˆ·è§’色列表
     */
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/unallocatedList")
    public TableDataInfo unallocatedList(SysUser user)
    {
        startPage();
        List<SysUser> list = userService.selectUnallocatedList(user);
        return getDataTable(list);
    }
    /**
     * å–消授权用户
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancel")
    public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
    {
        return toAjax(roleService.deleteAuthUser(userRole));
    }
    /**
     * æ‰¹é‡å–消授权用户
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancelAll")
    public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
    {
        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
    }
    /**
     * æ‰¹é‡é€‰æ‹©ç”¨æˆ·æŽˆæƒ
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/selectAll")
    public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
    {
        roleService.checkRoleDataScope(roleId);
        return toAjax(roleService.insertAuthUsers(roleId, userIds));
    }
    /**
     * èŽ·å–对应角色部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping(value = "/deptTree/{roleId}")
    public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
    {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
        return ajax;
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/system/SysUserController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,251 @@
package com.jcdm.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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 org.springframework.web.multipart.MultipartFile;
import com.jcdm.common.annotation.Log;
import com.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.entity.SysDept;
import com.jcdm.common.core.domain.entity.SysRole;
import com.jcdm.common.core.domain.entity.SysUser;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.enums.BusinessType;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.poi.ExcelUtil;
import com.jcdm.system.service.ISysDeptService;
import com.jcdm.system.service.ISysPostService;
import com.jcdm.system.service.ISysRoleService;
import com.jcdm.system.service.ISysUserService;
/**
 * ç”¨æˆ·ä¿¡æ¯
 *
 * @author jc
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private ISysPostService postService;
    /**
     * èŽ·å–用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user)
    {
        startPage();
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }
    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysUser user)
    {
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, list, "用户数据");
    }
    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return success(message);
    }
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response)
    {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }
    /**
     * æ ¹æ®ç”¨æˆ·ç¼–号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = { "/", "/{userId}" })
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
    {
        userService.checkUserDataScope(userId);
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId))
        {
            SysUser sysUser = userService.selectUserById(userId);
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
        }
        return ajax;
    }
    /**
     * æ–°å¢žç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user)
    {
        if (!userService.checkUserNameUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }
    /**
     * ä¿®æ”¹ç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        if (!userService.checkUserNameUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUser(user));
    }
    /**
     * åˆ é™¤ç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds)
    {
        if (ArrayUtils.contains(userIds, getUserId()))
        {
            return error("当前用户不能删除");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }
    /**
     * é‡ç½®å¯†ç 
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }
    /**
     * çŠ¶æ€ä¿®æ”¹
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserStatus(user));
    }
    /**
     * æ ¹æ®ç”¨æˆ·ç¼–号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId)
    {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }
    /**
     * ç”¨æˆ·æŽˆæƒè§’色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
    {
        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return success();
    }
    /**
     * èŽ·å–部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept)
    {
        return success(deptService.selectDeptTreeList(dept));
    }
}
jcdm-admin/src/main/java/com/jcdm/web/controller/tool/TestController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,183 @@
package com.jcdm.web.controller.tool;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
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.jcdm.common.core.controller.BaseController;
import com.jcdm.common.core.domain.R;
import com.jcdm.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
/**
 * swagger ç”¨æˆ·æµ‹è¯•æ–¹æ³•
 *
 * @author jc
 */
@Api("用户信息管理")
@RestController
@RequestMapping("/test/user")
public class TestController extends BaseController
{
    private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
    {
        users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
        users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
    }
    @ApiOperation("获取用户列表")
    @GetMapping("/list")
    public R<List<UserEntity>> userList()
    {
        List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
        return R.ok(userList);
    }
    @ApiOperation("获取用户详细")
    @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
    @GetMapping("/{userId}")
    public R<UserEntity> getUser(@PathVariable Integer userId)
    {
        if (!users.isEmpty() && users.containsKey(userId))
        {
            return R.ok(users.get(userId));
        }
        else
        {
            return R.fail("用户不存在");
        }
    }
    @ApiOperation("新增用户")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
        @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
        @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
        @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
    })
    @PostMapping("/save")
    public R<String> save(UserEntity user)
    {
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
        {
            return R.fail("用户ID不能为空");
        }
        users.put(user.getUserId(), user);
        return R.ok();
    }
    @ApiOperation("更新用户")
    @PutMapping("/update")
    public R<String> update(@RequestBody UserEntity user)
    {
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
        {
            return R.fail("用户ID不能为空");
        }
        if (users.isEmpty() || !users.containsKey(user.getUserId()))
        {
            return R.fail("用户不存在");
        }
        users.remove(user.getUserId());
        users.put(user.getUserId(), user);
        return R.ok();
    }
    @ApiOperation("删除用户信息")
    @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
    @DeleteMapping("/{userId}")
    public R<String> delete(@PathVariable Integer userId)
    {
        if (!users.isEmpty() && users.containsKey(userId))
        {
            users.remove(userId);
            return R.ok();
        }
        else
        {
            return R.fail("用户不存在");
        }
    }
}
@ApiModel(value = "UserEntity", description = "用户实体")
class UserEntity
{
    @ApiModelProperty("用户ID")
    private Integer userId;
    @ApiModelProperty("用户名称")
    private String username;
    @ApiModelProperty("用户密码")
    private String password;
    @ApiModelProperty("用户手机")
    private String mobile;
    public UserEntity()
    {
    }
    public UserEntity(Integer userId, String username, String password, String mobile)
    {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.mobile = mobile;
    }
    public Integer getUserId()
    {
        return userId;
    }
    public void setUserId(Integer userId)
    {
        this.userId = userId;
    }
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getMobile()
    {
        return mobile;
    }
    public void setMobile(String mobile)
    {
        this.mobile = mobile;
    }
}
jcdm-admin/src/main/java/com/jcdm/web/core/config/SwaggerConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,125 @@
package com.jcdm.web.core.config;
import java.util.ArrayList;
import java.util.List;
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.jcdm.common.config.MesConfig;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
/**
 * Swagger2的接口配置
 *
 * @author jc
 */
@Configuration
public class SwaggerConfig
{
    /** ç³»ç»ŸåŸºç¡€é…ç½® */
    @Autowired
    private MesConfig mesConfig;
    /** æ˜¯å¦å¼€å¯swagger */
    @Value("${swagger.enabled}")
    private boolean enabled;
    /** è®¾ç½®è¯·æ±‚的统一前缀 */
    @Value("${swagger.pathMapping}")
    private String pathMapping;
    /**
     * åˆ›å»ºAPI
     */
    @Bean
    public Docket createRestApi()
    {
        return new Docket(DocumentationType.OAS_30)
                // æ˜¯å¦å¯ç”¨Swagger
                .enable(enabled)
                // ç”¨æ¥åˆ›å»ºè¯¥API的基本信息,展示在文档的页面中(自定义展示的信息)
                .apiInfo(apiInfo())
                // è®¾ç½®å“ªäº›æŽ¥å£æš´éœ²ç»™Swagger展示
                .select()
                // æ‰«ææ‰€æœ‰æœ‰æ³¨è§£çš„api,用这种方式更灵活
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                // æ‰«ææŒ‡å®šåŒ…中的swagger注解
                // .apis(RequestHandlerSelectors.basePackage("com.jcdm.project.tool.swagger"))
                // æ‰«ææ‰€æœ‰ .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                /* è®¾ç½®å®‰å…¨æ¨¡å¼ï¼Œswagger可以设置访问token */
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .pathMapping(pathMapping);
    }
    /**
     * å®‰å…¨æ¨¡å¼ï¼Œè¿™é‡ŒæŒ‡å®štoken通过Authorization头请求头传递
     */
    private List<SecurityScheme> securitySchemes()
    {
        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
        return apiKeyList;
    }
    /**
     * å®‰å…¨ä¸Šä¸‹æ–‡
     */
    private List<SecurityContext> securityContexts()
    {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                        .build());
        return securityContexts;
    }
    /**
     * é»˜è®¤çš„安全上引用
     */
    private List<SecurityReference> defaultAuth()
    {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }
    /**
     * æ·»åŠ æ‘˜è¦ä¿¡æ¯
     */
    private ApiInfo apiInfo()
    {
        // ç”¨ApiInfoBuilder进行定制
        return new ApiInfoBuilder()
                // è®¾ç½®æ ‡é¢˜
                .title("标题:江宸MES管理系统_接口文档")
                // æè¿°
                .description("描述:用于工厂生产现场管理")
                // ä½œè€…信息
                .contact(new Contact(mesConfig.getName(), null, null))
                // ç‰ˆæœ¬
                .version("版本号:" + mesConfig.getVersion())
                .build();
    }
}
jcdm-admin/src/main/resources/META-INF/spring-devtools.properties
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
restart.include.json=/com.alibaba.fastjson.*.jar
jcdm-admin/src/main/resources/application-druid.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
# æ•°æ®æºé…ç½®
spring:
#    datasource:
#        type: com.alibaba.druid.pool.DruidDataSource
#        driverClassName: com.mysql.cj.jdbc.Driver
#        druid:
#            # ä¸»åº“数据源
#            master:
#                url: jdbc:mysql://192.168.0.189:3306/jcdm-mes-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#                username: root
#                password: root
    # æ•°æ®æºé…ç½®
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
        druid:
            # ä¸»åº“数据源
            master:
                url: jdbc:sqlserver://192.168.0.189:1433;DataBaseName=jcdm-mes
                username: sa
                password: JCDM@2023
            # ä»Žåº“数据源
            slave:
                # ä»Žæ•°æ®æºå¼€å…³/默认关闭
                enabled: false
                url:
                username:
                password:
            # åˆå§‹è¿žæŽ¥æ•°
            initialSize: 5
            # æœ€å°è¿žæŽ¥æ± æ•°é‡
            minIdle: 10
            # æœ€å¤§è¿žæŽ¥æ± æ•°é‡
            maxActive: 20
            # é…ç½®èŽ·å–连接等待超时的时间
            maxWait: 60000
            # é…ç½®è¿žæŽ¥è¶…时时间
            connectTimeout: 30000
            # é…ç½®ç½‘络超时时间
            socketTimeout: 60000
            # é…ç½®é—´éš”多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å°ç”Ÿå­˜çš„时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å¤§ç”Ÿå­˜çš„时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # é…ç½®æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ
#            validationQuery: SELECT 1 FROM DUAL
            validationQuery: SELECT 1
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # è®¾ç½®ç™½åå•ï¼Œä¸å¡«åˆ™å…è®¸æ‰€æœ‰è®¿é—®
                allow:
                url-pattern: /druid/*
                # æŽ§åˆ¶å°ç®¡ç†ç”¨æˆ·åå’Œå¯†ç 
                login-username: jcdm
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # æ…¢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true
jcdm-admin/src/main/resources/application.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,132 @@
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  # åç§°
  name: RuoYi
  # ç‰ˆæœ¬
  version: 3.8.6
  # ç‰ˆæƒå¹´ä»½
  copyrightYear: 2023
  # å®žä¾‹æ¼”示开关
  demoEnabled: true
  # æ–‡ä»¶è·¯å¾„ ç¤ºä¾‹ï¼ˆ Windows配置D:/jcdm/uploadPath,Linux配置 /home/jcdm/uploadPath)
  profile: D:/mes/uploadPath
  # èŽ·å–ip地址开关
  addressEnabled: false
  # éªŒè¯ç ç±»åž‹ math æ•°å­—计算 char å­—符验证
  captchaType: math
# å¼€å‘环境配置
server:
  # æœåŠ¡å™¨çš„HTTP端口,默认为8080
  port: 8080
  servlet:
    # åº”用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # è¿žæŽ¥æ•°æ»¡åŽçš„排队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# æ—¥å¿—配置
logging:
  level:
    com.jcdm: debug
    org.springframework: warn
# ç”¨æˆ·é…ç½®
user:
  password:
    # å¯†ç æœ€å¤§é”™è¯¯æ¬¡æ•°
    maxRetryCount: 5
    # å¯†ç é”å®šæ—¶é—´ï¼ˆé»˜è®¤10分钟)
    lockTime: 10
# Spring配置
spring:
  # èµ„源信息
  messages:
    # å›½é™…化资源文件路径
    basename: i18n/messages
  profiles:
    active: druid
  # æ–‡ä»¶ä¸Šä¼ 
  servlet:
    multipart:
      # å•ä¸ªæ–‡ä»¶å¤§å°
      max-file-size: 10MB
      # è®¾ç½®æ€»ä¸Šä¼ çš„文件大小
      max-request-size: 20MB
  # æœåŠ¡æ¨¡å—
  devtools:
    restart:
      # çƒ­éƒ¨ç½²å¼€å…³
      enabled: true
  # redis é…ç½®
#  redis:
#    # åœ°å€
#    host: localhost
#    # ç«¯å£ï¼Œé»˜è®¤ä¸º6379
#    port: 6379
#    # æ•°æ®åº“索引
#    database: 0
#    # å¯†ç 
#    password:
#    # è¿žæŽ¥è¶…时时间
#    timeout: 10s
#    lettuce:
#      pool:
#        # è¿žæŽ¥æ± ä¸­çš„最小空闲连接
#        min-idle: 0
#        # è¿žæŽ¥æ± ä¸­çš„最大空闲连接
#        max-idle: 8
#        # è¿žæŽ¥æ± çš„最大数据库连接数
#        max-active: 8
#        # #连接池最大阻塞等待时间(使用负值表示没有限制)
#        max-wait: -1ms
# token配置
token:
  # ä»¤ç‰Œè‡ªå®šä¹‰æ ‡è¯†
  header: Authorization
  # ä»¤ç‰Œå¯†é’¥
  secret: abcdefghijklmnopqrstuvwxyz
  # ä»¤ç‰Œæœ‰æ•ˆæœŸï¼ˆé»˜è®¤30分钟)
  expireTime: 30
# MyBatis配置
mybatis:
  # æœç´¢æŒ‡å®šåŒ…别名
  typeAliasesPackage: com.jcdm.**.domain
  # é…ç½®mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # åŠ è½½å…¨å±€çš„配置文件
  configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
#  helperDialect: mysql
  supportMethodsArguments: true
  params: count=countSql
  autoRuntimeDialect: true
# Swagger配置
swagger:
  # æ˜¯å¦å¼€å¯swagger
  enabled: true
  # è¯·æ±‚前缀
  pathMapping: /dev-api
# é˜²æ­¢XSS攻击
xss:
  # è¿‡æ»¤å¼€å…³
  enabled: true
  # æŽ’除链接(多个用逗号分隔)
  excludes: /system/notice
  # åŒ¹é…é“¾æŽ¥
  urlPatterns: /system/*,/monitor/*,/tool/*
jcdm-admin/src/main/resources/banner.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
Application Version: ${ruoyi.version}
Spring Boot Version: ${spring-boot.version}
////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O\  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \\|     |//  `.                         //
//                   /  \\|||  :  |||//  \                        //
//                  /  _||||| -:- |||||-  \                       //
//                  |   | \\\  -  /// |   |                       //
//                  | \_|  ''\---/''  |   |                       //
//                  \  .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--\  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//             ä½›ç¥–保佑       æ°¸ä¸å®•æœº      æ°¸æ— BUG               //
////////////////////////////////////////////////////////////////////
jcdm-admin/src/main/resources/i18n/messages.properties
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
#错误消息
not.null=* å¿…须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=用户不存在/密码错误
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号已被删除
user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员
login.blocked=很遗憾,访问IP已被列入系统黑名单
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
jcdm-admin/src/main/resources/logback.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- æ—¥å¿—存放路径 -->
    <property name="log.path" value="/home/mes/logs" />
    <!-- æ—¥å¿—输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
    <!-- æŽ§åˆ¶å°è¾“出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
    <!-- ç³»ç»Ÿæ—¥å¿—输出 -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-info.log</file>
        <!-- å¾ªçŽ¯æ”¿ç­–:基于时间创建日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æ—¥å¿—文件名格式 -->
            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- è¿‡æ»¤çš„级别 -->
            <level>INFO</level>
            <!-- åŒ¹é…æ—¶çš„操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- ä¸åŒ¹é…æ—¶çš„操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-error.log</file>
        <!-- å¾ªçŽ¯æ”¿ç­–:基于时间创建日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æ—¥å¿—文件名格式 -->
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- è¿‡æ»¤çš„级别 -->
            <level>ERROR</level>
            <!-- åŒ¹é…æ—¶çš„操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- ä¸åŒ¹é…æ—¶çš„操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- ç”¨æˆ·è®¿é—®æ—¥å¿—输出  -->
    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-user.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æŒ‰å¤©å›žæ»š daily -->
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
    <!-- ç³»ç»Ÿæ¨¡å—日志级别控制  -->
    <logger name="com.jcdm" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
    <root level="info">
        <appender-ref ref="console" />
    </root>
    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
    <!--系统用户操作日志-->
    <logger name="sys-user" level="info">
        <appender-ref ref="sys-user"/>
    </logger>
</configuration>
jcdm-admin/src/main/resources/mybatis/mybatis-config.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- å…¨å±€å‚æ•° -->
    <settings>
        <!-- ä½¿å…¨å±€çš„映射器启用或禁用缓存 -->
        <setting name="cacheEnabled"             value="true"   />
        <!-- å…è®¸JDBC æ”¯æŒè‡ªåŠ¨ç”Ÿæˆä¸»é”® -->
        <setting name="useGeneratedKeys"         value="true"   />
        <!-- é…ç½®é»˜è®¤çš„执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
        <setting name="defaultExecutorType"      value="SIMPLE" />
        <!-- æŒ‡å®š MyBatis æ‰€ç”¨æ—¥å¿—的具体实现 -->
        <setting name="logImpl"                  value="SLF4J"  />
        <!-- ä½¿ç”¨é©¼å³°å‘½åæ³•è½¬æ¢å­—段 -->
        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
    </settings>
</configuration>
jcdm-common/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>jcdm</artifactId>
        <groupId>com.jcdm</groupId>
        <version>3.8.6</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>jcdm-common</artifactId>
    <description>
        common通用工具
    </description>
    <dependencies>
        <!-- Spring框架基本的核心工具 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- SpringWeb模块 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <!-- spring security å®‰å…¨è®¤è¯ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- pagehelper åˆ†é¡µæ’件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
        <!-- mybatis-plus å¢žå¼ºCRUD -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!-- è‡ªå®šä¹‰éªŒè¯æ³¨è§£ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!--常用工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!-- JSON工具类 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <!-- åŠ¨æ€æ•°æ®æº -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- é˜¿é‡ŒJSON解析器 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>
        <!-- io常用工具类 -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </dependency>
        <!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>
        <!-- yml解析器 -->
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
        </dependency>
        <!-- Token生成与解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <!-- Jaxb -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <!-- redis ç¼“存操作 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- pool å¯¹è±¡æ±  -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- è§£æžå®¢æˆ·ç«¯æ“ä½œç³»ç»Ÿã€æµè§ˆå™¨ç­‰ -->
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
        </dependency>
        <!-- servlet包 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <!-- mybatis-plus å¢žå¼ºCRUD -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
    </dependencies>
</project>
jcdm-common/src/main/java/com/jcdm/common/annotation/Anonymous.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.jcdm.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;
/**
 * åŒ¿åè®¿é—®ä¸é‰´æƒæ³¨è§£
 *
 * @author jc
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous
{
}
jcdm-common/src/main/java/com/jcdm/common/annotation/DataScope.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.jcdm.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;
/**
 * æ•°æ®æƒé™è¿‡æ»¤æ³¨è§£
 *
 * @author jc
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{
    /**
     * éƒ¨é—¨è¡¨çš„别名
     */
    public String deptAlias() default "";
    /**
     * ç”¨æˆ·è¡¨çš„别名
     */
    public String userAlias() default "";
    /**
     * æƒé™å­—符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
     */
    public String permission() default "";
}
jcdm-common/src/main/java/com/jcdm/common/annotation/DataSource.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.jcdm.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;
import com.jcdm.common.enums.DataSourceType;
/**
 * è‡ªå®šä¹‰å¤šæ•°æ®æºåˆ‡æ¢æ³¨è§£
 *
 * ä¼˜å…ˆçº§ï¼šå…ˆæ–¹æ³•ï¼ŒåŽç±»ï¼Œå¦‚果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
 *
 * @author jc
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
    /**
     * åˆ‡æ¢æ•°æ®æºåç§°
     */
    public DataSourceType value() default DataSourceType.MASTER;
}
jcdm-common/src/main/java/com/jcdm/common/annotation/Excel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,187 @@
package com.jcdm.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.jcdm.common.utils.poi.ExcelHandlerAdapter;
/**
 * è‡ªå®šä¹‰å¯¼å‡ºExcel数据注解
 *
 * @author jc
 */
@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 "";
    /**
     * å¦‚果是字典类型,请设置字典的type值 (如: sys_user_sex)
     */
    public String dictType() default "";
    /**
     * è¯»å–内容转表达式 (如: 0=男,1=女,2=未知)
     */
    public String readConverterExp() default "";
    /**
     * åˆ†éš”符,读取字符串组内容
     */
    public String separator() default ",";
    /**
     * BigDecimal ç²¾åº¦ é»˜è®¤:-1(默认不开启BigDecimal格式化)
     */
    public int scale() default -1;
    /**
     * BigDecimal èˆå…¥è§„则 é»˜è®¤:BigDecimal.ROUND_HALF_EVEN
     */
    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
    /**
     * å¯¼å‡ºæ—¶åœ¨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 {};
    /**
     * æ˜¯å¦éœ€è¦çºµå‘合并单元格,应对需求:含有list集合单元格)
     */
    public boolean needMerge() default false;
    /**
     * æ˜¯å¦å¯¼å‡ºæ•°æ®,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
     */
    public boolean isExport() default true;
    /**
     * å¦ä¸€ä¸ªç±»ä¸­çš„属性名称,支持多级获取,以小数点隔开
     */
    public String targetAttr() default "";
    /**
     * æ˜¯å¦è‡ªåŠ¨ç»Ÿè®¡æ•°æ®,在最后追加一行统计数据总和
     */
    public boolean isStatistics() default false;
    /**
     * å¯¼å‡ºç±»åž‹ï¼ˆ0数字 1字符串 2图片)
     */
    public ColumnType cellType() default ColumnType.STRING;
    /**
     * å¯¼å‡ºåˆ—头背景颜色
     */
    public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
    /**
     * å¯¼å‡ºåˆ—头字体颜色
     */
    public IndexedColors headerColor() default IndexedColors.WHITE;
    /**
     * å¯¼å‡ºå•å…ƒæ ¼èƒŒæ™¯é¢œè‰²
     */
    public IndexedColors backgroundColor() default IndexedColors.WHITE;
    /**
     * å¯¼å‡ºå•å…ƒæ ¼å­—体颜色
     */
    public IndexedColors color() default IndexedColors.BLACK;
    /**
     * å¯¼å‡ºå­—段对齐方式
     */
    public HorizontalAlignment align() default HorizontalAlignment.CENTER;
    /**
     * è‡ªå®šä¹‰æ•°æ®å¤„理器
     */
    public Class<?> handler() default ExcelHandlerAdapter.class;
    /**
     * è‡ªå®šä¹‰æ•°æ®å¤„理器参数
     */
    public String[] args() 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), IMAGE(2);
        private final int value;
        ColumnType(int value)
        {
            this.value = value;
        }
        public int value()
        {
            return this.value;
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/annotation/Excels.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.jcdm.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Excel注解集
 *
 * @author jc
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
    public Excel[] value();
}
jcdm-common/src/main/java/com/jcdm/common/annotation/Log.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
package com.jcdm.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.jcdm.common.enums.BusinessType;
import com.jcdm.common.enums.OperatorType;
/**
 * è‡ªå®šä¹‰æ“ä½œæ—¥å¿—记录注解
 *
 * @author jc
 *
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * æ¨¡å—
     */
    public String title() default "";
    /**
     * åŠŸèƒ½
     */
    public BusinessType businessType() default BusinessType.OTHER;
    /**
     * æ“ä½œäººç±»åˆ«
     */
    public OperatorType operatorType() default OperatorType.MANAGE;
    /**
     * æ˜¯å¦ä¿å­˜è¯·æ±‚的参数
     */
    public boolean isSaveRequestData() default true;
    /**
     * æ˜¯å¦ä¿å­˜å“åº”的参数
     */
    public boolean isSaveResponseData() default true;
    /**
     * æŽ’除指定的请求参数
     */
    public String[] excludeParamNames() default {};
}
jcdm-common/src/main/java/com/jcdm/common/annotation/RateLimiter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.jcdm.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.jcdm.common.constant.CacheConstants;
import com.jcdm.common.enums.LimitType;
/**
 * é™æµæ³¨è§£
 *
 * @author jc
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
    /**
     * é™æµkey
     */
    public String key() default CacheConstants.RATE_LIMIT_KEY;
    /**
     * é™æµæ—¶é—´,单位秒
     */
    public int time() default 60;
    /**
     * é™æµæ¬¡æ•°
     */
    public int count() default 100;
    /**
     * é™æµç±»åž‹
     */
    public LimitType limitType() default LimitType.DEFAULT;
}
jcdm-common/src/main/java/com/jcdm/common/annotation/RepeatSubmit.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.jcdm.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 jc
 *
 */
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmit
{
    /**
     * é—´éš”时间(ms),小于此时间视为重复提交
     */
    public int interval() default 5000;
    /**
     * æç¤ºæ¶ˆæ¯
     */
    public String message() default "不允许重复提交,请稍候再试";
}
jcdm-common/src/main/java/com/jcdm/common/config/MesConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,135 @@
package com.jcdm.common.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * è¯»å–项目相关配置
 *
 * @author jc
 */
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class MesConfig
{
    /** é¡¹ç›®åç§° */
    private String name;
    /** ç‰ˆæœ¬ */
    private String version;
    /** ç‰ˆæƒå¹´ä»½ */
    private String copyrightYear;
    /** å®žä¾‹æ¼”示开关 */
    private boolean demoEnabled;
    /** ä¸Šä¼ è·¯å¾„ */
    private static String profile;
    /** èŽ·å–地址开关 */
    private static boolean addressEnabled;
    /** éªŒè¯ç ç±»åž‹ */
    private static String captchaType;
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public String getVersion()
    {
        return version;
    }
    public void setVersion(String version)
    {
        this.version = version;
    }
    public String getCopyrightYear()
    {
        return copyrightYear;
    }
    public void setCopyrightYear(String copyrightYear)
    {
        this.copyrightYear = copyrightYear;
    }
    public boolean isDemoEnabled()
    {
        return demoEnabled;
    }
    public void setDemoEnabled(boolean demoEnabled)
    {
        this.demoEnabled = demoEnabled;
    }
    public static String getProfile()
    {
        return profile;
    }
    public void setProfile(String profile)
    {
        MesConfig.profile = profile;
    }
    public static boolean isAddressEnabled()
    {
        return addressEnabled;
    }
    public void setAddressEnabled(boolean addressEnabled)
    {
        MesConfig.addressEnabled = addressEnabled;
    }
    public static String getCaptchaType() {
        return captchaType;
    }
    public void setCaptchaType(String captchaType) {
        MesConfig.captchaType = captchaType;
    }
    /**
     * èŽ·å–导入上传路径
     */
    public static String getImportPath()
    {
        return getProfile() + "/import";
    }
    /**
     * èŽ·å–头像上传路径
     */
    public static String getAvatarPath()
    {
        return getProfile() + "/avatar";
    }
    /**
     * èŽ·å–下载路径
     */
    public static String getDownloadPath()
    {
        return getProfile() + "/download/";
    }
    /**
     * èŽ·å–上传路径
     */
    public static String getUploadPath()
    {
        return getProfile() + "/upload";
    }
}
jcdm-common/src/main/java/com/jcdm/common/constant/CacheConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.jcdm.common.constant;
/**
 * ç¼“存的key å¸¸é‡
 *
 * @author jc
 */
public class CacheConstants
{
    /**
     * ç™»å½•ç”¨æˆ· redis key
     */
    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
    /**
     * éªŒè¯ç  redis key
     */
    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
    /**
     * å‚数管理 cache key
     */
    public static final String SYS_CONFIG_KEY = "sys_config:";
    /**
     * å­—典管理 cache key
     */
    public static final String SYS_DICT_KEY = "sys_dict:";
    /**
     * é˜²é‡æäº¤ redis key
     */
    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
    /**
     * é™æµ redis key
     */
    public static final String RATE_LIMIT_KEY = "rate_limit:";
    /**
     * ç™»å½•è´¦æˆ·å¯†ç é”™è¯¯æ¬¡æ•° redis key
     */
    public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
}
jcdm-common/src/main/java/com/jcdm/common/constant/Constants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
package com.jcdm.common.constant;
import io.jsonwebtoken.Claims;
/**
 * é€šç”¨å¸¸é‡ä¿¡æ¯
 *
 * @author jc
 */
public class Constants
{
    /**
     * UTF-8 å­—符集
     */
    public static final String UTF8 = "UTF-8";
    /**
     * GBK å­—符集
     */
    public static final String GBK = "GBK";
    /**
     * www主域
     */
    public static final String WWW = "www.";
    /**
     * http请求
     */
    public static final String HTTP = "http://";
    /**
     * https请求
     */
    public static final String HTTPS = "https://";
    /**
     * é€šç”¨æˆåŠŸæ ‡è¯†
     */
    public static final String SUCCESS = "0";
    /**
     * é€šç”¨å¤±è´¥æ ‡è¯†
     */
    public static final String FAIL = "1";
    /**
     * ç™»å½•æˆåŠŸ
     */
    public static final String LOGIN_SUCCESS = "Success";
    /**
     * æ³¨é”€
     */
    public static final String LOGOUT = "Logout";
    /**
     * æ³¨å†Œ
     */
    public static final String REGISTER = "Register";
    /**
     * ç™»å½•å¤±è´¥
     */
    public static final String LOGIN_FAIL = "Error";
    /**
     * æ‰€æœ‰æƒé™æ ‡è¯†
     */
    public static final String ALL_PERMISSION = "*:*:*";
    /**
     * ç®¡ç†å‘˜è§’色权限标识
     */
    public static final String SUPER_ADMIN = "admin";
    /**
     * è§’色权限分隔符
     */
    public static final String ROLE_DELIMETER = ",";
    /**
     * æƒé™æ ‡è¯†åˆ†éš”符
     */
    public static final String PERMISSION_DELIMETER = ",";
    /**
     * éªŒè¯ç æœ‰æ•ˆæœŸï¼ˆåˆ†é’Ÿï¼‰
     */
    public static final Integer CAPTCHA_EXPIRATION = 2;
    /**
     * ä»¤ç‰Œ
     */
    public static final String TOKEN = "token";
    /**
     * ä»¤ç‰Œå‰ç¼€
     */
    public static final String TOKEN_PREFIX = "Bearer ";
    /**
     * ä»¤ç‰Œå‰ç¼€
     */
    public static final String LOGIN_USER_KEY = "login_user_key";
    /**
     * ç”¨æˆ·ID
     */
    public static final String JWT_USERID = "userid";
    /**
     * ç”¨æˆ·åç§°
     */
    public static final String JWT_USERNAME = Claims.SUBJECT;
    /**
     * ç”¨æˆ·å¤´åƒ
     */
    public static final String JWT_AVATAR = "avatar";
    /**
     * åˆ›å»ºæ—¶é—´
     */
    public static final String JWT_CREATED = "created";
    /**
     * ç”¨æˆ·æƒé™
     */
    public static final String JWT_AUTHORITIES = "authorities";
    /**
     * èµ„源映射路径 å‰ç¼€
     */
    public static final String RESOURCE_PREFIX = "/profile";
    /**
     * RMI è¿œç¨‹æ–¹æ³•è°ƒç”¨
     */
    public static final String LOOKUP_RMI = "rmi:";
    /**
     * LDAP è¿œç¨‹æ–¹æ³•è°ƒç”¨
     */
    public static final String LOOKUP_LDAP = "ldap:";
    /**
     * LDAPS è¿œç¨‹æ–¹æ³•è°ƒç”¨
     */
    public static final String LOOKUP_LDAPS = "ldaps:";
    /**
     * è‡ªåŠ¨è¯†åˆ«json对象白名单配置(仅允许解析的包名,范围越小越安全)
     */
    public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.jcdm" };
    /**
     * å®šæ—¶ä»»åŠ¡ç™½åå•é…ç½®ï¼ˆä»…允许访问的包名,如其他需要可以自行添加)
     */
    public static final String[] JOB_WHITELIST_STR = { "com.jcdm" };
    /**
     * å®šæ—¶ä»»åŠ¡è¿è§„的字符
     */
    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
            "org.springframework", "org.apache", "com.jcdm.common.utils.file", "com.jcdm.common.config" };
}
jcdm-common/src/main/java/com/jcdm/common/constant/GenConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
package com.jcdm.common.constant;
/**
 * ä»£ç ç”Ÿæˆé€šç”¨å¸¸é‡
 *
 * @author jc
 */
public class GenConstants
{
    /** å•è¡¨ï¼ˆå¢žåˆ æ”¹æŸ¥ï¼‰ */
    public static final String TPL_CRUD = "crud";
    /** æ ‘表(增删改查) */
    public static final String TPL_TREE = "tree";
    /** ä¸»å­è¡¨ï¼ˆå¢žåˆ æ”¹æŸ¥ï¼‰ */
    public static final String TPL_SUB = "sub";
    /** æ ‘编码字段 */
    public static final String TREE_CODE = "treeCode";
    /** æ ‘父编码字段 */
    public static final String TREE_PARENT_CODE = "treeParentCode";
    /** æ ‘名称字段 */
    public static final String TREE_NAME = "treeName";
    /** ä¸Šçº§èœå•ID字段 */
    public static final String PARENT_MENU_ID = "parentMenuId";
    /** ä¸Šçº§èœå•åç§°å­—段 */
    public static final String PARENT_MENU_NAME = "parentMenuName";
    /** æ•°æ®åº“字符串类型 */
    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
    /** æ•°æ®åº“文本类型 */
    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
    /** æ•°æ®åº“时间类型 */
    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
    /** æ•°æ®åº“数字类型 */
    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
            "bit", "bigint", "float", "double", "decimal" };
    /** é¡µé¢ä¸éœ€è¦ç¼–辑字段 */
    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
    /** é¡µé¢ä¸éœ€è¦æ˜¾ç¤ºçš„列表字段 */
    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
            "update_time" };
    /** é¡µé¢ä¸éœ€è¦æŸ¥è¯¢å­—段 */
    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
            "update_time", "remark" };
    /** Entity基类字段 */
    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
    /** Tree基类字段 */
    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
    /** æ–‡æœ¬æ¡† */
    public static final String HTML_INPUT = "input";
    /** æ–‡æœ¬åŸŸ */
    public static final String HTML_TEXTAREA = "textarea";
    /** ä¸‹æ‹‰æ¡† */
    public static final String HTML_SELECT = "select";
    /** å•é€‰æ¡† */
    public static final String HTML_RADIO = "radio";
    /** å¤é€‰æ¡† */
    public static final String HTML_CHECKBOX = "checkbox";
    /** æ—¥æœŸæŽ§ä»¶ */
    public static final String HTML_DATETIME = "datetime";
    /** å›¾ç‰‡ä¸Šä¼ æŽ§ä»¶ */
    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
    /** æ–‡ä»¶ä¸Šä¼ æŽ§ä»¶ */
    public static final String HTML_FILE_UPLOAD = "fileUpload";
    /** å¯Œæ–‡æœ¬æŽ§ä»¶ */
    public static final String HTML_EDITOR = "editor";
    /** å­—符串类型 */
    public static final String TYPE_STRING = "String";
    /** æ•´åž‹ */
    public static final String TYPE_INTEGER = "Integer";
    /** é•¿æ•´åž‹ */
    public static final String TYPE_LONG = "Long";
    /** æµ®ç‚¹åž‹ */
    public static final String TYPE_DOUBLE = "Double";
    /** é«˜ç²¾åº¦è®¡ç®—类型 */
    public static final String TYPE_BIGDECIMAL = "BigDecimal";
    /** æ—¶é—´ç±»åž‹ */
    public static final String TYPE_DATE = "Date";
    /** æ¨¡ç³ŠæŸ¥è¯¢ */
    public static final String QUERY_LIKE = "LIKE";
    /** ç›¸ç­‰æŸ¥è¯¢ */
    public static final String QUERY_EQ = "EQ";
    /** éœ€è¦ */
    public static final String REQUIRE = "1";
}
jcdm-common/src/main/java/com/jcdm/common/constant/HttpStatus.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.jcdm.common.constant;
/**
 * è¿”回状态码
 *
 * @author jc
 */
public class HttpStatus
{
    /**
     * æ“ä½œæˆåŠŸ
     */
    public static final int SUCCESS = 200;
    /**
     * å¯¹è±¡åˆ›å»ºæˆåŠŸ
     */
    public static final int CREATED = 201;
    /**
     * è¯·æ±‚已经被接受
     */
    public static final int ACCEPTED = 202;
    /**
     * æ“ä½œå·²ç»æ‰§è¡ŒæˆåŠŸï¼Œä½†æ˜¯æ²¡æœ‰è¿”回数据
     */
    public static final int NO_CONTENT = 204;
    /**
     * èµ„源已被移除
     */
    public static final int MOVED_PERM = 301;
    /**
     * é‡å®šå‘
     */
    public static final int SEE_OTHER = 303;
    /**
     * èµ„源没有被修改
     */
    public static final int NOT_MODIFIED = 304;
    /**
     * å‚数列表错误(缺少,格式不匹配)
     */
    public static final int BAD_REQUEST = 400;
    /**
     * æœªæŽˆæƒ
     */
    public static final int UNAUTHORIZED = 401;
    /**
     * è®¿é—®å—限,授权过期
     */
    public static final int FORBIDDEN = 403;
    /**
     * èµ„源,服务未找到
     */
    public static final int NOT_FOUND = 404;
    /**
     * ä¸å…è®¸çš„http方法
     */
    public static final int BAD_METHOD = 405;
    /**
     * èµ„源冲突,或者资源被锁
     */
    public static final int CONFLICT = 409;
    /**
     * ä¸æ”¯æŒçš„数据,媒体类型
     */
    public static final int UNSUPPORTED_TYPE = 415;
    /**
     * ç³»ç»Ÿå†…部错误
     */
    public static final int ERROR = 500;
    /**
     * æŽ¥å£æœªå®žçŽ°
     */
    public static final int NOT_IMPLEMENTED = 501;
    /**
     * ç³»ç»Ÿè­¦å‘Šæ¶ˆæ¯
     */
    public static final int WARN = 601;
}
jcdm-common/src/main/java/com/jcdm/common/constant/ScheduleConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.jcdm.common.constant;
/**
 * ä»»åŠ¡è°ƒåº¦é€šç”¨å¸¸é‡
 *
 * @author jc
 */
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;
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/constant/UserConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
package com.jcdm.common.constant;
/**
 * ç”¨æˆ·å¸¸é‡ä¿¡æ¯
 *
 * @author jc
 */
public class UserConstants
{
    /**
     * å¹³å°å†…系统用户的唯一标志
     */
    public static final String SYS_USER = "SYS_USER";
    /** æ­£å¸¸çŠ¶æ€ */
    public static final String NORMAL = "0";
    /** å¼‚常状态 */
    public static final String EXCEPTION = "1";
    /** ç”¨æˆ·å°ç¦çŠ¶æ€ */
    public static final String USER_DISABLE = "1";
    /** è§’色封禁状态 */
    public static final String ROLE_DISABLE = "1";
    /** éƒ¨é—¨æ­£å¸¸çŠ¶æ€ */
    public static final String DEPT_NORMAL = "0";
    /** éƒ¨é—¨åœç”¨çŠ¶æ€ */
    public static final String DEPT_DISABLE = "1";
    /** å­—典正常状态 */
    public static final String DICT_NORMAL = "0";
    /** æ˜¯å¦ä¸ºç³»ç»Ÿé»˜è®¤ï¼ˆæ˜¯ï¼‰ */
    public static final String YES = "Y";
    /** æ˜¯å¦èœå•å¤–链(是) */
    public static final String YES_FRAME = "0";
    /** æ˜¯å¦èœå•å¤–链(否) */
    public static final String NO_FRAME = "1";
    /** èœå•ç±»åž‹ï¼ˆç›®å½•ï¼‰ */
    public static final String TYPE_DIR = "M";
    /** èœå•ç±»åž‹ï¼ˆèœå•ï¼‰ */
    public static final String TYPE_MENU = "C";
    /** èœå•ç±»åž‹ï¼ˆæŒ‰é’®ï¼‰ */
    public static final String TYPE_BUTTON = "F";
    /** Layout组件标识 */
    public final static String LAYOUT = "Layout";
    /** ParentView组件标识 */
    public final static String PARENT_VIEW = "ParentView";
    /** InnerLink组件标识 */
    public final static String INNER_LINK = "InnerLink";
    /** æ ¡éªŒæ˜¯å¦å”¯ä¸€çš„返回标识 */
    public final static boolean UNIQUE = true;
    public final static boolean NOT_UNIQUE = false;
    /**
     * ç”¨æˆ·åé•¿åº¦é™åˆ¶
     */
    public static final int USERNAME_MIN_LENGTH = 2;
    public static final int USERNAME_MAX_LENGTH = 20;
    /**
     * å¯†ç é•¿åº¦é™åˆ¶
     */
    public static final int PASSWORD_MIN_LENGTH = 5;
    public static final int PASSWORD_MAX_LENGTH = 20;
}
jcdm-common/src/main/java/com/jcdm/common/core/controller/BaseController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
package com.jcdm.common.core.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jcdm.common.constant.HttpStatus;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.core.page.PageDomain;
import com.jcdm.common.core.page.TableDataInfo;
import com.jcdm.common.core.page.TableSupport;
import com.jcdm.common.utils.DateUtils;
import com.jcdm.common.utils.PageUtils;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.sql.SqlUtil;
/**
 * web层通用数据处理
 *
 * @author jc
 */
public class BaseController
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * å°†å‰å°ä¼ é€’过来的日期格式的字符串,自动转化为Date类型
     */
    @InitBinder
    public void initBinder(WebDataBinder binder)
    {
        // Date ç±»åž‹è½¬æ¢
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
        {
            @Override
            public void setAsText(String text)
            {
                setValue(DateUtils.parseDate(text));
            }
        });
    }
    /**
     * è®¾ç½®è¯·æ±‚分页数据
     */
    protected void startPage()
    {
        PageUtils.startPage();
    }
    /**
     * è®¾ç½®è¯·æ±‚排序数据
     */
    protected void startOrderBy()
    {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
        {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.orderBy(orderBy);
        }
    }
    /**
     * æ¸…理分页的线程变量
     */
    protected void clearPage()
    {
        PageUtils.clearPage();
    }
    /**
     * å“åº”请求分页数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected TableDataInfo getDataTable(List<?> list)
    {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }
    /**
     * è¿”回成功
     */
    public AjaxResult success()
    {
        return AjaxResult.success();
    }
    /**
     * è¿”回失败消息
     */
    public AjaxResult error()
    {
        return AjaxResult.error();
    }
    /**
     * è¿”回成功消息
     */
    public AjaxResult success(String message)
    {
        return AjaxResult.success(message);
    }
    /**
     * è¿”回成功消息
     */
    public AjaxResult success(Object data)
    {
        return AjaxResult.success(data);
    }
    /**
     * è¿”回失败消息
     */
    public AjaxResult error(String message)
    {
        return AjaxResult.error(message);
    }
    /**
     * è¿”回警告消息
     */
    public AjaxResult warn(String message)
    {
        return AjaxResult.warn(message);
    }
    /**
     * å“åº”返回结果
     *
     * @param rows å½±å“è¡Œæ•°
     * @return æ“ä½œç»“æžœ
     */
    protected AjaxResult toAjax(int rows)
    {
        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
    }
    /**
     * å“åº”返回结果
     *
     * @param result ç»“æžœ
     * @return æ“ä½œç»“æžœ
     */
    protected AjaxResult toAjax(boolean result)
    {
        return result ? success() : error();
    }
    /**
     * é¡µé¢è·³è½¬
     */
    public String redirect(String url)
    {
        return StringUtils.format("redirect:{}", url);
    }
    /**
     * èŽ·å–用户缓存信息
     */
    public LoginUser getLoginUser()
    {
        return SecurityUtils.getLoginUser();
    }
    /**
     * èŽ·å–登录用户id
     */
    public Long getUserId()
    {
        return getLoginUser().getUserId();
    }
    /**
     * èŽ·å–登录部门id
     */
    public Long getDeptId()
    {
        return getLoginUser().getDeptId();
    }
    /**
     * èŽ·å–登录用户名
     */
    public String getUsername()
    {
        return getLoginUser().getUsername();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/AjaxResult.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
package com.jcdm.common.core.domain;
import java.util.HashMap;
import java.util.Objects;
import com.jcdm.common.constant.HttpStatus;
import com.jcdm.common.utils.StringUtils;
/**
 * æ“ä½œæ¶ˆæ¯æé†’
 *
 * @author jc
 */
public class AjaxResult extends HashMap<String, Object>
{
    private static final long serialVersionUID = 1L;
    /** çŠ¶æ€ç  */
    public static final String CODE_TAG = "code";
    /** è¿”回内容 */
    public static final String MSG_TAG = "msg";
    /** æ•°æ®å¯¹è±¡ */
    public static final String DATA_TAG = "data";
    /**
     * åˆå§‹åŒ–一个新创建的 AjaxResult å¯¹è±¡ï¼Œä½¿å…¶è¡¨ç¤ºä¸€ä¸ªç©ºæ¶ˆæ¯ã€‚
     */
    public AjaxResult()
    {
    }
    /**
     * åˆå§‹åŒ–一个新创建的 AjaxResult å¯¹è±¡
     *
     * @param code çŠ¶æ€ç 
     * @param msg è¿”回内容
     */
    public AjaxResult(int code, String msg)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }
    /**
     * åˆå§‹åŒ–一个新创建的 AjaxResult å¯¹è±¡
     *
     * @param code çŠ¶æ€ç 
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     */
    public AjaxResult(int code, String msg, Object data)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (StringUtils.isNotNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }
    /**
     * è¿”回成功消息
     *
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success()
    {
        return AjaxResult.success("操作成功");
    }
    /**
     * è¿”回成功数据
     *
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success(Object data)
    {
        return AjaxResult.success("操作成功", data);
    }
    /**
     * è¿”回成功消息
     *
     * @param msg è¿”回内容
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success(String msg)
    {
        return AjaxResult.success(msg, null);
    }
    /**
     * è¿”回成功消息
     *
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
    }
    /**
     * è¿”回警告消息
     *
     * @param msg è¿”回内容
     * @return è­¦å‘Šæ¶ˆæ¯
     */
    public static AjaxResult warn(String msg)
    {
        return AjaxResult.warn(msg, null);
    }
    /**
     * è¿”回警告消息
     *
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     * @return è­¦å‘Šæ¶ˆæ¯
     */
    public static AjaxResult warn(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.WARN, msg, data);
    }
    /**
     * è¿”回错误消息
     *
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error()
    {
        return AjaxResult.error("操作失败");
    }
    /**
     * è¿”回错误消息
     *
     * @param msg è¿”回内容
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error(String msg)
    {
        return AjaxResult.error(msg, null);
    }
    /**
     * è¿”回错误消息
     *
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.ERROR, msg, data);
    }
    /**
     * è¿”回错误消息
     *
     * @param code çŠ¶æ€ç 
     * @param msg è¿”回内容
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error(int code, String msg)
    {
        return new AjaxResult(code, msg, null);
    }
    /**
     * æ˜¯å¦ä¸ºæˆåŠŸæ¶ˆæ¯
     *
     * @return ç»“æžœ
     */
    public boolean isSuccess()
    {
        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
    }
    /**
     * æ˜¯å¦ä¸ºè­¦å‘Šæ¶ˆæ¯
     *
     * @return ç»“æžœ
     */
    public boolean isWarn()
    {
        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
    }
    /**
     * æ˜¯å¦ä¸ºé”™è¯¯æ¶ˆæ¯
     *
     * @return ç»“æžœ
     */
    public boolean isError()
    {
        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
    }
    /**
     * æ–¹ä¾¿é“¾å¼è°ƒç”¨
     *
     * @param key é”®
     * @param value å€¼
     * @return æ•°æ®å¯¹è±¡
     */
    @Override
    public AjaxResult put(String key, Object value)
    {
        super.put(key, value);
        return this;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/BaseEntity.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,118 @@
package com.jcdm.common.core.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
 * Entity基类
 *
 * @author jc
 */
public class BaseEntity implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** æœç´¢å€¼ */
    @JsonIgnore
    private String searchValue;
    /** åˆ›å»ºè€… */
    private String createBy;
    /** åˆ›å»ºæ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /** æ›´æ–°è€… */
    private String updateBy;
    /** æ›´æ–°æ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /** å¤‡æ³¨ */
    private String remark;
    /** è¯·æ±‚参数 */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private Map<String, Object> params;
    public String getSearchValue()
    {
        return searchValue;
    }
    public void setSearchValue(String searchValue)
    {
        this.searchValue = searchValue;
    }
    public String getCreateBy()
    {
        return createBy;
    }
    public void setCreateBy(String createBy)
    {
        this.createBy = createBy;
    }
    public Date getCreateTime()
    {
        return createTime;
    }
    public void setCreateTime(Date createTime)
    {
        this.createTime = createTime;
    }
    public String getUpdateBy()
    {
        return updateBy;
    }
    public void setUpdateBy(String updateBy)
    {
        this.updateBy = updateBy;
    }
    public Date getUpdateTime()
    {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime)
    {
        this.updateTime = updateTime;
    }
    public String getRemark()
    {
        return remark;
    }
    public void setRemark(String remark)
    {
        this.remark = remark;
    }
    public Map<String, Object> getParams()
    {
        if (params == null)
        {
            params = new HashMap<>();
        }
        return params;
    }
    public void setParams(Map<String, Object> params)
    {
        this.params = params;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/R.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
package com.jcdm.common.core.domain;
import java.io.Serializable;
import com.jcdm.common.constant.HttpStatus;
/**
 * å“åº”信息主体
 *
 * @author jc
 */
public class R<T> implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** æˆåŠŸ */
    public static final int SUCCESS = HttpStatus.SUCCESS;
    /** å¤±è´¥ */
    public static final int FAIL = HttpStatus.ERROR;
    private int code;
    private String msg;
    private T data;
    public static <T> R<T> ok()
    {
        return restResult(null, SUCCESS, "操作成功");
    }
    public static <T> R<T> ok(T data)
    {
        return restResult(data, SUCCESS, "操作成功");
    }
    public static <T> R<T> ok(T data, String msg)
    {
        return restResult(data, SUCCESS, msg);
    }
    public static <T> R<T> fail()
    {
        return restResult(null, FAIL, "操作失败");
    }
    public static <T> R<T> fail(String msg)
    {
        return restResult(null, FAIL, msg);
    }
    public static <T> R<T> fail(T data)
    {
        return restResult(data, FAIL, "操作失败");
    }
    public static <T> R<T> fail(T data, String msg)
    {
        return restResult(data, FAIL, msg);
    }
    public static <T> R<T> fail(int code, String msg)
    {
        return restResult(null, code, msg);
    }
    private static <T> R<T> restResult(T data, int code, String msg)
    {
        R<T> apiResult = new R<>();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }
    public int getCode()
    {
        return code;
    }
    public void setCode(int code)
    {
        this.code = code;
    }
    public String getMsg()
    {
        return msg;
    }
    public void setMsg(String msg)
    {
        this.msg = msg;
    }
    public T getData()
    {
        return data;
    }
    public void setData(T data)
    {
        this.data = data;
    }
    public static <T> Boolean isError(R<T> ret)
    {
        return !isSuccess(ret);
    }
    public static <T> Boolean isSuccess(R<T> ret)
    {
        return R.SUCCESS == ret.getCode();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeEntity.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
package com.jcdm.common.core.domain;
import java.util.ArrayList;
import java.util.List;
/**
 * Tree基类
 *
 * @author jc
 */
public class TreeEntity extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** çˆ¶èœå•åç§° */
    private String parentName;
    /** çˆ¶èœå•ID */
    private Long parentId;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** ç¥–级列表 */
    private String ancestors;
    /** å­éƒ¨é—¨ */
    private List<?> children = new ArrayList<>();
    public String getParentName()
    {
        return parentName;
    }
    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }
    public Long getParentId()
    {
        return parentId;
    }
    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }
    public Integer getOrderNum()
    {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }
    public String getAncestors()
    {
        return ancestors;
    }
    public void setAncestors(String ancestors)
    {
        this.ancestors = ancestors;
    }
    public List<?> getChildren()
    {
        return children;
    }
    public void setChildren(List<?> children)
    {
        this.children = children;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/TreeSelect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
package com.jcdm.common.core.domain;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.jcdm.common.core.domain.entity.SysDept;
import com.jcdm.common.core.domain.entity.SysMenu;
/**
 * Treeselect树结构实体类
 *
 * @author jc
 */
public class TreeSelect implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** èŠ‚点ID */
    private Long id;
    /** èŠ‚点名称 */
    private String label;
    /** å­èŠ‚点 */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private List<TreeSelect> children;
    public TreeSelect()
    {
    }
    public TreeSelect(SysDept dept)
    {
        this.id = dept.getDeptId();
        this.label = dept.getDeptName();
        this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
    }
    public TreeSelect(SysMenu menu)
    {
        this.id = menu.getMenuId();
        this.label = menu.getMenuName();
        this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
    }
    public Long getId()
    {
        return id;
    }
    public void setId(Long id)
    {
        this.id = id;
    }
    public String getLabel()
    {
        return label;
    }
    public void setLabel(String label)
    {
        this.label = label;
    }
    public List<TreeSelect> getChildren()
    {
        return children;
    }
    public void setChildren(List<TreeSelect> children)
    {
        this.children = children;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDept.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,203 @@
package com.jcdm.common.core.domain.entity;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.jcdm.common.core.domain.BaseEntity;
/**
 * éƒ¨é—¨è¡¨ sys_dept
 *
 * @author jc
 */
public class SysDept extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** éƒ¨é—¨ID */
    private Long deptId;
    /** çˆ¶éƒ¨é—¨ID */
    private Long parentId;
    /** ç¥–级列表 */
    private String ancestors;
    /** éƒ¨é—¨åç§° */
    private String deptName;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** è´Ÿè´£äºº */
    private String leader;
    /** è”系电话 */
    private String phone;
    /** é‚®ç®± */
    private String email;
    /** éƒ¨é—¨çŠ¶æ€:0正常,1停用 */
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** çˆ¶éƒ¨é—¨åç§° */
    private String parentName;
    /** å­éƒ¨é—¨ */
    private List<SysDept> children = new ArrayList<SysDept>();
    public Long getDeptId()
    {
        return deptId;
    }
    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }
    public Long getParentId()
    {
        return parentId;
    }
    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }
    public String getAncestors()
    {
        return ancestors;
    }
    public void setAncestors(String ancestors)
    {
        this.ancestors = ancestors;
    }
    @NotBlank(message = "部门名称不能为空")
    @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
    public String getDeptName()
    {
        return deptName;
    }
    public void setDeptName(String deptName)
    {
        this.deptName = deptName;
    }
    @NotNull(message = "显示顺序不能为空")
    public Integer getOrderNum()
    {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }
    public String getLeader()
    {
        return leader;
    }
    public void setLeader(String leader)
    {
        this.leader = leader;
    }
    @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
    public String getPhone()
    {
        return phone;
    }
    public void setPhone(String phone)
    {
        this.phone = phone;
    }
    @Email(message = "邮箱格式不正确")
    @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
    public String getEmail()
    {
        return email;
    }
    public void setEmail(String email)
    {
        this.email = email;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    public String getDelFlag()
    {
        return delFlag;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }
    public String getParentName()
    {
        return parentName;
    }
    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }
    public List<SysDept> getChildren()
    {
        return children;
    }
    public void setChildren(List<SysDept> children)
    {
        this.children = children;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("deptId", getDeptId())
            .append("parentId", getParentId())
            .append("ancestors", getAncestors())
            .append("deptName", getDeptName())
            .append("orderNum", getOrderNum())
            .append("leader", getLeader())
            .append("phone", getPhone())
            .append("email", getEmail())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
package com.jcdm.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.jcdm.common.annotation.Excel;
import com.jcdm.common.annotation.Excel.ColumnType;
import com.jcdm.common.constant.UserConstants;
import com.jcdm.common.core.domain.BaseEntity;
/**
 * å­—典数据表 sys_dict_data
 *
 * @author jc
 */
public class SysDictData extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** å­—典编码 */
    @Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
    private Long dictCode;
    /** å­—典排序 */
    @Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
    private Long dictSort;
    /** å­—典标签 */
    @Excel(name = "字典标签")
    private String dictLabel;
    /** å­—典键值 */
    @Excel(name = "字典键值")
    private String dictValue;
    /** å­—典类型 */
    @Excel(name = "字典类型")
    private String dictType;
    /** æ ·å¼å±žæ€§ï¼ˆå…¶ä»–样式扩展) */
    private String cssClass;
    /** è¡¨æ ¼å­—典样式 */
    private String listClass;
    /** æ˜¯å¦é»˜è®¤ï¼ˆY是 N否) */
    @Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
    private String isDefault;
    /** çŠ¶æ€ï¼ˆ0正常 1停用) */
    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
    private String status;
    public Long getDictCode()
    {
        return dictCode;
    }
    public void setDictCode(Long dictCode)
    {
        this.dictCode = dictCode;
    }
    public Long getDictSort()
    {
        return dictSort;
    }
    public void setDictSort(Long dictSort)
    {
        this.dictSort = dictSort;
    }
    @NotBlank(message = "字典标签不能为空")
    @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
    public String getDictLabel()
    {
        return dictLabel;
    }
    public void setDictLabel(String dictLabel)
    {
        this.dictLabel = dictLabel;
    }
    @NotBlank(message = "字典键值不能为空")
    @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
    public String getDictValue()
    {
        return dictValue;
    }
    public void setDictValue(String dictValue)
    {
        this.dictValue = dictValue;
    }
    @NotBlank(message = "字典类型不能为空")
    @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
    public String getDictType()
    {
        return dictType;
    }
    public void setDictType(String dictType)
    {
        this.dictType = dictType;
    }
    @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
    public String getCssClass()
    {
        return cssClass;
    }
    public void setCssClass(String cssClass)
    {
        this.cssClass = cssClass;
    }
    public String getListClass()
    {
        return listClass;
    }
    public void setListClass(String listClass)
    {
        this.listClass = listClass;
    }
    public boolean getDefault()
    {
        return UserConstants.YES.equals(this.isDefault);
    }
    public String getIsDefault()
    {
        return isDefault;
    }
    public void setIsDefault(String isDefault)
    {
        this.isDefault = isDefault;
    }
    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("dictCode", getDictCode())
            .append("dictSort", getDictSort())
            .append("dictLabel", getDictLabel())
            .append("dictValue", getDictValue())
            .append("dictType", getDictType())
            .append("cssClass", getCssClass())
            .append("listClass", getListClass())
            .append("isDefault", getIsDefault())
            .append("status", getStatus())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysDictType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
package com.jcdm.common.core.domain.entity;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.jcdm.common.annotation.Excel;
import com.jcdm.common.annotation.Excel.ColumnType;
import com.jcdm.common.core.domain.BaseEntity;
/**
 * å­—典类型表 sys_dict_type
 *
 * @author jc
 */
public class SysDictType extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** å­—典主键 */
    @Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
    private Long dictId;
    /** å­—典名称 */
    @Excel(name = "字典名称")
    private String dictName;
    /** å­—典类型 */
    @Excel(name = "字典类型")
    private String dictType;
    /** çŠ¶æ€ï¼ˆ0正常 1停用) */
    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
    private String status;
    public Long getDictId()
    {
        return dictId;
    }
    public void setDictId(Long dictId)
    {
        this.dictId = dictId;
    }
    @NotBlank(message = "字典名称不能为空")
    @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
    public String getDictName()
    {
        return dictName;
    }
    public void setDictName(String dictName)
    {
        this.dictName = dictName;
    }
    @NotBlank(message = "字典类型不能为空")
    @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
    public String getDictType()
    {
        return dictType;
    }
    public void setDictType(String dictType)
    {
        this.dictType = dictType;
    }
    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("dictId", getDictId())
            .append("dictName", getDictName())
            .append("dictType", getDictType())
            .append("status", getStatus())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysMenu.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,259 @@
package com.jcdm.common.core.domain.entity;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.jcdm.common.core.domain.BaseEntity;
/**
 * èœå•æƒé™è¡¨ sys_menu
 *
 * @author jc
 */
public class SysMenu extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** èœå•ID */
    private Long menuId;
    /** èœå•åç§° */
    private String menuName;
    /** çˆ¶èœå•åç§° */
    private String parentName;
    /** çˆ¶èœå•ID */
    private Long parentId;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** è·¯ç”±åœ°å€ */
    private String path;
    /** ç»„件路径 */
    private String component;
    /** è·¯ç”±å‚æ•° */
    private String query;
    /** æ˜¯å¦ä¸ºå¤–链(0是 1否) */
    private String isFrame;
    /** æ˜¯å¦ç¼“存(0缓存 1不缓存) */
    private String isCache;
    /** ç±»åž‹ï¼ˆM目录 C菜单 F按钮) */
    private String menuType;
    /** æ˜¾ç¤ºçŠ¶æ€ï¼ˆ0显示 1隐藏) */
    private String visible;
    /** èœå•çŠ¶æ€ï¼ˆ0正常 1停用) */
    private String status;
    /** æƒé™å­—符串 */
    private String perms;
    /** èœå•å›¾æ ‡ */
    private String icon;
    /** å­èœå• */
    private List<SysMenu> children = new ArrayList<SysMenu>();
    public Long getMenuId()
    {
        return menuId;
    }
    public void setMenuId(Long menuId)
    {
        this.menuId = menuId;
    }
    @NotBlank(message = "菜单名称不能为空")
    @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
    public String getMenuName()
    {
        return menuName;
    }
    public void setMenuName(String menuName)
    {
        this.menuName = menuName;
    }
    public String getParentName()
    {
        return parentName;
    }
    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }
    public Long getParentId()
    {
        return parentId;
    }
    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }
    @NotNull(message = "显示顺序不能为空")
    public Integer getOrderNum()
    {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }
    @Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
    public String getPath()
    {
        return path;
    }
    public void setPath(String path)
    {
        this.path = path;
    }
    @Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
    public String getComponent()
    {
        return component;
    }
    public void setComponent(String component)
    {
        this.component = component;
    }
    public String getQuery()
    {
        return query;
    }
    public void setQuery(String query)
    {
        this.query = query;
    }
    public String getIsFrame()
    {
        return isFrame;
    }
    public void setIsFrame(String isFrame)
    {
        this.isFrame = isFrame;
    }
    public String getIsCache()
    {
        return isCache;
    }
    public void setIsCache(String isCache)
    {
        this.isCache = isCache;
    }
    @NotBlank(message = "菜单类型不能为空")
    public String getMenuType()
    {
        return menuType;
    }
    public void setMenuType(String menuType)
    {
        this.menuType = menuType;
    }
    public String getVisible()
    {
        return visible;
    }
    public void setVisible(String visible)
    {
        this.visible = visible;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
    public String getPerms()
    {
        return perms;
    }
    public void setPerms(String perms)
    {
        this.perms = perms;
    }
    public String getIcon()
    {
        return icon;
    }
    public void setIcon(String icon)
    {
        this.icon = icon;
    }
    public List<SysMenu> getChildren()
    {
        return children;
    }
    public void setChildren(List<SysMenu> children)
    {
        this.children = children;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("menuId", getMenuId())
            .append("menuName", getMenuName())
            .append("parentId", getParentId())
            .append("orderNum", getOrderNum())
            .append("path", getPath())
            .append("component", getComponent())
            .append("isFrame", getIsFrame())
            .append("IsCache", getIsCache())
            .append("menuType", getMenuType())
            .append("visible", getVisible())
            .append("status ", getStatus())
            .append("perms", getPerms())
            .append("icon", getIcon())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysRole.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,241 @@
package com.jcdm.common.core.domain.entity;
import java.util.Set;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.jcdm.common.annotation.Excel;
import com.jcdm.common.annotation.Excel.ColumnType;
import com.jcdm.common.core.domain.BaseEntity;
/**
 * è§’色表 sys_role
 *
 * @author jc
 */
public class SysRole extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** è§’色ID */
    @Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
    private Long roleId;
    /** è§’色名称 */
    @Excel(name = "角色名称")
    private String roleName;
    /** è§’色权限 */
    @Excel(name = "角色权限")
    private String roleKey;
    /** è§’色排序 */
    @Excel(name = "角色排序")
    private Integer roleSort;
    /** æ•°æ®èŒƒå›´ï¼ˆ1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
    @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
    private String dataScope;
    /** èœå•æ ‘选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
    private boolean menuCheckStrictly;
    /** éƒ¨é—¨æ ‘选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ï¼‰ */
    private boolean deptCheckStrictly;
    /** è§’色状态(0正常 1停用) */
    @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** ç”¨æˆ·æ˜¯å¦å­˜åœ¨æ­¤è§’色标识 é»˜è®¤ä¸å­˜åœ¨ */
    private boolean flag = false;
    /** èœå•ç»„ */
    private Long[] menuIds;
    /** éƒ¨é—¨ç»„(数据权限) */
    private Long[] deptIds;
    /** è§’色菜单权限 */
    private Set<String> permissions;
    public SysRole()
    {
    }
    public SysRole(Long roleId)
    {
        this.roleId = roleId;
    }
    public Long getRoleId()
    {
        return roleId;
    }
    public void setRoleId(Long roleId)
    {
        this.roleId = roleId;
    }
    public boolean isAdmin()
    {
        return isAdmin(this.roleId);
    }
    public static boolean isAdmin(Long roleId)
    {
        return roleId != null && 1L == roleId;
    }
    @NotBlank(message = "角色名称不能为空")
    @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
    public String getRoleName()
    {
        return roleName;
    }
    public void setRoleName(String roleName)
    {
        this.roleName = roleName;
    }
    @NotBlank(message = "权限字符不能为空")
    @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
    public String getRoleKey()
    {
        return roleKey;
    }
    public void setRoleKey(String roleKey)
    {
        this.roleKey = roleKey;
    }
    @NotNull(message = "显示顺序不能为空")
    public Integer getRoleSort()
    {
        return roleSort;
    }
    public void setRoleSort(Integer roleSort)
    {
        this.roleSort = roleSort;
    }
    public String getDataScope()
    {
        return dataScope;
    }
    public void setDataScope(String dataScope)
    {
        this.dataScope = dataScope;
    }
    public boolean isMenuCheckStrictly()
    {
        return menuCheckStrictly;
    }
    public void setMenuCheckStrictly(boolean menuCheckStrictly)
    {
        this.menuCheckStrictly = menuCheckStrictly;
    }
    public boolean isDeptCheckStrictly()
    {
        return deptCheckStrictly;
    }
    public void setDeptCheckStrictly(boolean deptCheckStrictly)
    {
        this.deptCheckStrictly = deptCheckStrictly;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    public String getDelFlag()
    {
        return delFlag;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }
    public boolean isFlag()
    {
        return flag;
    }
    public void setFlag(boolean flag)
    {
        this.flag = flag;
    }
    public Long[] getMenuIds()
    {
        return menuIds;
    }
    public void setMenuIds(Long[] menuIds)
    {
        this.menuIds = menuIds;
    }
    public Long[] getDeptIds()
    {
        return deptIds;
    }
    public void setDeptIds(Long[] deptIds)
    {
        this.deptIds = deptIds;
    }
    public Set<String> getPermissions()
    {
        return permissions;
    }
    public void setPermissions(Set<String> permissions)
    {
        this.permissions = permissions;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("roleId", getRoleId())
            .append("roleName", getRoleName())
            .append("roleKey", getRoleKey())
            .append("roleSort", getRoleSort())
            .append("dataScope", getDataScope())
            .append("menuCheckStrictly", isMenuCheckStrictly())
            .append("deptCheckStrictly", isDeptCheckStrictly())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/entity/SysUser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,324 @@
package com.jcdm.common.core.domain.entity;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.jcdm.common.annotation.Excel;
import com.jcdm.common.annotation.Excel.ColumnType;
import com.jcdm.common.annotation.Excel.Type;
import com.jcdm.common.annotation.Excels;
import com.jcdm.common.core.domain.BaseEntity;
import com.jcdm.common.xss.Xss;
/**
 * ç”¨æˆ·å¯¹è±¡ sys_user
 *
 * @author jc
 */
public class SysUser extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** ç”¨æˆ·ID */
    @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
    private Long userId;
    /** éƒ¨é—¨ID */
    @Excel(name = "部门编号", type = Type.IMPORT)
    private Long deptId;
    /** ç”¨æˆ·è´¦å· */
    @Excel(name = "登录名称")
    private String userName;
    /** ç”¨æˆ·æ˜µç§° */
    @Excel(name = "用户名称")
    private String nickName;
    /** ç”¨æˆ·é‚®ç®± */
    @Excel(name = "用户邮箱")
    private String email;
    /** æ‰‹æœºå·ç  */
    @Excel(name = "手机号码")
    private String phonenumber;
    /** ç”¨æˆ·æ€§åˆ« */
    @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
    private String sex;
    /** ç”¨æˆ·å¤´åƒ */
    private String avatar;
    /** å¯†ç  */
    private String password;
    /** å¸å·çŠ¶æ€ï¼ˆ0正常 1停用) */
    @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** æœ€åŽç™»å½•IP */
    @Excel(name = "最后登录IP", type = Type.EXPORT)
    private String loginIp;
    /** æœ€åŽç™»å½•æ—¶é—´ */
    @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
    private Date loginDate;
    /** éƒ¨é—¨å¯¹è±¡ */
    @Excels({
        @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
        @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
    })
    private SysDept dept;
    /** è§’色对象 */
    private List<SysRole> roles;
    /** è§’色组 */
    private Long[] roleIds;
    /** å²—位组 */
    private Long[] postIds;
    /** è§’色ID */
    private Long roleId;
    public SysUser()
    {
    }
    public SysUser(Long userId)
    {
        this.userId = userId;
    }
    public Long getUserId()
    {
        return userId;
    }
    public void setUserId(Long userId)
    {
        this.userId = userId;
    }
    public boolean isAdmin()
    {
        return isAdmin(this.userId);
    }
    public static boolean isAdmin(Long userId)
    {
        return userId != null && 1L == userId;
    }
    public Long getDeptId()
    {
        return deptId;
    }
    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }
    @Xss(message = "用户昵称不能包含脚本字符")
    @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
    public String getNickName()
    {
        return nickName;
    }
    public void setNickName(String nickName)
    {
        this.nickName = nickName;
    }
    @Xss(message = "用户账号不能包含脚本字符")
    @NotBlank(message = "用户账号不能为空")
    @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
    public String getUserName()
    {
        return userName;
    }
    public void setUserName(String userName)
    {
        this.userName = userName;
    }
    @Email(message = "邮箱格式不正确")
    @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
    public String getEmail()
    {
        return email;
    }
    public void setEmail(String email)
    {
        this.email = email;
    }
    @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
    public String getPhonenumber()
    {
        return phonenumber;
    }
    public void setPhonenumber(String phonenumber)
    {
        this.phonenumber = phonenumber;
    }
    public String getSex()
    {
        return sex;
    }
    public void setSex(String sex)
    {
        this.sex = sex;
    }
    public String getAvatar()
    {
        return avatar;
    }
    public void setAvatar(String avatar)
    {
        this.avatar = avatar;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    public String getDelFlag()
    {
        return delFlag;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }
    public String getLoginIp()
    {
        return loginIp;
    }
    public void setLoginIp(String loginIp)
    {
        this.loginIp = loginIp;
    }
    public Date getLoginDate()
    {
        return loginDate;
    }
    public void setLoginDate(Date loginDate)
    {
        this.loginDate = loginDate;
    }
    public SysDept getDept()
    {
        return dept;
    }
    public void setDept(SysDept dept)
    {
        this.dept = dept;
    }
    public List<SysRole> getRoles()
    {
        return roles;
    }
    public void setRoles(List<SysRole> roles)
    {
        this.roles = roles;
    }
    public Long[] getRoleIds()
    {
        return roleIds;
    }
    public void setRoleIds(Long[] roleIds)
    {
        this.roleIds = roleIds;
    }
    public Long[] getPostIds()
    {
        return postIds;
    }
    public void setPostIds(Long[] postIds)
    {
        this.postIds = postIds;
    }
    public Long getRoleId()
    {
        return roleId;
    }
    public void setRoleId(Long roleId)
    {
        this.roleId = roleId;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("userId", getUserId())
            .append("deptId", getDeptId())
            .append("userName", getUserName())
            .append("nickName", getNickName())
            .append("email", getEmail())
            .append("phonenumber", getPhonenumber())
            .append("sex", getSex())
            .append("avatar", getAvatar())
            .append("password", getPassword())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("loginIp", getLoginIp())
            .append("loginDate", getLoginDate())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .append("dept", getDept())
            .toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginBody.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.jcdm.common.core.domain.model;
/**
 * ç”¨æˆ·ç™»å½•å¯¹è±¡
 *
 * @author jc
 */
public class LoginBody
{
    /**
     * ç”¨æˆ·å
     */
    private String username;
    /**
     * ç”¨æˆ·å¯†ç 
     */
    private String password;
    /**
     * éªŒè¯ç 
     */
    private String code;
    /**
     * å”¯ä¸€æ ‡è¯†
     */
    private String uuid;
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getCode()
    {
        return code;
    }
    public void setCode(String code)
    {
        this.code = code;
    }
    public String getUuid()
    {
        return uuid;
    }
    public void setUuid(String uuid)
    {
        this.uuid = uuid;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/model/LoginUser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,266 @@
package com.jcdm.common.core.domain.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.jcdm.common.core.domain.entity.SysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
/**
 * ç™»å½•ç”¨æˆ·èº«ä»½æƒé™
 *
 * @author jc
 */
public class LoginUser implements UserDetails
{
    private static final long serialVersionUID = 1L;
    /**
     * ç”¨æˆ·ID
     */
    private Long userId;
    /**
     * éƒ¨é—¨ID
     */
    private Long deptId;
    /**
     * ç”¨æˆ·å”¯ä¸€æ ‡è¯†
     */
    private String token;
    /**
     * ç™»å½•æ—¶é—´
     */
    private Long loginTime;
    /**
     * è¿‡æœŸæ—¶é—´
     */
    private Long expireTime;
    /**
     * ç™»å½•IP地址
     */
    private String ipaddr;
    /**
     * ç™»å½•åœ°ç‚¹
     */
    private String loginLocation;
    /**
     * æµè§ˆå™¨ç±»åž‹
     */
    private String browser;
    /**
     * æ“ä½œç³»ç»Ÿ
     */
    private String os;
    /**
     * æƒé™åˆ—表
     */
    private Set<String> permissions;
    /**
     * ç”¨æˆ·ä¿¡æ¯
     */
    private SysUser user;
    public LoginUser()
    {
    }
    public LoginUser(SysUser user, Set<String> permissions)
    {
        this.user = user;
        this.permissions = permissions;
    }
    public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
    {
        this.userId = userId;
        this.deptId = deptId;
        this.user = user;
        this.permissions = permissions;
    }
    public Long getUserId()
    {
        return userId;
    }
    public void setUserId(Long userId)
    {
        this.userId = userId;
    }
    public Long getDeptId()
    {
        return deptId;
    }
    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }
    public String getToken()
    {
        return token;
    }
    public void setToken(String token)
    {
        this.token = token;
    }
    @JSONField(serialize = false)
    @Override
    public String getPassword()
    {
        return user.getPassword();
    }
    @Override
    public String getUsername()
    {
        return user.getUserName();
    }
    /**
     * è´¦æˆ·æ˜¯å¦æœªè¿‡æœŸ,过期无法验证
     */
    @JSONField(serialize = false)
    @Override
    public boolean isAccountNonExpired()
    {
        return true;
    }
    /**
     * æŒ‡å®šç”¨æˆ·æ˜¯å¦è§£é”,锁定的用户无法进行身份验证
     *
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public boolean isAccountNonLocked()
    {
        return true;
    }
    /**
     * æŒ‡ç¤ºæ˜¯å¦å·²è¿‡æœŸçš„用户的凭据(密码),过期的凭据防止认证
     *
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public boolean isCredentialsNonExpired()
    {
        return true;
    }
    /**
     * æ˜¯å¦å¯ç”¨ ,禁用的用户不能身份验证
     *
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public boolean isEnabled()
    {
        return true;
    }
    public Long getLoginTime()
    {
        return loginTime;
    }
    public void setLoginTime(Long loginTime)
    {
        this.loginTime = loginTime;
    }
    public String getIpaddr()
    {
        return ipaddr;
    }
    public void setIpaddr(String ipaddr)
    {
        this.ipaddr = ipaddr;
    }
    public String getLoginLocation()
    {
        return loginLocation;
    }
    public void setLoginLocation(String loginLocation)
    {
        this.loginLocation = loginLocation;
    }
    public String getBrowser()
    {
        return browser;
    }
    public void setBrowser(String browser)
    {
        this.browser = browser;
    }
    public String getOs()
    {
        return os;
    }
    public void setOs(String os)
    {
        this.os = os;
    }
    public Long getExpireTime()
    {
        return expireTime;
    }
    public void setExpireTime(Long expireTime)
    {
        this.expireTime = expireTime;
    }
    public Set<String> getPermissions()
    {
        return permissions;
    }
    public void setPermissions(Set<String> permissions)
    {
        this.permissions = permissions;
    }
    public SysUser getUser()
    {
        return user;
    }
    public void setUser(SysUser user)
    {
        this.user = user;
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities()
    {
        return null;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/domain/model/RegisterBody.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package com.jcdm.common.core.domain.model;
/**
 * ç”¨æˆ·æ³¨å†Œå¯¹è±¡
 *
 * @author jc
 */
public class RegisterBody extends LoginBody
{
}
jcdm-common/src/main/java/com/jcdm/common/core/page/PageDomain.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
package com.jcdm.common.core.page;
import com.jcdm.common.utils.StringUtils;
/**
 * åˆ†é¡µæ•°æ®
 *
 * @author jc
 */
public class PageDomain
{
    /** å½“前记录起始索引 */
    private Integer pageNum;
    /** æ¯é¡µæ˜¾ç¤ºè®°å½•æ•° */
    private Integer pageSize;
    /** æŽ’序列 */
    private String orderByColumn;
    /** æŽ’序的方向desc或者asc */
    private String isAsc = "asc";
    /** åˆ†é¡µå‚数合理化 */
    private Boolean reasonable = true;
    public String getOrderBy()
    {
        if (StringUtils.isEmpty(orderByColumn))
        {
            return "";
        }
        return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
    }
    public Integer getPageNum()
    {
        return pageNum;
    }
    public void setPageNum(Integer pageNum)
    {
        this.pageNum = pageNum;
    }
    public Integer getPageSize()
    {
        return pageSize;
    }
    public void setPageSize(Integer pageSize)
    {
        this.pageSize = pageSize;
    }
    public String getOrderByColumn()
    {
        return orderByColumn;
    }
    public void setOrderByColumn(String orderByColumn)
    {
        this.orderByColumn = orderByColumn;
    }
    public String getIsAsc()
    {
        return isAsc;
    }
    public void setIsAsc(String isAsc)
    {
        if (StringUtils.isNotEmpty(isAsc))
        {
            // å…¼å®¹å‰ç«¯æŽ’序类型
            if ("ascending".equals(isAsc))
            {
                isAsc = "asc";
            }
            else if ("descending".equals(isAsc))
            {
                isAsc = "desc";
            }
            this.isAsc = isAsc;
        }
    }
    public Boolean getReasonable()
    {
        if (StringUtils.isNull(reasonable))
        {
            return Boolean.TRUE;
        }
        return reasonable;
    }
    public void setReasonable(Boolean reasonable)
    {
        this.reasonable = reasonable;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/page/TableDataInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
package com.jcdm.common.core.page;
import java.io.Serializable;
import java.util.List;
/**
 * è¡¨æ ¼åˆ†é¡µæ•°æ®å¯¹è±¡
 *
 * @author jc
 */
public class TableDataInfo implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** æ€»è®°å½•æ•° */
    private long total;
    /** åˆ—表数据 */
    private List<?> rows;
    /** æ¶ˆæ¯çŠ¶æ€ç  */
    private int code;
    /** æ¶ˆæ¯å†…容 */
    private String msg;
    /**
     * è¡¨æ ¼æ•°æ®å¯¹è±¡
     */
    public TableDataInfo()
    {
    }
    /**
     * åˆ†é¡µ
     *
     * @param list åˆ—表数据
     * @param total æ€»è®°å½•æ•°
     */
    public TableDataInfo(List<?> list, int total)
    {
        this.rows = list;
        this.total = total;
    }
    public long getTotal()
    {
        return total;
    }
    public void setTotal(long total)
    {
        this.total = total;
    }
    public List<?> getRows()
    {
        return rows;
    }
    public void setRows(List<?> rows)
    {
        this.rows = rows;
    }
    public int getCode()
    {
        return code;
    }
    public void setCode(int code)
    {
        this.code = code;
    }
    public String getMsg()
    {
        return msg;
    }
    public void setMsg(String msg)
    {
        this.msg = msg;
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/page/TableSupport.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.jcdm.common.core.page;
import com.jcdm.common.core.text.Convert;
import com.jcdm.common.utils.ServletUtils;
/**
 * è¡¨æ ¼æ•°æ®å¤„理
 *
 * @author jc
 */
public class TableSupport
{
    /**
     * å½“前记录起始索引
     */
    public static final String PAGE_NUM = "pageNum";
    /**
     * æ¯é¡µæ˜¾ç¤ºè®°å½•æ•°
     */
    public static final String PAGE_SIZE = "pageSize";
    /**
     * æŽ’序列
     */
    public static final String ORDER_BY_COLUMN = "orderByColumn";
    /**
     * æŽ’序的方向 "desc" æˆ–者 "asc".
     */
    public static final String IS_ASC = "isAsc";
    /**
     * åˆ†é¡µå‚数合理化
     */
    public static final String REASONABLE = "reasonable";
    /**
     * å°è£…分页对象
     */
    public static PageDomain getPageDomain()
    {
        PageDomain pageDomain = new PageDomain();
        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
        return pageDomain;
    }
    public static PageDomain buildPageRequest()
    {
        return getPageDomain();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/redis/MyCache.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.jcdm.common.core.redis;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class MyCache implements Cache {
    // ä½¿ç”¨ConcurrentHashMap作为数据的存储
    private Map<String, Object> storage = new ConcurrentHashMap<>();
    // getName获取cache的名称,存取数据的时候用来区分是针对哪个cache操作
    @Override
    public String getName() {
        return null;
    }
    @Override
    public Object getNativeCache() {
        return null;
    }
    public boolean hasKey(String key){
        return storage.containsKey(key);
    }
    @Override
    public ValueWrapper get(Object key) {
        String k = key.toString();
        Object value = storage.get(k);
        // æ³¨æ„è¿”回的数据,要和存放时接收到数据保持一致,要将数据反序列化回来。
        return Objects.isNull(value) ? null : new SimpleValueWrapper(value);
    }
    @Override
    public <T> T get(Object key, Class<T> type) {
        return null;
    }
    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        return null;
    }
    // put方法,就是执行将数据进行缓存
    @Override
    public void put(Object key, Object value) {
        if (Objects.isNull(value)) {
            return;
        }
        //存值
        storage.put(key.toString(), value);
    }
    // evict方法,是用来清除某个缓存项
    @Override
    public void evict(Object key) {
        storage.remove(key.toString());
    }
    // åˆ é™¤é›†åˆ
    public boolean deleteObject(final Collection collection){
        collection.forEach(o -> {
            storage.remove(o.toString());
        } );
        return true;
    }
    // èŽ·å–所有的keys
    public Collection<String> keys(final String pattern){
        return storage.keySet();
    }
    @Override
    public void clear() {
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/redis/RedisCache.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,279 @@
package com.jcdm.common.core.redis;
import org.springframework.cache.Cache;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
/**
 * spring redis å·¥å…·ç±»
 *
 * @author jc
 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
//    @Autowired
//    public RedisTemplate redisTemplate;
    @Resource
    public MyCache myCache;
    /**
     * ç¼“存基本的对象,Integer、String、实体类等
     *
     * @param key ç¼“存的键值
     * @param value ç¼“存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        myCache.put(key,value);
//        redisTemplate.opsForValue().set(key, value);
    }
    /**
     * ç¼“存基本的对象,Integer、String、实体类等
     *
     * @param key ç¼“存的键值
     * @param value ç¼“存的值
     * @param timeout æ—¶é—´
     * @param timeUnit æ—¶é—´é¢—粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
    {
        myCache.put(key,value);
//        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }
    /**
     * è®¾ç½®æœ‰æ•ˆæ—¶é—´
     *
     * @param key Redis键
     * @param timeout è¶…时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout)
    {
        return expire(key, timeout, TimeUnit.SECONDS);
    }
    /**
     * è®¾ç½®æœ‰æ•ˆæ—¶é—´
     *
     * @param key Redis键
     * @param timeout è¶…时时间
     * @param unit æ—¶é—´å•ä½
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit)
    {
        return true;
//        return redisTemplate.expire(key, timeout, unit);
    }
    /**
     * èŽ·å–有效时间
     *
     * @param key Redis键
     * @return æœ‰æ•ˆæ—¶é—´
     */
//    public long getExpire(final String key)
//    {
//        return redisTemplate.getExpire(key);
//    }
    /**
     * åˆ¤æ–­ key是否存在
     *
     * @param key é”®
     * @return true å­˜åœ¨ false不存在
     */
    public Boolean hasKey(String key)
    {
        return myCache.hasKey(key);
//        return redisTemplate.hasKey(key);
    }
    /**
     * èŽ·å¾—缓存的基本对象。
     *
     * @param key ç¼“存键值
     * @return ç¼“存键值对应的数据
     */
    public <T> T getCacheObject(final String key)
    {
        Cache.ValueWrapper valueWrapper = myCache.get(key);
        if (valueWrapper == null){
            return null;
        }else {
            return (T) valueWrapper.get();
        }
//        ValueOperations<String, T> operation = redisTemplate.opsForValue();
//        return operation.get(key);
    }
    /**
     * åˆ é™¤å•ä¸ªå¯¹è±¡
     *
     * @param key
     */
    public boolean deleteObject(final String key)
    {
        myCache.evict(key);
        return true;
//        return redisTemplate.delete(key);
    }
    /**
     * åˆ é™¤é›†åˆå¯¹è±¡
     *
     * @param collection å¤šä¸ªå¯¹è±¡
     * @return
     */
    public boolean deleteObject(final Collection collection)
    {
        return myCache.deleteObject(collection);
//        return redisTemplate.delete(collection) > 0;
    }
    /**
     * ç¼“å­˜List数据
     *
     * @param key ç¼“存的键值
     * @param dataList å¾…缓存的List数据
     * @return ç¼“存的对象
     */
//    public <T> long setCacheList(final String key, final List<T> dataList)
//    {
//        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
//        return count == null ? 0 : count;
//    }
    /**
     * èŽ·å¾—缓存的list对象
     *
     * @param key ç¼“存的键值
     * @return ç¼“存键值对应的数据
     */
//    public <T> List<T> getCacheList(final String key)
//    {
//        return redisTemplate.opsForList().range(key, 0, -1);
//    }
    /**
     * ç¼“å­˜Set
     *
     * @param key ç¼“存键值
     * @param dataSet ç¼“存的数据
     * @return ç¼“存数据的对象
     */
//    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
//    {
//        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
//        Iterator<T> it = dataSet.iterator();
//        while (it.hasNext())
//        {
//            setOperation.add(it.next());
//        }
//        return setOperation;
//    }
    /**
     * èŽ·å¾—缓存的set
     *
     * @param key
     * @return
     */
//    public <T> Set<T> getCacheSet(final String key)
//    {
//        return redisTemplate.opsForSet().members(key);
//    }
    /**
     * ç¼“å­˜Map
     *
     * @param key
     * @param dataMap
     */
//    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
//    {
//        if (dataMap != null) {
//            redisTemplate.opsForHash().putAll(key, dataMap);
//        }
//    }
    /**
     * èŽ·å¾—缓存的Map
     *
     * @param key
     * @return
     */
//    public <T> Map<String, T> getCacheMap(final String key)
//    {
//        return redisTemplate.opsForHash().entries(key);
//    }
    /**
     * å¾€Hash中存入数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @param value å€¼
     */
//    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
//    {
//        redisTemplate.opsForHash().put(key, hKey, value);
//    }
    /**
     * èŽ·å–Hash中的数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
//    public <T> T getCacheMapValue(final String key, final String hKey)
//    {
//        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
//        return opsForHash.get(key, hKey);
//    }
    /**
     * èŽ·å–多个Hash中的数据
     *
     * @param key Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
//    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
//    {
//        return redisTemplate.opsForHash().multiGet(key, hKeys);
//    }
    /**
     * åˆ é™¤Hash中的某条数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return æ˜¯å¦æˆåŠŸ
     */
//    public boolean deleteCacheMapValue(final String key, final String hKey)
//    {
//        return redisTemplate.opsForHash().delete(key, hKey) > 0;
//    }
    /**
     * èŽ·å¾—缓存的基本对象列表
     *
     * @param pattern å­—符串前缀
     * @return å¯¹è±¡åˆ—表
     */
    public Collection<String> keys(final String pattern)
    {
        return myCache.keys(pattern);
//        return redisTemplate.keys(pattern);
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/text/CharsetKit.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.jcdm.common.core.text;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.jcdm.common.utils.StringUtils;
/**
 * å­—符集工具类
 *
 * @author jc
 */
public class CharsetKit
{
    /** ISO-8859-1 */
    public static final String ISO_8859_1 = "ISO-8859-1";
    /** UTF-8 */
    public static final String UTF_8 = "UTF-8";
    /** GBK */
    public static final String GBK = "GBK";
    /** ISO-8859-1 */
    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
    /** UTF-8 */
    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
    /** GBK */
    public static final Charset CHARSET_GBK = Charset.forName(GBK);
    /**
     * è½¬æ¢ä¸ºCharset对象
     *
     * @param charset å­—符集,为空则返回默认字符集
     * @return Charset
     */
    public static Charset charset(String charset)
    {
        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
    }
    /**
     * è½¬æ¢å­—符串的字符集编码
     *
     * @param source å­—符串
     * @param srcCharset æºå­—符集,默认ISO-8859-1
     * @param destCharset ç›®æ ‡å­—符集,默认UTF-8
     * @return è½¬æ¢åŽçš„字符集
     */
    public static String convert(String source, String srcCharset, String destCharset)
    {
        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
    }
    /**
     * è½¬æ¢å­—符串的字符集编码
     *
     * @param source å­—符串
     * @param srcCharset æºå­—符集,默认ISO-8859-1
     * @param destCharset ç›®æ ‡å­—符集,默认UTF-8
     * @return è½¬æ¢åŽçš„字符集
     */
    public static String convert(String source, Charset srcCharset, Charset destCharset)
    {
        if (null == srcCharset)
        {
            srcCharset = StandardCharsets.ISO_8859_1;
        }
        if (null == destCharset)
        {
            destCharset = StandardCharsets.UTF_8;
        }
        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
        {
            return source;
        }
        return new String(source.getBytes(srcCharset), destCharset);
    }
    /**
     * @return ç³»ç»Ÿå­—符集编码
     */
    public static String systemCharset()
    {
        return Charset.defaultCharset().name();
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/text/Convert.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1006 @@
package com.jcdm.common.core.text;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.Set;
import com.jcdm.common.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
/**
 * ç±»åž‹è½¬æ¢å™¨
 *
 * @author jc
 */
public class Convert
{
    /**
     * è½¬æ¢ä¸ºå­—符串<br>
     * å¦‚果给定的值为null,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static String toStr(Object value, String defaultValue)
    {
        if (null == value)
        {
            return defaultValue;
        }
        if (value instanceof String)
        {
            return (String) value;
        }
        return value.toString();
    }
    /**
     * è½¬æ¢ä¸ºå­—符串<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String toStr(Object value)
    {
        return toStr(value, null);
    }
    /**
     * è½¬æ¢ä¸ºå­—符<br>
     * å¦‚果给定的值为null,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Character toChar(Object value, Character defaultValue)
    {
        if (null == value)
        {
            return defaultValue;
        }
        if (value instanceof Character)
        {
            return (Character) value;
        }
        final String valueStr = toStr(value, null);
        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
    }
    /**
     * è½¬æ¢ä¸ºå­—符<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Character toChar(Object value)
    {
        return toChar(value, null);
    }
    /**
     * è½¬æ¢ä¸ºbyte<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Byte toByte(Object value, Byte defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Byte)
        {
            return (Byte) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).byteValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Byte.parseByte(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºbyte<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Byte toByte(Object value)
    {
        return toByte(value, null);
    }
    /**
     * è½¬æ¢ä¸ºShort<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Short toShort(Object value, Short defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Short)
        {
            return (Short) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).shortValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Short.parseShort(valueStr.trim());
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºShort<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Short toShort(Object value)
    {
        return toShort(value, null);
    }
    /**
     * è½¬æ¢ä¸ºNumber<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Number toNumber(Object value, Number defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Number)
        {
            return (Number) value;
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return NumberFormat.getInstance().parse(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºNumber<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Number toNumber(Object value)
    {
        return toNumber(value, null);
    }
    /**
     * è½¬æ¢ä¸ºint<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Integer toInt(Object value, Integer defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Integer)
        {
            return (Integer) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).intValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Integer.parseInt(valueStr.trim());
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºint<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer toInt(Object value)
    {
        return toInt(value, null);
    }
    /**
     * è½¬æ¢ä¸ºInteger数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer[] toIntArray(String str)
    {
        return toIntArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºLong数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long[] toLongArray(String str)
    {
        return toLongArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºInteger数组<br>
     *
     * @param split åˆ†éš”符
     * @param split è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer[] toIntArray(String split, String str)
    {
        if (StringUtils.isEmpty(str))
        {
            return new Integer[] {};
        }
        String[] arr = str.split(split);
        final Integer[] ints = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++)
        {
            final Integer v = toInt(arr[i], 0);
            ints[i] = v;
        }
        return ints;
    }
    /**
     * è½¬æ¢ä¸ºLong数组<br>
     *
     * @param split åˆ†éš”符
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long[] toLongArray(String split, String str)
    {
        if (StringUtils.isEmpty(str))
        {
            return new Long[] {};
        }
        String[] arr = str.split(split);
        final Long[] longs = new Long[arr.length];
        for (int i = 0; i < arr.length; i++)
        {
            final Long v = toLong(arr[i], null);
            longs[i] = v;
        }
        return longs;
    }
    /**
     * è½¬æ¢ä¸ºString数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String[] toStrArray(String str)
    {
        return toStrArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºString数组<br>
     *
     * @param split åˆ†éš”符
     * @param split è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String[] toStrArray(String split, String str)
    {
        return str.split(split);
    }
    /**
     * è½¬æ¢ä¸ºlong<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Long toLong(Object value, Long defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Long)
        {
            return (Long) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).longValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            // æ”¯æŒç§‘学计数法
            return new BigDecimal(valueStr.trim()).longValue();
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºlong<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long toLong(Object value)
    {
        return toLong(value, null);
    }
    /**
     * è½¬æ¢ä¸ºdouble<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Double toDouble(Object value, Double defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Double)
        {
            return (Double) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).doubleValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            // æ”¯æŒç§‘学计数法
            return new BigDecimal(valueStr.trim()).doubleValue();
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºdouble<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Double toDouble(Object value)
    {
        return toDouble(value, null);
    }
    /**
     * è½¬æ¢ä¸ºFloat<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Float toFloat(Object value, Float defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Float)
        {
            return (Float) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).floatValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Float.parseFloat(valueStr.trim());
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºFloat<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Float toFloat(Object value)
    {
        return toFloat(value, null);
    }
    /**
     * è½¬æ¢ä¸ºboolean<br>
     * String支持的值为:true、false、yes、ok、no,1,0 å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Boolean toBool(Object value, Boolean defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Boolean)
        {
            return (Boolean) value;
        }
        String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        valueStr = valueStr.trim().toLowerCase();
        switch (valueStr)
        {
            case "true":
            case "yes":
            case "ok":
            case "1":
                return true;
            case "false":
            case "no":
            case "0":
                return false;
            default:
                return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºboolean<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Boolean toBool(Object value)
    {
        return toBool(value, null);
    }
    /**
     * è½¬æ¢ä¸ºEnum对象<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     *
     * @param clazz Enum的Class
     * @param value å€¼
     * @param defaultValue é»˜è®¤å€¼
     * @return Enum
     */
    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (clazz.isAssignableFrom(value.getClass()))
        {
            @SuppressWarnings("unchecked")
            E myE = (E) value;
            return myE;
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Enum.valueOf(clazz, valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºEnum对象<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     *
     * @param clazz Enum的Class
     * @param value å€¼
     * @return Enum
     */
    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
    {
        return toEnum(clazz, value, null);
    }
    /**
     * è½¬æ¢ä¸ºBigInteger<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof BigInteger)
        {
            return (BigInteger) value;
        }
        if (value instanceof Long)
        {
            return BigInteger.valueOf((Long) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return new BigInteger(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºBigInteger<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static BigInteger toBigInteger(Object value)
    {
        return toBigInteger(value, null);
    }
    /**
     * è½¬æ¢ä¸ºBigDecimal<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof BigDecimal)
        {
            return (BigDecimal) value;
        }
        if (value instanceof Long)
        {
            return new BigDecimal((Long) value);
        }
        if (value instanceof Double)
        {
            return BigDecimal.valueOf((Double) value);
        }
        if (value instanceof Integer)
        {
            return new BigDecimal((Integer) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return new BigDecimal(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºBigDecimal<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static BigDecimal toBigDecimal(Object value)
    {
        return toBigDecimal(value, null);
    }
    /**
     * å°†å¯¹è±¡è½¬ä¸ºå­—符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj å¯¹è±¡
     * @return å­—符串
     */
    public static String utf8Str(Object obj)
    {
        return str(obj, CharsetKit.CHARSET_UTF_8);
    }
    /**
     * å°†å¯¹è±¡è½¬ä¸ºå­—符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj å¯¹è±¡
     * @param charsetName å­—符集
     * @return å­—符串
     */
    public static String str(Object obj, String charsetName)
    {
        return str(obj, Charset.forName(charsetName));
    }
    /**
     * å°†å¯¹è±¡è½¬ä¸ºå­—符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj å¯¹è±¡
     * @param charset å­—符集
     * @return å­—符串
     */
    public static String str(Object obj, Charset charset)
    {
        if (null == obj)
        {
            return null;
        }
        if (obj instanceof String)
        {
            return (String) obj;
        }
        else if (obj instanceof byte[])
        {
            return str((byte[]) obj, charset);
        }
        else if (obj instanceof Byte[])
        {
            byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
            return str(bytes, charset);
        }
        else if (obj instanceof ByteBuffer)
        {
            return str((ByteBuffer) obj, charset);
        }
        return obj.toString();
    }
    /**
     * å°†byte数组转为字符串
     *
     * @param bytes byte数组
     * @param charset å­—符集
     * @return å­—符串
     */
    public static String str(byte[] bytes, String charset)
    {
        return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
    }
    /**
     * è§£ç å­—节码
     *
     * @param data å­—符串
     * @param charset å­—符集,如果此字段为空,则解码的结果取决于平台
     * @return è§£ç åŽçš„字符串
     */
    public static String str(byte[] data, Charset charset)
    {
        if (data == null)
        {
            return null;
        }
        if (null == charset)
        {
            return new String(data);
        }
        return new String(data, charset);
    }
    /**
     * å°†ç¼–码的byteBuffer数据转换为字符串
     *
     * @param data æ•°æ®
     * @param charset å­—符集,如果为空使用当前系统字符集
     * @return å­—符串
     */
    public static String str(ByteBuffer data, String charset)
    {
        if (data == null)
        {
            return null;
        }
        return str(data, Charset.forName(charset));
    }
    /**
     * å°†ç¼–码的byteBuffer数据转换为字符串
     *
     * @param data æ•°æ®
     * @param charset å­—符集,如果为空使用当前系统字符集
     * @return å­—符串
     */
    public static String str(ByteBuffer data, Charset charset)
    {
        if (null == charset)
        {
            charset = Charset.defaultCharset();
        }
        return charset.decode(data).toString();
    }
    // ----------------------------------------------------------------------- å…¨è§’半角转换
    /**
     * åŠè§’转全角
     *
     * @param input String.
     * @return å…¨è§’字符串.
     */
    public static String toSBC(String input)
    {
        return toSBC(input, null);
    }
    /**
     * åŠè§’转全角
     *
     * @param input String
     * @param notConvertSet ä¸æ›¿æ¢çš„字符集合
     * @return å…¨è§’字符串.
     */
    public static String toSBC(String input, Set<Character> notConvertSet)
    {
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++)
        {
            if (null != notConvertSet && notConvertSet.contains(c[i]))
            {
                // è·³è¿‡ä¸æ›¿æ¢çš„字符
                continue;
            }
            if (c[i] == ' ')
            {
                c[i] = '\u3000';
            }
            else if (c[i] < '\177')
            {
                c[i] = (char) (c[i] + 65248);
            }
        }
        return new String(c);
    }
    /**
     * å…¨è§’转半角
     *
     * @param input String.
     * @return åŠè§’字符串
     */
    public static String toDBC(String input)
    {
        return toDBC(input, null);
    }
    /**
     * æ›¿æ¢å…¨è§’为半角
     *
     * @param text æ–‡æœ¬
     * @param notConvertSet ä¸æ›¿æ¢çš„字符集合
     * @return æ›¿æ¢åŽçš„字符
     */
    public static String toDBC(String text, Set<Character> notConvertSet)
    {
        char[] c = text.toCharArray();
        for (int i = 0; i < c.length; i++)
        {
            if (null != notConvertSet && notConvertSet.contains(c[i]))
            {
                // è·³è¿‡ä¸æ›¿æ¢çš„字符
                continue;
            }
            if (c[i] == '\u3000')
            {
                c[i] = ' ';
            }
            else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
            {
                c[i] = (char) (c[i] - 65248);
            }
        }
        String returnString = new String(c);
        return returnString;
    }
    /**
     * æ•°å­—金额大写转换 å…ˆå†™ä¸ªå®Œæ•´çš„然后将如零拾替换成零
     *
     * @param n æ•°å­—
     * @return ä¸­æ–‡å¤§å†™æ•°å­—
     */
    public static String digitUppercase(double n)
    {
        String[] fraction = { "角", "分" };
        String[] digit = { "零", "壹", "è´°", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
        String[][] unit = { { "元", "万", "亿" }, { "", "拾", "ä½°", "仟" } };
        String head = n < 0 ? "负" : "";
        n = Math.abs(n);
        String s = "";
        for (int i = 0; i < fraction.length; i++)
        {
            // ä¼˜åŒ–double计算精度丢失问题
            BigDecimal nNum = new BigDecimal(n);
            BigDecimal decimal = new BigDecimal(10);
            BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
            double d = scale.doubleValue();
            s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if (s.length() < 1)
        {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);
        for (int i = 0; i < unit[0].length && integerPart > 0; i++)
        {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++)
            {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }
}
jcdm-common/src/main/java/com/jcdm/common/core/text/StrFormatter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
package com.jcdm.common.core.text;
import com.jcdm.common.utils.StringUtils;
/**
 * å­—符串格式化
 *
 * @author jc
 */
public class StrFormatter
{
    public static final String EMPTY_JSON = "{}";
    public static final char C_BACKSLASH = '\\';
    public static final char C_DELIM_START = '{';
    public static final char C_DELIM_END = '}';
    /**
     * æ ¼å¼åŒ–字符串<br>
     * æ­¤æ–¹æ³•åªæ˜¯ç®€å•å°†å ä½ç¬¦ {} æŒ‰ç…§é¡ºåºæ›¿æ¢ä¸ºå‚æ•°<br>
     * å¦‚果想输出 {} ä½¿ç”¨ \\转义 { å³å¯ï¼Œå¦‚果想输出 {} ä¹‹å‰çš„ \ ä½¿ç”¨åŒè½¬ä¹‰ç¬¦ \\\\ å³å¯<br>
     * ä¾‹ï¼š<br>
     * é€šå¸¸ä½¿ç”¨ï¼šformat("this is {} for {}", "a", "b") -> this is a for b<br>
     * è½¬ä¹‰{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * è½¬ä¹‰\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     *
     * @param strPattern å­—符串模板
     * @param argArray å‚数列表
     * @return ç»“æžœ
     */
    public static String format(final String strPattern, final Object... argArray)
    {
        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
        {
            return strPattern;
        }
        final int strPatternLength = strPattern.length();
        // åˆå§‹åŒ–定义好的长度以获得更好的性能
        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
        int handledPosition = 0;
        int delimIndex;// å ä½ç¬¦æ‰€åœ¨ä½ç½®
        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
        {
            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
            if (delimIndex == -1)
            {
                if (handledPosition == 0)
                {
                    return strPattern;
                }
                else
                { // å­—符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
                    sbuf.append(strPattern, handledPosition, strPatternLength);
                    return sbuf.toString();
                }
            }
            else
            {
                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
                {
                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
                    {
                        // è½¬ä¹‰ç¬¦ä¹‹å‰è¿˜æœ‰ä¸€ä¸ªè½¬ä¹‰ç¬¦ï¼Œå ä½ç¬¦ä¾æ—§æœ‰æ•ˆ
                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
                        handledPosition = delimIndex + 2;
                    }
                    else
                    {
                        // å ä½ç¬¦è¢«è½¬ä¹‰
                        argIndex--;
                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
                        sbuf.append(C_DELIM_START);
                        handledPosition = delimIndex + 1;
                    }
                }
                else
                {
                    // æ­£å¸¸å ä½ç¬¦
                    sbuf.append(strPattern, handledPosition, delimIndex);
                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
                    handledPosition = delimIndex + 2;
                }
            }
        }
        // åŠ å…¥æœ€åŽä¸€ä¸ªå ä½ç¬¦åŽæ‰€æœ‰çš„字符
        sbuf.append(strPattern, handledPosition, strPattern.length());
        return sbuf.toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/enums/BusinessStatus.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.jcdm.common.enums;
/**
 * æ“ä½œçŠ¶æ€
 *
 * @author jc
 *
 */
public enum BusinessStatus
{
    /**
     * æˆåŠŸ
     */
    SUCCESS,
    /**
     * å¤±è´¥
     */
    FAIL,
}
jcdm-common/src/main/java/com/jcdm/common/enums/BusinessType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package com.jcdm.common.enums;
/**
 * ä¸šåŠ¡æ“ä½œç±»åž‹
 *
 * @author jc
 */
public enum BusinessType
{
    /**
     * å…¶å®ƒ
     */
    OTHER,
    /**
     * æ–°å¢ž
     */
    INSERT,
    /**
     * ä¿®æ”¹
     */
    UPDATE,
    /**
     * åˆ é™¤
     */
    DELETE,
    /**
     * æŽˆæƒ
     */
    GRANT,
    /**
     * å¯¼å‡º
     */
    EXPORT,
    /**
     * å¯¼å…¥
     */
    IMPORT,
    /**
     * å¼ºé€€
     */
    FORCE,
    /**
     * ç”Ÿæˆä»£ç 
     */
    GENCODE,
    /**
     * æ¸…空数据
     */
    CLEAN,
}
jcdm-common/src/main/java/com/jcdm/common/enums/DataSourceType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.jcdm.common.enums;
/**
 * æ•°æ®æº
 *
 * @author jc
 */
public enum DataSourceType
{
    /**
     * ä¸»åº“
     */
    MASTER,
    /**
     * ä»Žåº“
     */
    SLAVE
}
jcdm-common/src/main/java/com/jcdm/common/enums/HttpMethod.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package com.jcdm.common.enums;
import java.util.HashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
/**
 * è¯·æ±‚方式
 *
 * @author jc
 */
public enum HttpMethod
{
    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
    private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
    static
    {
        for (HttpMethod httpMethod : values())
        {
            mappings.put(httpMethod.name(), httpMethod);
        }
    }
    @Nullable
    public static HttpMethod resolve(@Nullable String method)
    {
        return (method != null ? mappings.get(method) : null);
    }
    public boolean matches(String method)
    {
        return (this == resolve(method));
    }
}
jcdm-common/src/main/java/com/jcdm/common/enums/LimitType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.jcdm.common.enums;
/**
 * é™æµç±»åž‹
 *
 * @author jc
 */
public enum LimitType
{
    /**
     * é»˜è®¤ç­–略全局限流
     */
    DEFAULT,
    /**
     * æ ¹æ®è¯·æ±‚者IP进行限流
     */
    IP
}
jcdm-common/src/main/java/com/jcdm/common/enums/OperatorType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.jcdm.common.enums;
/**
 * æ“ä½œäººç±»åˆ«
 *
 * @author jc
 */
public enum OperatorType
{
    /**
     * å…¶å®ƒ
     */
    OTHER,
    /**
     * åŽå°ç”¨æˆ·
     */
    MANAGE,
    /**
     * æ‰‹æœºç«¯ç”¨æˆ·
     */
    MOBILE
}
jcdm-common/src/main/java/com/jcdm/common/enums/UserStatus.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.jcdm.common.enums;
/**
 * ç”¨æˆ·çŠ¶æ€
 *
 * @author jc
 */
public enum UserStatus
{
    OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
    private final String code;
    private final String info;
    UserStatus(String code, String info)
    {
        this.code = code;
        this.info = info;
    }
    public String getCode()
    {
        return code;
    }
    public String getInfo()
    {
        return info;
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/DemoModeException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.jcdm.common.exception;
/**
 * æ¼”示模式异常
 *
 * @author jc
 */
public class DemoModeException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    public DemoModeException()
    {
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/GlobalException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.jcdm.common.exception;
/**
 * å…¨å±€å¼‚常
 *
 * @author jc
 */
public class GlobalException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    /**
     * é”™è¯¯æç¤º
     */
    private String message;
    /**
     * é”™è¯¯æ˜Žç»†ï¼Œå†…部调试错误
     *
     * å’Œ {@link CommonResult#getDetailMessage()} ä¸€è‡´çš„设计
     */
    private String detailMessage;
    /**
     * ç©ºæž„造方法,避免反序列化问题
     */
    public GlobalException()
    {
    }
    public GlobalException(String message)
    {
        this.message = message;
    }
    public String getDetailMessage()
    {
        return detailMessage;
    }
    public GlobalException setDetailMessage(String detailMessage)
    {
        this.detailMessage = detailMessage;
        return this;
    }
    @Override
    public String getMessage()
    {
        return message;
    }
    public GlobalException setMessage(String message)
    {
        this.message = message;
        return this;
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/ServiceException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package com.jcdm.common.exception;
/**
 * ä¸šåŠ¡å¼‚常
 *
 * @author jc
 */
public final class ServiceException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    /**
     * é”™è¯¯ç 
     */
    private Integer code;
    /**
     * é”™è¯¯æç¤º
     */
    private String message;
    /**
     * é”™è¯¯æ˜Žç»†ï¼Œå†…部调试错误
     *
     * å’Œ {@link CommonResult#getDetailMessage()} ä¸€è‡´çš„设计
     */
    private String detailMessage;
    /**
     * ç©ºæž„造方法,避免反序列化问题
     */
    public ServiceException()
    {
    }
    public ServiceException(String message)
    {
        this.message = message;
    }
    public ServiceException(String message, Integer code)
    {
        this.message = message;
        this.code = code;
    }
    public String getDetailMessage()
    {
        return detailMessage;
    }
    @Override
    public String getMessage()
    {
        return message;
    }
    public Integer getCode()
    {
        return code;
    }
    public ServiceException setMessage(String message)
    {
        this.message = message;
        return this;
    }
    public ServiceException setDetailMessage(String detailMessage)
    {
        this.detailMessage = detailMessage;
        return this;
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/UtilException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.jcdm.common.exception;
/**
 * å·¥å…·ç±»å¼‚常
 *
 * @author jc
 */
public class UtilException extends RuntimeException
{
    private static final long serialVersionUID = 8247610319171014183L;
    public UtilException(Throwable e)
    {
        super(e.getMessage(), e);
    }
    public UtilException(String message)
    {
        super(message);
    }
    public UtilException(String message, Throwable throwable)
    {
        super(message, throwable);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/base/BaseException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
package com.jcdm.common.exception.base;
import com.jcdm.common.utils.MessageUtils;
import com.jcdm.common.utils.StringUtils;
/**
 * åŸºç¡€å¼‚常
 *
 * @author jc
 */
public class BaseException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    /**
     * æ‰€å±žæ¨¡å—
     */
    private String module;
    /**
     * é”™è¯¯ç 
     */
    private String code;
    /**
     * é”™è¯¯ç å¯¹åº”的参数
     */
    private Object[] args;
    /**
     * é”™è¯¯æ¶ˆæ¯
     */
    private String defaultMessage;
    public BaseException(String module, String code, Object[] args, String defaultMessage)
    {
        this.module = module;
        this.code = code;
        this.args = args;
        this.defaultMessage = defaultMessage;
    }
    public BaseException(String module, String code, Object[] args)
    {
        this(module, code, args, null);
    }
    public BaseException(String module, String defaultMessage)
    {
        this(module, null, null, defaultMessage);
    }
    public BaseException(String code, Object[] args)
    {
        this(null, code, args, null);
    }
    public BaseException(String defaultMessage)
    {
        this(null, null, null, defaultMessage);
    }
    @Override
    public String getMessage()
    {
        String message = null;
        if (!StringUtils.isEmpty(code))
        {
            message = MessageUtils.message(code, args);
        }
        if (message == null)
        {
            message = defaultMessage;
        }
        return message;
    }
    public String getModule()
    {
        return module;
    }
    public String getCode()
    {
        return code;
    }
    public Object[] getArgs()
    {
        return args;
    }
    public String getDefaultMessage()
    {
        return defaultMessage;
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.jcdm.common.exception.file;
import com.jcdm.common.exception.base.BaseException;
/**
 * æ–‡ä»¶ä¿¡æ¯å¼‚常类
 *
 * @author jc
 */
public class FileException extends BaseException
{
    private static final long serialVersionUID = 1L;
    public FileException(String code, Object[] args)
    {
        super("file", code, args, null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileNameLengthLimitExceededException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.file;
/**
 * æ–‡ä»¶åç§°è¶…长限制异常类
 *
 * @author jc
 */
public class FileNameLengthLimitExceededException extends FileException
{
    private static final long serialVersionUID = 1L;
    public FileNameLengthLimitExceededException(int defaultFileNameLength)
    {
        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileSizeLimitExceededException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.file;
/**
 * æ–‡ä»¶åå¤§å°é™åˆ¶å¼‚常类
 *
 * @author jc
 */
public class FileSizeLimitExceededException extends FileException
{
    private static final long serialVersionUID = 1L;
    public FileSizeLimitExceededException(long defaultMaxSize)
    {
        super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/file/FileUploadException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.jcdm.common.exception.file;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
 * æ–‡ä»¶ä¸Šä¼ å¼‚常类
 *
 * @author jc
 */
public class FileUploadException extends Exception
{
    private static final long serialVersionUID = 1L;
    private final Throwable cause;
    public FileUploadException()
    {
        this(null, null);
    }
    public FileUploadException(final String msg)
    {
        this(msg, null);
    }
    public FileUploadException(String msg, Throwable cause)
    {
        super(msg);
        this.cause = cause;
    }
    @Override
    public void printStackTrace(PrintStream stream)
    {
        super.printStackTrace(stream);
        if (cause != null)
        {
            stream.println("Caused by:");
            cause.printStackTrace(stream);
        }
    }
    @Override
    public void printStackTrace(PrintWriter writer)
    {
        super.printStackTrace(writer);
        if (cause != null)
        {
            writer.println("Caused by:");
            cause.printStackTrace(writer);
        }
    }
    @Override
    public Throwable getCause()
    {
        return cause;
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/file/InvalidExtensionException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
package com.jcdm.common.exception.file;
import java.util.Arrays;
/**
 * æ–‡ä»¶ä¸Šä¼  è¯¯å¼‚常类
 *
 * @author jc
 */
public class InvalidExtensionException extends FileUploadException
{
    private static final long serialVersionUID = 1L;
    private String[] allowedExtension;
    private String extension;
    private String filename;
    public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
    {
        super("文件[" + filename + "]后缀[" + extension + "]不正确,请上传" + Arrays.toString(allowedExtension) + "格式");
        this.allowedExtension = allowedExtension;
        this.extension = extension;
        this.filename = filename;
    }
    public String[] getAllowedExtension()
    {
        return allowedExtension;
    }
    public String getExtension()
    {
        return extension;
    }
    public String getFilename()
    {
        return filename;
    }
    public static class InvalidImageExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
    public static class InvalidFlashExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
    public static class InvalidMediaExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
    public static class InvalidVideoExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/job/TaskException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.jcdm.common.exception.job;
/**
 * è®¡åˆ’策略异常
 *
 * @author jc
 */
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
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/BlackListException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.user;
/**
 * é»‘名单IP异常类
 *
 * @author jc
 */
public class BlackListException extends UserException
{
    private static final long serialVersionUID = 1L;
    public BlackListException()
    {
        super("login.blocked", null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.user;
/**
 * éªŒè¯ç é”™è¯¯å¼‚常类
 *
 * @author jc
 */
public class CaptchaException extends UserException
{
    private static final long serialVersionUID = 1L;
    public CaptchaException()
    {
        super("user.jcaptcha.error", null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/CaptchaExpireException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.user;
/**
 * éªŒè¯ç å¤±æ•ˆå¼‚常类
 *
 * @author jc
 */
public class CaptchaExpireException extends UserException
{
    private static final long serialVersionUID = 1L;
    public CaptchaExpireException()
    {
        super("user.jcaptcha.expire", null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.jcdm.common.exception.user;
import com.jcdm.common.exception.base.BaseException;
/**
 * ç”¨æˆ·ä¿¡æ¯å¼‚常类
 *
 * @author jc
 */
public class UserException extends BaseException
{
    private static final long serialVersionUID = 1L;
    public UserException(String code, Object[] args)
    {
        super("user", code, args, null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserNotExistsException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.user;
/**
 * ç”¨æˆ·ä¸å­˜åœ¨å¼‚常类
 *
 * @author jc
 */
public class UserNotExistsException extends UserException
{
    private static final long serialVersionUID = 1L;
    public UserNotExistsException()
    {
        super("user.not.exists", null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordNotMatchException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.user;
/**
 * ç”¨æˆ·å¯†ç ä¸æ­£ç¡®æˆ–不符合规范异常类
 *
 * @author jc
 */
public class UserPasswordNotMatchException extends UserException
{
    private static final long serialVersionUID = 1L;
    public UserPasswordNotMatchException()
    {
        super("user.password.not.match", null);
    }
}
jcdm-common/src/main/java/com/jcdm/common/exception/user/UserPasswordRetryLimitExceedException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.jcdm.common.exception.user;
/**
 * ç”¨æˆ·é”™è¯¯æœ€å¤§æ¬¡æ•°å¼‚常类
 *
 * @author jc
 */
public class UserPasswordRetryLimitExceedException extends UserException
{
    private static final long serialVersionUID = 1L;
    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
    {
        super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
    }
}
jcdm-common/src/main/java/com/jcdm/common/filter/PropertyPreExcludeFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.jcdm.common.filter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
/**
 * æŽ’除JSON敏感属性
 *
 * @author jc
 */
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
{
    public PropertyPreExcludeFilter()
    {
    }
    public PropertyPreExcludeFilter addExcludes(String... filters)
    {
        for (int i = 0; i < filters.length; i++)
        {
            this.getExcludes().add(filters[i]);
        }
        return this;
    }
}
jcdm-common/src/main/java/com/jcdm/common/filter/RepeatableFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.jcdm.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.jcdm.common.utils.StringUtils;
/**
 * Repeatable è¿‡æ»¤å™¨
 *
 * @author jc
 */
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.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
        {
            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
        }
        if (null == requestWrapper)
        {
            chain.doFilter(request, response);
        }
        else
        {
            chain.doFilter(requestWrapper, response);
        }
    }
    @Override
    public void destroy()
    {
    }
}
jcdm-common/src/main/java/com/jcdm/common/filter/RepeatedlyRequestWrapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.jcdm.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.jcdm.common.utils.http.HttpHelper;
import com.jcdm.common.constant.Constants;
/**
 * æž„建可重复读取inputStream的request
 *
 * @author jc
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
    private final byte[] body;
    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
    {
        super(request);
        request.setCharacterEncoding(Constants.UTF8);
        response.setCharacterEncoding(Constants.UTF8);
        body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
    }
    @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 int available() throws IOException
            {
                return body.length;
            }
            @Override
            public boolean isFinished()
            {
                return false;
            }
            @Override
            public boolean isReady()
            {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener)
            {
            }
        };
    }
}
jcdm-common/src/main/java/com/jcdm/common/filter/XssFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
package com.jcdm.common.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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 javax.servlet.http.HttpServletResponse;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.enums.HttpMethod;
/**
 * é˜²æ­¢XSS攻击的过滤器
 *
 * @author jc
 */
public class XssFilter implements Filter
{
    /**
     * æŽ’除链接
     */
    public List<String> excludes = new ArrayList<>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        String tempExcludes = filterConfig.getInitParameter("excludes");
        if (StringUtils.isNotEmpty(tempExcludes))
        {
            String[] url = tempExcludes.split(",");
            for (int i = 0; url != null && i < url.length; i++)
            {
                excludes.add(url[i]);
            }
        }
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        if (handleExcludeURL(req, resp))
        {
            chain.doFilter(request, response);
            return;
        }
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(xssRequest, response);
    }
    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
    {
        String url = request.getServletPath();
        String method = request.getMethod();
        // GET DELETE ä¸è¿‡æ»¤
        if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
        {
            return true;
        }
        return StringUtils.matches(url, excludes);
    }
    @Override
    public void destroy()
    {
    }
}
jcdm-common/src/main/java/com/jcdm/common/filter/XssHttpServletRequestWrapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
package com.jcdm.common.filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.html.EscapeUtil;
/**
 * XSS过滤处理
 *
 * @author jc
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
    /**
     * @param request
     */
    public XssHttpServletRequestWrapper(HttpServletRequest request)
    {
        super(request);
    }
    @Override
    public String[] getParameterValues(String name)
    {
        String[] values = super.getParameterValues(name);
        if (values != null)
        {
            int length = values.length;
            String[] escapesValues = new String[length];
            for (int i = 0; i < length; i++)
            {
                // é˜²xss攻击和过滤前后空格
                escapesValues[i] = EscapeUtil.clean(values[i]).trim();
            }
            return escapesValues;
        }
        return super.getParameterValues(name);
    }
    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        // éžjson类型,直接返回
        if (!isJsonRequest())
        {
            return super.getInputStream();
        }
        // ä¸ºç©ºï¼Œç›´æŽ¥è¿”回
        String json = IOUtils.toString(super.getInputStream(), "utf-8");
        if (StringUtils.isEmpty(json))
        {
            return super.getInputStream();
        }
        // xss过滤
        json = EscapeUtil.clean(json).trim();
        byte[] jsonBytes = json.getBytes("utf-8");
        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
        return new ServletInputStream()
        {
            @Override
            public boolean isFinished()
            {
                return true;
            }
            @Override
            public boolean isReady()
            {
                return true;
            }
            @Override
            public int available() throws IOException
            {
                return jsonBytes.length;
            }
            @Override
            public void setReadListener(ReadListener readListener)
            {
            }
            @Override
            public int read() throws IOException
            {
                return bis.read();
            }
        };
    }
    /**
     * æ˜¯å¦æ˜¯Json请求
     *
     * @param request
     */
    public boolean isJsonRequest()
    {
        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/Arith.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,114 @@
package com.jcdm.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
 * ç²¾ç¡®çš„浮点数运算
 *
 * @author jc
 */
public class Arith
{
    /** é»˜è®¤é™¤æ³•è¿ç®—精度 */
    private static final int DEF_DIV_SCALE = 10;
    /** è¿™ä¸ªç±»ä¸èƒ½å®žä¾‹åŒ– */
    private Arith()
    {
    }
    /**
     * æä¾›ç²¾ç¡®çš„加法运算。
     * @param v1 è¢«åŠ æ•°
     * @param v2 åŠ æ•°
     * @return ä¸¤ä¸ªå‚æ•°çš„å’Œ
     */
    public static double add(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }
    /**
     * æä¾›ç²¾ç¡®çš„减法运算。
     * @param v1 è¢«å‡æ•°
     * @param v2 å‡æ•°
     * @return ä¸¤ä¸ªå‚æ•°çš„å·®
     */
    public static double sub(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }
    /**
     * æä¾›ç²¾ç¡®çš„乘法运算。
     * @param v1 è¢«ä¹˜æ•°
     * @param v2 ä¹˜æ•°
     * @return ä¸¤ä¸ªå‚数的积
     */
    public static double mul(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }
    /**
     * æä¾›ï¼ˆç›¸å¯¹ï¼‰ç²¾ç¡®çš„除法运算,当发生除不尽的情况时,精确到
     * å°æ•°ç‚¹ä»¥åŽ10位,以后的数字四舍五入。
     * @param v1 è¢«é™¤æ•°
     * @param v2 é™¤æ•°
     * @return ä¸¤ä¸ªå‚数的商
     */
    public static double div(double v1, double v2)
    {
        return div(v1, v2, DEF_DIV_SCALE);
    }
    /**
     * æä¾›ï¼ˆç›¸å¯¹ï¼‰ç²¾ç¡®çš„除法运算。当发生除不尽的情况时,由scale参数指
     * å®šç²¾åº¦ï¼Œä»¥åŽçš„数字四舍五入。
     * @param v1 è¢«é™¤æ•°
     * @param v2 é™¤æ•°
     * @param scale è¡¨ç¤ºè¡¨ç¤ºéœ€è¦ç²¾ç¡®åˆ°å°æ•°ç‚¹ä»¥åŽå‡ ä½ã€‚
     * @return ä¸¤ä¸ªå‚数的商
     */
    public static double div(double v1, double v2, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        if (b1.compareTo(BigDecimal.ZERO) == 0)
        {
            return BigDecimal.ZERO.doubleValue();
        }
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }
    /**
     * æä¾›ç²¾ç¡®çš„小数位四舍五入处理。
     * @param v éœ€è¦å››èˆäº”入的数字
     * @param scale å°æ•°ç‚¹åŽä¿ç•™å‡ ä½
     * @return å››èˆäº”入后的结果
     */
    public static double round(double v, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = BigDecimal.ONE;
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/DateUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,191 @@
package com.jcdm.common.utils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
 * æ—¶é—´å·¥å…·ç±»
 *
 * @author jc
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";
    public static String YYYY_MM = "yyyy-MM";
    public static String YYYY_MM_DD = "yyyy-MM-dd";
    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
    /**
     * èŽ·å–当前Date型日期
     *
     * @return Date() å½“前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }
    /**
     * èŽ·å–当前日期, é»˜è®¤æ ¼å¼ä¸ºyyyy-MM-dd
     *
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }
    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }
    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }
    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }
    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }
    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }
    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }
    /**
     * æ—¥æœŸè·¯å¾„ å³å¹´/月/日 å¦‚2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }
    /**
     * æ—¥æœŸè·¯å¾„ å³å¹´/月/日 å¦‚20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }
    /**
     * æ—¥æœŸåž‹å­—符串转化为日期 æ ¼å¼
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }
    /**
     * èŽ·å–服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }
    /**
     * è®¡ç®—相差天数
     */
    public static int differentDaysByMillisecond(Date date1, Date date2)
    {
        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
    }
    /**
     * è®¡ç®—时间差
     *
     * @param endDate æœ€åŽæ—¶é—´
     * @param startTime å¼€å§‹æ—¶é—´
     * @return æ—¶é—´å·®ï¼ˆå¤©/小时/分钟)
     */
    public static String timeDistance(Date endDate, Date startTime)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // èŽ·å¾—两个时间的毫秒时间差异
        long diff = endDate.getTime() - startTime.getTime();
        // è®¡ç®—差多少天
        long day = diff / nd;
        // è®¡ç®—差多少小时
        long hour = diff % nd / nh;
        // è®¡ç®—差多少分钟
        long min = diff % nd % nh / nm;
        // è®¡ç®—差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
    /**
     * å¢žåŠ  LocalDateTime ==> Date
     */
    public static Date toDate(LocalDateTime temporalAccessor)
    {
        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
    /**
     * å¢žåŠ  LocalDate ==> Date
     */
    public static Date toDate(LocalDate temporalAccessor)
    {
        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/DictUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,204 @@
package com.jcdm.common.utils;
import java.util.Collection;
import java.util.List;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.jcdm.common.constant.CacheConstants;
import com.jcdm.common.core.domain.entity.SysDictData;
import com.jcdm.common.core.redis.RedisCache;
import com.jcdm.common.utils.spring.SpringUtils;
/**
 * å­—典工具类
 *
 * @author jc
 */
public class DictUtils
{
    /**
     * åˆ†éš”符
     */
    public static final String SEPARATOR = ",";
    /**
     * è®¾ç½®å­—典缓存
     *
     * @param key å‚æ•°é”®
     * @param dictDatas å­—典数据列表
     */
    public static void setDictCache(String key, List<SysDictData> dictDatas)
    {
        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
    }
//    /**
//     * èŽ·å–字典缓存
//     *
//     * @param key å‚æ•°é”®
//     * @return dictDatas å­—典数据列表
//     */
//    public static List<SysDictData> getDictCache(String key)
//    {
//        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
//        if (StringUtils.isNotNull(arrayCache))
//        {
//            return arrayCache.toList(SysDictData.class);
//        }
//        return null;
//    }
    /**
     * èŽ·å–字典缓存
     *
     * @param key å‚æ•°é”®
     * @return dictDatas å­—典数据列表
     */
    public static List<SysDictData> getDictCache(String key)
    {
        JSONArray arrayCache = JSONArray.parseArray(JSON.toJSONString(SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key))));
//        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
        if (StringUtils.isNotNull(arrayCache))
        {
            return arrayCache.toList(SysDictData.class);
        }
        return null;
    }
    /**
     * æ ¹æ®å­—典类型和字典值获取字典标签
     *
     * @param dictType å­—典类型
     * @param dictValue å­—典值
     * @return å­—典标签
     */
    public static String getDictLabel(String dictType, String dictValue)
    {
        return getDictLabel(dictType, dictValue, SEPARATOR);
    }
    /**
     * æ ¹æ®å­—典类型和字典标签获取字典值
     *
     * @param dictType å­—典类型
     * @param dictLabel å­—典标签
     * @return å­—典值
     */
    public static String getDictValue(String dictType, String dictLabel)
    {
        return getDictValue(dictType, dictLabel, SEPARATOR);
    }
    /**
     * æ ¹æ®å­—典类型和字典值获取字典标签
     *
     * @param dictType å­—典类型
     * @param dictValue å­—典值
     * @param separator åˆ†éš”符
     * @return å­—典标签
     */
    public static String getDictLabel(String dictType, String dictValue, String separator)
    {
        StringBuilder propertyString = new StringBuilder();
        List<SysDictData> datas = getDictCache(dictType);
        if (StringUtils.isNotNull(datas))
        {
            if (StringUtils.containsAny(separator, dictValue))
            {
                for (SysDictData dict : datas)
                {
                    for (String value : dictValue.split(separator))
                    {
                        if (value.equals(dict.getDictValue()))
                        {
                            propertyString.append(dict.getDictLabel()).append(separator);
                            break;
                        }
                    }
                }
            }
            else
            {
                for (SysDictData dict : datas)
                {
                    if (dictValue.equals(dict.getDictValue()))
                    {
                        return dict.getDictLabel();
                    }
                }
            }
        }
        return StringUtils.stripEnd(propertyString.toString(), separator);
    }
    /**
     * æ ¹æ®å­—典类型和字典标签获取字典值
     *
     * @param dictType å­—典类型
     * @param dictLabel å­—典标签
     * @param separator åˆ†éš”符
     * @return å­—典值
     */
    public static String getDictValue(String dictType, String dictLabel, String separator)
    {
        StringBuilder propertyString = new StringBuilder();
        List<SysDictData> datas = getDictCache(dictType);
        if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
        {
            for (SysDictData dict : datas)
            {
                for (String label : dictLabel.split(separator))
                {
                    if (label.equals(dict.getDictLabel()))
                    {
                        propertyString.append(dict.getDictValue()).append(separator);
                        break;
                    }
                }
            }
        }
        else
        {
            for (SysDictData dict : datas)
            {
                if (dictLabel.equals(dict.getDictLabel()))
                {
                    return dict.getDictValue();
                }
            }
        }
        return StringUtils.stripEnd(propertyString.toString(), separator);
    }
    /**
     * åˆ é™¤æŒ‡å®šå­—典缓存
     *
     * @param key å­—典键
     */
    public static void removeDictCache(String key)
    {
        SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
    }
    /**
     * æ¸…空字典缓存
     */
    public static void clearDictCache()
    {
        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*");
        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
    }
    /**
     * è®¾ç½®cache key
     *
     * @param configKey å‚æ•°é”®
     * @return ç¼“存键key
     */
    public static String getCacheKey(String configKey)
    {
        return CacheConstants.SYS_DICT_KEY + configKey;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/ExceptionUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.jcdm.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;
/**
 * é”™è¯¯ä¿¡æ¯å¤„理类。
 *
 * @author jc
 */
public class ExceptionUtil
{
    /**
     * èŽ·å–exception的详细错误信息。
     */
    public static String getExceptionMessage(Throwable e)
    {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw, true));
        return sw.toString();
    }
    public static String getRootErrorMessage(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);
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/LogUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.jcdm.common.utils;
/**
 * å¤„理并记录日志文件
 *
 * @author jc
 */
public class LogUtils
{
    public static String getBlock(Object msg)
    {
        if (msg == null)
        {
            msg = "";
        }
        return "[" + msg.toString() + "]";
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/MessageUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.jcdm.common.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.jcdm.common.utils.spring.SpringUtils;
/**
 * èŽ·å–i18n资源文件
 *
 * @author jc
 */
public class MessageUtils
{
    /**
     * æ ¹æ®æ¶ˆæ¯é”®å’Œå‚æ•° èŽ·å–消息 å§”托给spring messageSource
     *
     * @param code æ¶ˆæ¯é”®
     * @param args å‚æ•°
     * @return èŽ·å–国际化翻译值
     */
    public static String message(String code, Object... args)
    {
        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/PageUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
package com.jcdm.common.utils;
import com.github.pagehelper.PageHelper;
import com.jcdm.common.core.page.PageDomain;
import com.jcdm.common.core.page.TableSupport;
import com.jcdm.common.utils.sql.SqlUtil;
/**
 * åˆ†é¡µå·¥å…·ç±»
 *
 * @author jc
 */
public class PageUtils extends PageHelper
{
    /**
     * è®¾ç½®è¯·æ±‚分页数据
     */
    public static void startPage()
    {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
        Boolean reasonable = pageDomain.getReasonable();
        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
    }
    /**
     * æ¸…理分页的线程变量
     */
    public static void clearPage()
    {
        PageHelper.clearPage();
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/SecurityUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,178 @@
package com.jcdm.common.utils;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.PatternMatchUtils;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.constant.HttpStatus;
import com.jcdm.common.core.domain.entity.SysRole;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.exception.ServiceException;
/**
 * å®‰å…¨æœåŠ¡å·¥å…·ç±»
 *
 * @author jc
 */
public class SecurityUtils
{
    /**
     * ç”¨æˆ·ID
     **/
    public static Long getUserId()
    {
        try
        {
            return getLoginUser().getUserId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–部门ID
     **/
    public static Long getDeptId()
    {
        try
        {
            return getLoginUser().getDeptId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–用户账户
     **/
    public static String getUsername()
    {
        try
        {
            return getLoginUser().getUsername();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–用户
     **/
    public static LoginUser getLoginUser()
    {
        try
        {
            return (LoginUser) getAuthentication().getPrincipal();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–Authentication
     */
    public static Authentication getAuthentication()
    {
        return SecurityContextHolder.getContext().getAuthentication();
    }
    /**
     * ç”ŸæˆBCryptPasswordEncoder密码
     *
     * @param password å¯†ç 
     * @return åŠ å¯†å­—符串
     */
    public static String encryptPassword(String password)
    {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.encode(password);
    }
    /**
     * åˆ¤æ–­å¯†ç æ˜¯å¦ç›¸åŒ
     *
     * @param rawPassword çœŸå®žå¯†ç 
     * @param encodedPassword åŠ å¯†åŽå­—符
     * @return ç»“æžœ
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword)
    {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }
    /**
     * æ˜¯å¦ä¸ºç®¡ç†å‘˜
     *
     * @param userId ç”¨æˆ·ID
     * @return ç»“æžœ
     */
    public static boolean isAdmin(Long userId)
    {
        return userId != null && 1L == userId;
    }
    /**
     * éªŒè¯ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™
     *
     * @param permission æƒé™å­—符串
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™
     */
    public static boolean hasPermi(String permission)
    {
        return hasPermi(getLoginUser().getPermissions(), permission);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦åŒ…含权限
     *
     * @param authorities æƒé™åˆ—表
     * @param permission æƒé™å­—符串
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™
     */
    public static boolean hasPermi(Collection<String> authorities, String permission)
    {
        return authorities.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
    }
    /**
     * éªŒè¯ç”¨æˆ·æ˜¯å¦æ‹¥æœ‰æŸä¸ªè§’色
     *
     * @param role è§’色标识
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸè§’色
     */
    public static boolean hasRole(String role)
    {
        List<SysRole> roleList = getLoginUser().getUser().getRoles();
        Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
        return hasRole(roles, role);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦åŒ…含角色
     *
     * @param roles è§’色列表
     * @param role è§’色
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸè§’色权限
     */
    public static boolean hasRole(Collection<String> roles, String role)
    {
        return roles.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/ServletUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,218 @@
package com.jcdm.common.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.core.text.Convert;
/**
 * å®¢æˆ·ç«¯å·¥å…·ç±»
 *
 * @author jc
 */
public class ServletUtils
{
    /**
     * èŽ·å–String参数
     */
    public static String getParameter(String name)
    {
        return getRequest().getParameter(name);
    }
    /**
     * èŽ·å–String参数
     */
    public static String getParameter(String name, String defaultValue)
    {
        return Convert.toStr(getRequest().getParameter(name), defaultValue);
    }
    /**
     * èŽ·å–Integer参数
     */
    public static Integer getParameterToInt(String name)
    {
        return Convert.toInt(getRequest().getParameter(name));
    }
    /**
     * èŽ·å–Integer参数
     */
    public static Integer getParameterToInt(String name, Integer defaultValue)
    {
        return Convert.toInt(getRequest().getParameter(name), defaultValue);
    }
    /**
     * èŽ·å–Boolean参数
     */
    public static Boolean getParameterToBool(String name)
    {
        return Convert.toBool(getRequest().getParameter(name));
    }
    /**
     * èŽ·å–Boolean参数
     */
    public static Boolean getParameterToBool(String name, Boolean defaultValue)
    {
        return Convert.toBool(getRequest().getParameter(name), defaultValue);
    }
    /**
     * èŽ·å¾—所有请求参数
     *
     * @param request è¯·æ±‚对象{@link ServletRequest}
     * @return Map
     */
    public static Map<String, String[]> getParams(ServletRequest request)
    {
        final Map<String, String[]> map = request.getParameterMap();
        return Collections.unmodifiableMap(map);
    }
    /**
     * èŽ·å¾—所有请求参数
     *
     * @param request è¯·æ±‚对象{@link ServletRequest}
     * @return Map
     */
    public static Map<String, String> getParamMap(ServletRequest request)
    {
        Map<String, String> params = new HashMap<>();
        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
        {
            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
        }
        return params;
    }
    /**
     * èŽ·å–request
     */
    public static HttpServletRequest getRequest()
    {
        return getRequestAttributes().getRequest();
    }
    /**
     * èŽ·å–response
     */
    public static HttpServletResponse getResponse()
    {
        return getRequestAttributes().getResponse();
    }
    /**
     * èŽ·å–session
     */
    public static HttpSession getSession()
    {
        return getRequest().getSession();
    }
    public static ServletRequestAttributes getRequestAttributes()
    {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes) attributes;
    }
    /**
     * å°†å­—符串渲染到客户端
     *
     * @param response æ¸²æŸ“对象
     * @param string å¾…渲染的字符串
     */
    public static void renderString(HttpServletResponse response, String string)
    {
        try
        {
            response.setStatus(200);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    /**
     * æ˜¯å¦æ˜¯Ajax异步请求
     *
     * @param request
     */
    public static boolean isAjaxRequest(HttpServletRequest request)
    {
        String accept = request.getHeader("accept");
        if (accept != null && accept.contains("application/json"))
        {
            return true;
        }
        String xRequestedWith = request.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
        {
            return true;
        }
        String uri = request.getRequestURI();
        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
        {
            return true;
        }
        String ajax = request.getParameter("__ajax");
        return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
    }
    /**
     * å†…容编码
     *
     * @param str å†…容
     * @return ç¼–码后的内容
     */
    public static String urlEncode(String str)
    {
        try
        {
            return URLEncoder.encode(str, Constants.UTF8);
        }
        catch (UnsupportedEncodingException e)
        {
            return StringUtils.EMPTY;
        }
    }
    /**
     * å†…容解码
     *
     * @param str å†…容
     * @return è§£ç åŽçš„内容
     */
    public static String urlDecode(String str)
    {
        try
        {
            return URLDecoder.decode(str, Constants.UTF8);
        }
        catch (UnsupportedEncodingException e)
        {
            return StringUtils.EMPTY;
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/StringUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,638 @@
package com.jcdm.common.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.util.AntPathMatcher;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.core.text.StrFormatter;
/**
 * å­—符串工具类
 *
 * @author jc
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
    /** ç©ºå­—符串 */
    private static final String NULLSTR = "";
    /** ä¸‹åˆ’线 */
    private static final char SEPARATOR = '_';
    /**
     * èŽ·å–参数不为空值
     *
     * @param value defaultValue è¦åˆ¤æ–­çš„value
     * @return value è¿”回值
     */
    public static <T> T nvl(T value, T defaultValue)
    {
        return value != null ? value : defaultValue;
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªCollection是否为空, åŒ…含List,Set,Queue
     *
     * @param coll è¦åˆ¤æ–­çš„Collection
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(Collection<?> coll)
    {
        return isNull(coll) || coll.isEmpty();
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªCollection是否非空,包含List,Set,Queue
     *
     * @param coll è¦åˆ¤æ–­çš„Collection
     * @return true:非空 false:空
     */
    public static boolean isNotEmpty(Collection<?> coll)
    {
        return !isEmpty(coll);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ•°ç»„是否为空
     *
     * @param objects è¦åˆ¤æ–­çš„对象数组
     ** @return true:为空 false:非空
     */
    public static boolean isEmpty(Object[] objects)
    {
        return isNull(objects) || (objects.length == 0);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ•°ç»„是否非空
     *
     * @param objects è¦åˆ¤æ–­çš„对象数组
     * @return true:非空 false:空
     */
    public static boolean isNotEmpty(Object[] objects)
    {
        return !isEmpty(objects);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªMap是否为空
     *
     * @param map è¦åˆ¤æ–­çš„Map
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(Map<?, ?> map)
    {
        return isNull(map) || map.isEmpty();
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªMap是否为空
     *
     * @param map è¦åˆ¤æ–­çš„Map
     * @return true:非空 false:空
     */
    public static boolean isNotEmpty(Map<?, ?> map)
    {
        return !isEmpty(map);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå­—符串是否为空串
     *
     * @param str String
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(String str)
    {
        return isNull(str) || NULLSTR.equals(str.trim());
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå­—符串是否为非空串
     *
     * @param str String
     * @return true:非空串 false:空串
     */
    public static boolean isNotEmpty(String str)
    {
        return !isEmpty(str);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦ä¸ºç©º
     *
     * @param object Object
     * @return true:为空 false:非空
     */
    public static boolean isNull(Object object)
    {
        return object == null;
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦éžç©º
     *
     * @param object Object
     * @return true:非空 false:空
     */
    public static boolean isNotNull(Object object)
    {
        return !isNull(object);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦æ˜¯æ•°ç»„类型(Java基本型别的数组)
     *
     * @param object å¯¹è±¡
     * @return true:是数组 false:不是数组
     */
    public static boolean isArray(Object object)
    {
        return isNotNull(object) && object.getClass().isArray();
    }
    /**
     * åŽ»ç©ºæ ¼
     */
    public static String trim(String str)
    {
        return (str == null ? "" : str.trim());
    }
    /**
     * æˆªå–字符串
     *
     * @param str å­—符串
     * @param start å¼€å§‹
     * @return ç»“æžœ
     */
    public static String substring(final String str, int start)
    {
        if (str == null)
        {
            return NULLSTR;
        }
        if (start < 0)
        {
            start = str.length() + start;
        }
        if (start < 0)
        {
            start = 0;
        }
        if (start > str.length())
        {
            return NULLSTR;
        }
        return str.substring(start);
    }
    /**
     * æˆªå–字符串
     *
     * @param str å­—符串
     * @param start å¼€å§‹
     * @param end ç»“束
     * @return ç»“æžœ
     */
    public static String substring(final String str, int start, int end)
    {
        if (str == null)
        {
            return NULLSTR;
        }
        if (end < 0)
        {
            end = str.length() + end;
        }
        if (start < 0)
        {
            start = str.length() + start;
        }
        if (end > str.length())
        {
            end = str.length();
        }
        if (start > end)
        {
            return NULLSTR;
        }
        if (start < 0)
        {
            start = 0;
        }
        if (end < 0)
        {
            end = 0;
        }
        return str.substring(start, end);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦ä¸ºç©ºï¼Œå¹¶ä¸”不是空白字符
     *
     * @param str è¦åˆ¤æ–­çš„value
     * @return ç»“æžœ
     */
    public static boolean hasText(String str)
    {
        return (str != null && !str.isEmpty() && containsText(str));
    }
    private static boolean containsText(CharSequence str)
    {
        int strLen = str.length();
        for (int i = 0; i < strLen; i++)
        {
            if (!Character.isWhitespace(str.charAt(i)))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * æ ¼å¼åŒ–文本, {} è¡¨ç¤ºå ä½ç¬¦<br>
     * æ­¤æ–¹æ³•åªæ˜¯ç®€å•å°†å ä½ç¬¦ {} æŒ‰ç…§é¡ºåºæ›¿æ¢ä¸ºå‚æ•°<br>
     * å¦‚果想输出 {} ä½¿ç”¨ \\转义 { å³å¯ï¼Œå¦‚果想输出 {} ä¹‹å‰çš„ \ ä½¿ç”¨åŒè½¬ä¹‰ç¬¦ \\\\ å³å¯<br>
     * ä¾‹ï¼š<br>
     * é€šå¸¸ä½¿ç”¨ï¼šformat("this is {} for {}", "a", "b") -> this is a for b<br>
     * è½¬ä¹‰{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * è½¬ä¹‰\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     *
     * @param template æ–‡æœ¬æ¨¡æ¿ï¼Œè¢«æ›¿æ¢çš„部分用 {} è¡¨ç¤º
     * @param params å‚数值
     * @return æ ¼å¼åŒ–后的文本
     */
    public static String format(String template, Object... params)
    {
        if (isEmpty(params) || isEmpty(template))
        {
            return template;
        }
        return StrFormatter.format(template, params);
    }
    /**
     * æ˜¯å¦ä¸ºhttp(s)://开头
     *
     * @param link é“¾æŽ¥
     * @return ç»“æžœ
     */
    public static boolean ishttp(String link)
    {
        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
    }
    /**
     * å­—符串转set
     *
     * @param str å­—符串
     * @param sep åˆ†éš”符
     * @return set集合
     */
    public static final Set<String> str2Set(String str, String sep)
    {
        return new HashSet<String>(str2List(str, sep, true, false));
    }
    /**
     * å­—符串转list
     *
     * @param str å­—符串
     * @param sep åˆ†éš”符
     * @param filterBlank è¿‡æ»¤çº¯ç©ºç™½
     * @param trim åŽ»æŽ‰é¦–尾空白
     * @return list集合
     */
    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
    {
        List<String> list = new ArrayList<String>();
        if (StringUtils.isEmpty(str))
        {
            return list;
        }
        // è¿‡æ»¤ç©ºç™½å­—符串
        if (filterBlank && StringUtils.isBlank(str))
        {
            return list;
        }
        String[] split = str.split(sep);
        for (String string : split)
        {
            if (filterBlank && StringUtils.isBlank(string))
            {
                continue;
            }
            if (trim)
            {
                string = string.trim();
            }
            list.add(string);
        }
        return list;
    }
    /**
     * åˆ¤æ–­ç»™å®šçš„collection列表中是否包含数组array åˆ¤æ–­ç»™å®šçš„数组array中是否包含给定的元素value
     *
     * @param collection ç»™å®šçš„集合
     * @param array ç»™å®šçš„数组
     * @return boolean ç»“æžœ
     */
    public static boolean containsAny(Collection<String> collection, String... array)
    {
        if (isEmpty(collection) || isEmpty(array))
        {
            return false;
        }
        else
        {
            for (String str : array)
            {
                if (collection.contains(str))
                {
                    return true;
                }
            }
            return false;
        }
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
     *
     * @param cs æŒ‡å®šå­—符串
     * @param searchCharSequences éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return æ˜¯å¦åŒ…含任意一个字符串
     */
    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
    {
        if (isEmpty(cs) || isEmpty(searchCharSequences))
        {
            return false;
        }
        for (CharSequence testStr : searchCharSequences)
        {
            if (containsIgnoreCase(cs, testStr))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * é©¼å³°è½¬ä¸‹åˆ’线命名
     */
    public static String toUnderScoreCase(String str)
    {
        if (str == null)
        {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // å‰ç½®å­—符是否大写
        boolean preCharIsUpperCase = true;
        // å½“前字符是否大写
        boolean curreCharIsUpperCase = true;
        // ä¸‹ä¸€å­—符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++)
        {
            char c = str.charAt(i);
            if (i > 0)
            {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            }
            else
            {
                preCharIsUpperCase = false;
            }
            curreCharIsUpperCase = Character.isUpperCase(c);
            if (i < (str.length() - 1))
            {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }
            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
            {
                sb.append(SEPARATOR);
            }
            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
            {
                sb.append(SEPARATOR);
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }
    /**
     * æ˜¯å¦åŒ…含字符串
     *
     * @param str éªŒè¯å­—符串
     * @param strs å­—符串组
     * @return åŒ…含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs)
    {
        if (str != null && strs != null)
        {
            for (String s : strs)
            {
                if (str.equalsIgnoreCase(trim(s)))
                {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * å°†ä¸‹åˆ’线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 ä¾‹å¦‚:HELLO_WORLD->HelloWorld
     *
     * @param name è½¬æ¢å‰çš„下划线大写方式命名的字符串
     * @return è½¬æ¢åŽçš„驼峰式命名的字符串
     */
    public static String convertToCamelCase(String name)
    {
        StringBuilder result = new StringBuilder();
        // å¿«é€Ÿæ£€æŸ¥
        if (name == null || name.isEmpty())
        {
            // æ²¡å¿…要转换
            return "";
        }
        else if (!name.contains("_"))
        {
            // ä¸å«ä¸‹åˆ’线,仅将首字母大写
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        // ç”¨ä¸‹åˆ’线将原始字符串分割
        String[] camels = name.split("_");
        for (String camel : camels)
        {
            // è·³è¿‡åŽŸå§‹å­—符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty())
            {
                continue;
            }
            // é¦–字母大写
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }
    /**
     * é©¼å³°å¼å‘½åæ³•
     * ä¾‹å¦‚:user_name->userName
     */
    public static String toCamelCase(String s)
    {
        if (s == null)
        {
            return null;
        }
        if (s.indexOf(SEPARATOR) == -1)
        {
            return s;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);
            if (c == SEPARATOR)
            {
                upperCase = true;
            }
            else if (upperCase)
            {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            }
            else
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否匹配指定字符串列表中的任意一个字符串
     *
     * @param str æŒ‡å®šå­—符串
     * @param strs éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return æ˜¯å¦åŒ¹é…
     */
    public static boolean matches(String str, List<String> strs)
    {
        if (isEmpty(str) || isEmpty(strs))
        {
            return false;
        }
        for (String pattern : strs)
        {
            if (isMatch(pattern, str))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * åˆ¤æ–­url是否与规则配置:
     * ? è¡¨ç¤ºå•ä¸ªå­—符;
     * * è¡¨ç¤ºä¸€å±‚路径内的任意字符串,不可跨层级;
     * ** è¡¨ç¤ºä»»æ„å±‚路径;
     *
     * @param pattern åŒ¹é…è§„则
     * @param url éœ€è¦åŒ¹é…çš„url
     * @return
     */
    public static boolean isMatch(String pattern, String url)
    {
        AntPathMatcher matcher = new AntPathMatcher();
        return matcher.match(pattern, url);
    }
    @SuppressWarnings("unchecked")
    public static <T> T cast(Object obj)
    {
        return (T) obj;
    }
    /**
     * æ•°å­—左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 æœ€åŽsize个字符。
     *
     * @param num æ•°å­—对象
     * @param size å­—符串指定长度
     * @return è¿”回数字的字符串格式,该字符串为指定长度。
     */
    public static final String padl(final Number num, final int size)
    {
        return padl(num.toString(), size, '0');
    }
    /**
     * å­—符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
     *
     * @param s åŽŸå§‹å­—符串
     * @param size å­—符串指定长度
     * @param c ç”¨äºŽè¡¥é½çš„字符
     * @return è¿”回指定长度的字符串,由原字符串左补齐或截取得到。
     */
    public static final String padl(final String s, final int size, final char c)
    {
        final StringBuilder sb = new StringBuilder(size);
        if (s != null)
        {
            final int len = s.length();
            if (s.length() <= size)
            {
                for (int i = size - len; i > 0; i--)
                {
                    sb.append(c);
                }
                sb.append(s);
            }
            else
            {
                return s.substring(len - size, len);
            }
        }
        else
        {
            for (int i = size; i > 0; i--)
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/Threads.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
package com.jcdm.common.utils;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * çº¿ç¨‹ç›¸å…³å·¥å…·ç±».
 *
 * @author jc
 */
public class Threads
{
    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
    /**
     * sleep等待,单位为毫秒
     */
    public static void sleep(long milliseconds)
    {
        try
        {
            Thread.sleep(milliseconds);
        }
        catch (InterruptedException e)
        {
            return;
        }
    }
    /**
     * åœæ­¢çº¿ç¨‹æ± 
     * å…ˆä½¿ç”¨shutdown, åœæ­¢æŽ¥æ”¶æ–°ä»»åŠ¡å¹¶å°è¯•å®Œæˆæ‰€æœ‰å·²å­˜åœ¨ä»»åŠ¡.
     * å¦‚果超时, åˆ™è°ƒç”¨shutdownNow, å–消在workQueue中Pending的任务,并中断所有阻塞函数.
     * å¦‚果仍然超時,則強制退出.
     * å¦å¯¹åœ¨shutdown时线程本身被调用中断做了处理.
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool)
    {
        if (pool != null && !pool.isShutdown())
        {
            pool.shutdown();
            try
            {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
                {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
                    {
                        logger.info("Pool did not terminate");
                    }
                }
            }
            catch (InterruptedException ie)
            {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    /**
     * æ‰“印线程异常信息
     */
    public static void printException(Runnable r, Throwable t)
    {
        if (t == null && r instanceof Future<?>)
        {
            try
            {
                Future<?> future = (Future<?>) r;
                if (future.isDone())
                {
                    future.get();
                }
            }
            catch (CancellationException ce)
            {
                t = ce;
            }
            catch (ExecutionException ee)
            {
                t = ee.getCause();
            }
            catch (InterruptedException ie)
            {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null)
        {
            logger.error(t.getMessage(), t);
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
package com.jcdm.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 jc
 */
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<Method> getSetterMethods(Object obj)
    {
        // setter方法列表
        List<Method> setterMethods = new ArrayList<Method>();
        // èŽ·å–所有方法
        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<Method> getGetterMethods(Object obj)
    {
        // getter方法列表
        List<Method> getterMethods = new ArrayList<Method>();
        // èŽ·å–所有方法
        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方法名中的属性名是否相等。<br>
     * å¦‚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));
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/bean/BeanValidators.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.jcdm.common.utils.bean;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
/**
 * bean对象属性验证
 *
 * @author jc
 */
public class BeanValidators
{
    public static void validateWithException(Validator validator, Object object, Class<?>... groups)
            throws ConstraintViolationException
    {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty())
        {
            throw new ConstraintViolationException(constraintViolations);
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/file/FileTypeUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.jcdm.common.utils.file;
import java.io.File;
import org.apache.commons.lang3.StringUtils;
/**
 * æ–‡ä»¶ç±»åž‹å·¥å…·ç±»
 *
 * @author jc
 */
public class FileTypeUtils
{
    /**
     * èŽ·å–文件类型
     * <p>
     * ä¾‹å¦‚: jcdm.txt, è¿”回: txt
     *
     * @param file æ–‡ä»¶å
     * @return åŽç¼€ï¼ˆä¸å«".")
     */
    public static String getFileType(File file)
    {
        if (null == file)
        {
            return StringUtils.EMPTY;
        }
        return getFileType(file.getName());
    }
    /**
     * èŽ·å–文件类型
     * <p>
     * ä¾‹å¦‚: jcdm.txt, è¿”回: txt
     *
     * @param fileName æ–‡ä»¶å
     * @return åŽç¼€ï¼ˆä¸å«".")
     */
    public static String getFileType(String fileName)
    {
        int separatorIndex = fileName.lastIndexOf(".");
        if (separatorIndex < 0)
        {
            return "";
        }
        return fileName.substring(separatorIndex + 1).toLowerCase();
    }
    /**
     * èŽ·å–文件类型
     *
     * @param photoByte æ–‡ä»¶å­—节码
     * @return åŽç¼€ï¼ˆä¸å«".")
     */
    public static String getFileExtendName(byte[] photoByte)
    {
        String strFileExtendName = "JPG";
        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
        {
            strFileExtendName = "GIF";
        }
        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
        {
            strFileExtendName = "JPG";
        }
        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
        {
            strFileExtendName = "BMP";
        }
        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
        {
            strFileExtendName = "PNG";
        }
        return strFileExtendName;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUploadUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,232 @@
package com.jcdm.common.utils.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.exception.file.FileNameLengthLimitExceededException;
import com.jcdm.common.exception.file.FileSizeLimitExceededException;
import com.jcdm.common.exception.file.InvalidExtensionException;
import com.jcdm.common.utils.DateUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.uuid.Seq;
/**
 * æ–‡ä»¶ä¸Šä¼ å·¥å…·ç±»
 *
 * @author jc
 */
public class FileUploadUtils
{
    /**
     * é»˜è®¤å¤§å° 50M
     */
    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
    /**
     * é»˜è®¤çš„文件名最大长度 100
     */
    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
    /**
     * é»˜è®¤ä¸Šä¼ çš„地址
     */
    private static String defaultBaseDir = MesConfig.getProfile();
    public static void setDefaultBaseDir(String defaultBaseDir)
    {
        FileUploadUtils.defaultBaseDir = defaultBaseDir;
    }
    public static String getDefaultBaseDir()
    {
        return defaultBaseDir;
    }
    /**
     * ä»¥é»˜è®¤é…ç½®è¿›è¡Œæ–‡ä»¶ä¸Šä¼ 
     *
     * @param file ä¸Šä¼ çš„文件
     * @return æ–‡ä»¶åç§°
     * @throws Exception
     */
    public static final String upload(MultipartFile file) throws IOException
    {
        try
        {
            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }
    /**
     * æ ¹æ®æ–‡ä»¶è·¯å¾„上传
     *
     * @param baseDir ç›¸å¯¹åº”用的基目录
     * @param file ä¸Šä¼ çš„文件
     * @return æ–‡ä»¶åç§°
     * @throws IOException
     */
    public static final String upload(String baseDir, MultipartFile file) throws IOException
    {
        try
        {
            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }
    /**
     * æ–‡ä»¶ä¸Šä¼ 
     *
     * @param baseDir ç›¸å¯¹åº”用的基目录
     * @param file ä¸Šä¼ çš„文件
     * @param allowedExtension ä¸Šä¼ æ–‡ä»¶ç±»åž‹
     * @return è¿”回上传成功的文件名
     * @throws FileSizeLimitExceededException å¦‚果超出最大大小
     * @throws FileNameLengthLimitExceededException æ–‡ä»¶åå¤ªé•¿
     * @throws IOException æ¯”如读写文件出错时
     * @throws InvalidExtensionException æ–‡ä»¶æ ¡éªŒå¼‚常
     */
    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }
        assertAllowed(file, allowedExtension);
        String fileName = extractFilename(file);
        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
        file.transferTo(Paths.get(absPath));
        return getPathFileName(baseDir, fileName);
    }
    /**
     * ç¼–码文件名
     */
    public static final String extractFilename(MultipartFile file)
    {
        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
    }
    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
    {
        File desc = new File(uploadDir + File.separator + fileName);
        if (!desc.exists())
        {
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
        }
        return desc;
    }
    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
    {
        int dirLastIndex = MesConfig.getProfile().length() + 1;
        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
        return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
    }
    /**
     * æ–‡ä»¶å¤§å°æ ¡éªŒ
     *
     * @param file ä¸Šä¼ çš„文件
     * @return
     * @throws FileSizeLimitExceededException å¦‚果超出最大大小
     * @throws InvalidExtensionException
     */
    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, InvalidExtensionException
    {
        long size = file.getSize();
        if (size > DEFAULT_MAX_SIZE)
        {
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
        }
        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
        {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            }
            else
            {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }
    }
    /**
     * åˆ¤æ–­MIME类型是否是允许的MIME类型
     *
     * @param extension
     * @param allowedExtension
     * @return
     */
    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
    {
        for (String str : allowedExtension)
        {
            if (str.equalsIgnoreCase(extension))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * èŽ·å–文件名的后缀
     *
     * @param file è¡¨å•æ–‡ä»¶
     * @return åŽç¼€å
     */
    public static final String getExtension(MultipartFile file)
    {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        if (StringUtils.isEmpty(extension))
        {
            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
        }
        return extension;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/file/FileUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,291 @@
package com.jcdm.common.utils.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.utils.DateUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.uuid.IdUtils;
import org.apache.commons.io.FilenameUtils;
/**
 * æ–‡ä»¶å¤„理工具类
 *
 * @author jc
 */
public class FileUtils
{
    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
    /**
     * è¾“出指定文件的byte数组
     *
     * @param filePath æ–‡ä»¶è·¯å¾„
     * @param os è¾“出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
            if (!file.exists())
            {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            IOUtils.close(os);
            IOUtils.close(fis);
        }
    }
    /**
     * å†™æ•°æ®åˆ°æ–‡ä»¶ä¸­
     *
     * @param data æ•°æ®
     * @return ç›®æ ‡æ–‡ä»¶
     * @throws IOException IO异常
     */
    public static String writeImportBytes(byte[] data) throws IOException
    {
        return writeBytes(data, MesConfig.getImportPath());
    }
    /**
     * å†™æ•°æ®åˆ°æ–‡ä»¶ä¸­
     *
     * @param data æ•°æ®
     * @param uploadDir ç›®æ ‡æ–‡ä»¶
     * @return ç›®æ ‡æ–‡ä»¶
     * @throws IOException IO异常
     */
    public static String writeBytes(byte[] data, String uploadDir) throws IOException
    {
        FileOutputStream fos = null;
        String pathName = "";
        try
        {
            String extension = getFileExtendName(data);
            pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
            File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
            fos = new FileOutputStream(file);
            fos.write(data);
        }
        finally
        {
            IOUtils.close(fos);
        }
        return FileUploadUtils.getPathFileName(uploadDir, pathName);
    }
    /**
     * åˆ é™¤æ–‡ä»¶
     *
     * @param filePath æ–‡ä»¶
     * @return
     */
    public static boolean deleteFile(String filePath)
    {
        boolean flag = false;
        File file = new File(filePath);
        // è·¯å¾„为文件且不为空则进行删除
        if (file.isFile() && file.exists())
        {
            flag = file.delete();
        }
        return flag;
    }
    /**
     * æ–‡ä»¶åç§°éªŒè¯
     *
     * @param filename æ–‡ä»¶åç§°
     * @return true æ­£å¸¸ false éžæ³•
     */
    public static boolean isValidFilename(String filename)
    {
        return filename.matches(FILENAME_PATTERN);
    }
    /**
     * æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å¯ä¸‹è½½
     *
     * @param resource éœ€è¦ä¸‹è½½çš„文件
     * @return true æ­£å¸¸ false éžæ³•
     */
    public static boolean checkAllowDownload(String resource)
    {
        // ç¦æ­¢ç›®å½•ä¸Šè·³çº§åˆ«
        if (StringUtils.contains(resource, ".."))
        {
            return false;
        }
        // æ£€æŸ¥å…è®¸ä¸‹è½½çš„文件规则
        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
        {
            return true;
        }
        // ä¸åœ¨å…è®¸ä¸‹è½½çš„文件规则
        return false;
    }
    /**
     * ä¸‹è½½æ–‡ä»¶åé‡æ–°ç¼–码
     *
     * @param request è¯·æ±‚对象
     * @param fileName æ–‡ä»¶å
     * @return ç¼–码后的文件名
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
    {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE"))
        {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }
        else if (agent.contains("Firefox"))
        {
            // ç«ç‹æµè§ˆå™¨
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }
        else if (agent.contains("Chrome"))
        {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        else
        {
            // å…¶å®ƒæµè§ˆå™¨
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
    /**
     * ä¸‹è½½æ–‡ä»¶åé‡æ–°ç¼–码
     *
     * @param response å“åº”对象
     * @param realFileName çœŸå®žæ–‡ä»¶å
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
    {
        String percentEncodedFileName = percentEncode(realFileName);
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
    }
    /**
     * ç™¾åˆ†å·ç¼–码工具方法
     *
     * @param s éœ€è¦ç™¾åˆ†å·ç¼–码的字符串
     * @return ç™¾åˆ†å·ç¼–码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException
    {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }
    /**
     * èŽ·å–图像后缀
     *
     * @param photoByte å›¾åƒæ•°æ®
     * @return åŽç¼€å
     */
    public static String getFileExtendName(byte[] photoByte)
    {
        String strFileExtendName = "jpg";
        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
        {
            strFileExtendName = "gif";
        }
        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
        {
            strFileExtendName = "jpg";
        }
        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
        {
            strFileExtendName = "bmp";
        }
        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
        {
            strFileExtendName = "png";
        }
        return strFileExtendName;
    }
    /**
     * èŽ·å–文件名称 /profile/upload/2022/04/16/jcdm.png
     *
     * @param fileName è·¯å¾„名称
     * @return æ²¡æœ‰æ–‡ä»¶è·¯å¾„的名称
     */
    public static String getName(String fileName)
    {
        if (fileName == null)
        {
            return null;
        }
        int lastUnixPos = fileName.lastIndexOf('/');
        int lastWindowsPos = fileName.lastIndexOf('\\');
        int index = Math.max(lastUnixPos, lastWindowsPos);
        return fileName.substring(index + 1);
    }
    /**
     * èŽ·å–不带后缀文件名称 /profile/upload/2022/04/16/jcdm.png
     *
     * @param fileName è·¯å¾„名称
     * @return æ²¡æœ‰æ–‡ä»¶è·¯å¾„和后缀的名称
     */
    public static String getNameNotSuffix(String fileName)
    {
        if (fileName == null)
        {
            return null;
        }
        String baseName = FilenameUtils.getBaseName(fileName);
        return baseName;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/file/ImageUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,98 @@
package com.jcdm.common.utils.file;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.utils.StringUtils;
/**
 * å›¾ç‰‡å¤„理工具类
 *
 * @author jc
 */
public class ImageUtils
{
    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
    public static byte[] getImage(String imagePath)
    {
        InputStream is = getFile(imagePath);
        try
        {
            return IOUtils.toByteArray(is);
        }
        catch (Exception e)
        {
            log.error("图片加载异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
    }
    public static InputStream getFile(String imagePath)
    {
        try
        {
            byte[] result = readFile(imagePath);
            result = Arrays.copyOf(result, result.length);
            return new ByteArrayInputStream(result);
        }
        catch (Exception e)
        {
            log.error("获取图片异常 {}", e);
        }
        return null;
    }
    /**
     * è¯»å–文件为字节数据
     *
     * @param url åœ°å€
     * @return å­—节数据
     */
    public static byte[] readFile(String url)
    {
        InputStream in = null;
        try
        {
            if (url.startsWith("http"))
            {
                // ç½‘络地址
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                urlConnection.setConnectTimeout(30 * 1000);
                urlConnection.setReadTimeout(60 * 1000);
                urlConnection.setDoInput(true);
                in = urlConnection.getInputStream();
            }
            else
            {
                // æœ¬æœºåœ°å€
                String localPath = MesConfig.getProfile();
                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
                in = new FileInputStream(downloadPath);
            }
            return IOUtils.toByteArray(in);
        }
        catch (Exception e)
        {
            log.error("获取文件路径异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(in);
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/file/MimeTypeUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package com.jcdm.common.utils.file;
/**
 * åª’体类型工具类
 *
 * @author jc
 */
public class MimeTypeUtils
{
    public static final String IMAGE_PNG = "image/png";
    public static final String IMAGE_JPG = "image/jpg";
    public static final String IMAGE_JPEG = "image/jpeg";
    public static final String IMAGE_BMP = "image/bmp";
    public static final String IMAGE_GIF = "image/gif";
    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
            "asf", "rm", "rmvb" };
    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
            // å›¾ç‰‡
            "bmp", "gif", "jpg", "jpeg", "png",
            // word excel powerpoint
            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
            // åŽ‹ç¼©æ–‡ä»¶
            "rar", "zip", "gz", "bz2",
            // è§†é¢‘格式
            "mp4", "avi", "rmvb",
            // pdf
            "pdf" };
    public static String getExtension(String prefix)
    {
        switch (prefix)
        {
            case IMAGE_PNG:
                return "png";
            case IMAGE_JPG:
                return "jpg";
            case IMAGE_JPEG:
                return "jpeg";
            case IMAGE_BMP:
                return "bmp";
            case IMAGE_GIF:
                return "gif";
            default:
                return "";
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/html/EscapeUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
package com.jcdm.common.utils.html;
import com.jcdm.common.utils.StringUtils;
/**
 * è½¬ä¹‰å’Œåè½¬ä¹‰å·¥å…·ç±»
 *
 * @author jc
 */
public class EscapeUtil
{
    public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
    private static final char[][] TEXT = new char[64][];
    static
    {
        for (int i = 0; i < 64; i++)
        {
            TEXT[i] = new char[] { (char) i };
        }
        // special HTML characters
        TEXT['\''] = "&#039;".toCharArray(); // å•å¼•å·
        TEXT['"'] = "&#34;".toCharArray(); // åŒå¼•å·
        TEXT['&'] = "&#38;".toCharArray(); // &符
        TEXT['<'] = "&#60;".toCharArray(); // å°äºŽå·
        TEXT['>'] = "&#62;".toCharArray(); // å¤§äºŽå·
    }
    /**
     * è½¬ä¹‰æ–‡æœ¬ä¸­çš„HTML字符为安全的字符
     *
     * @param text è¢«è½¬ä¹‰çš„文本
     * @return è½¬ä¹‰åŽçš„文本
     */
    public static String escape(String text)
    {
        return encode(text);
    }
    /**
     * è¿˜åŽŸè¢«è½¬ä¹‰çš„HTML特殊字符
     *
     * @param content åŒ…含转义符的HTML内容
     * @return è½¬æ¢åŽçš„字符串
     */
    public static String unescape(String content)
    {
        return decode(content);
    }
    /**
     * æ¸…除所有HTML标签,但是不删除标签内的内容
     *
     * @param content æ–‡æœ¬
     * @return æ¸…除标签后的文本
     */
    public static String clean(String content)
    {
        return new HTMLFilter().filter(content);
    }
    /**
     * Escape编码
     *
     * @param text è¢«ç¼–码的文本
     * @return ç¼–码后的字符
     */
    private static String encode(String text)
    {
        if (StringUtils.isEmpty(text))
        {
            return StringUtils.EMPTY;
        }
        final StringBuilder tmp = new StringBuilder(text.length() * 6);
        char c;
        for (int i = 0; i < text.length(); i++)
        {
            c = text.charAt(i);
            if (c < 256)
            {
                tmp.append("%");
                if (c < 16)
                {
                    tmp.append("0");
                }
                tmp.append(Integer.toString(c, 16));
            }
            else
            {
                tmp.append("%u");
                if (c <= 0xfff)
                {
                    // issue#I49JU8@Gitee
                    tmp.append("0");
                }
                tmp.append(Integer.toString(c, 16));
            }
        }
        return tmp.toString();
    }
    /**
     * Escape解码
     *
     * @param content è¢«è½¬ä¹‰çš„内容
     * @return è§£ç åŽçš„字符串
     */
    public static String decode(String content)
    {
        if (StringUtils.isEmpty(content))
        {
            return content;
        }
        StringBuilder tmp = new StringBuilder(content.length());
        int lastPos = 0, pos = 0;
        char ch;
        while (lastPos < content.length())
        {
            pos = content.indexOf("%", lastPos);
            if (pos == lastPos)
            {
                if (content.charAt(pos + 1) == 'u')
                {
                    ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
                    tmp.append(ch);
                    lastPos = pos + 6;
                }
                else
                {
                    ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
                    tmp.append(ch);
                    lastPos = pos + 3;
                }
            }
            else
            {
                if (pos == -1)
                {
                    tmp.append(content.substring(lastPos));
                    lastPos = content.length();
                }
                else
                {
                    tmp.append(content.substring(lastPos, pos));
                    lastPos = pos;
                }
            }
        }
        return tmp.toString();
    }
    public static void main(String[] args)
    {
        String html = "<script>alert(1);</script>";
        String escape = EscapeUtil.escape(html);
        // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
        // String html = "<123";
        // String html = "123>";
        System.out.println("clean: " + EscapeUtil.clean(html));
        System.out.println("escape: " + escape);
        System.out.println("unescape: " + EscapeUtil.unescape(escape));
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/html/HTMLFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,570 @@
package com.jcdm.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 jc
 */
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<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
    private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
    /**
     * set of allowed html elements, along with allowed attributes for each element
     **/
    private final Map<String, List<String>> vAllowed;
    /**
     * counts of open tags for each (allowable) html element
     **/
    private final Map<String, Integer> vTagCounts = new HashMap<>();
    /**
     * html elements which must always be self-closing (e.g. "<img />")
     **/
    private final String[] vSelfClosingTags;
    /**
     * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
     **/
    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. "<b></b>" or "<b />")
     **/
    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. "<b text </b>"
     * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
     */
    private final boolean alwaysMakeTags;
    /**
     * Default constructor.
     */
    public HTMLFilter()
    {
        vAllowed = new HashMap<>();
        final ArrayList<String> a_atts = new ArrayList<>();
        a_atts.add("href");
        a_atts.add("target");
        vAllowed.put("a", a_atts);
        final ArrayList<String> 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<String> 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 = false;
    }
    /**
     * Map-parameter configurable constructor.
     *
     * @param conf map containing configuration. keys match field names.
     */
    @SuppressWarnings("unchecked")
    public HTMLFilter(final Map<String, Object> 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<String, List<String>>) 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, "&amp;", result);
        result = regexReplace(P_QUOTE, "&quot;", result);
        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
        result = regexReplace(P_RIGHT_ARROW, "&gt;", 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("<!--" + htmlSpecialChars(match) + "-->"));
        }
        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, "&lt;$1", s);
            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", 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("</").append(key).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[^>]*)?></" + tag + ">"));
            }
            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 (!inArray(name, vSelfClosingTags))
                {
                    if (vTagCounts.containsKey(name))
                    {
                        vTagCounts.put(name, vTagCounts.get(name) - 1);
                        return "</" + name + ">";
                    }
                }
            }
        }
        // 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<String> paramNames = new ArrayList<>();
                final List<String> 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); // (<|$)
                // ä¸æ›¿æ¢åŒå¼•å·ä¸º&quot;,防止json格式无效 regexReplace(P_QUOTE, "&quot;", 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 : "&amp;" + 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));
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpHelper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.jcdm.common.utils.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletRequest;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * é€šç”¨http工具封装
 *
 * @author jc
 */
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, StandardCharsets.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();
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/http/HttpUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,274 @@
package com.jcdm.common.utils.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.utils.StringUtils;
/**
 * é€šç”¨http发送方法
 *
 * @author jc
 */
public class HttpUtils
{
    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
    /**
     * å‘指定 URL å‘送GET方法的请求
     *
     * @param url å‘送请求的 URL
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendGet(String url)
    {
        return sendGet(url, StringUtils.EMPTY);
    }
    /**
     * å‘指定 URL å‘送GET方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数,请求参数应该是 name1=value1&name2=value2 çš„形式。
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendGet(String url, String param)
    {
        return sendGet(url, param, Constants.UTF8);
    }
    /**
     * å‘指定 URL å‘送GET方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数,请求参数应该是 name1=value1&name2=value2 çš„形式。
     * @param contentType ç¼–码类型
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendGet(String url, String param, String contentType)
    {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try
        {
            String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
            log.info("sendGet - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (Exception ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
    /**
     * å‘指定 URL å‘送POST方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数,请求参数应该是 name1=value1&name2=value2 çš„形式。
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendPost(String url, String param)
    {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try
        {
            log.info("sendPost - {}", url);
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
    public static String sendSSLPost(String url, String param)
    {
        StringBuilder result = new StringBuilder();
        String urlNameString = url + "?" + param;
        try
        {
            log.info("sendSSLPost - {}", urlNameString);
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
            URL console = new URL(urlNameString);
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String ret = "";
            while ((ret = br.readLine()) != null)
            {
                if (ret != null && !"".equals(ret.trim()))
                {
                    result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
                }
            }
            log.info("recv - {}", result);
            conn.disconnect();
            br.close();
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
        }
        return result.toString();
    }
    private static class TrustAnyTrustManager implements X509TrustManager
    {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
        {
        }
        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
        {
        }
        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[] {};
        }
    }
    private static class TrustAnyHostnameVerifier implements HostnameVerifier
    {
        @Override
        public boolean verify(String hostname, SSLSession session)
        {
            return true;
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/ip/AddressUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.jcdm.common.utils.ip;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.http.HttpUtils;
/**
 * èŽ·å–地址类
 *
 * @author jc
 */
public class AddressUtils
{
    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
    // IP地址查询
    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
    // æœªçŸ¥åœ°å€
    public static final String UNKNOWN = "XX XX";
    public static String getRealAddressByIP(String ip)
    {
        // å†…网不查询
        if (IpUtils.internalIp(ip))
        {
            return "内网IP";
        }
        if (MesConfig.isAddressEnabled())
        {
            try
            {
                String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
                if (StringUtils.isEmpty(rspStr))
                {
                    log.error("获取地理位置异常 {}", ip);
                    return UNKNOWN;
                }
                JSONObject obj = JSON.parseObject(rspStr);
                String region = obj.getString("pro");
                String city = obj.getString("city");
                return String.format("%s %s", region, city);
            }
            catch (Exception e)
            {
                log.error("获取地理位置异常 {}", ip);
            }
        }
        return UNKNOWN;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/ip/IpUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,382 @@
package com.jcdm.common.utils.ip;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import com.jcdm.common.utils.ServletUtils;
import com.jcdm.common.utils.StringUtils;
/**
 * èŽ·å–IP方法
 *
 * @author jc
 */
public class IpUtils
{
    public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
    // åŒ¹é… ip
    public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
    public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
    // åŒ¹é…ç½‘段
    public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
    /**
     * èŽ·å–客户端IP
     *
     * @return IP地址
     */
    public static String getIpAddr()
    {
        return getIpAddr(ServletUtils.getRequest());
    }
    /**
     * èŽ·å–客户端IP
     *
     * @param request è¯·æ±‚对象
     * @return IP地址
     */
    public static String getIpAddr(HttpServletRequest request)
    {
        if (request == null)
        {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
    }
    /**
     * æ£€æŸ¥æ˜¯å¦ä¸ºå†…部IP地址
     *
     * @param ip IP地址
     * @return ç»“æžœ
     */
    public static boolean internalIp(String ip)
    {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }
    /**
     * æ£€æŸ¥æ˜¯å¦ä¸ºå†…部IP地址
     *
     * @param addr byte地址
     * @return ç»“æžœ
     */
    private static boolean internalIp(byte[] addr)
    {
        if (StringUtils.isNull(addr) || addr.length < 2)
        {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0)
        {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4)
                {
                    return true;
                }
            case SECTION_5:
                switch (b1)
                {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }
    /**
     * å°†IPv4地址转换成字节
     *
     * @param text IPv4地址
     * @return byte å­—节
     */
    public static byte[] textToNumericFormatV4(String text)
    {
        if (text.length() == 0)
        {
            return null;
        }
        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try
        {
            long l;
            int i;
            switch (elements.length)
            {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                    {
                        return null;
                    }
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                    {
                        return null;
                    }
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        }
        catch (NumberFormatException e)
        {
            return null;
        }
        return bytes;
    }
    /**
     * èŽ·å–IP地址
     *
     * @return æœ¬åœ°IP地址
     */
    public static String getHostIp()
    {
        try
        {
            return InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException e)
        {
        }
        return "127.0.0.1";
    }
    /**
     * èŽ·å–主机名
     *
     * @return æœ¬åœ°ä¸»æœºå
     */
    public static String getHostName()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e)
        {
        }
        return "未知";
    }
    /**
     * ä»Žå¤šçº§åå‘代理中获得第一个非unknown IP地址
     *
     * @param ip èŽ·å¾—çš„IP地址
     * @return ç¬¬ä¸€ä¸ªéžunknown IP地址
     */
    public static String getMultistageReverseProxyIp(String ip)
    {
        // å¤šçº§åå‘代理检测
        if (ip != null && ip.indexOf(",") > 0)
        {
            final String[] ips = ip.trim().split(",");
            for (String subIp : ips)
            {
                if (false == isUnknown(subIp))
                {
                    ip = subIp;
                    break;
                }
            }
        }
        return StringUtils.substring(ip, 0, 255);
    }
    /**
     * æ£€æµ‹ç»™å®šå­—符串是否为未知,多用于检测HTTP请求相关
     *
     * @param checkString è¢«æ£€æµ‹çš„字符串
     * @return æ˜¯å¦æœªçŸ¥
     */
    public static boolean isUnknown(String checkString)
    {
        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
    }
    /**
     * æ˜¯å¦ä¸ºIP
     */
    public static boolean isIP(String ip)
    {
        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
    }
    /**
     * æ˜¯å¦ä¸ºIP,或 *为间隔的通配符地址
     */
    public static boolean isIpWildCard(String ip)
    {
        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
    }
    /**
     * æ£€æµ‹å‚数是否在ip通配符里
     */
    public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
    {
        String[] s1 = ipWildCard.split("\\.");
        String[] s2 = ip.split("\\.");
        boolean isMatchedSeg = true;
        for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
        {
            if (!s1[i].equals(s2[i]))
            {
                isMatchedSeg = false;
                break;
            }
        }
        return isMatchedSeg;
    }
    /**
     * æ˜¯å¦ä¸ºç‰¹å®šæ ¼å¼å¦‚:“10.10.10.1-10.10.10.99”的ip段字符串
     */
    public static boolean isIPSegment(String ipSeg)
    {
        return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
    }
    /**
     * åˆ¤æ–­ip是否在指定网段中
     */
    public static boolean ipIsInNetNoCheck(String iparea, String ip)
    {
        int idx = iparea.indexOf('-');
        String[] sips = iparea.substring(0, idx).split("\\.");
        String[] sipe = iparea.substring(idx + 1).split("\\.");
        String[] sipt = ip.split("\\.");
        long ips = 0L, ipe = 0L, ipt = 0L;
        for (int i = 0; i < 4; ++i)
        {
            ips = ips << 8 | Integer.parseInt(sips[i]);
            ipe = ipe << 8 | Integer.parseInt(sipe[i]);
            ipt = ipt << 8 | Integer.parseInt(sipt[i]);
        }
        if (ips > ipe)
        {
            long t = ips;
            ips = ipe;
            ipe = t;
        }
        return ips <= ipt && ipt <= ipe;
    }
    /**
     * æ ¡éªŒip是否符合过滤串规则
     *
     * @param filter è¿‡æ»¤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99`
     * @param ip æ ¡éªŒIP地址
     * @return boolean ç»“æžœ
     */
    public static boolean isMatchedIp(String filter, String ip)
    {
        if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
        {
            return false;
        }
        String[] ips = filter.split(";");
        for (String iStr : ips)
        {
            if (isIP(iStr) && iStr.equals(ip))
            {
                return true;
            }
            else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
            {
                return true;
            }
            else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
            {
                return true;
            }
        }
        return false;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelHandlerAdapter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.jcdm.common.utils.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
/**
 * Excel数据格式处理适配器
 *
 * @author jc
 */
public interface ExcelHandlerAdapter
{
    /**
     * æ ¼å¼åŒ–
     *
     * @param value å•å…ƒæ ¼æ•°æ®å€¼
     * @param args excel注解args参数组
     * @param cell å•å…ƒæ ¼å¯¹è±¡
     * @param wb å·¥ä½œç°¿å¯¹è±¡
     *
     * @return å¤„理后的值
     */
    Object format(Object value, String[] args, Cell cell, Workbook wb);
}
jcdm-common/src/main/java/com/jcdm/common/utils/poi/ExcelUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1758 @@
package com.jcdm.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.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ooxml.POIXMLDocumentPart;
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.ClientAnchor;
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.Drawing;
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.Name;
import org.apache.poi.ss.usermodel.PictureData;
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.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcdm.common.annotation.Excel;
import com.jcdm.common.annotation.Excel.ColumnType;
import com.jcdm.common.annotation.Excel.Type;
import com.jcdm.common.annotation.Excels;
import com.jcdm.common.config.MesConfig;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.core.text.Convert;
import com.jcdm.common.exception.UtilException;
import com.jcdm.common.utils.DateUtils;
import com.jcdm.common.utils.DictUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.file.FileTypeUtils;
import com.jcdm.common.utils.file.FileUtils;
import com.jcdm.common.utils.file.ImageUtils;
import com.jcdm.common.utils.reflect.ReflectUtils;
/**
 * Excel相关处理
 *
 * @author jc
 */
public class ExcelUtil<T>
{
    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
    /**
     * ç”¨äºŽdictType属性数据存储,避免重复查缓存
     */
    public Map<String, String> sysDictMap = new HashMap<String, String>();
    /**
     * 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<String, CellStyle> styles;
    /**
     * å¯¼å…¥å¯¼å‡ºæ•°æ®åˆ—表
     */
    private List<T> list;
    /**
     * æ³¨è§£åˆ—表
     */
    private List<Object[]> fields;
    /**
     * å½“前行号
     */
    private int rownum;
    /**
     * æ ‡é¢˜
     */
    private String title;
    /**
     * æœ€å¤§é«˜åº¦
     */
    private short maxHeight;
    /**
     * åˆå¹¶åŽæœ€åŽè¡Œæ•°
     */
    private int subMergedLastRowNum = 0;
    /**
     * åˆå¹¶åŽå¼€å§‹è¡Œæ•°
     */
    private int subMergedFirstRowNum = 1;
    /**
     * å¯¹è±¡çš„子列表方法
     */
    private Method subMethod;
    /**
     * å¯¹è±¡çš„子列表属性
     */
    private List<Field> subFields;
    /**
     * ç»Ÿè®¡åˆ—表
     */
    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
    /**
     * æ•°å­—格式
     */
    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
    /**
     * å®žä½“对象
     */
    public Class<T> clazz;
    /**
     * éœ€è¦æŽ’除列属性
     */
    public String[] excludeFields;
    public ExcelUtil(Class<T> clazz)
    {
        this.clazz = clazz;
    }
    /**
     * éšè—Excel中列属性
     *
     * @param fields åˆ—属性名 ç¤ºä¾‹[单个"name"/多个"id","name"]
     * @throws Exception
     */
    public void hideColumn(String... fields)
    {
        this.excludeFields = fields;
    }
    public void init(List<T> list, String sheetName, String title, Type type)
    {
        if (list == null)
        {
            list = new ArrayList<T>();
        }
        this.list = list;
        this.sheetName = sheetName;
        this.type = type;
        this.title = title;
        createExcelField();
        createWorkbook();
        createTitle();
        createSubHead();
    }
    /**
     * åˆ›å»ºexcel第一行标题
     */
    public void createTitle()
    {
        if (StringUtils.isNotEmpty(title))
        {
            subMergedFirstRowNum++;
            subMergedLastRowNum++;
            int titleLastCol = this.fields.size() - 1;
            if (isSubList())
            {
                titleLastCol = titleLastCol + subFields.size() - 1;
            }
            Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
            titleRow.setHeightInPoints(30);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellStyle(styles.get("title"));
            titleCell.setCellValue(title);
            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
        }
    }
    /**
     * åˆ›å»ºå¯¹è±¡çš„子列表名称
     */
    public void createSubHead()
    {
        if (isSubList())
        {
            subMergedFirstRowNum++;
            subMergedLastRowNum++;
            Row subRow = sheet.createRow(rownum);
            int excelNum = 0;
            for (Object[] objects : fields)
            {
                Excel attr = (Excel) objects[1];
                Cell headCell1 = subRow.createCell(excelNum);
                headCell1.setCellValue(attr.name());
                headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
                excelNum++;
            }
            int headFirstRow = excelNum - 1;
            int headLastRow = headFirstRow + subFields.size() - 1;
            if (headLastRow > headFirstRow)
            {
                sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
            }
            rownum++;
        }
    }
    /**
     * å¯¹excel表单默认第一个索引名转换成list
     *
     * @param is è¾“入流
     * @return è½¬æ¢åŽé›†åˆ
     */
    public List<T> importExcel(InputStream is)
    {
        List<T> list = null;
        try
        {
            list = importExcel(is, 0);
        }
        catch (Exception e)
        {
            log.error("导入Excel异常{}", e.getMessage());
            throw new UtilException(e.getMessage());
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
        return list;
    }
    /**
     * å¯¹excel表单默认第一个索引名转换成list
     *
     * @param is è¾“入流
     * @param titleNum æ ‡é¢˜å ç”¨è¡Œæ•°
     * @return è½¬æ¢åŽé›†åˆ
     */
    public List<T> importExcel(InputStream is, int titleNum) throws Exception
    {
        return importExcel(StringUtils.EMPTY, is, titleNum);
    }
    /**
     * å¯¹excel表单指定表格索引名转换成list
     *
     * @param sheetName è¡¨æ ¼ç´¢å¼•å
     * @param titleNum æ ‡é¢˜å ç”¨è¡Œæ•°
     * @param is è¾“入流
     * @return è½¬æ¢åŽé›†åˆ
     */
    public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
    {
        this.type = Type.IMPORT;
        this.wb = WorkbookFactory.create(is);
        List<T> list = new ArrayList<T>();
        // å¦‚果指定sheet名,则取指定sheet中的内容 å¦åˆ™é»˜è®¤æŒ‡å‘第1个sheet
        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
        if (sheet == null)
        {
            throw new IOException("文件sheet不存在");
        }
        boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
        Map<String, PictureData> pictures;
        if (isXSSFWorkbook)
        {
            pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
        }
        else
        {
            pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
        }
        // èŽ·å–最后一个非空行的行下标,比如总行数为n,则返回的为n-1
        int rows = sheet.getLastRowNum();
        if (rows > 0)
        {
            // å®šä¹‰ä¸€ä¸ªmap用于存放excel列的序号和field.
            Map<String, Integer> cellMap = new HashMap<String, Integer>();
            // èŽ·å–表头
            Row heard = sheet.getRow(titleNum);
            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.
            List<Object[]> fields = this.getFields();
            Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
            for (Object[] objects : fields)
            {
                Excel attr = (Excel) objects[1];
                Integer column = cellMap.get(attr.name());
                if (column != null)
                {
                    fieldsMap.put(column, objects);
                }
            }
            for (int i = titleNum + 1; i <= rows; i++)
            {
                // ä»Žç¬¬2行开始取数据,默认第一行是表头.
                Row row = sheet.getRow(i);
                // åˆ¤æ–­å½“前行是否是空行
                if (isRowEmpty(row))
                {
                    continue;
                }
                T entity = null;
                for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
                {
                    Object val = this.getCellValue(row, entry.getKey());
                    // å¦‚果不存在实例则新建.
                    entity = (entity == null ? clazz.newInstance() : entity);
                    // ä»Žmap中得到对应列的field.
                    Field field = (Field) entry.getValue()[0];
                    Excel attr = (Excel) entry.getValue()[1];
                    // å–得类型,并根据对象类型设置值.
                    Class<?> fieldType = field.getType();
                    if (String.class == fieldType)
                    {
                        String s = Convert.toStr(val);
                        if (StringUtils.endsWith(s, ".0"))
                        {
                            val = StringUtils.substringBefore(s, ".0");
                        }
                        else
                        {
                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
                            if (StringUtils.isNotEmpty(dateFormat))
                            {
                                val = parseDateToStr(dateFormat, val);
                            }
                            else
                            {
                                val = Convert.toStr(val);
                            }
                        }
                    }
                    else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
                    {
                        val = Convert.toInt(val);
                    }
                    else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
                    {
                        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);
                        }
                    }
                    else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
                    {
                        val = Convert.toBool(val, false);
                    }
                    if (StringUtils.isNotNull(fieldType))
                    {
                        String propertyName = field.getName();
                        if (StringUtils.isNotEmpty(attr.targetAttr()))
                        {
                            propertyName = field.getName() + "." + attr.targetAttr();
                        }
                        if (StringUtils.isNotEmpty(attr.readConverterExp()))
                        {
                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
                        }
                        else if (StringUtils.isNotEmpty(attr.dictType()))
                        {
                            val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
                        }
                        else if (!attr.handler().equals(ExcelHandlerAdapter.class))
                        {
                            val = dataFormatHandlerAdapter(val, attr, null);
                        }
                        else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
                        {
                            PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
                            if (image == null)
                            {
                                val = "";
                            }
                            else
                            {
                                byte[] data = image.getData();
                                val = FileUtils.writeImportBytes(data);
                            }
                        }
                        ReflectUtils.invokeSetter(entity, propertyName, val);
                    }
                }
                list.add(entity);
            }
        }
        return list;
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public AjaxResult exportExcel(List<T> list, String sheetName)
    {
        return exportExcel(list, sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public AjaxResult exportExcel(List<T> list, String sheetName, String title)
    {
        this.init(list, sheetName, title, Type.EXPORT);
        return exportExcel();
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param response è¿”回数据
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
    {
        exportExcel(response, list, sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param response è¿”回数据
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
    {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        this.init(list, sheetName, title, Type.EXPORT);
        exportExcel(response);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public AjaxResult importTemplateExcel(String sheetName)
    {
        return importTemplateExcel(sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public AjaxResult importTemplateExcel(String sheetName, String title)
    {
        this.init(null, sheetName, title, Type.IMPORT);
        return exportExcel();
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public void importTemplateExcel(HttpServletResponse response, String sheetName)
    {
        importTemplateExcel(response, sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
    {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        this.init(null, sheetName, title, Type.IMPORT);
        exportExcel(response);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @return ç»“æžœ
     */
    public void exportExcel(HttpServletResponse response)
    {
        try
        {
            writeSheet();
            wb.write(response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
        }
        finally
        {
            IOUtils.closeQuietly(wb);
        }
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @return ç»“æžœ
     */
    public AjaxResult exportExcel()
    {
        OutputStream out = null;
        try
        {
            writeSheet();
            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 UtilException("导出Excel失败,请联系网站管理员!");
        }
        finally
        {
            IOUtils.closeQuietly(wb);
            IOUtils.closeQuietly(out);
        }
    }
    /**
     * åˆ›å»ºå†™å…¥æ•°æ®åˆ°Sheet
     */
    public void writeSheet()
    {
        // å–出一共有多少个sheet.
        int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
        for (int index = 0; index < sheetNo; index++)
        {
            createSheet(sheetNo, index);
            // äº§ç”Ÿä¸€è¡Œ
            Row row = sheet.createRow(rownum);
            int column = 0;
            // å†™å…¥å„个字段的列头名称
            for (Object[] os : fields)
            {
                Field field = (Field) os[0];
                Excel excel = (Excel) os[1];
                if (Collection.class.isAssignableFrom(field.getType()))
                {
                    for (Field subField : subFields)
                    {
                        Excel subExcel = subField.getAnnotation(Excel.class);
                        this.createHeadCell(subExcel, row, column++);
                    }
                }
                else
                {
                    this.createHeadCell(excel, row, column++);
                }
            }
            if (Type.EXPORT.equals(type))
            {
                fillExcelData(index, row);
                addStatisticsRow();
            }
        }
    }
    /**
     * å¡«å……excel数据
     *
     * @param index åºå·
     * @param row å•å…ƒæ ¼è¡Œ
     */
    @SuppressWarnings("unchecked")
    public void fillExcelData(int index, Row row)
    {
        int startNo = index * sheetSize;
        int endNo = Math.min(startNo + sheetSize, list.size());
        int rowNo = (1 + rownum) - startNo;
        for (int i = startNo; i < endNo; i++)
        {
            rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
            row = sheet.createRow(rowNo);
            // å¾—到导出对象.
            T vo = (T) list.get(i);
            Collection<?> subList = null;
            if (isSubList())
            {
                if (isSubListValue(vo))
                {
                    subList = getListCellValue(vo);
                    subMergedLastRowNum = subMergedLastRowNum + subList.size();
                }
                else
                {
                    subMergedFirstRowNum++;
                    subMergedLastRowNum++;
                }
            }
            int column = 0;
            for (Object[] os : fields)
            {
                Field field = (Field) os[0];
                Excel excel = (Excel) os[1];
                if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
                {
                    boolean subFirst = false;
                    for (Object obj : subList)
                    {
                        if (subFirst)
                        {
                            rowNo++;
                            row = sheet.createRow(rowNo);
                        }
                        List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
                        int subIndex = 0;
                        for (Field subField : subFields)
                        {
                            if (subField.isAnnotationPresent(Excel.class))
                            {
                                subField.setAccessible(true);
                                Excel attr = subField.getAnnotation(Excel.class);
                                this.addCell(attr, row, (T) obj, subField, column + subIndex);
                            }
                            subIndex++;
                        }
                        subFirst = true;
                    }
                    this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
                }
                else
                {
                    this.addCell(excel, row, vo, field, column++);
                }
            }
        }
    }
    /**
     * åˆ›å»ºè¡¨æ ¼æ ·å¼
     *
     * @param wb å·¥ä½œè–„对象
     * @return æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> createStyles(Workbook wb)
    {
        // å†™å…¥å„条记录,每条记录对应excel表中的一行
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = wb.createFont();
        titleFont.setFontName("Arial");
        titleFont.setFontHeightInPoints((short) 16);
        titleFont.setBold(true);
        style.setFont(titleFont);
        styles.put("title", style);
        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.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font totalFont = wb.createFont();
        totalFont.setFontName("Arial");
        totalFont.setFontHeightInPoints((short) 10);
        style.setFont(totalFont);
        styles.put("total", style);
        styles.putAll(annotationHeaderStyles(wb, styles));
        styles.putAll(annotationDataStyles(wb));
        return styles;
    }
    /**
     * æ ¹æ®Excel注解创建表格头样式
     *
     * @param wb å·¥ä½œè–„对象
     * @return è‡ªå®šä¹‰æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
    {
        Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
        for (Object[] os : fields)
        {
            Excel excel = (Excel) os[1];
            String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
            if (!headerStyles.containsKey(key))
            {
                CellStyle style = wb.createCellStyle();
                style.cloneStyleFrom(styles.get("data"));
                style.setAlignment(HorizontalAlignment.CENTER);
                style.setVerticalAlignment(VerticalAlignment.CENTER);
                style.setFillForegroundColor(excel.headerBackgroundColor().index);
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                Font headerFont = wb.createFont();
                headerFont.setFontName("Arial");
                headerFont.setFontHeightInPoints((short) 10);
                headerFont.setBold(true);
                headerFont.setColor(excel.headerColor().index);
                style.setFont(headerFont);
                headerStyles.put(key, style);
            }
        }
        return headerStyles;
    }
    /**
     * æ ¹æ®Excel注解创建表格列样式
     *
     * @param wb å·¥ä½œè–„对象
     * @return è‡ªå®šä¹‰æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> annotationDataStyles(Workbook wb)
    {
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
        for (Object[] os : fields)
        {
            Excel excel = (Excel) os[1];
            String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
            if (!styles.containsKey(key))
            {
                CellStyle style = wb.createCellStyle();
                style.setAlignment(excel.align());
                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());
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                style.setFillForegroundColor(excel.backgroundColor().getIndex());
                Font dataFont = wb.createFont();
                dataFont.setFontName("Arial");
                dataFont.setFontHeightInPoints((short) 10);
                dataFont.setColor(excel.color().index);
                style.setFont(dataFont);
                styles.put(key, style);
            }
        }
        return styles;
    }
    /**
     * åˆ›å»ºå•å…ƒæ ¼
     */
    public Cell createHeadCell(Excel attr, Row row, int column)
    {
        // åˆ›å»ºåˆ—
        Cell cell = row.createCell(column);
        // å†™å…¥åˆ—信息
        cell.setCellValue(attr.name());
        setDataValidation(attr, row, column);
        cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
        if (isSubList())
        {
            // å¡«å……默认样式,防止合并单元格样式失效
            sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
            if (attr.needMerge())
            {
                sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
            }
        }
        return cell;
    }
    /**
     * è®¾ç½®å•å…ƒæ ¼ä¿¡æ¯
     *
     * @param value å•å…ƒæ ¼å€¼
     * @param attr æ³¨è§£ç›¸å…³
     * @param cell å•å…ƒæ ¼ä¿¡æ¯
     */
    public void setCellVo(Object value, Excel attr, Cell cell)
    {
        if (ColumnType.STRING == attr.cellType())
        {
            String cellValue = Convert.toStr(value);
            // å¯¹äºŽä»»ä½•ä»¥è¡¨è¾¾å¼è§¦å‘字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
            if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
            {
                cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
            }
            if (value instanceof Collection && StringUtils.equals("[]", cellValue))
            {
                cellValue = StringUtils.EMPTY;
            }
            cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
        }
        else if (ColumnType.NUMERIC == attr.cellType())
        {
            if (StringUtils.isNotNull(value))
            {
                cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
            }
        }
        else if (ColumnType.IMAGE == attr.cellType())
        {
            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
            String imagePath = Convert.toStr(value);
            if (StringUtils.isNotEmpty(imagePath))
            {
                byte[] data = ImageUtils.getImage(imagePath);
                getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
                        cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
            }
        }
    }
    /**
     * èŽ·å–画布
     */
    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
    {
        if (sheet.getDrawingPatriarch() == null)
        {
            sheet.createDrawingPatriarch();
        }
        return sheet.getDrawingPatriarch();
    }
    /**
     * èŽ·å–图片类型,设置图片插入类型
     */
    public int getImageType(byte[] value)
    {
        String type = FileTypeUtils.getFileExtendName(value);
        if ("JPG".equalsIgnoreCase(type))
        {
            return Workbook.PICTURE_TYPE_JPEG;
        }
        else if ("PNG".equalsIgnoreCase(type))
        {
            return Workbook.PICTURE_TYPE_PNG;
        }
        return Workbook.PICTURE_TYPE_JPEG;
    }
    /**
     * åˆ›å»ºè¡¨æ ¼æ ·å¼
     */
    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));
        }
        if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
        {
            if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
            {
                // å¦‚果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
                setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
            }
            else
            {
                // æç¤ºä¿¡æ¯æˆ–只能选择不能输入的列内容.
                setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
            }
        }
    }
    /**
     * æ·»åŠ å•å…ƒæ ¼
     */
    public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
    {
        Cell cell = null;
        try
        {
            // è®¾ç½®è¡Œé«˜
            row.setHeight(maxHeight);
            // æ ¹æ®Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
            if (attr.isExport())
            {
                // åˆ›å»ºcell
                cell = row.createCell(column);
                if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
                {
                    CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
                    sheet.addMergedRegion(cellAddress);
                }
                cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
                // ç”¨äºŽè¯»å–对象中的属性
                Object value = getTargetValue(vo, field, attr);
                String dateFormat = attr.dateFormat();
                String readConverterExp = attr.readConverterExp();
                String separator = attr.separator();
                String dictType = attr.dictType();
                if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
                {
                    cell.setCellValue(parseDateToStr(dateFormat, value));
                }
                else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
                {
                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
                }
                else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
                {
                    if (!sysDictMap.containsKey(dictType + value))
                    {
                        String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
                        sysDictMap.put(dictType + value, lable);
                    }
                    cell.setCellValue(sysDictMap.get(dictType + value));
                }
                else if (value instanceof BigDecimal && -1 != attr.scale())
                {
                    cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
                }
                else if (!attr.handler().equals(ExcelHandlerAdapter.class))
                {
                    cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
                }
                else
                {
                    // è®¾ç½®åˆ—类型
                    setCellVo(value, attr, cell);
                }
                addStatisticsData(column, Convert.toStr(value), attr);
            }
        }
        catch (Exception e)
        {
            log.error("导出Excel失败{}", e);
        }
        return cell;
    }
    /**
     * è®¾ç½® POI XSSFSheet å•å…ƒæ ¼æç¤ºæˆ–选择框
     *
     * @param sheet è¡¨å•
     * @param textlist ä¸‹æ‹‰æ¡†æ˜¾ç¤ºçš„内容
     * @param promptContent æç¤ºå†…容
     * @param firstRow å¼€å§‹è¡Œ
     * @param endRow ç»“束行
     * @param firstCol å¼€å§‹åˆ—
     * @param endCol ç»“束列
     */
    public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
            int firstCol, int endCol)
    {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        DataValidation dataValidation = helper.createValidation(constraint, regions);
        if (StringUtils.isNotEmpty(promptContent))
        {
            // å¦‚果设置了提示信息则鼠标放上去提示
            dataValidation.createPromptBox("", promptContent);
            dataValidation.setShowPromptBox(true);
        }
        // å¤„理Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation)
        {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        }
        else
        {
            dataValidation.setSuppressDropDownArrow(false);
        }
        sheet.addValidationData(dataValidation);
    }
    /**
     * è®¾ç½®æŸäº›åˆ—的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框).
     *
     * @param sheet è¦è®¾ç½®çš„sheet.
     * @param textlist ä¸‹æ‹‰æ¡†æ˜¾ç¤ºçš„内容
     * @param promptContent æç¤ºå†…容
     * @param firstRow å¼€å§‹è¡Œ
     * @param endRow ç»“束行
     * @param firstCol å¼€å§‹åˆ—
     * @param endCol ç»“束列
     */
    public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
    {
        String hideSheetName = "combo_" + firstCol + "_" + endCol;
        Sheet hideSheet = wb.createSheet(hideSheetName); // ç”¨äºŽå­˜å‚¨ ä¸‹æ‹‰èœå•æ•°æ®
        for (int i = 0; i < textlist.length; i++)
        {
            hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
        }
        // åˆ›å»ºåç§°ï¼Œå¯è¢«å…¶ä»–单元格引用
        Name name = wb.createName();
        name.setNameName(hideSheetName + "_data");
        name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
        DataValidationHelper helper = sheet.getDataValidationHelper();
        // åŠ è½½ä¸‹æ‹‰åˆ—表内容
        DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
        // è®¾ç½®æ•°æ®æœ‰æ•ˆæ€§åŠ è½½åœ¨å“ªä¸ªå•å…ƒæ ¼ä¸Š,四个参数分别是:起始行、终止行、起始列、终止列
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        // æ•°æ®æœ‰æ•ˆæ€§å¯¹è±¡
        DataValidation dataValidation = helper.createValidation(constraint, regions);
        if (StringUtils.isNotEmpty(promptContent))
        {
            // å¦‚果设置了提示信息则鼠标放上去提示
            dataValidation.createPromptBox("", promptContent);
            dataValidation.setShowPromptBox(true);
        }
        // å¤„理Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation)
        {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        }
        else
        {
            dataValidation.setSuppressDropDownArrow(false);
        }
        sheet.addValidationData(dataValidation);
        // è®¾ç½®hiddenSheet隐藏
        wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
    }
    /**
     * è§£æžå¯¼å‡ºå€¼ 0=男,1=女,2=未知
     *
     * @param propertyValue å‚数值
     * @param converterExp ç¿»è¯‘注解
     * @param separator åˆ†éš”符
     * @return è§£æžåŽå€¼
     */
    public static String convertByExp(String propertyValue, String converterExp, String separator)
    {
        StringBuilder propertyString = new StringBuilder();
        String[] convertSource = converterExp.split(",");
        for (String item : convertSource)
        {
            String[] itemArray = item.split("=");
            if (StringUtils.containsAny(propertyValue, separator))
            {
                for (String value : propertyValue.split(separator))
                {
                    if (itemArray[0].equals(value))
                    {
                        propertyString.append(itemArray[1] + separator);
                        break;
                    }
                }
            }
            else
            {
                if (itemArray[0].equals(propertyValue))
                {
                    return itemArray[1];
                }
            }
        }
        return StringUtils.stripEnd(propertyString.toString(), separator);
    }
    /**
     * åå‘解析值 ç”·=0,女=1,未知=2
     *
     * @param propertyValue å‚数值
     * @param converterExp ç¿»è¯‘注解
     * @param separator åˆ†éš”符
     * @return è§£æžåŽå€¼
     */
    public static String reverseByExp(String propertyValue, String converterExp, String separator)
    {
        StringBuilder propertyString = new StringBuilder();
        String[] convertSource = converterExp.split(",");
        for (String item : convertSource)
        {
            String[] itemArray = item.split("=");
            if (StringUtils.containsAny(propertyValue, separator))
            {
                for (String value : propertyValue.split(separator))
                {
                    if (itemArray[1].equals(value))
                    {
                        propertyString.append(itemArray[0] + separator);
                        break;
                    }
                }
            }
            else
            {
                if (itemArray[1].equals(propertyValue))
                {
                    return itemArray[0];
                }
            }
        }
        return StringUtils.stripEnd(propertyString.toString(), separator);
    }
    /**
     * è§£æžå­—典值
     *
     * @param dictValue å­—典值
     * @param dictType å­—典类型
     * @param separator åˆ†éš”符
     * @return å­—典标签
     */
    public static String convertDictByExp(String dictValue, String dictType, String separator)
    {
        return DictUtils.getDictLabel(dictType, dictValue, separator);
    }
    /**
     * åå‘解析值字典值
     *
     * @param dictLabel å­—典标签
     * @param dictType å­—典类型
     * @param separator åˆ†éš”符
     * @return å­—典值
     */
    public static String reverseDictByExp(String dictLabel, String dictType, String separator)
    {
        return DictUtils.getDictValue(dictType, dictLabel, separator);
    }
    /**
     * æ•°æ®å¤„理器
     *
     * @param value æ•°æ®å€¼
     * @param excel æ•°æ®æ³¨è§£
     * @return
     */
    public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
    {
        try
        {
            Object instance = excel.handler().newInstance();
            Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
            value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
        }
        catch (Exception e)
        {
            log.error("不能格式化数据 " + excel.handler(), e.getMessage());
        }
        return Convert.toStr(value);
    }
    /**
     * åˆè®¡ç»Ÿè®¡ä¿¡æ¯
     */
    private void addStatisticsData(Integer index, String text, Excel entity)
    {
        if (entity != null && entity.isStatistics())
        {
            Double temp = 0D;
            if (!statistics.containsKey(index))
            {
                statistics.put(index, temp);
            }
            try
            {
                temp = Double.valueOf(text);
            }
            catch (NumberFormatException e)
            {
            }
            statistics.put(index, statistics.get(index) + temp);
        }
    }
    /**
     * åˆ›å»ºç»Ÿè®¡è¡Œ
     */
    public void addStatisticsRow()
    {
        if (statistics.size() > 0)
        {
            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
            Set<Integer> keys = statistics.keySet();
            Cell cell = row.createCell(0);
            cell.setCellStyle(styles.get("total"));
            cell.setCellValue("合计");
            for (Integer key : keys)
            {
                cell = row.createCell(key);
                cell.setCellStyle(styles.get("total"));
                cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
            }
            statistics.clear();
        }
    }
    /**
     * ç¼–码文件名
     */
    public String encodingFilename(String filename)
    {
        filename = UUID.randomUUID() + "_" + filename + ".xlsx";
        return filename;
    }
    /**
     * èŽ·å–下载路径
     *
     * @param filename æ–‡ä»¶åç§°
     */
    public String getAbsoluteFile(String filename)
    {
        String downloadPath = MesConfig.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.contains("."))
            {
                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.isNotNull(o) && StringUtils.isNotEmpty(name))
        {
            Class<?> clazz = o.getClass();
            Field field = clazz.getDeclaredField(name);
            field.setAccessible(true);
            o = field.get(o);
        }
        return o;
    }
    /**
     * å¾—到所有定义字段
     */
    private void createExcelField()
    {
        this.fields = getFields();
        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
        this.maxHeight = getRowHeight();
    }
    /**
     * èŽ·å–字段注解信息
     */
    public List<Object[]> getFields()
    {
        List<Object[]> fields = new ArrayList<Object[]>();
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        for (Field field : tempFields)
        {
            if (!ArrayUtils.contains(this.excludeFields, field.getName()))
            {
                // å•æ³¨è§£
                if (field.isAnnotationPresent(Excel.class))
                {
                    Excel attr = field.getAnnotation(Excel.class);
                    if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
                    {
                        field.setAccessible(true);
                        fields.add(new Object[] { field, attr });
                    }
                    if (Collection.class.isAssignableFrom(field.getType()))
                    {
                        subMethod = getSubMethod(field.getName(), clazz);
                        ParameterizedType pt = (ParameterizedType) field.getGenericType();
                        Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
                        this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
                    }
                }
                // å¤šæ³¨è§£
                if (field.isAnnotationPresent(Excels.class))
                {
                    Excels attrs = field.getAnnotation(Excels.class);
                    Excel[] excels = attrs.value();
                    for (Excel attr : excels)
                    {
                        if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
                                && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
                        {
                            field.setAccessible(true);
                            fields.add(new Object[] { field, attr });
                        }
                    }
                }
            }
        }
        return fields;
    }
    /**
     * æ ¹æ®æ³¨è§£èŽ·å–最大行高
     */
    public short getRowHeight()
    {
        double maxHeight = 0;
        for (Object[] os : this.fields)
        {
            Excel excel = (Excel) os[1];
            maxHeight = Math.max(maxHeight, excel.height());
        }
        return (short) (maxHeight * 20);
    }
    /**
     * åˆ›å»ºä¸€ä¸ªå·¥ä½œç°¿
     */
    public void createWorkbook()
    {
        this.wb = new SXSSFWorkbook(500);
        this.sheet = wb.createSheet();
        wb.setSheetName(0, sheetName);
        this.styles = createStyles(wb);
    }
    /**
     * åˆ›å»ºå·¥ä½œè¡¨
     *
     * @param sheetNo sheet数量
     * @param index åºå·
     */
    public void createSheet(int sheetNo, int index)
    {
        // è®¾ç½®å·¥ä½œè¡¨çš„名称.
        if (sheetNo > 1 && index > 0)
        {
            this.sheet = wb.createSheet();
            this.createTitle();
            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.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
                {
                    val = cell.getNumericCellValue();
                    if (DateUtil.isCellDateFormatted(cell))
                    {
                        val = DateUtil.getJavaDate((Double) val); // POI Excel æ—¥æœŸæ ¼å¼è½¬æ¢
                    }
                    else
                    {
                        if ((Double) val % 1 != 0)
                        {
                            val = new BigDecimal(val.toString());
                        }
                        else
                        {
                            val = new DecimalFormat("0").format(val);
                        }
                    }
                }
                else if (cell.getCellType() == CellType.STRING)
                {
                    val = cell.getStringCellValue();
                }
                else if (cell.getCellType() == CellType.BOOLEAN)
                {
                    val = cell.getBooleanCellValue();
                }
                else if (cell.getCellType() == CellType.ERROR)
                {
                    val = cell.getErrorCellValue();
                }
            }
        }
        catch (Exception e)
        {
            return val;
        }
        return val;
    }
    /**
     * åˆ¤æ–­æ˜¯å¦æ˜¯ç©ºè¡Œ
     *
     * @param row åˆ¤æ–­çš„è¡Œ
     * @return
     */
    private boolean isRowEmpty(Row row)
    {
        if (row == null)
        {
            return true;
        }
        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
        {
            Cell cell = row.getCell(i);
            if (cell != null && cell.getCellType() != CellType.BLANK)
            {
                return false;
            }
        }
        return true;
    }
    /**
     * èŽ·å–Excel2003图片
     *
     * @param sheet å½“前sheet对象
     * @param workbook å·¥ä½œç°¿å¯¹è±¡
     * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData
     */
    public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
    {
        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
        List<HSSFPictureData> pictures = workbook.getAllPictures();
        if (!pictures.isEmpty())
        {
            for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
            {
                HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
                if (shape instanceof HSSFPicture)
                {
                    HSSFPicture pic = (HSSFPicture) shape;
                    int pictureIndex = pic.getPictureIndex() - 1;
                    HSSFPictureData picData = pictures.get(pictureIndex);
                    String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
                    sheetIndexPicMap.put(picIndex, picData);
                }
            }
            return sheetIndexPicMap;
        }
        else
        {
            return sheetIndexPicMap;
        }
    }
    /**
     * èŽ·å–Excel2007图片
     *
     * @param sheet å½“前sheet对象
     * @param workbook å·¥ä½œç°¿å¯¹è±¡
     * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData
     */
    public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
    {
        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
        for (POIXMLDocumentPart dr : sheet.getRelations())
        {
            if (dr instanceof XSSFDrawing)
            {
                XSSFDrawing drawing = (XSSFDrawing) dr;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes)
                {
                    if (shape instanceof XSSFPicture)
                    {
                        XSSFPicture pic = (XSSFPicture) shape;
                        XSSFClientAnchor anchor = pic.getPreferredSize();
                        CTMarker ctMarker = anchor.getFrom();
                        String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
                        sheetIndexPicMap.put(picIndex, pic.getPictureData());
                    }
                }
            }
        }
        return sheetIndexPicMap;
    }
    /**
     * æ ¼å¼åŒ–不同类型的日期对象
     *
     * @param dateFormat æ—¥æœŸæ ¼å¼
     * @param val è¢«æ ¼å¼åŒ–的日期对象
     * @return æ ¼å¼åŒ–后的日期字符
     */
    public String parseDateToStr(String dateFormat, Object val)
    {
        if (val == null)
        {
            return "";
        }
        String str;
        if (val instanceof Date)
        {
            str = DateUtils.parseDateToStr(dateFormat, (Date) val);
        }
        else if (val instanceof LocalDateTime)
        {
            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
        }
        else if (val instanceof LocalDate)
        {
            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
        }
        else
        {
            str = val.toString();
        }
        return str;
    }
    /**
     * æ˜¯å¦æœ‰å¯¹è±¡çš„子列表
     */
    public boolean isSubList()
    {
        return StringUtils.isNotNull(subFields) && subFields.size() > 0;
    }
    /**
     * æ˜¯å¦æœ‰å¯¹è±¡çš„子列表,集合不为空
     */
    public boolean isSubListValue(T vo)
    {
        return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
    }
    /**
     * èŽ·å–集合的值
     */
    public Collection<?> getListCellValue(Object obj)
    {
        Object value;
        try
        {
            value = subMethod.invoke(obj, new Object[] {});
        }
        catch (Exception e)
        {
            return new ArrayList<Object>();
        }
        return (Collection<?>) value;
    }
    /**
     * èŽ·å–对象的子列表方法
     *
     * @param name åç§°
     * @param pojoClass ç±»å¯¹è±¡
     * @return å­åˆ—表方法
     */
    public Method getSubMethod(String name, Class<?> pojoClass)
    {
        StringBuffer getMethodName = new StringBuffer("get");
        getMethodName.append(name.substring(0, 1).toUpperCase());
        getMethodName.append(name.substring(1));
        Method method = null;
        try
        {
            method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
        }
        catch (Exception e)
        {
            log.error("获取对象异常{}", e.getMessage());
        }
        return method;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/reflect/ReflectUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,410 @@
package com.jcdm.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.jcdm.common.core.text.Convert;
import com.jcdm.common.utils.DateUtils;
/**
 * åå°„工具类. æä¾›è°ƒç”¨getter/setter方法, è®¿é—®ç§æœ‰å˜é‡, è°ƒç”¨ç§æœ‰æ–¹æ³•, èŽ·å–泛型类型Class, è¢«AOP过的真实类等工具函数.
 *
 * @author jc
 */
@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> 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 <E> 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> 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 <E> 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> 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> 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]);
                        }
                    }
                    else if (cs[i] == boolean.class || cs[i] == Boolean.class)
                    {
                        args[i] = Convert.toBool(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 <T> Class<T> 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);
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/sign/Base64.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,291 @@
package com.jcdm.common.utils.sign;
/**
 * Base64工具类
 *
 * @author jc
 */
public final class Base64
{
    static private final int     BASELENGTH           = 128;
    static private final int     LOOKUPLENGTH         = 64;
    static private final int     TWENTYFOURBITGROUP   = 24;
    static private final int     EIGHTBIT             = 8;
    static private final int     SIXTEENBIT           = 16;
    static private final int     FOURBYTE             = 4;
    static private final int     SIGN                 = -128;
    static private final char    PAD                  = '=';
    static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
    static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];
    static
    {
        for (int i = 0; i < BASELENGTH; ++i)
        {
            base64Alphabet[i] = -1;
        }
        for (int i = 'Z'; i >= 'A'; i--)
        {
            base64Alphabet[i] = (byte) (i - 'A');
        }
        for (int i = 'z'; i >= 'a'; i--)
        {
            base64Alphabet[i] = (byte) (i - 'a' + 26);
        }
        for (int i = '9'; i >= '0'; i--)
        {
            base64Alphabet[i] = (byte) (i - '0' + 52);
        }
        base64Alphabet['+'] = 62;
        base64Alphabet['/'] = 63;
        for (int i = 0; i <= 25; i++)
        {
            lookUpBase64Alphabet[i] = (char) ('A' + i);
        }
        for (int i = 26, j = 0; i <= 51; i++, j++)
        {
            lookUpBase64Alphabet[i] = (char) ('a' + j);
        }
        for (int i = 52, j = 0; i <= 61; i++, j++)
        {
            lookUpBase64Alphabet[i] = (char) ('0' + j);
        }
        lookUpBase64Alphabet[62] = (char) '+';
        lookUpBase64Alphabet[63] = (char) '/';
    }
    private static boolean isWhiteSpace(char octect)
    {
        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
    }
    private static boolean isPad(char octect)
    {
        return (octect == PAD);
    }
    private static boolean isData(char octect)
    {
        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
    }
    /**
     * Encodes hex octects into Base64
     *
     * @param binaryData Array containing binaryData
     * @return Encoded Base64 array
     */
    public static String encode(byte[] binaryData)
    {
        if (binaryData == null)
        {
            return null;
        }
        int lengthDataBits = binaryData.length * EIGHTBIT;
        if (lengthDataBits == 0)
        {
            return "";
        }
        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
        char encodedData[] = null;
        encodedData = new char[numberQuartet * 4];
        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        for (int i = 0; i < numberTriplets; i++)
        {
            b1 = binaryData[dataIndex++];
            b2 = binaryData[dataIndex++];
            b3 = binaryData[dataIndex++];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
        }
        // form integral number of 6-bit groups
        if (fewerThan24bits == EIGHTBIT)
        {
            b1 = binaryData[dataIndex];
            k = (byte) (b1 & 0x03);
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
            encodedData[encodedIndex++] = PAD;
            encodedData[encodedIndex++] = PAD;
        }
        else if (fewerThan24bits == SIXTEENBIT)
        {
            b1 = binaryData[dataIndex];
            b2 = binaryData[dataIndex + 1];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
            encodedData[encodedIndex++] = PAD;
        }
        return new String(encodedData);
    }
    /**
     * Decodes Base64 data into octects
     *
     * @param encoded string containing Base64 data
     * @return Array containind decoded data.
     */
    public static byte[] decode(String encoded)
    {
        if (encoded == null)
        {
            return null;
        }
        char[] base64Data = encoded.toCharArray();
        // remove white spaces
        int len = removeWhiteSpace(base64Data);
        if (len % FOURBYTE != 0)
        {
            return null;// should be divisible by four
        }
        int numberQuadruple = (len / FOURBYTE);
        if (numberQuadruple == 0)
        {
            return new byte[0];
        }
        byte decodedData[] = null;
        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
        int i = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        decodedData = new byte[(numberQuadruple) * 3];
        for (; i < numberQuadruple - 1; i++)
        {
            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
                    || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
            {
                return null;
            } // if found "no data" just return null
            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }
        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
        {
            return null;// if found "no data" just return null
        }
        b1 = base64Alphabet[d1];
        b2 = base64Alphabet[d2];
        d3 = base64Data[dataIndex++];
        d4 = base64Data[dataIndex++];
        if (!isData((d3)) || !isData((d4)))
        {// Check if they are PAD characters
            if (isPad(d3) && isPad(d4))
            {
                if ((b2 & 0xf) != 0)// last 4 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 1];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                return tmp;
            }
            else if (!isPad(d3) && isPad(d4))
            {
                b3 = base64Alphabet[d3];
                if ((b3 & 0x3) != 0)// last 2 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 2];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                return tmp;
            }
            else
            {
                return null;
            }
        }
        else
        { // No PAD e.g 3cQl
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }
        return decodedData;
    }
    /**
     * remove WhiteSpace from MIME containing encoded Base64 data.
     *
     * @param data the byte array of base64 data (with WS)
     * @return the new length
     */
    private static int removeWhiteSpace(char[] data)
    {
        if (data == null)
        {
            return 0;
        }
        // count characters that's not whitespace
        int newSize = 0;
        int len = data.length;
        for (int i = 0; i < len; i++)
        {
            if (!isWhiteSpace(data[i]))
            {
                data[newSize++] = data[i];
            }
        }
        return newSize;
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/sign/Md5Utils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
package com.jcdm.common.utils.sign;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * Md5加密方法
 *
 * @author jc
 */
public class Md5Utils
{
    private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
    private static byte[] md5(String s)
    {
        MessageDigest algorithm;
        try
        {
            algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(s.getBytes("UTF-8"));
            byte[] messageDigest = algorithm.digest();
            return messageDigest;
        }
        catch (Exception e)
        {
            log.error("MD5 Error...", e);
        }
        return null;
    }
    private static final String toHex(byte hash[])
    {
        if (hash == null)
        {
            return null;
        }
        StringBuffer buf = new StringBuffer(hash.length * 2);
        int i;
        for (i = 0; i < hash.length; i++)
        {
            if ((hash[i] & 0xff) < 0x10)
            {
                buf.append("0");
            }
            buf.append(Long.toString(hash[i] & 0xff, 16));
        }
        return buf.toString();
    }
    public static String hash(String s)
    {
        try
        {
            return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
        }
        catch (Exception e)
        {
            log.error("not supported charset...{}", e);
            return s;
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/spring/SpringUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,158 @@
package com.jcdm.common.utils.spring;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.jcdm.common.utils.StringUtils;
/**
 * spring工具类 æ–¹ä¾¿åœ¨éžspring管理环境中获取bean
 *
 * @author jc
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
    /** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;
    private static ApplicationContext applicationContext;
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        SpringUtils.beanFactory = beanFactory;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        SpringUtils.applicationContext = applicationContext;
    }
    /**
     * èŽ·å–对象
     *
     * @param name
     * @return Object ä¸€ä¸ªä»¥æ‰€ç»™åå­—注册的bean的实例
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }
    /**
     * èŽ·å–类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }
    /**
     * å¦‚æžœBeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }
    /**
     * åˆ¤æ–­ä»¥ç»™å®šåå­—注册的bean定义是一个singleton还是一个prototype。 å¦‚果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }
    /**
     * @param name
     * @return Class æ³¨å†Œå¯¹è±¡çš„类型
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }
    /**
     * å¦‚果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }
    /**
     * èŽ·å–aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker)
    {
        return (T) AopContext.currentProxy();
    }
    /**
     * èŽ·å–当前的环境配置,无配置返回null
     *
     * @return å½“前的环境配置
     */
    public static String[] getActiveProfiles()
    {
        return applicationContext.getEnvironment().getActiveProfiles();
    }
    /**
     * èŽ·å–当前的环境配置,当有多个环境配置时,只获取第一个
     *
     * @return å½“前的环境配置
     */
    public static String getActiveProfile()
    {
        final String[] activeProfiles = getActiveProfiles();
        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
    }
    /**
     * èŽ·å–配置文件中的值
     *
     * @param key é…ç½®æ–‡ä»¶çš„key
     * @return å½“前的配置文件的值
     *
     */
    public static String getRequiredProperty(String key)
    {
        return applicationContext.getEnvironment().getRequiredProperty(key);
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/sql/SqlUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
package com.jcdm.common.utils.sql;
import com.jcdm.common.exception.UtilException;
import com.jcdm.common.utils.StringUtils;
/**
 * sql操作工具类
 *
 * @author jc
 */
public class SqlUtil
{
    /**
     * å®šä¹‰å¸¸ç”¨çš„ sql关键字
     */
    public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
    /**
     * ä»…支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
     */
    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
    /**
     * é™åˆ¶orderBy最大长度
     */
    private static final int ORDER_BY_MAX_LENGTH = 500;
    /**
     * æ£€æŸ¥å­—符,防止注入绕过
     */
    public static String escapeOrderBySql(String value)
    {
        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
        {
            throw new UtilException("参数不符合规范,不能进行查询");
        }
        if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
        {
            throw new UtilException("参数已超过最大限制,不能进行查询");
        }
        return value;
    }
    /**
     * éªŒè¯ order by è¯­æ³•æ˜¯å¦ç¬¦åˆè§„范
     */
    public static boolean isValidOrderBySql(String value)
    {
        return value.matches(SQL_PATTERN);
    }
    /**
     * SQL关键字检查
     */
    public static void filterKeyword(String value)
    {
        if (StringUtils.isEmpty(value))
        {
            return;
        }
        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
        for (String sqlKeyword : sqlKeywords)
        {
            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
            {
                throw new UtilException("参数存在SQL注入风险");
            }
        }
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/uuid/IdUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
package com.jcdm.common.utils.uuid;
/**
 * ID生成器工具类
 *
 * @author jc
 */
public class IdUtils
{
    /**
     * èŽ·å–随机UUID
     *
     * @return éšæœºUUID
     */
    public static String randomUUID()
    {
        return UUID.randomUUID().toString();
    }
    /**
     * ç®€åŒ–çš„UUID,去掉了横线
     *
     * @return ç®€åŒ–çš„UUID,去掉了横线
     */
    public static String simpleUUID()
    {
        return UUID.randomUUID().toString(true);
    }
    /**
     * èŽ·å–随机UUID,使用性能更好的ThreadLocalRandom生成UUID
     *
     * @return éšæœºUUID
     */
    public static String fastUUID()
    {
        return UUID.fastUUID().toString();
    }
    /**
     * ç®€åŒ–çš„UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
     *
     * @return ç®€åŒ–çš„UUID,去掉了横线
     */
    public static String fastSimpleUUID()
    {
        return UUID.fastUUID().toString(true);
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/uuid/Seq.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.jcdm.common.utils.uuid;
import java.util.concurrent.atomic.AtomicInteger;
import com.jcdm.common.utils.DateUtils;
import com.jcdm.common.utils.StringUtils;
/**
 * @author jc åºåˆ—生成类
 */
public class Seq
{
    // é€šç”¨åºåˆ—类型
    public static final String commSeqType = "COMMON";
    // ä¸Šä¼ åºåˆ—类型
    public static final String uploadSeqType = "UPLOAD";
    // é€šç”¨æŽ¥å£åºåˆ—æ•°
    private static AtomicInteger commSeq = new AtomicInteger(1);
    // ä¸Šä¼ æŽ¥å£åºåˆ—æ•°
    private static AtomicInteger uploadSeq = new AtomicInteger(1);
    // æœºå™¨æ ‡è¯†
    private static final String machineCode = "A";
    /**
     * èŽ·å–通用序列号
     *
     * @return åºåˆ—值
     */
    public static String getId()
    {
        return getId(commSeqType);
    }
    /**
     * é»˜è®¤16位序列号 yyMMddHHmmss + ä¸€ä½æœºå™¨æ ‡è¯† + 3长度循环递增字符串
     *
     * @return åºåˆ—值
     */
    public static String getId(String type)
    {
        AtomicInteger atomicInt = commSeq;
        if (uploadSeqType.equals(type))
        {
            atomicInt = uploadSeq;
        }
        return getId(atomicInt, 3);
    }
    /**
     * é€šç”¨æŽ¥å£åºåˆ—号 yyMMddHHmmss + ä¸€ä½æœºå™¨æ ‡è¯† + length长度循环递增字符串
     *
     * @param atomicInt åºåˆ—æ•°
     * @param length æ•°å€¼é•¿åº¦
     * @return åºåˆ—值
     */
    public static String getId(AtomicInteger atomicInt, int length)
    {
        String result = DateUtils.dateTimeNow();
        result += machineCode;
        result += getSeq(atomicInt, length);
        return result;
    }
    /**
     * åºåˆ—循环递增字符串[1, 10 çš„ (length)幂次方), ç”¨0左补齐length位数
     *
     * @return åºåˆ—值
     */
    private synchronized static String getSeq(AtomicInteger atomicInt, int length)
    {
        // å…ˆå–值再+1
        int value = atomicInt.getAndIncrement();
        // å¦‚果更新后值>=10 çš„ (length)幂次方则重置为1
        int maxSeq = (int) Math.pow(10, length);
        if (atomicInt.get() >= maxSeq)
        {
            atomicInt.set(1);
        }
        // è½¬å­—符串,用0左补齐
        return StringUtils.padl(value, length);
    }
}
jcdm-common/src/main/java/com/jcdm/common/utils/uuid/UUID.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,484 @@
package com.jcdm.common.utils.uuid;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.jcdm.common.exception.UtilException;
/**
 * æä¾›é€šç”¨å”¯ä¸€è¯†åˆ«ç ï¼ˆuniversally unique identifier)(UUID)实现
 *
 * @author jc
 */
public final class UUID implements java.io.Serializable, Comparable<UUID>
{
    private static final long serialVersionUID = -1185015143654744140L;
    /**
     * SecureRandom çš„单例
     *
     */
    private static class Holder
    {
        static final SecureRandom numberGenerator = getSecureRandom();
    }
    /** æ­¤UUID的最高64有效位 */
    private final long mostSigBits;
    /** æ­¤UUID的最低64有效位 */
    private final long leastSigBits;
    /**
     * ç§æœ‰æž„造
     *
     * @param data æ•°æ®
     */
    private UUID(byte[] data)
    {
        long msb = 0;
        long lsb = 0;
        assert data.length == 16 : "data must be 16 bytes in length";
        for (int i = 0; i < 8; i++)
        {
            msb = (msb << 8) | (data[i] & 0xff);
        }
        for (int i = 8; i < 16; i++)
        {
            lsb = (lsb << 8) | (data[i] & 0xff);
        }
        this.mostSigBits = msb;
        this.leastSigBits = lsb;
    }
    /**
     * ä½¿ç”¨æŒ‡å®šçš„数据构造新的 UUID。
     *
     * @param mostSigBits ç”¨äºŽ {@code UUID} çš„最高有效 64 ä½
     * @param leastSigBits ç”¨äºŽ {@code UUID} çš„最低有效 64 ä½
     */
    public UUID(long mostSigBits, long leastSigBits)
    {
        this.mostSigBits = mostSigBits;
        this.leastSigBits = leastSigBits;
    }
    /**
     * èŽ·å–类型 4(伪随机生成的)UUID çš„静态工厂。
     *
     * @return éšæœºç”Ÿæˆçš„ {@code UUID}
     */
    public static UUID fastUUID()
    {
        return randomUUID(false);
    }
    /**
     * èŽ·å–类型 4(伪随机生成的)UUID çš„静态工厂。 ä½¿ç”¨åŠ å¯†çš„强伪随机数生成器生成该 UUID。
     *
     * @return éšæœºç”Ÿæˆçš„ {@code UUID}
     */
    public static UUID randomUUID()
    {
        return randomUUID(true);
    }
    /**
     * èŽ·å–类型 4(伪随机生成的)UUID çš„静态工厂。 ä½¿ç”¨åŠ å¯†çš„强伪随机数生成器生成该 UUID。
     *
     * @param isSecure æ˜¯å¦ä½¿ç”¨{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
     * @return éšæœºç”Ÿæˆçš„ {@code UUID}
     */
    public static UUID randomUUID(boolean isSecure)
    {
        final Random ng = isSecure ? Holder.numberGenerator : getRandom();
        byte[] randomBytes = new byte[16];
        ng.nextBytes(randomBytes);
        randomBytes[6] &= 0x0f; /* clear version */
        randomBytes[6] |= 0x40; /* set to version 4 */
        randomBytes[8] &= 0x3f; /* clear variant */
        randomBytes[8] |= 0x80; /* set to IETF variant */
        return new UUID(randomBytes);
    }
    /**
     * æ ¹æ®æŒ‡å®šçš„字节数组获取类型 3(基于名称的)UUID çš„静态工厂。
     *
     * @param name ç”¨äºŽæž„造 UUID çš„字节数组。
     *
     * @return æ ¹æ®æŒ‡å®šæ•°ç»„生成的 {@code UUID}
     */
    public static UUID nameUUIDFromBytes(byte[] name)
    {
        MessageDigest md;
        try
        {
            md = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException nsae)
        {
            throw new InternalError("MD5 not supported");
        }
        byte[] md5Bytes = md.digest(name);
        md5Bytes[6] &= 0x0f; /* clear version */
        md5Bytes[6] |= 0x30; /* set to version 3 */
        md5Bytes[8] &= 0x3f; /* clear variant */
        md5Bytes[8] |= 0x80; /* set to IETF variant */
        return new UUID(md5Bytes);
    }
    /**
     * æ ¹æ® {@link #toString()} æ–¹æ³•ä¸­æè¿°çš„字符串标准表示形式创建{@code UUID}。
     *
     * @param name æŒ‡å®š {@code UUID} å­—符串
     * @return å…·æœ‰æŒ‡å®šå€¼çš„ {@code UUID}
     * @throws IllegalArgumentException å¦‚æžœ name ä¸Ž {@link #toString} ä¸­æè¿°çš„字符串表示形式不符抛出此异常
     *
     */
    public static UUID fromString(String name)
    {
        String[] components = name.split("-");
        if (components.length != 5)
        {
            throw new IllegalArgumentException("Invalid UUID string: " + name);
        }
        for (int i = 0; i < 5; i++)
        {
            components[i] = "0x" + components[i];
        }
        long mostSigBits = Long.decode(components[0]).longValue();
        mostSigBits <<= 16;
        mostSigBits |= Long.decode(components[1]).longValue();
        mostSigBits <<= 16;
        mostSigBits |= Long.decode(components[2]).longValue();
        long leastSigBits = Long.decode(components[3]).longValue();
        leastSigBits <<= 48;
        leastSigBits |= Long.decode(components[4]).longValue();
        return new UUID(mostSigBits, leastSigBits);
    }
    /**
     * è¿”回此 UUID çš„ 128 ä½å€¼ä¸­çš„最低有效 64 ä½ã€‚
     *
     * @return æ­¤ UUID çš„ 128 ä½å€¼ä¸­çš„最低有效 64 ä½ã€‚
     */
    public long getLeastSignificantBits()
    {
        return leastSigBits;
    }
    /**
     * è¿”回此 UUID çš„ 128 ä½å€¼ä¸­çš„最高有效 64 ä½ã€‚
     *
     * @return æ­¤ UUID çš„ 128 ä½å€¼ä¸­æœ€é«˜æœ‰æ•ˆ 64 ä½ã€‚
     */
    public long getMostSignificantBits()
    {
        return mostSigBits;
    }
    /**
     * ä¸Žæ­¤ {@code UUID} ç›¸å…³è”的版本号. ç‰ˆæœ¬å·æè¿°æ­¤ {@code UUID} æ˜¯å¦‚何生成的。
     * <p>
     * ç‰ˆæœ¬å·å…·æœ‰ä»¥ä¸‹å«æ„:
     * <ul>
     * <li>1 åŸºäºŽæ—¶é—´çš„ UUID
     * <li>2 DCE å®‰å…¨ UUID
     * <li>3 åŸºäºŽåç§°çš„ UUID
     * <li>4 éšæœºç”Ÿæˆçš„ UUID
     * </ul>
     *
     * @return æ­¤ {@code UUID} çš„版本号
     */
    public int version()
    {
        // Version is bits masked by 0x000000000000F000 in MS long
        return (int) ((mostSigBits >> 12) & 0x0f);
    }
    /**
     * ä¸Žæ­¤ {@code UUID} ç›¸å…³è”的变体号。变体号描述 {@code UUID} çš„布局。
     * <p>
     * å˜ä½“号具有以下含意:
     * <ul>
     * <li>0 ä¸º NCS å‘后兼容保留
     * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), ç”¨äºŽæ­¤ç±»
     * <li>6 ä¿ç•™ï¼Œå¾®è½¯å‘后兼容
     * <li>7 ä¿ç•™ä¾›ä»¥åŽå®šä¹‰ä½¿ç”¨
     * </ul>
     *
     * @return æ­¤ {@code UUID} ç›¸å…³è”的变体号
     */
    public int variant()
    {
        // This field is composed of a varying number of bits.
        // 0 - - Reserved for NCS backward compatibility
        // 1 0 - The IETF aka Leach-Salz variant (used by this class)
        // 1 1 0 Reserved, Microsoft backward compatibility
        // 1 1 1 Reserved for future definition.
        return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
    }
    /**
     * ä¸Žæ­¤ UUID ç›¸å…³è”的时间戳值。
     *
     * <p>
     * 60 ä½çš„时间戳值根据此 {@code UUID} çš„ time_low、time_mid å’Œ time_hi å­—段构造。<br>
     * æ‰€å¾—到的时间戳以 100 æ¯«å¾®ç§’为单位,从 UTC(通用协调时间) 1582 å¹´ 10 æœˆ 15 æ—¥é›¶æ—¶å¼€å§‹ã€‚
     *
     * <p>
     * æ—¶é—´æˆ³å€¼ä»…在在基于时间的 UUID(其 version ç±»åž‹ä¸º 1)中才有意义。<br>
     * å¦‚果此 {@code UUID} ä¸æ˜¯åŸºäºŽæ—¶é—´çš„ UUID,则此方法抛出 UnsupportedOperationException。
     *
     * @throws UnsupportedOperationException å¦‚果此 {@code UUID} ä¸æ˜¯ version ä¸º 1 çš„ UUID。
     */
    public long timestamp() throws UnsupportedOperationException
    {
        checkTimeBase();
        return (mostSigBits & 0x0FFFL) << 48//
                | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
                | mostSigBits >>> 32;
    }
    /**
     * ä¸Žæ­¤ UUID ç›¸å…³è”的时钟序列值。
     *
     * <p>
     * 14 ä½çš„时钟序列值根据此 UUID çš„ clock_seq å­—段构造。clock_seq å­—段用于保证在基于时间的 UUID ä¸­çš„时间唯一性。
     * <p>
     * {@code clockSequence} å€¼ä»…在基于时间的 UUID(其 version ç±»åž‹ä¸º 1)中才有意义。 å¦‚果此 UUID ä¸æ˜¯åŸºäºŽæ—¶é—´çš„ UUID,则此方法抛出
     * UnsupportedOperationException。
     *
     * @return æ­¤ {@code UUID} çš„时钟序列
     *
     * @throws UnsupportedOperationException å¦‚果此 UUID çš„ version ä¸ä¸º 1
     */
    public int clockSequence() throws UnsupportedOperationException
    {
        checkTimeBase();
        return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
    }
    /**
     * ä¸Žæ­¤ UUID ç›¸å…³çš„节点值。
     *
     * <p>
     * 48 ä½çš„节点值根据此 UUID çš„ node å­—段构造。此字段旨在用于保存机器的 IEEE 802 åœ°å€ï¼Œè¯¥åœ°å€ç”¨äºŽç”Ÿæˆæ­¤ UUID ä»¥ä¿è¯ç©ºé—´å”¯ä¸€æ€§ã€‚
     * <p>
     * èŠ‚点值仅在基于时间的 UUID(其 version ç±»åž‹ä¸º 1)中才有意义。<br>
     * å¦‚果此 UUID ä¸æ˜¯åŸºäºŽæ—¶é—´çš„ UUID,则此方法抛出 UnsupportedOperationException。
     *
     * @return æ­¤ {@code UUID} çš„节点值
     *
     * @throws UnsupportedOperationException å¦‚果此 UUID çš„ version ä¸ä¸º 1
     */
    public long node() throws UnsupportedOperationException
    {
        checkTimeBase();
        return leastSigBits & 0x0000FFFFFFFFFFFFL;
    }
    /**
     * è¿”回此{@code UUID} çš„字符串表现形式。
     *
     * <p>
     * UUID çš„字符串表示形式由此 BNF æè¿°ï¼š
     *
     * <pre>
     * {@code
     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
     * time_low               = 4*<hexOctet>
     * time_mid               = 2*<hexOctet>
     * time_high_and_version  = 2*<hexOctet>
     * variant_and_sequence   = 2*<hexOctet>
     * node                   = 6*<hexOctet>
     * hexOctet               = <hexDigit><hexDigit>
     * hexDigit               = [0-9a-fA-F]
     * }
     * </pre>
     *
     * </blockquote>
     *
     * @return æ­¤{@code UUID} çš„字符串表现形式
     * @see #toString(boolean)
     */
    @Override
    public String toString()
    {
        return toString(false);
    }
    /**
     * è¿”回此{@code UUID} çš„字符串表现形式。
     *
     * <p>
     * UUID çš„字符串表示形式由此 BNF æè¿°ï¼š
     *
     * <pre>
     * {@code
     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
     * time_low               = 4*<hexOctet>
     * time_mid               = 2*<hexOctet>
     * time_high_and_version  = 2*<hexOctet>
     * variant_and_sequence   = 2*<hexOctet>
     * node                   = 6*<hexOctet>
     * hexOctet               = <hexDigit><hexDigit>
     * hexDigit               = [0-9a-fA-F]
     * }
     * </pre>
     *
     * </blockquote>
     *
     * @param isSimple æ˜¯å¦ç®€å•æ¨¡å¼ï¼Œç®€å•æ¨¡å¼ä¸ºä¸å¸¦'-'的UUID字符串
     * @return æ­¤{@code UUID} çš„字符串表现形式
     */
    public String toString(boolean isSimple)
    {
        final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
        // time_low
        builder.append(digits(mostSigBits >> 32, 8));
        if (!isSimple)
        {
            builder.append('-');
        }
        // time_mid
        builder.append(digits(mostSigBits >> 16, 4));
        if (!isSimple)
        {
            builder.append('-');
        }
        // time_high_and_version
        builder.append(digits(mostSigBits, 4));
        if (!isSimple)
        {
            builder.append('-');
        }
        // variant_and_sequence
        builder.append(digits(leastSigBits >> 48, 4));
        if (!isSimple)
        {
            builder.append('-');
        }
        // node
        builder.append(digits(leastSigBits, 12));
        return builder.toString();
    }
    /**
     * è¿”回此 UUID çš„哈希码。
     *
     * @return UUID çš„哈希码值。
     */
    @Override
    public int hashCode()
    {
        long hilo = mostSigBits ^ leastSigBits;
        return ((int) (hilo >> 32)) ^ (int) hilo;
    }
    /**
     * å°†æ­¤å¯¹è±¡ä¸ŽæŒ‡å®šå¯¹è±¡æ¯”较。
     * <p>
     * å½“且仅当参数不为 {@code null}、而是一个 UUID å¯¹è±¡ã€å…·æœ‰ä¸Žæ­¤ UUID ç›¸åŒçš„ varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
     *
     * @param obj è¦ä¸Žä¹‹æ¯”较的对象
     *
     * @return å¦‚果对象相同,则返回 {@code true};否则返回 {@code false}
     */
    @Override
    public boolean equals(Object obj)
    {
        if ((null == obj) || (obj.getClass() != UUID.class))
        {
            return false;
        }
        UUID id = (UUID) obj;
        return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
    }
    // Comparison Operations
    /**
     * å°†æ­¤ UUID ä¸ŽæŒ‡å®šçš„ UUID æ¯”较。
     *
     * <p>
     * å¦‚果两个 UUID ä¸åŒï¼Œä¸”第一个 UUID çš„最高有效字段大于第二个 UUID çš„对应字段,则第一个 UUID å¤§äºŽç¬¬äºŒä¸ª UUID。
     *
     * @param val ä¸Žæ­¤ UUID æ¯”较的 UUID
     *
     * @return åœ¨æ­¤ UUID å°äºŽã€ç­‰äºŽæˆ–大于 val æ—¶ï¼Œåˆ†åˆ«è¿”回 -1、0 æˆ– 1。
     *
     */
    @Override
    public int compareTo(UUID val)
    {
        // The ordering is intentionally set up so that the UUIDs
        // can simply be numerically compared as two numbers
        return (this.mostSigBits < val.mostSigBits ? -1 : //
                (this.mostSigBits > val.mostSigBits ? 1 : //
                        (this.leastSigBits < val.leastSigBits ? -1 : //
                                (this.leastSigBits > val.leastSigBits ? 1 : //
                                        0))));
    }
    // -------------------------------------------------------------------------------------------------------------------
    // Private method start
    /**
     * è¿”回指定数字对应的hex值
     *
     * @param val å€¼
     * @param digits ä½
     * @return å€¼
     */
    private static String digits(long val, int digits)
    {
        long hi = 1L << (digits * 4);
        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
    }
    /**
     * æ£€æŸ¥æ˜¯å¦ä¸ºtime-based版本UUID
     */
    private void checkTimeBase()
    {
        if (version() != 1)
        {
            throw new UnsupportedOperationException("Not a time-based UUID");
        }
    }
    /**
     * èŽ·å–{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
     *
     * @return {@link SecureRandom}
     */
    public static SecureRandom getSecureRandom()
    {
        try
        {
            return SecureRandom.getInstance("SHA1PRNG");
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new UtilException(e);
        }
    }
    /**
     * èŽ·å–随机数生成器对象<br>
     * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
     *
     * @return {@link ThreadLocalRandom}
     */
    public static ThreadLocalRandom getRandom()
    {
        return ThreadLocalRandom.current();
    }
}
jcdm-common/src/main/java/com/jcdm/common/xss/Xss.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.jcdm.common.xss;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * è‡ªå®šä¹‰xss校验注解
 *
 * @author jc
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Constraint(validatedBy = { XssValidator.class })
public @interface Xss
{
    String message()
    default "不允许任何脚本运行";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
jcdm-common/src/main/java/com/jcdm/common/xss/XssValidator.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.jcdm.common.xss;
import com.jcdm.common.utils.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * è‡ªå®šä¹‰xss校验注解实现
 *
 * @author jc
 */
public class XssValidator implements ConstraintValidator<Xss, String>
{
    private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
    {
        if (StringUtils.isBlank(value))
        {
            return true;
        }
        return !containsHtml(value);
    }
    public static boolean containsHtml(String value)
    {
        Pattern pattern = Pattern.compile(HTML_PATTERN);
        Matcher matcher = pattern.matcher(value);
        return matcher.matches();
    }
}
jcdm-framework/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>jcdm</artifactId>
        <groupId>com.jcdm</groupId>
        <version>3.8.6</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>jcdm-framework</artifactId>
    <description>
        framework框架核心
    </description>
    <dependencies>
        <!-- SpringBoot Web容器 -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- SpringBoot æ‹¦æˆªå™¨ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- é˜¿é‡Œæ•°æ®åº“连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <!-- éªŒè¯ç  -->
        <dependency>
            <groupId>pro.fessional</groupId>
            <artifactId>kaptcha</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>servlet-api</artifactId>
                    <groupId>javax.servlet</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- èŽ·å–系统信息 -->
        <dependency>
            <groupId>com.github.oshi</groupId>
            <artifactId>oshi-core</artifactId>
        </dependency>
        <!-- ç³»ç»Ÿæ¨¡å—-->
        <dependency>
            <groupId>com.jcdm</groupId>
            <artifactId>jcdm-system</artifactId>
        </dependency>
        <!-- SpringBoot Websocket -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
    </dependencies>
</project>
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataScopeAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,174 @@
package com.jcdm.framework.aspectj;
import java.util.ArrayList;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.jcdm.common.annotation.DataScope;
import com.jcdm.common.core.domain.BaseEntity;
import com.jcdm.common.core.domain.entity.SysRole;
import com.jcdm.common.core.domain.entity.SysUser;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.core.text.Convert;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.framework.security.context.PermissionContextHolder;
/**
 * æ•°æ®è¿‡æ»¤å¤„理
 *
 * @author jc
 */
@Aspect
@Component
public class DataScopeAspect
{
    /**
     * å…¨éƒ¨æ•°æ®æƒé™
     */
    public static final String DATA_SCOPE_ALL = "1";
    /**
     * è‡ªå®šæ•°æ®æƒé™
     */
    public static final String DATA_SCOPE_CUSTOM = "2";
    /**
     * éƒ¨é—¨æ•°æ®æƒé™
     */
    public static final String DATA_SCOPE_DEPT = "3";
    /**
     * éƒ¨é—¨åŠä»¥ä¸‹æ•°æ®æƒé™
     */
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
    /**
     * ä»…本人数据权限
     */
    public static final String DATA_SCOPE_SELF = "5";
    /**
     * æ•°æ®æƒé™è¿‡æ»¤å…³é”®å­—
     */
    public static final String DATA_SCOPE = "dataScope";
    @Before("@annotation(controllerDataScope)")
    public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
    {
        clearDataScope(point);
        handleDataScope(point, controllerDataScope);
    }
    protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
    {
        // èŽ·å–当前的用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (StringUtils.isNotNull(loginUser))
        {
            SysUser currentUser = loginUser.getUser();
            // å¦‚果是超级管理员,则不过滤数据
            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
            {
                String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
                        controllerDataScope.userAlias(), permission);
            }
        }
    }
    /**
     * æ•°æ®èŒƒå›´è¿‡æ»¤
     *
     * @param joinPoint åˆ‡ç‚¹
     * @param user ç”¨æˆ·
     * @param deptAlias éƒ¨é—¨åˆ«å
     * @param userAlias ç”¨æˆ·åˆ«å
     * @param permission æƒé™å­—符
     */
    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
    {
        StringBuilder sqlString = new StringBuilder();
        List<String> conditions = new ArrayList<String>();
        for (SysRole role : user.getRoles())
        {
            String dataScope = role.getDataScope();
            if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
            {
                continue;
            }
            if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
                    && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
            {
                continue;
            }
            if (DATA_SCOPE_ALL.equals(dataScope))
            {
                sqlString = new StringBuilder();
                conditions.add(dataScope);
                break;
            }
            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
            {
                sqlString.append(StringUtils.format(
                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
                        role.getRoleId()));
            }
            else if (DATA_SCOPE_DEPT.equals(dataScope))
            {
                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
            }
            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
            {
                sqlString.append(StringUtils.format(
                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                        deptAlias, user.getDeptId(), user.getDeptId()));
            }
            else if (DATA_SCOPE_SELF.equals(dataScope))
            {
                if (StringUtils.isNotBlank(userAlias))
                {
                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
                }
                else
                {
                    // æ•°æ®æƒé™ä¸ºä»…本人且没有userAlias别名不查询任何数据
                    sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
                }
            }
            conditions.add(dataScope);
        }
        // å¤šè§’色情况下,所有角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
        if (StringUtils.isEmpty(conditions))
        {
            sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
        }
        if (StringUtils.isNotBlank(sqlString.toString()))
        {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
            {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
            }
        }
    }
    /**
     * æ‹¼æŽ¥æƒé™sql前先清空params.dataScope参数防止注入
     */
    private void clearDataScope(final JoinPoint joinPoint)
    {
        Object params = joinPoint.getArgs()[0];
        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
        {
            BaseEntity baseEntity = (BaseEntity) params;
            baseEntity.getParams().put(DATA_SCOPE, "");
        }
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/DataSourceAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
package com.jcdm.framework.aspectj;
import java.util.Objects;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.jcdm.common.annotation.DataSource;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.framework.datasource.DynamicDataSourceContextHolder;
/**
 * å¤šæ•°æ®æºå¤„理
 *
 * @author jc
 */
@Aspect
@Order(1)
@Component
public class DataSourceAspect
{
    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Pointcut("@annotation(com.jcdm.common.annotation.DataSource)"
            + "|| @within(com.jcdm.common.annotation.DataSource)")
    public void dsPointCut()
    {
    }
    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable
    {
        DataSource dataSource = getDataSource(point);
        if (StringUtils.isNotNull(dataSource))
        {
            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
        }
        try
        {
            return point.proceed();
        }
        finally
        {
            // é”€æ¯æ•°æ®æº åœ¨æ‰§è¡Œæ–¹æ³•ä¹‹åŽ
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }
    /**
     * èŽ·å–需要切换的数据源
     */
    public DataSource getDataSource(ProceedingJoinPoint point)
    {
        MethodSignature signature = (MethodSignature) point.getSignature();
        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
        if (Objects.nonNull(dataSource))
        {
            return dataSource;
        }
        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/LogAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,249 @@
package com.jcdm.framework.aspectj;
import java.util.Collection;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson2.JSON;
import com.jcdm.common.annotation.Log;
import com.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.enums.BusinessStatus;
import com.jcdm.common.enums.HttpMethod;
import com.jcdm.common.filter.PropertyPreExcludeFilter;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.common.utils.ServletUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.ip.IpUtils;
import com.jcdm.framework.manager.AsyncManager;
import com.jcdm.framework.manager.factory.AsyncFactory;
import com.jcdm.system.domain.SysOperLog;
/**
 * æ“ä½œæ—¥å¿—记录处理
 *
 * @author jc
 */
@Aspect
@Component
public class LogAspect
{
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
    /** æŽ’除敏感属性字段 */
    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
    /** è®¡ç®—操作消耗时间 */
    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
    /**
     * å¤„理请求前执行
     */
    @Before(value = "@annotation(controllerLog)")
    public void boBefore(JoinPoint joinPoint, Log controllerLog)
    {
        TIME_THREADLOCAL.set(System.currentTimeMillis());
    }
    /**
     * å¤„理完请求后执行
     *
     * @param joinPoint åˆ‡ç‚¹
     */
    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
    {
        handleLog(joinPoint, controllerLog, null, jsonResult);
    }
    /**
     * æ‹¦æˆªå¼‚常操作
     *
     * @param joinPoint åˆ‡ç‚¹
     * @param e å¼‚常
     */
    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
    {
        handleLog(joinPoint, controllerLog, e, null);
    }
    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
    {
        try
        {
            // èŽ·å–当前的用户
            LoginUser loginUser = SecurityUtils.getLoginUser();
            // *========数据库日志=========*//
            SysOperLog operLog = new SysOperLog();
            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
            // è¯·æ±‚的地址
            String ip = IpUtils.getIpAddr();
            operLog.setOperIp(ip);
            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
            if (loginUser != null)
            {
                operLog.setOperName(loginUser.getUsername());
            }
            if (e != null)
            {
                operLog.setStatus(BusinessStatus.FAIL.ordinal());
                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            // è®¾ç½®æ–¹æ³•åç§°
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // è®¾ç½®è¯·æ±‚方式
            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
            // å¤„理设置注解上的参数
            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
            // è®¾ç½®æ¶ˆè€—时间
            operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
            // ä¿å­˜æ•°æ®åº“
            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
        }
        catch (Exception exp)
        {
            // è®°å½•æœ¬åœ°å¼‚常日志
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
        finally
        {
            TIME_THREADLOCAL.remove();
        }
    }
    /**
     * èŽ·å–注解中对方法的描述信息 ç”¨äºŽController层注解
     *
     * @param log æ—¥å¿—
     * @param operLog æ“ä½œæ—¥å¿—
     * @throws Exception
     */
    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
    {
        // è®¾ç½®action动作
        operLog.setBusinessType(log.businessType().ordinal());
        // è®¾ç½®æ ‡é¢˜
        operLog.setTitle(log.title());
        // è®¾ç½®æ“ä½œäººç±»åˆ«
        operLog.setOperatorType(log.operatorType().ordinal());
        // æ˜¯å¦éœ€è¦ä¿å­˜request,参数和值
        if (log.isSaveRequestData())
        {
            // èŽ·å–参数的信息,传入到数据库中。
            setRequestValue(joinPoint, operLog, log.excludeParamNames());
        }
        // æ˜¯å¦éœ€è¦ä¿å­˜response,参数和值
        if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
        {
            operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
        }
    }
    /**
     * èŽ·å–请求的参数,放到log中
     *
     * @param operLog æ“ä½œæ—¥å¿—
     * @throws Exception å¼‚常
     */
    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
    {
        Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
        String requestMethod = operLog.getRequestMethod();
        if (StringUtils.isEmpty(paramsMap)
                && (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
        {
            String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
        }
        else
        {
            operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
        }
    }
    /**
     * å‚数拼装
     */
    private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
    {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0)
        {
            for (Object o : paramsArray)
            {
                if (StringUtils.isNotNull(o) && !isFilterObject(o))
                {
                    try
                    {
                        String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
                        params += jsonObj.toString() + " ";
                    }
                    catch (Exception e)
                    {
                    }
                }
            }
        }
        return params.trim();
    }
    /**
     * å¿½ç•¥æ•æ„Ÿå±žæ€§
     */
    public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
    {
        return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
    }
    /**
     * åˆ¤æ–­æ˜¯å¦éœ€è¦è¿‡æ»¤çš„对象。
     *
     * @param o å¯¹è±¡ä¿¡æ¯ã€‚
     * @return å¦‚果是需要过滤的对象,则返回true;否则返回false。
     */
    @SuppressWarnings("rawtypes")
    public boolean isFilterObject(final Object o)
    {
        Class<?> clazz = o.getClass();
        if (clazz.isArray())
        {
            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
        }
        else if (Collection.class.isAssignableFrom(clazz))
        {
            Collection collection = (Collection) o;
            for (Object value : collection)
            {
                return value instanceof MultipartFile;
            }
        }
        else if (Map.class.isAssignableFrom(clazz))
        {
            Map map = (Map) o;
            for (Object value : map.entrySet())
            {
                Map.Entry entry = (Map.Entry) value;
                return entry.getValue() instanceof MultipartFile;
            }
        }
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
                || o instanceof BindingResult;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/aspectj/RateLimiterAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
package com.jcdm.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import com.jcdm.common.annotation.RateLimiter;
import com.jcdm.common.enums.LimitType;
import com.jcdm.common.exception.ServiceException;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.ip.IpUtils;
/**
 * é™æµå¤„理
 *
 * @author jc
 */
//@Aspect
//@Component
public class RateLimiterAspect
{
    private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
    private RedisTemplate<Object, Object> redisTemplate;
    private RedisScript<Long> limitScript;
//    @Autowired
    public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
    {
        this.redisTemplate = redisTemplate;
    }
//    @Autowired
    public void setLimitScript(RedisScript<Long> limitScript)
    {
        this.limitScript = limitScript;
    }
    @Before("@annotation(rateLimiter)")
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
    {
        int time = rateLimiter.time();
        int count = rateLimiter.count();
        String combineKey = getCombineKey(rateLimiter, point);
        List<Object> keys = Collections.singletonList(combineKey);
        try
        {
            Long number = redisTemplate.execute(limitScript, keys, count, time);
            if (StringUtils.isNull(number) || number.intValue() > count)
            {
                throw new ServiceException("访问过于频繁,请稍候再试");
            }
            log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey);
        }
        catch (ServiceException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new RuntimeException("服务器限流异常,请稍候再试");
        }
    }
    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
    {
        StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
        if (rateLimiter.limitType() == LimitType.IP)
        {
            stringBuffer.append(IpUtils.getIpAddr()).append("-");
        }
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
        return stringBuffer.toString();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/ApplicationConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.jcdm.framework.config;
import java.util.TimeZone;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
 * ç¨‹åºæ³¨è§£é…ç½®
 *
 * @author jc
 */
@Configuration
// è¡¨ç¤ºé€šè¿‡aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// æŒ‡å®šè¦æ‰«æçš„Mapper类的包的路径
@MapperScan("com.jcdm.**.mapper")
public class ApplicationConfig
{
    /**
     * æ—¶åŒºé…ç½®
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
    {
        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/CaptchaConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
package com.jcdm.framework.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import static com.google.code.kaptcha.Constants.*;
/**
 * éªŒè¯ç é…ç½®
 *
 * @author jc
 */
@Configuration
public class CaptchaConfig
{
    @Bean(name = "captchaProducer")
    public DefaultKaptcha getKaptchaBean()
    {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        // æ˜¯å¦æœ‰è¾¹æ¡† é»˜è®¤ä¸ºtrue æˆ‘们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // éªŒè¯ç æ–‡æœ¬å­—符颜色 é»˜è®¤ä¸ºColor.BLACK
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
        // éªŒè¯ç å›¾ç‰‡å®½åº¦ é»˜è®¤ä¸º200
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        // éªŒè¯ç å›¾ç‰‡é«˜åº¦ é»˜è®¤ä¸º50
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        // éªŒè¯ç æ–‡æœ¬å­—符大小 é»˜è®¤ä¸º40
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
        // KAPTCHA_SESSION_KEY
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
        // éªŒè¯ç æ–‡æœ¬å­—符长度 é»˜è®¤ä¸º5
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        // éªŒè¯ç æ–‡æœ¬å­—体样式 é»˜è®¤ä¸ºnew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        // å›¾ç‰‡æ ·å¼ æ°´çº¹com.google.code.kaptcha.impl.WaterRipple é±¼çœ¼com.google.code.kaptcha.impl.FishEyeGimpy é˜´å½±com.google.code.kaptcha.impl.ShadowGimpy
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
    @Bean(name = "captchaProducerMath")
    public DefaultKaptcha getKaptchaBeanMath()
    {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        // æ˜¯å¦æœ‰è¾¹æ¡† é»˜è®¤ä¸ºtrue æˆ‘们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // è¾¹æ¡†é¢œè‰² é»˜è®¤ä¸ºColor.BLACK
        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
        // éªŒè¯ç æ–‡æœ¬å­—符颜色 é»˜è®¤ä¸ºColor.BLACK
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        // éªŒè¯ç å›¾ç‰‡å®½åº¦ é»˜è®¤ä¸º200
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        // éªŒè¯ç å›¾ç‰‡é«˜åº¦ é»˜è®¤ä¸º50
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        // éªŒè¯ç æ–‡æœ¬å­—符大小 é»˜è®¤ä¸º40
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
        // KAPTCHA_SESSION_KEY
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
        // éªŒè¯ç æ–‡æœ¬ç”Ÿæˆå™¨
        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.jcdm.framework.config.KaptchaTextCreator");
        // éªŒè¯ç æ–‡æœ¬å­—符间距 é»˜è®¤ä¸º2
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
        // éªŒè¯ç æ–‡æœ¬å­—符长度 é»˜è®¤ä¸º5
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
        // éªŒè¯ç æ–‡æœ¬å­—体样式 é»˜è®¤ä¸ºnew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        // éªŒè¯ç å™ªç‚¹é¢œè‰² é»˜è®¤ä¸ºColor.BLACK
        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
        // å¹²æ‰°å®žçŽ°ç±»
        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
        // å›¾ç‰‡æ ·å¼ æ°´çº¹com.google.code.kaptcha.impl.WaterRipple é±¼çœ¼com.google.code.kaptcha.impl.FishEyeGimpy é˜´å½±com.google.code.kaptcha.impl.ShadowGimpy
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/DruidConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
package com.jcdm.framework.config;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.jcdm.common.enums.DataSourceType;
import com.jcdm.common.utils.spring.SpringUtils;
import com.jcdm.framework.config.properties.DruidProperties;
import com.jcdm.framework.datasource.DynamicDataSource;
/**
 * druid é…ç½®å¤šæ•°æ®æº
 *
 * @author jc
 */
@Configuration
public class DruidConfig
{
    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }
    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public DataSource slaveDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }
    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource)
    {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }
    /**
     * è®¾ç½®æ•°æ®æº
     *
     * @param targetDataSources å¤‡é€‰æ•°æ®æºé›†åˆ
     * @param sourceName æ•°æ®æºåç§°
     * @param beanName bean名称
     */
    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
    {
        try
        {
            DataSource dataSource = SpringUtils.getBean(beanName);
            targetDataSources.put(sourceName, dataSource);
        }
        catch (Exception e)
        {
        }
    }
    /**
     * åŽ»é™¤ç›‘控页面底部的广告
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
    {
        // èŽ·å–web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // æå–common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        final String filePath = "support/http/resources/js/common.js";
        // åˆ›å»ºfilter进行过滤
        Filter filter = new Filter()
        {
            @Override
            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
            {
            }
            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException
            {
                chain.doFilter(request, response);
                // é‡ç½®ç¼“冲区,响应头不会被重置
                response.resetBuffer();
                // èŽ·å–common.js
                String text = Utils.readFromResource(filePath);
                // æ­£åˆ™æ›¿æ¢banner, é™¤åŽ»åº•éƒ¨çš„广告信息
                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
                text = text.replaceAll("powered.*?shrek.wang</a>", "");
                response.getWriter().write(text);
            }
            @Override
            public void destroy()
            {
            }
        };
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns(commonJsPattern);
        return registrationBean;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/FastJson2JsonRedisSerializer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.jcdm.framework.config;
import java.nio.charset.Charset;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.jcdm.common.constant.Constants;
/**
 * Redis使用FastJson序列化
 *
 * @author jc
 */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
    private Class<T> clazz;
    public FastJson2JsonRedisSerializer(Class<T> clazz)
    {
        super();
        this.clazz = clazz;
    }
    @Override
    public byte[] serialize(T t) throws SerializationException
    {
        if (t == null)
        {
            return new byte[0];
        }
        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }
    @Override
    public T deserialize(byte[] bytes) throws SerializationException
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/FilterConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.jcdm.framework.config;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.jcdm.common.filter.RepeatableFilter;
import com.jcdm.common.filter.XssFilter;
import com.jcdm.common.utils.StringUtils;
/**
 * Filter配置
 *
 * @author jc
 */
@Configuration
public class FilterConfig
{
    @Value("${xss.excludes}")
    private String excludes;
    @Value("${xss.urlPatterns}")
    private String urlPatterns;
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
    public FilterRegistrationBean xssFilterRegistration()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new XssFilter());
        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
        registration.setName("xssFilter");
        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
        Map<String, String> initParameters = new HashMap<String, String>();
        initParameters.put("excludes", excludes);
        registration.setInitParameters(initParameters);
        return registration;
    }
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean someFilterRegistration()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new RepeatableFilter());
        registration.addUrlPatterns("/*");
        registration.setName("repeatableFilter");
        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
        return registration;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/KaptchaTextCreator.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package com.jcdm.framework.config;
import java.util.Random;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
 * éªŒè¯ç æ–‡æœ¬ç”Ÿæˆå™¨
 *
 * @author jc
 */
public class KaptchaTextCreator extends DefaultTextCreator
{
    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
    @Override
    public String getText()
    {
        Integer result = 0;
        Random random = new Random();
        int x = random.nextInt(10);
        int y = random.nextInt(10);
        StringBuilder suChinese = new StringBuilder();
        int randomoperands = random.nextInt(3);
        if (randomoperands == 0)
        {
            result = x * y;
            suChinese.append(CNUMBERS[x]);
            suChinese.append("*");
            suChinese.append(CNUMBERS[y]);
        }
        else if (randomoperands == 1)
        {
            if ((x != 0) && y % x == 0)
            {
                result = y / x;
                suChinese.append(CNUMBERS[y]);
                suChinese.append("/");
                suChinese.append(CNUMBERS[x]);
            }
            else
            {
                result = x + y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("+");
                suChinese.append(CNUMBERS[y]);
            }
        }
        else
        {
            if (x >= y)
            {
                result = x - y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("-");
                suChinese.append(CNUMBERS[y]);
            }
            else
            {
                result = y - x;
                suChinese.append(CNUMBERS[y]);
                suChinese.append("-");
                suChinese.append(CNUMBERS[x]);
            }
        }
        suChinese.append("=?@" + result);
        return suChinese.toString();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/MyBatisConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,132 @@
package com.jcdm.framework.config;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import javax.sql.DataSource;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import com.jcdm.common.utils.StringUtils;
/**
 * Mybatis支持*匹配扫描包
 *
 * @author jc
 */
@Configuration
public class MyBatisConfig
{
    @Autowired
    private Environment env;
    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
    public static String setTypeAliasesPackage(String typeAliasesPackage)
    {
        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
        List<String> allResult = new ArrayList<String>();
        try
        {
            for (String aliasesPackage : typeAliasesPackage.split(","))
            {
                List<String> result = new ArrayList<String>();
                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
                Resource[] resources = resolver.getResources(aliasesPackage);
                if (resources != null && resources.length > 0)
                {
                    MetadataReader metadataReader = null;
                    for (Resource resource : resources)
                    {
                        if (resource.isReadable())
                        {
                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
                            try
                            {
                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
                            }
                            catch (ClassNotFoundException e)
                            {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                if (result.size() > 0)
                {
                    HashSet<String> hashResult = new HashSet<String>(result);
                    allResult.addAll(hashResult);
                }
            }
            if (allResult.size() > 0)
            {
                typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
            }
            else
            {
                throw new RuntimeException("mybatis typeAliasesPackage è·¯å¾„扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return typeAliasesPackage;
    }
    public Resource[] resolveMapperLocations(String[] mapperLocations)
    {
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        List<Resource> resources = new ArrayList<Resource>();
        if (mapperLocations != null)
        {
            for (String mapperLocation : mapperLocations)
            {
                try
                {
                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
                    resources.addAll(Arrays.asList(mappers));
                }
                catch (IOException e)
                {
                    // ignore
                }
            }
        }
        return resources.toArray(new Resource[resources.size()]);
    }
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
    {
        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
        String mapperLocations = env.getProperty("mybatis.mapperLocations");
        String configLocation = env.getProperty("mybatis.configLocation");
        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
        VFS.addImplClass(SpringBootVFS.class);
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
        return sessionFactory.getObject();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/RedisConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.jcdm.framework.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
 * redis配置
 *
 * @author jc
 */
//@Configuration
//@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
//    @Bean
    @SuppressWarnings(value = { "unchecked", "rawtypes" })
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
    {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
        // ä½¿ç”¨StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
//    @Bean
    public DefaultRedisScript<Long> limitScript()
    {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(limitScriptText());
        redisScript.setResultType(Long.class);
        return redisScript;
    }
    /**
     * é™æµè„šæœ¬
     */
    private String limitScriptText()
    {
        return "local key = KEYS[1]\n" +
                "local count = tonumber(ARGV[1])\n" +
                "local time = tonumber(ARGV[2])\n" +
                "local current = redis.call('get', key);\n" +
                "if current and tonumber(current) > count then\n" +
                "    return tonumber(current);\n" +
                "end\n" +
                "current = redis.call('incr', key)\n" +
                "if tonumber(current) == 1 then\n" +
                "    redis.call('expire', key, time)\n" +
                "end\n" +
                "return tonumber(current);";
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/ResourcesConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
package com.jcdm.framework.config;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
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.jcdm.common.config.MesConfig;
import com.jcdm.common.constant.Constants;
import com.jcdm.framework.interceptor.RepeatSubmitInterceptor;
/**
 * é€šç”¨é…ç½®
 *
 * @author jc
 */
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
    @Autowired
    private RepeatSubmitInterceptor repeatSubmitInterceptor;
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        /** æœ¬åœ°æ–‡ä»¶ä¸Šä¼ è·¯å¾„ */
        registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
                .addResourceLocations("file:" + MesConfig.getProfile() + "/");
        /** swagger配置 */
        registry.addResourceHandler("/swagger-ui/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
                .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
    }
    /**
     * è‡ªå®šä¹‰æ‹¦æˆªè§„则
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
    }
    /**
     * è·¨åŸŸé…ç½®
     */
    @Bean
    public CorsFilter corsFilter()
    {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // è®¾ç½®è®¿é—®æºåœ°å€
        config.addAllowedOriginPattern("*");
        // è®¾ç½®è®¿é—®æºè¯·æ±‚头
        config.addAllowedHeader("*");
        // è®¾ç½®è®¿é—®æºè¯·æ±‚方法
        config.addAllowedMethod("*");
        // æœ‰æ•ˆæœŸ 1800秒
        config.setMaxAge(1800L);
        // æ·»åŠ æ˜ å°„路径,拦截一切请求
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        // è¿”回新的CorsFilter
        return new CorsFilter(source);
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/SecurityConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,148 @@
package com.jcdm.framework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
import com.jcdm.framework.config.properties.PermitAllUrlProperties;
import com.jcdm.framework.security.filter.JwtAuthenticationTokenFilter;
import com.jcdm.framework.security.handle.AuthenticationEntryPointImpl;
import com.jcdm.framework.security.handle.LogoutSuccessHandlerImpl;
/**
 * spring security配置
 *
 * @author jc
 */
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    /**
     * è‡ªå®šä¹‰ç”¨æˆ·è®¤è¯é€»è¾‘
     */
    @Autowired
    private UserDetailsService userDetailsService;
    /**
     * è®¤è¯å¤±è´¥å¤„理类
     */
    @Autowired
    private AuthenticationEntryPointImpl unauthorizedHandler;
    /**
     * é€€å‡ºå¤„理类
     */
    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;
    /**
     * token认证过滤器
     */
    @Autowired
    private JwtAuthenticationTokenFilter authenticationTokenFilter;
    /**
     * è·¨åŸŸè¿‡æ»¤å™¨
     */
    @Autowired
    private CorsFilter corsFilter;
    /**
     * å…è®¸åŒ¿åè®¿é—®çš„地址
     */
    @Autowired
    private PermitAllUrlProperties permitAllUrl;
    /**
     * è§£å†³ æ— æ³•ç›´æŽ¥æ³¨å…¥ AuthenticationManager
     *
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception
    {
        return super.authenticationManagerBean();
    }
    /**
     * anyRequest          |   åŒ¹é…æ‰€æœ‰è¯·æ±‚路径
     * access              |   SpringEl表达式结果为true时可以访问
     * anonymous           |   åŒ¿åå¯ä»¥è®¿é—®
     * denyAll             |   ç”¨æˆ·ä¸èƒ½è®¿é—®
     * fullyAuthenticated  |   ç”¨æˆ·å®Œå…¨è®¤è¯å¯ä»¥è®¿é—®ï¼ˆéžremember-me下自动登录)
     * hasAnyAuthority     |   å¦‚果有参数,参数表示权限,则其中任何一个权限可以访问
     * hasAnyRole          |   å¦‚果有参数,参数表示角色,则其中任何一个角色可以访问
     * hasAuthority        |   å¦‚果有参数,参数表示权限,则其权限可以访问
     * hasIpAddress        |   å¦‚果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
     * hasRole             |   å¦‚果有参数,参数表示角色,则其角色可以访问
     * permitAll           |   ç”¨æˆ·å¯ä»¥ä»»æ„è®¿é—®
     * rememberMe          |   å…è®¸é€šè¿‡remember-me登录的用户访问
     * authenticated       |   ç”¨æˆ·ç™»å½•åŽå¯è®¿é—®
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
        // æ³¨è§£æ ‡è®°å…è®¸åŒ¿åè®¿é—®çš„url
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
        permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
        httpSecurity
                // CSRF禁用,因为不使用session
                .csrf().disable()
                // ç¦ç”¨HTTP响应标头
                .headers().cacheControl().disable().and()
                // è®¤è¯å¤±è´¥å¤„理类
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                // åŸºäºŽtoken,所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                // è¿‡æ»¤è¯·æ±‚
                .authorizeRequests()
                // å¯¹äºŽç™»å½•login æ³¨å†Œregister éªŒè¯ç captchaImage å…è®¸åŒ¿åè®¿é—®
                .antMatchers("/login", "/register", "/captchaImage","/websocket/**","/postWebsocket/**").permitAll()
                // é™æ€èµ„源,可匿名访问
                .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
                // é™¤ä¸Šé¢å¤–的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                .and()
                .headers().frameOptions().disable();
        // æ·»åŠ Logout filter
        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
        // æ·»åŠ JWT filter
        httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        // æ·»åŠ CORS filter
        httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
        httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
    }
    /**
     * å¼ºæ•£åˆ—哈希加密实现
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder()
    {
        return new BCryptPasswordEncoder();
    }
    /**
     * èº«ä»½è®¤è¯æŽ¥å£
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/ServerConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.jcdm.framework.config;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.jcdm.common.utils.ServletUtils;
/**
 * æœåŠ¡ç›¸å…³é…ç½®
 *
 * @author jc
 */
@Component
public class ServerConfig
{
    /**
     * èŽ·å–完整的请求路径,包括:域名,端口,上下文访问路径
     *
     * @return æœåŠ¡åœ°å€
     */
    public String getUrl()
    {
        HttpServletRequest request = ServletUtils.getRequest();
        return getDomain(request);
    }
    public static String getDomain(HttpServletRequest request)
    {
        StringBuffer url = request.getRequestURL();
        String contextPath = request.getServletContext().getContextPath();
        return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/ThreadPoolConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
package com.jcdm.framework.config;
import com.jcdm.common.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
 * çº¿ç¨‹æ± é…ç½®
 *
 * @author jc
 **/
@Configuration
public class ThreadPoolConfig
{
    // æ ¸å¿ƒçº¿ç¨‹æ± å¤§å°
    private int corePoolSize = 50;
    // æœ€å¤§å¯åˆ›å»ºçš„线程数
    private int maxPoolSize = 200;
    // é˜Ÿåˆ—最大长度
    private int queueCapacity = 1000;
    // çº¿ç¨‹æ± ç»´æŠ¤çº¿ç¨‹æ‰€å…è®¸çš„空闲时间
    private int keepAliveSeconds = 300;
    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
    {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // çº¿ç¨‹æ± å¯¹æ‹’绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
    /**
     * æ‰§è¡Œå‘¨æœŸæ€§æˆ–定时任务
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService()
    {
        return new ScheduledThreadPoolExecutor(corePoolSize,
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
                new ThreadPoolExecutor.CallerRunsPolicy())
        {
            @Override
            protected void afterExecute(Runnable r, Throwable t)
            {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/properties/DruidProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
package com.jcdm.framework.config.properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
/**
 * druid é…ç½®å±žæ€§
 *
 * @author jc
 */
@Configuration
public class DruidProperties
{
    @Value("${spring.datasource.druid.initialSize}")
    private int initialSize;
    @Value("${spring.datasource.druid.minIdle}")
    private int minIdle;
    @Value("${spring.datasource.druid.maxActive}")
    private int maxActive;
    @Value("${spring.datasource.druid.maxWait}")
    private int maxWait;
    @Value("${spring.datasource.druid.connectTimeout}")
    private int connectTimeout;
    @Value("${spring.datasource.druid.socketTimeout}")
    private int socketTimeout;
    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;
    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;
    @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
    private int maxEvictableIdleTimeMillis;
    @Value("${spring.datasource.druid.validationQuery}")
    private String validationQuery;
    @Value("${spring.datasource.druid.testWhileIdle}")
    private boolean testWhileIdle;
    @Value("${spring.datasource.druid.testOnBorrow}")
    private boolean testOnBorrow;
    @Value("${spring.datasource.druid.testOnReturn}")
    private boolean testOnReturn;
    public DruidDataSource dataSource(DruidDataSource datasource)
    {
        /** é…ç½®åˆå§‹åŒ–大小、最小、最大 */
        datasource.setInitialSize(initialSize);
        datasource.setMaxActive(maxActive);
        datasource.setMinIdle(minIdle);
        /** é…ç½®èŽ·å–连接等待超时的时间 */
        datasource.setMaxWait(maxWait);
        /** é…ç½®é©±åŠ¨è¿žæŽ¥è¶…时时间,检测数据库建立连接的超时时间,单位是毫秒 */
        datasource.setConnectTimeout(connectTimeout);
        /** é…ç½®ç½‘络超时时间,等待数据库操作完成的网络超时时间,单位是毫秒 */
        datasource.setSocketTimeout(socketTimeout);
        /** é…ç½®é—´éš”多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        /** é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å°ã€æœ€å¤§ç”Ÿå­˜çš„时间,单位是毫秒 */
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
        /**
         * ç”¨æ¥æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆçš„sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
         */
        datasource.setValidationQuery(validationQuery);
        /** å»ºè®®é…ç½®ä¸ºtrue,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
        datasource.setTestWhileIdle(testWhileIdle);
        /** ç”³è¯·è¿žæŽ¥æ—¶æ‰§è¡ŒvalidationQuery检测连接是否有效,做了这个配置会降低性能。 */
        datasource.setTestOnBorrow(testOnBorrow);
        /** å½’还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
        datasource.setTestOnReturn(testOnReturn);
        return datasource;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/config/properties/PermitAllUrlProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
package com.jcdm.framework.config.properties;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import org.apache.commons.lang3.RegExUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import com.jcdm.common.annotation.Anonymous;
/**
 * è®¾ç½®Anonymous注解允许匿名访问的url
 *
 * @author jc
 */
@Configuration
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
{
    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
    private ApplicationContext applicationContext;
    private List<String> urls = new ArrayList<>();
    public String ASTERISK = "*";
    @Override
    public void afterPropertiesSet()
    {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        map.keySet().forEach(info -> {
            HandlerMethod handlerMethod = map.get(info);
            // èŽ·å–方法上边的注解 æ›¿ä»£path variable ä¸º *
            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
            // èŽ·å–类上边的注解, æ›¿ä»£path variable ä¸º *
            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
        });
    }
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException
    {
        this.applicationContext = context;
    }
    public List<String> getUrls()
    {
        return urls;
    }
    public void setUrls(List<String> urls)
    {
        this.urls = urls;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSource.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.jcdm.framework.datasource;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
 * åŠ¨æ€æ•°æ®æº
 *
 * @author jc
 */
public class DynamicDataSource extends AbstractRoutingDataSource
{
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
    {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
    @Override
    protected Object determineCurrentLookupKey()
    {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/datasource/DynamicDataSourceContextHolder.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.jcdm.framework.datasource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * æ•°æ®æºåˆ‡æ¢å¤„理
 *
 * @author jc
 */
public class DynamicDataSourceContextHolder
{
    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
    /**
     * ä½¿ç”¨ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
     * æ‰€ä»¥æ¯ä¸€ä¸ªçº¿ç¨‹éƒ½å¯ä»¥ç‹¬ç«‹åœ°æ”¹å˜è‡ªå·±çš„副本,而不会影响其它线程所对应的副本。
     */
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
    /**
     * è®¾ç½®æ•°æ®æºçš„变量
     */
    public static void setDataSourceType(String dsType)
    {
        log.info("切换到{}数据源", dsType);
        CONTEXT_HOLDER.set(dsType);
    }
    /**
     * èŽ·å¾—数据源的变量
     */
    public static String getDataSourceType()
    {
        return CONTEXT_HOLDER.get();
    }
    /**
     * æ¸…空数据源变量
     */
    public static void clearDataSourceType()
    {
        CONTEXT_HOLDER.remove();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/interceptor/RepeatSubmitInterceptor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.jcdm.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.HandlerInterceptor;
import com.alibaba.fastjson2.JSON;
import com.jcdm.common.annotation.RepeatSubmit;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.utils.ServletUtils;
/**
 * é˜²æ­¢é‡å¤æäº¤æ‹¦æˆªå™¨
 *
 * @author jc
 */
@Component
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
{
    @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, annotation))
                {
                    AjaxResult ajaxResult = AjaxResult.error(annotation.message());
                    ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
                    return false;
                }
            }
            return true;
        }
        else
        {
            return true;
        }
    }
    /**
     * éªŒè¯æ˜¯å¦é‡å¤æäº¤ç”±å­ç±»å®žçŽ°å…·ä½“的防重复提交的规则
     *
     * @param request è¯·æ±‚信息
     * @param annotation é˜²é‡å¤æ³¨è§£å‚æ•°
     * @return ç»“æžœ
     * @throws Exception
     */
    public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
}
jcdm-framework/src/main/java/com/jcdm/framework/interceptor/impl/SameUrlDataInterceptor.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
package com.jcdm.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.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson2.JSON;
import com.jcdm.common.annotation.RepeatSubmit;
import com.jcdm.common.constant.CacheConstants;
import com.jcdm.common.core.redis.RedisCache;
import com.jcdm.common.filter.RepeatedlyRequestWrapper;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.http.HttpHelper;
import com.jcdm.framework.interceptor.RepeatSubmitInterceptor;
/**
 * åˆ¤æ–­è¯·æ±‚url和数据是否和上一次相同,
 * å¦‚果和上次相同,则是重复提交表单。 æœ‰æ•ˆæ—¶é—´ä¸º10秒内。
 *
 * @author jc
 */
@Component
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
{
    public final String REPEAT_PARAMS = "repeatParams";
    public final String REPEAT_TIME = "repeatTime";
    // ä»¤ç‰Œè‡ªå®šä¹‰æ ‡è¯†
    @Value("${token.header}")
    private String header;
    @Autowired
    private RedisCache redisCache;
    @SuppressWarnings("unchecked")
    @Override
    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
    {
        String nowParams = "";
        if (request instanceof RepeatedlyRequestWrapper)
        {
            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
        }
        // body参数为空,获取Parameter的数据
        if (StringUtils.isEmpty(nowParams))
        {
            nowParams = JSON.toJSONString(request.getParameterMap());
        }
        Map<String, Object> nowDataMap = new HashMap<String, Object>();
        nowDataMap.put(REPEAT_PARAMS, nowParams);
        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
        // è¯·æ±‚地址(作为存放cache的key值)
        String url = request.getRequestURI();
        // å”¯ä¸€å€¼ï¼ˆæ²¡æœ‰æ¶ˆæ¯å¤´åˆ™ä½¿ç”¨è¯·æ±‚地址)
        String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
        // å”¯ä¸€æ ‡è¯†ï¼ˆæŒ‡å®škey + url + æ¶ˆæ¯å¤´ï¼‰
        String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
        Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
        if (sessionObj != null)
        {
            Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
            if (sessionMap.containsKey(url))
            {
                Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
                {
                    return true;
                }
            }
        }
        Map<String, Object> cacheMap = new HashMap<String, Object>();
        cacheMap.put(url, nowDataMap);
        redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
        return false;
    }
    /**
     * åˆ¤æ–­å‚数是否相同
     */
    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
    {
        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
        String preParams = (String) preMap.get(REPEAT_PARAMS);
        return nowParams.equals(preParams);
    }
    /**
     * åˆ¤æ–­ä¸¤æ¬¡é—´éš”时间
     */
    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
    {
        long time1 = (Long) nowMap.get(REPEAT_TIME);
        long time2 = (Long) preMap.get(REPEAT_TIME);
        if ((time1 - time2) < interval)
        {
            return true;
        }
        return false;
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/manager/AsyncManager.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.jcdm.framework.manager;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.jcdm.common.utils.Threads;
import com.jcdm.common.utils.spring.SpringUtils;
/**
 * å¼‚步任务管理器
 *
 * @author jc
 */
public class AsyncManager
{
    /**
     * æ“ä½œå»¶è¿Ÿ10毫秒
     */
    private final int OPERATE_DELAY_TIME = 10;
    /**
     * å¼‚步操作任务调度线程池
     */
    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
    /**
     * å•ä¾‹æ¨¡å¼
     */
    private AsyncManager(){}
    private static AsyncManager me = new AsyncManager();
    public static AsyncManager me()
    {
        return me;
    }
    /**
     * æ‰§è¡Œä»»åŠ¡
     *
     * @param task ä»»åŠ¡
     */
    public void execute(TimerTask task)
    {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }
    /**
     * åœæ­¢ä»»åŠ¡çº¿ç¨‹æ± 
     */
    public void shutdown()
    {
        Threads.shutdownAndAwaitTermination(executor);
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/manager/ShutdownManager.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.jcdm.framework.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
/**
 * ç¡®ä¿åº”用退出时能关闭后台线程
 *
 * @author jc
 */
@Component
public class ShutdownManager
{
    private static final Logger logger = LoggerFactory.getLogger("sys-user");
    @PreDestroy
    public void destroy()
    {
        shutdownAsyncManager();
    }
    /**
     * åœæ­¢å¼‚步执行任务
     */
    private void shutdownAsyncManager()
    {
        try
        {
            logger.info("====关闭后台任务任务线程池====");
            AsyncManager.me().shutdown();
        }
        catch (Exception e)
        {
            logger.error(e.getMessage(), e);
        }
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/manager/factory/AsyncFactory.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,102 @@
package com.jcdm.framework.manager.factory;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcdm.common.constant.Constants;
import com.jcdm.common.utils.LogUtils;
import com.jcdm.common.utils.ServletUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.common.utils.ip.AddressUtils;
import com.jcdm.common.utils.ip.IpUtils;
import com.jcdm.common.utils.spring.SpringUtils;
import com.jcdm.system.domain.SysLogininfor;
import com.jcdm.system.domain.SysOperLog;
import com.jcdm.system.service.ISysLogininforService;
import com.jcdm.system.service.ISysOperLogService;
import eu.bitwalker.useragentutils.UserAgent;
/**
 * å¼‚步工厂(产生任务用)
 *
 * @author jc
 */
public class AsyncFactory
{
    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
    /**
     * è®°å½•ç™»å½•ä¿¡æ¯
     *
     * @param username ç”¨æˆ·å
     * @param status çŠ¶æ€
     * @param message æ¶ˆæ¯
     * @param args åˆ—表
     * @return ä»»åŠ¡task
     */
    public static TimerTask recordLogininfor(final String username, final String status, final String message,
            final Object... args)
    {
        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        final String ip = IpUtils.getIpAddr();
        return new TimerTask()
        {
            @Override
            public void run()
            {
                String address = AddressUtils.getRealAddressByIP(ip);
                StringBuilder s = new StringBuilder();
                s.append(LogUtils.getBlock(ip));
                s.append(address);
                s.append(LogUtils.getBlock(username));
                s.append(LogUtils.getBlock(status));
                s.append(LogUtils.getBlock(message));
                // æ‰“印信息到日志
                sys_user_logger.info(s.toString(), args);
                // èŽ·å–客户端操作系统
                String os = userAgent.getOperatingSystem().getName();
                // èŽ·å–客户端浏览器
                String browser = userAgent.getBrowser().getName();
                // å°è£…对象
                SysLogininfor logininfor = new SysLogininfor();
                logininfor.setUserName(username);
                logininfor.setIpaddr(ip);
                logininfor.setLoginLocation(address);
                logininfor.setBrowser(browser);
                logininfor.setOs(os);
                logininfor.setMsg(message);
                // æ—¥å¿—状态
                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
                {
                    logininfor.setStatus(Constants.SUCCESS);
                }
                else if (Constants.LOGIN_FAIL.equals(status))
                {
                    logininfor.setStatus(Constants.FAIL);
                }
                // æ’入数据
                SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
            }
        };
    }
    /**
     * æ“ä½œæ—¥å¿—记录
     *
     * @param operLog æ“ä½œæ—¥å¿—信息
     * @return ä»»åŠ¡task
     */
    public static TimerTask recordOper(final SysOperLog operLog)
    {
        return new TimerTask()
        {
            @Override
            public void run()
            {
                // è¿œç¨‹æŸ¥è¯¢æ“ä½œåœ°ç‚¹
                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
            }
        };
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/security/context/AuthenticationContextHolder.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.jcdm.framework.security.context;
import org.springframework.security.core.Authentication;
/**
 * èº«ä»½éªŒè¯ä¿¡æ¯
 *
 * @author jc
 */
public class AuthenticationContextHolder
{
    private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
    public static Authentication getContext()
    {
        return contextHolder.get();
    }
    public static void setContext(Authentication context)
    {
        contextHolder.set(context);
    }
    public static void clearContext()
    {
        contextHolder.remove();
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/security/context/PermissionContextHolder.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.jcdm.framework.security.context;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.jcdm.common.core.text.Convert;
/**
 * æƒé™ä¿¡æ¯
 *
 * @author jc
 */
public class PermissionContextHolder
{
    private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
    public static void setContext(String permission)
    {
        RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
                RequestAttributes.SCOPE_REQUEST);
    }
    public static String getContext()
    {
        return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
                RequestAttributes.SCOPE_REQUEST));
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/security/filter/JwtAuthenticationTokenFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.jcdm.framework.security.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.jcdm.common.core.domain.model.LoginUser;
import com.jcdm.common.utils.SecurityUtils;
import com.jcdm.common.utils.StringUtils;
import com.jcdm.framework.web.service.TokenService;
/**
 * token过滤器 éªŒè¯token有效性
 *
 * @author jc
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{
    @Autowired
    private TokenService tokenService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException
    {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
        {
            tokenService.verifyToken(loginUser);
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        chain.doFilter(request, response);
    }
}
jcdm-framework/src/main/java/com/jcdm/framework/security/handle/AuthenticationEntryPointImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.jcdm.framework.security.handle;
import java.io.IOException;
import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson2.JSON;
import com.jcdm.common.constant.HttpStatus;
import com.jcdm.common.core.domain.AjaxResult;
import com.jcdm.common.utils.ServletUtils;
import com.jcdm.common.utils.StringUtils;
/**
 * è®¤è¯å¤±è´¥å¤„理类 è¿”回未授权
 *
 * @author jc
 */
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
{
    private static final long serialVersionUID = -8970718410437077606L;
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
            throws IOException
    {
        int code = HttpStatus.UNAUTHORIZED;
        String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
    }
}
在上述文件截断后对比
jcdm-framework/src/main/java/com/jcdm/framework/security/handle/LogoutSuccessHandlerImpl.java jcdm-framework/src/main/java/com/jcdm/framework/web/domain/Server.java jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Cpu.java jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Jvm.java jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Mem.java jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/Sys.java jcdm-framework/src/main/java/com/jcdm/framework/web/domain/server/SysFile.java jcdm-framework/src/main/java/com/jcdm/framework/web/exception/GlobalExceptionHandler.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/PermissionService.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysLoginService.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPasswordService.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysPermissionService.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/SysRegisterService.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/TokenService.java jcdm-framework/src/main/java/com/jcdm/framework/web/service/UserDetailsServiceImpl.java jcdm-framework/src/main/java/com/jcdm/framework/websocket/PostController.java jcdm-framework/src/main/java/com/jcdm/framework/websocket/SemaphoreUtils.java jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketConfig.java jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketServer.java jcdm-framework/src/main/java/com/jcdm/framework/websocket/WebSocketUsers.java jcdm-generator/pom.xml jcdm-generator/src/main/java/com/jcdm/generator/config/GenConfig.java jcdm-generator/src/main/java/com/jcdm/generator/controller/GenController.java jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTable.java jcdm-generator/src/main/java/com/jcdm/generator/domain/GenTableColumn.java jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableColumnMapper.java jcdm-generator/src/main/java/com/jcdm/generator/mapper/GenTableMapper.java jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableColumnServiceImpl.java jcdm-generator/src/main/java/com/jcdm/generator/service/GenTableServiceImpl.java jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableColumnService.java jcdm-generator/src/main/java/com/jcdm/generator/service/IGenTableService.java jcdm-generator/src/main/java/com/jcdm/generator/util/GenUtils.java jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityInitializer.java jcdm-generator/src/main/java/com/jcdm/generator/util/VelocityUtils.java jcdm-generator/src/main/resources/generator.yml jcdm-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml jcdm-generator/src/main/resources/mapper/generator/GenTableMapper.xml jcdm-generator/src/main/resources/vm/java/controller.java.vm jcdm-generator/src/main/resources/vm/java/domain.java.vm jcdm-generator/src/main/resources/vm/java/mapper.java.vm jcdm-generator/src/main/resources/vm/java/service.java.vm jcdm-generator/src/main/resources/vm/java/serviceImpl.java.vm jcdm-generator/src/main/resources/vm/java/sub-domain.java.vm jcdm-generator/src/main/resources/vm/js/api.js.vm jcdm-generator/src/main/resources/vm/sql/sql.vm jcdm-generator/src/main/resources/vm/vue/index-tree.vue.vm jcdm-generator/src/main/resources/vm/vue/index.vue.vm jcdm-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm jcdm-generator/src/main/resources/vm/vue/v3/index.vue.vm jcdm-generator/src/main/resources/vm/xml/mapper.xml.vm jcdm-main/pom.xml jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/controller/BsBeatSettingController.java jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/domain/BsBeatSetting.java jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/mapper/BsBeatSettingMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/IBsBeatSettingService.java jcdm-main/src/main/java/com/jcdm/main/bs/beatSetting/service/impl/BsBeatSettingServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/formula/controller/BsFormulaInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/formula/domain/BsFormulaInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/formula/mapper/BsFormulaInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/IBsFormulaInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/formula/service/impl/BsFormulaInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/controller/BsFormulaChildInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/domain/BsFormulaChildInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/mapper/BsFormulaChildInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/IBsFormulaChildInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/formulaChild/service/impl/BsFormulaChildInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/controller/BsLineInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/domain/BsLineInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/mapper/BsLineInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/IBsLineInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/lineInfo/service/impl/BsLineInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/material/controller/BsMaterialInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/material/domain/BsMaterialInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/material/mapper/BsMaterialInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/material/service/IBsMaterialInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/material/service/impl/BsMaterialInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/processFile/controller/BsProcessFileController.java jcdm-main/src/main/java/com/jcdm/main/bs/processFile/domain/BsProcessFile.java jcdm-main/src/main/java/com/jcdm/main/bs/processFile/mapper/BsProcessFileMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/IBsProcessFileService.java jcdm-main/src/main/java/com/jcdm/main/bs/processFile/service/impl/BsProcessFileServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/processes/controller/BsProcessesInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/processes/domain/BsProcessesInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/processes/mapper/BsProcessesInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/IBsProcessesInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/processes/service/impl/BsProcessesInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/productBom/controller/BsProductBomInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/productBom/domain/BsProductBomInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/productBom/mapper/BsProductBomInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/IBsProductBomInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/productBom/service/impl/BsProductBomInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/controller/BsProductBomChildInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/domain/BsProductBomChildInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/mapper/BsProductBomChildInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/IBsProductBomChildInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/productBomChild/service/impl/BsProductBomChildInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/controller/BsTechnologyRouteInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/domain/BsTechnologyRouteInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/mapper/BsTechnologyRouteInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/IBsTechnologyRouteInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRoute/service/impl/BsTechnologyRouteInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/controller/BsTechnologyRouteChildInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/domain/BsTechnologyRouteChildInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/mapper/BsTechnologyRouteChildInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/IBsTechnologyRouteChildInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/technologyRouteChild/service/impl/BsTechnologyRouteChildInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/bs/workshop/controller/BsWorkshopInfoController.java jcdm-main/src/main/java/com/jcdm/main/bs/workshop/domain/BsWorkshopInfo.java jcdm-main/src/main/java/com/jcdm/main/bs/workshop/mapper/BsWorkshopInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/IBsWorkshopInfoService.java jcdm-main/src/main/java/com/jcdm/main/bs/workshop/service/impl/BsWorkshopInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/controller/DaCollectionParamConfController.java jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/domain/DaCollectionParamConf.java jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/mapper/DaCollectionParamConfMapper.java jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/IDaCollectionParamConfService.java jcdm-main/src/main/java/com/jcdm/main/da/collectionParamConf/service/impl/DaCollectionParamConfServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/KeyStoreLoader.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/cert/MethodName.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientHandler.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/client/ClientRunner.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/controller/DaOpcuaConfigController.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/DaOpcuaConfig.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/domain/NodeEntity.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/BeanUtils.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/OpcusConfigInit.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/init/Properties.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/mapper/DaOpcuaConfigMapper.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/IDaOpcuaConfigService.java jcdm-main/src/main/java/com/jcdm/main/da/opcuaconfig/service/impl/DaOpcuaConfigServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/controller/DaParamCollectionController.java jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/domain/DaParamCollection.java jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/mapper/DaParamCollectionMapper.java jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/IDaParamCollectionService.java jcdm-main/src/main/java/com/jcdm/main/da/paramCollection/service/impl/DaParamCollectionServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/common/Constants.java jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/controller/DaPassingStationCollectionController.java jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/domain/DaPassingStationCollection.java jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/mapper/DaPassingStationCollectionMapper.java jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/IDaPassingStationCollectionService.java jcdm-main/src/main/java/com/jcdm/main/da/passingStationCollection/service/impl/DaPassingStationCollectionServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/controller/EmEquipmentAlarmController.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/domain/EmEquipmentAlarm.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/mapper/EmEquipmentAlarmMapper.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/IEmEquipmentAlarmService.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentAlarm/service/impl/EmEquipmentAlarmServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/controller/EmEquipmentArchivesController.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/domain/EmEquipmentArchives.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/mapper/EmEquipmentArchivesMapper.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/IEmEquipmentArchivesService.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentArchives/service/impl/EmEquipmentArchivesServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/controller/EmEquipmentStatusController.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/domain/EmEquipmentStatus.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/mapper/EmEquipmentStatusMapper.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/IEmEquipmentStatusService.java jcdm-main/src/main/java/com/jcdm/main/em/equipmentStatus/service/impl/EmEquipmentStatusServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/controller/OmProductionOrdeInfoController.java jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/domain/OmProductionOrdeInfo.java jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/mapper/OmProductionOrdeInfoMapper.java jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/IOmProductionOrdeInfoService.java jcdm-main/src/main/java/com/jcdm/main/om/productionOrde/service/impl/OmProductionOrdeInfoServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/om/workReport/controller/OmWorkReportController.java jcdm-main/src/main/java/com/jcdm/main/om/workReport/domain/OmWorkReport.java jcdm-main/src/main/java/com/jcdm/main/om/workReport/mapper/OmWorkReportMapper.java jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/IOmWorkReportService.java jcdm-main/src/main/java/com/jcdm/main/om/workReport/service/impl/OmWorkReportServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/rm/repairData/controller/RmRepairDataController.java jcdm-main/src/main/java/com/jcdm/main/rm/repairData/domain/RmRepairData.java jcdm-main/src/main/java/com/jcdm/main/rm/repairData/mapper/RmRepairDataMapper.java jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/IRmRepairDataService.java jcdm-main/src/main/java/com/jcdm/main/rm/repairData/service/impl/RmRepairDataServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/controller/RmRepairRecordController.java jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/domain/RmRepairRecord.java jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/mapper/RmRepairRecordMapper.java jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/IRmRepairRecordService.java jcdm-main/src/main/java/com/jcdm/main/rm/repairRecord/service/impl/RmRepairRecordServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/controller/ScStationConfController.java jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/domain/ScStationConf.java jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/mapper/ScStationConfMapper.java jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/IScStationConfService.java jcdm-main/src/main/java/com/jcdm/main/sc/stationConf/service/impl/ScStationConfServiceImpl.java jcdm-main/src/main/java/com/jcdm/main/util/IpInfoUtils.java jcdm-main/src/main/java/com/jcdm/main/webservice/Item.java jcdm-main/src/main/java/com/jcdm/main/webservice/ItemList.java jcdm-main/src/main/java/com/jcdm/main/webservice/test.java jcdm-main/src/main/resources/mapper/bs/beatSetting/BsBeatSettingMapper.xml jcdm-main/src/main/resources/mapper/bs/formula/BsFormulaInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/formulaChild/BsFormulaChildInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/lineInfo/BsLineInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/material/BsMaterialInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/processFile/BsProcessFileMapper.xml jcdm-main/src/main/resources/mapper/bs/processes/BsProcessesInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/productBom/BsProductBomInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/productBomChild/BsProductBomChildInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/technologyRoute/BsTechnologyRouteInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/technologyRouteChild/BsTechnologyRouteChildInfoMapper.xml jcdm-main/src/main/resources/mapper/bs/workshop/BsWorkshopInfoMapper.xml jcdm-main/src/main/resources/mapper/da/collectionParamConf/DaCollectionParamConfMapper.xml jcdm-main/src/main/resources/mapper/da/opcuaconfig/DaOpcuaConfigMapper.xml jcdm-main/src/main/resources/mapper/da/paramCollection/DaParamCollectionMapper.xml jcdm-main/src/main/resources/mapper/da/passingStationCollection/DaPassingStationCollectionMapper.xml jcdm-main/src/main/resources/mapper/em/equipmentAlarm/EmEquipmentAlarmMapper.xml jcdm-main/src/main/resources/mapper/em/equipmentArchives/EmEquipmentArchivesMapper.xml jcdm-main/src/main/resources/mapper/em/equipmentStatus/EmEquipmentStatusMapper.xml jcdm-main/src/main/resources/mapper/om/productionOrde/OmProductionOrdeInfoMapper.xml jcdm-main/src/main/resources/mapper/om/workReport/OmWorkReportMapper.xml jcdm-main/src/main/resources/mapper/rm/repairData/RmRepairDataMapper.xml jcdm-main/src/main/resources/mapper/rm/repairRecord/RmRepairRecordMapper.xml jcdm-main/src/main/resources/mapper/sc/stationConf/ScStationConfMapper.xml jcdm-main/src/main/resources/opcua.properties jcdm-quartz/pom.xml jcdm-quartz/src/main/java/com/jcdm/quartz/config/ScheduleConfig.java jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobController.java jcdm-quartz/src/main/java/com/jcdm/quartz/controller/SysJobLogController.java jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJob.java jcdm-quartz/src/main/java/com/jcdm/quartz/domain/SysJobLog.java jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobLogMapper.java jcdm-quartz/src/main/java/com/jcdm/quartz/mapper/SysJobMapper.java jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobLogService.java jcdm-quartz/src/main/java/com/jcdm/quartz/service/ISysJobService.java jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobLogServiceImpl.java jcdm-quartz/src/main/java/com/jcdm/quartz/service/impl/SysJobServiceImpl.java jcdm-quartz/src/main/java/com/jcdm/quartz/task/RyTask.java jcdm-quartz/src/main/java/com/jcdm/quartz/util/AbstractQuartzJob.java jcdm-quartz/src/main/java/com/jcdm/quartz/util/CronUtils.java jcdm-quartz/src/main/java/com/jcdm/quartz/util/JobInvokeUtil.java jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzDisallowConcurrentExecution.java jcdm-quartz/src/main/java/com/jcdm/quartz/util/QuartzJobExecution.java jcdm-quartz/src/main/java/com/jcdm/quartz/util/ScheduleUtils.java jcdm-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml jcdm-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml jcdm-system/pom.xml jcdm-system/src/main/java/com/jcdm/system/domain/SysCache.java jcdm-system/src/main/java/com/jcdm/system/domain/SysConfig.java jcdm-system/src/main/java/com/jcdm/system/domain/SysLogininfor.java jcdm-system/src/main/java/com/jcdm/system/domain/SysNotice.java jcdm-system/src/main/java/com/jcdm/system/domain/SysOperLog.java jcdm-system/src/main/java/com/jcdm/system/domain/SysPost.java jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleDept.java jcdm-system/src/main/java/com/jcdm/system/domain/SysRoleMenu.java jcdm-system/src/main/java/com/jcdm/system/domain/SysUserOnline.java jcdm-system/src/main/java/com/jcdm/system/domain/SysUserPost.java jcdm-system/src/main/java/com/jcdm/system/domain/SysUserRole.java jcdm-system/src/main/java/com/jcdm/system/domain/vo/MetaVo.java jcdm-system/src/main/java/com/jcdm/system/domain/vo/RouterVo.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysConfigMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysDeptMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictDataMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysDictTypeMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysLogininforMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysMenuMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysNoticeMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysOperLogMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysPostMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleDeptMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysRoleMenuMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserPostMapper.java jcdm-system/src/main/java/com/jcdm/system/mapper/SysUserRoleMapper.java jcdm-system/src/main/java/com/jcdm/system/service/ISysConfigService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysDeptService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysDictDataService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysDictTypeService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysLogininforService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysMenuService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysNoticeService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysOperLogService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysPostService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysRoleService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysUserOnlineService.java jcdm-system/src/main/java/com/jcdm/system/service/ISysUserService.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysConfigServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDeptServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictDataServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysDictTypeServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysLogininforServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysMenuServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysNoticeServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysOperLogServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysPostServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysRoleServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserOnlineServiceImpl.java jcdm-system/src/main/java/com/jcdm/system/service/impl/SysUserServiceImpl.java jcdm-system/src/main/resources/mapper/system/SysConfigMapper.xml jcdm-system/src/main/resources/mapper/system/SysDeptMapper.xml jcdm-system/src/main/resources/mapper/system/SysDictDataMapper.xml jcdm-system/src/main/resources/mapper/system/SysDictTypeMapper.xml jcdm-system/src/main/resources/mapper/system/SysLogininforMapper.xml jcdm-system/src/main/resources/mapper/system/SysMenuMapper.xml jcdm-system/src/main/resources/mapper/system/SysNoticeMapper.xml jcdm-system/src/main/resources/mapper/system/SysOperLogMapper.xml jcdm-system/src/main/resources/mapper/system/SysPostMapper.xml jcdm-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml jcdm-system/src/main/resources/mapper/system/SysRoleMapper.xml jcdm-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml jcdm-system/src/main/resources/mapper/system/SysUserMapper.xml jcdm-system/src/main/resources/mapper/system/SysUserPostMapper.xml jcdm-system/src/main/resources/mapper/system/SysUserRoleMapper.xml jcdm-ui/.editorconfig jcdm-ui/.env.development jcdm-ui/.env.production jcdm-ui/.env.staging jcdm-ui/.eslintignore jcdm-ui/.eslintrc.js jcdm-ui/.gitignore jcdm-ui/README.md jcdm-ui/babel.config.js jcdm-ui/bin/build.bat jcdm-ui/bin/package.bat jcdm-ui/bin/run-web.bat jcdm-ui/build/index.js jcdm-ui/dist.rar jcdm-ui/package.json jcdm-ui/public/favicon.ico jcdm-ui/public/html/ie.html jcdm-ui/public/index.html jcdm-ui/public/robots.txt jcdm-ui/src/App.vue jcdm-ui/src/api/login.js jcdm-ui/src/api/main/bs/ProductBom/ProductBom.js jcdm-ui/src/api/main/bs/ProductBomChild/ProductBomChild.js jcdm-ui/src/api/main/bs/beatSetting/beatSetting.js jcdm-ui/src/api/main/bs/formula/formula.js jcdm-ui/src/api/main/bs/formulaChild/formulaChild.js jcdm-ui/src/api/main/bs/lineInfo/lineInfo.js jcdm-ui/src/api/main/bs/material/material.js jcdm-ui/src/api/main/bs/processFile/processFile.js jcdm-ui/src/api/main/bs/processes/processes.js jcdm-ui/src/api/main/bs/technologyRoute/technologyRoute.js jcdm-ui/src/api/main/bs/technologyRouteChild/technologyRouteChild.js jcdm-ui/src/api/main/bs/workshop/workshop.js jcdm-ui/src/api/main/da/collectionParamConf/collectionParamConf.js jcdm-ui/src/api/main/da/opcuaconfig/opcuaconfig.js jcdm-ui/src/api/main/da/paramCollection/paramCollection.js jcdm-ui/src/api/main/da/passingStationCollection/passingStationCollection.js jcdm-ui/src/api/main/em/equipmentAlarm/equipmentAlarm.js jcdm-ui/src/api/main/em/equipmentArchives/equipmentArchives.js jcdm-ui/src/api/main/em/equipmentStatus/equipmentStatus.js jcdm-ui/src/api/main/om/productionOrde/productionOrde.js jcdm-ui/src/api/main/om/workReport/workReport.js jcdm-ui/src/api/main/rm/repairData/repairData.js jcdm-ui/src/api/main/rm/repairRecord/repairRecord.js jcdm-ui/src/api/main/sc/stationConf.js jcdm-ui/src/api/menu.js jcdm-ui/src/api/monitor/cache.js jcdm-ui/src/api/monitor/job.js jcdm-ui/src/api/monitor/jobLog.js jcdm-ui/src/api/monitor/logininfor.js jcdm-ui/src/api/monitor/online.js jcdm-ui/src/api/monitor/operlog.js jcdm-ui/src/api/monitor/server.js jcdm-ui/src/api/system/config.js jcdm-ui/src/api/system/dept.js jcdm-ui/src/api/system/dict/data.js jcdm-ui/src/api/system/dict/type.js jcdm-ui/src/api/system/menu.js jcdm-ui/src/api/system/notice.js jcdm-ui/src/api/system/post.js jcdm-ui/src/api/system/role.js jcdm-ui/src/api/system/user.js jcdm-ui/src/api/tool/gen.js jcdm-ui/src/assets/401_images/401.gif jcdm-ui/src/assets/404_images/404.png jcdm-ui/src/assets/404_images/404_cloud.png jcdm-ui/src/assets/icons/index.js jcdm-ui/src/assets/icons/svg/404.svg jcdm-ui/src/assets/icons/svg/bug.svg jcdm-ui/src/assets/icons/svg/build.svg jcdm-ui/src/assets/icons/svg/button.svg jcdm-ui/src/assets/icons/svg/cascader.svg jcdm-ui/src/assets/icons/svg/chart.svg jcdm-ui/src/assets/icons/svg/checkbox.svg jcdm-ui/src/assets/icons/svg/clipboard.svg jcdm-ui/src/assets/icons/svg/code.svg jcdm-ui/src/assets/icons/svg/color.svg jcdm-ui/src/assets/icons/svg/component.svg jcdm-ui/src/assets/icons/svg/dashboard.svg jcdm-ui/src/assets/icons/svg/date-range.svg jcdm-ui/src/assets/icons/svg/date.svg jcdm-ui/src/assets/icons/svg/dict.svg jcdm-ui/src/assets/icons/svg/documentation.svg jcdm-ui/src/assets/icons/svg/download.svg jcdm-ui/src/assets/icons/svg/drag.svg jcdm-ui/src/assets/icons/svg/druid.svg jcdm-ui/src/assets/icons/svg/edit.svg jcdm-ui/src/assets/icons/svg/education.svg jcdm-ui/src/assets/icons/svg/email.svg jcdm-ui/src/assets/icons/svg/example.svg jcdm-ui/src/assets/icons/svg/excel.svg jcdm-ui/src/assets/icons/svg/exit-fullscreen.svg jcdm-ui/src/assets/icons/svg/eye-open.svg jcdm-ui/src/assets/icons/svg/eye.svg jcdm-ui/src/assets/icons/svg/form.svg jcdm-ui/src/assets/icons/svg/fullscreen.svg jcdm-ui/src/assets/icons/svg/github.svg jcdm-ui/src/assets/icons/svg/guide.svg jcdm-ui/src/assets/icons/svg/icon.svg jcdm-ui/src/assets/icons/svg/input.svg jcdm-ui/src/assets/icons/svg/international.svg jcdm-ui/src/assets/icons/svg/job.svg jcdm-ui/src/assets/icons/svg/language.svg jcdm-ui/src/assets/icons/svg/link.svg jcdm-ui/src/assets/icons/svg/list.svg jcdm-ui/src/assets/icons/svg/lock.svg jcdm-ui/src/assets/icons/svg/log.svg jcdm-ui/src/assets/icons/svg/logininfor.svg jcdm-ui/src/assets/icons/svg/message.svg jcdm-ui/src/assets/icons/svg/money.svg jcdm-ui/src/assets/icons/svg/monitor.svg jcdm-ui/src/assets/icons/svg/nested.svg jcdm-ui/src/assets/icons/svg/number.svg jcdm-ui/src/assets/icons/svg/online.svg jcdm-ui/src/assets/icons/svg/password.svg jcdm-ui/src/assets/icons/svg/pdf.svg jcdm-ui/src/assets/icons/svg/people.svg jcdm-ui/src/assets/icons/svg/peoples.svg jcdm-ui/src/assets/icons/svg/phone.svg jcdm-ui/src/assets/icons/svg/post.svg jcdm-ui/src/assets/icons/svg/qq.svg jcdm-ui/src/assets/icons/svg/question.svg jcdm-ui/src/assets/icons/svg/radio.svg jcdm-ui/src/assets/icons/svg/rate.svg jcdm-ui/src/assets/icons/svg/redis-list.svg jcdm-ui/src/assets/icons/svg/redis.svg jcdm-ui/src/assets/icons/svg/row.svg jcdm-ui/src/assets/icons/svg/search.svg jcdm-ui/src/assets/icons/svg/select.svg jcdm-ui/src/assets/icons/svg/server.svg jcdm-ui/src/assets/icons/svg/shopping.svg jcdm-ui/src/assets/icons/svg/size.svg jcdm-ui/src/assets/icons/svg/skill.svg jcdm-ui/src/assets/icons/svg/slider.svg jcdm-ui/src/assets/icons/svg/star.svg jcdm-ui/src/assets/icons/svg/swagger.svg jcdm-ui/src/assets/icons/svg/switch.svg jcdm-ui/src/assets/icons/svg/system.svg jcdm-ui/src/assets/icons/svg/tab.svg jcdm-ui/src/assets/icons/svg/table.svg jcdm-ui/src/assets/icons/svg/textarea.svg jcdm-ui/src/assets/icons/svg/theme.svg jcdm-ui/src/assets/icons/svg/time-range.svg jcdm-ui/src/assets/icons/svg/time.svg jcdm-ui/src/assets/icons/svg/tool.svg jcdm-ui/src/assets/icons/svg/tree-table.svg jcdm-ui/src/assets/icons/svg/tree.svg jcdm-ui/src/assets/icons/svg/upload.svg jcdm-ui/src/assets/icons/svg/user.svg jcdm-ui/src/assets/icons/svg/validCode.svg jcdm-ui/src/assets/icons/svg/wechat.svg jcdm-ui/src/assets/icons/svg/zip.svg jcdm-ui/src/assets/icons/svgo.yml jcdm-ui/src/assets/images/dark.svg jcdm-ui/src/assets/images/light.svg jcdm-ui/src/assets/images/login-background.jpg jcdm-ui/src/assets/images/login-background.png jcdm-ui/src/assets/images/login-background1.png jcdm-ui/src/assets/images/pay.png jcdm-ui/src/assets/images/profile.jpg jcdm-ui/src/assets/logo/logo.png jcdm-ui/src/assets/styles/btn.scss jcdm-ui/src/assets/styles/element-ui.scss jcdm-ui/src/assets/styles/element-variables.scss jcdm-ui/src/assets/styles/index.scss jcdm-ui/src/assets/styles/mixin.scss jcdm-ui/src/assets/styles/ruoyi.scss jcdm-ui/src/assets/styles/sidebar.scss jcdm-ui/src/assets/styles/transition.scss jcdm-ui/src/assets/styles/variables.scss jcdm-ui/src/components/Breadcrumb/index.vue jcdm-ui/src/components/Crontab/day.vue jcdm-ui/src/components/Crontab/hour.vue jcdm-ui/src/components/Crontab/index.vue jcdm-ui/src/components/Crontab/min.vue jcdm-ui/src/components/Crontab/month.vue jcdm-ui/src/components/Crontab/result.vue jcdm-ui/src/components/Crontab/second.vue jcdm-ui/src/components/Crontab/week.vue jcdm-ui/src/components/Crontab/year.vue jcdm-ui/src/components/DictData/index.js jcdm-ui/src/components/DictTag/index.vue jcdm-ui/src/components/Editor/index.vue jcdm-ui/src/components/FileUpload/index.vue jcdm-ui/src/components/Hamburger/index.vue jcdm-ui/src/components/HeaderSearch/index.vue jcdm-ui/src/components/IconSelect/index.vue jcdm-ui/src/components/IconSelect/requireIcons.js jcdm-ui/src/components/ImagePreview/index.vue jcdm-ui/src/components/ImageUpload/index.vue jcdm-ui/src/components/Pagination/index.vue jcdm-ui/src/components/PanThumb/index.vue jcdm-ui/src/components/ParentView/index.vue jcdm-ui/src/components/RightPanel/index.vue jcdm-ui/src/components/RightToolbar/index.vue jcdm-ui/src/components/RuoYi/Doc/index.vue jcdm-ui/src/components/RuoYi/Git/index.vue jcdm-ui/src/components/Screenfull/index.vue jcdm-ui/src/components/SizeSelect/index.vue jcdm-ui/src/components/SvgIcon/index.vue jcdm-ui/src/components/ThemePicker/index.vue jcdm-ui/src/components/TopNav/index.vue jcdm-ui/src/components/iFrame/index.vue jcdm-ui/src/components/itemSelect/index.vue jcdm-ui/src/components/itemSelect/single.vue jcdm-ui/src/directive/dialog/drag.js jcdm-ui/src/directive/dialog/dragHeight.js jcdm-ui/src/directive/dialog/dragWidth.js jcdm-ui/src/directive/index.js jcdm-ui/src/directive/module/clipboard.js jcdm-ui/src/directive/permission/hasPermi.js jcdm-ui/src/directive/permission/hasRole.js jcdm-ui/src/layout/components/AppMain.vue jcdm-ui/src/layout/components/IframeToggle/index.vue jcdm-ui/src/layout/components/InnerLink/index.vue jcdm-ui/src/layout/components/Navbar.vue jcdm-ui/src/layout/components/Settings/index.vue jcdm-ui/src/layout/components/Sidebar/FixiOSBug.js jcdm-ui/src/layout/components/Sidebar/Item.vue jcdm-ui/src/layout/components/Sidebar/Link.vue jcdm-ui/src/layout/components/Sidebar/Logo.vue jcdm-ui/src/layout/components/Sidebar/SidebarItem.vue jcdm-ui/src/layout/components/Sidebar/index.vue jcdm-ui/src/layout/components/TagsView/ScrollPane.vue jcdm-ui/src/layout/components/TagsView/index.vue jcdm-ui/src/layout/components/index.js jcdm-ui/src/layout/index.vue jcdm-ui/src/layout/mixin/ResizeHandler.js jcdm-ui/src/main.js jcdm-ui/src/permission.js jcdm-ui/src/plugins/auth.js jcdm-ui/src/plugins/cache.js jcdm-ui/src/plugins/download.js jcdm-ui/src/plugins/index.js jcdm-ui/src/plugins/modal.js jcdm-ui/src/plugins/tab.js jcdm-ui/src/router/directives.js jcdm-ui/src/router/index.js jcdm-ui/src/settings.js jcdm-ui/src/store/getters.js jcdm-ui/src/store/index.js jcdm-ui/src/store/modules/app.js jcdm-ui/src/store/modules/dict.js jcdm-ui/src/store/modules/permission.js jcdm-ui/src/store/modules/settings.js jcdm-ui/src/store/modules/tagsView.js jcdm-ui/src/store/modules/user.js jcdm-ui/src/utils/auth.js jcdm-ui/src/utils/dict/Dict.js jcdm-ui/src/utils/dict/DictConverter.js jcdm-ui/src/utils/dict/DictData.js jcdm-ui/src/utils/dict/DictMeta.js jcdm-ui/src/utils/dict/DictOptions.js jcdm-ui/src/utils/dict/index.js jcdm-ui/src/utils/errorCode.js jcdm-ui/src/utils/generator/config.js jcdm-ui/src/utils/generator/css.js jcdm-ui/src/utils/generator/drawingDefault.js jcdm-ui/src/utils/generator/html.js jcdm-ui/src/utils/generator/icon.json jcdm-ui/src/utils/generator/js.js jcdm-ui/src/utils/generator/render.js jcdm-ui/src/utils/index.js jcdm-ui/src/utils/jsencrypt.js jcdm-ui/src/utils/permission.js jcdm-ui/src/utils/request.js jcdm-ui/src/utils/ruoyi.js jcdm-ui/src/utils/scroll-to.js jcdm-ui/src/utils/validate.js jcdm-ui/src/views/components/icons/element-icons.js jcdm-ui/src/views/components/icons/index.vue jcdm-ui/src/views/components/icons/svg-icons.js jcdm-ui/src/views/dashboard/BarChart.vue jcdm-ui/src/views/dashboard/LineChart.vue jcdm-ui/src/views/dashboard/PanelGroup.vue jcdm-ui/src/views/dashboard/PieChart.vue jcdm-ui/src/views/dashboard/RaddarChart.vue jcdm-ui/src/views/dashboard/mixins/resize.js jcdm-ui/src/views/error/401.vue jcdm-ui/src/views/error/404.vue jcdm-ui/src/views/index.vue jcdm-ui/src/views/index_v1.vue jcdm-ui/src/views/login.vue jcdm-ui/src/views/main/bs/ProductBom/index.vue jcdm-ui/src/views/main/bs/ProductBomChild/index.vue jcdm-ui/src/views/main/bs/beatSetting/index.vue jcdm-ui/src/views/main/bs/formula/index.vue jcdm-ui/src/views/main/bs/formulaChild/index.vue jcdm-ui/src/views/main/bs/lineInfo/index.vue jcdm-ui/src/views/main/bs/material/index.vue jcdm-ui/src/views/main/bs/processFile/index.vue jcdm-ui/src/views/main/bs/processes/index.vue jcdm-ui/src/views/main/bs/technologyRoute/index.vue jcdm-ui/src/views/main/bs/technologyRouteChild/index.vue jcdm-ui/src/views/main/bs/workshop/index.vue jcdm-ui/src/views/main/cfkb/Instructions/index.vue jcdm-ui/src/views/main/da/collectionParamConf/index.vue jcdm-ui/src/views/main/da/opcuaconfig/index.vue jcdm-ui/src/views/main/da/paramCollection/index.vue jcdm-ui/src/views/main/da/passingStationCollection/index.vue jcdm-ui/src/views/main/em/equipmentAlarm/index.vue jcdm-ui/src/views/main/em/equipmentArchives/index.vue jcdm-ui/src/views/main/em/equipmentStatus/index.vue jcdm-ui/src/views/main/kb/stationTerminal/index.vue jcdm-ui/src/views/main/om/productionOrde/index.vue jcdm-ui/src/views/main/om/workReport/index.vue jcdm-ui/src/views/main/rm/repairData/index.vue jcdm-ui/src/views/main/rm/repairRecord/index.vue jcdm-ui/src/views/main/sc/stationConf/index.vue jcdm-ui/src/views/monitor/cache/index.vue jcdm-ui/src/views/monitor/cache/list.vue jcdm-ui/src/views/monitor/druid/index.vue jcdm-ui/src/views/monitor/job/index.vue jcdm-ui/src/views/monitor/job/log.vue jcdm-ui/src/views/monitor/logininfor/index.vue jcdm-ui/src/views/monitor/online/index.vue jcdm-ui/src/views/monitor/operlog/index.vue jcdm-ui/src/views/monitor/server/index.vue jcdm-ui/src/views/redirect.vue jcdm-ui/src/views/register.vue jcdm-ui/src/views/system/config/index.vue jcdm-ui/src/views/system/dept/index.vue jcdm-ui/src/views/system/dict/data.vue jcdm-ui/src/views/system/dict/index.vue jcdm-ui/src/views/system/menu/index.vue jcdm-ui/src/views/system/notice/index.vue jcdm-ui/src/views/system/post/index.vue jcdm-ui/src/views/system/role/authUser.vue jcdm-ui/src/views/system/role/index.vue jcdm-ui/src/views/system/role/selectUser.vue jcdm-ui/src/views/system/user/authRole.vue jcdm-ui/src/views/system/user/index.vue jcdm-ui/src/views/system/user/profile/index.vue jcdm-ui/src/views/system/user/profile/resetPwd.vue jcdm-ui/src/views/system/user/profile/userAvatar.vue jcdm-ui/src/views/system/user/profile/userInfo.vue jcdm-ui/src/views/tool/build/CodeTypeDialog.vue jcdm-ui/src/views/tool/build/DraggableItem.vue jcdm-ui/src/views/tool/build/IconsDialog.vue jcdm-ui/src/views/tool/build/RightPanel.vue jcdm-ui/src/views/tool/build/TreeNodeDialog.vue jcdm-ui/src/views/tool/build/index.vue jcdm-ui/src/views/tool/gen/basicInfoForm.vue jcdm-ui/src/views/tool/gen/editTable.vue jcdm-ui/src/views/tool/gen/genInfoForm.vue jcdm-ui/src/views/tool/gen/importTable.vue jcdm-ui/src/views/tool/gen/index.vue jcdm-ui/src/views/tool/swagger/index.vue jcdm-ui/vue.config.js package-lock.json pom.xml sql/quartz.sql sql/ry_20231130.sql