summaryrefslogtreecommitdiff
path: root/UI source code/dns-dev-2.0
diff options
context:
space:
mode:
authorunknown <[email protected]>2022-06-24 17:11:23 +0800
committerunknown <[email protected]>2022-06-24 17:11:23 +0800
commit8565e1bb597b481447d33bac6d8c48c2c45215de (patch)
treea4f10c8f7f85a1a8b5c947f7d0d2f967d808a9c4 /UI source code/dns-dev-2.0
parent8165dfcc7bdb0b2e6f1c05f8e7c93553c0e7911e (diff)
upload UI source codeHEADmain
Diffstat (limited to 'UI source code/dns-dev-2.0')
-rw-r--r--UI source code/dns-dev-2.0/.gitignore7
-rw-r--r--UI source code/dns-dev-2.0/LICENSE191
-rw-r--r--UI source code/dns-dev-2.0/README.md72
-rw-r--r--UI source code/dns-dev-2.0/dns-common/pom.xml26
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java30
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java47
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java50
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java87
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java90
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java99
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java27
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java40
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java85
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java50
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java45
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java60
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java217
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java38
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java148
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java98
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java35
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java49
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java109
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java58
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java43
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java47
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java62
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java160
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java70
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java100
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java356
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java63
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java208
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java708
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java33
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java198
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java95
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java145
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java264
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java66
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java45
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java50
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java46
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java53
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java74
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java145
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java64
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java40
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/pom.xml22
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/annotation/Log.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/aspect/LogAspect.java98
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/domain/Log.java80
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/repository/LogRepository.java39
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/rest/LogController.java109
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/LogService.java92
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogErrorDTO.java46
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogQueryCriteria.java39
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogSmallDTO.java40
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/impl/LogServiceImpl.java169
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogErrorMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogSmallMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/pom.xml103
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java64
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java88
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java236
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java36
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java33
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java62
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java58
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java63
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java39
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java48
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java24
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java66
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java24
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java51
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java75
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java28
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java71
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java75
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java24
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java76
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java93
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java20
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java20
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java32
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java27
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java15
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java20
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java19
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java13
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java13
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java108
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java631
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java15
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java66
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java43
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java192
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java61
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java43
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java135
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java72
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java146
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java68
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java39
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java43
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java109
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java123
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java192
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java53
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java110
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java159
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java39
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java79
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java73
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java117
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java99
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java99
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java94
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java47
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java147
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java45
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java154
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java196
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java86
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java54
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java56
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java73
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java110
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java99
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java125
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java35
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java47
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java69
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java36
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java43
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java42
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java85
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java80
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java130
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java34
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java124
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java63
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java75
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java88
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java125
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java136
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java114
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java78
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java46
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java40
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java33
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java39
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java30
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java46
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java40
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java33
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java41
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java60
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java36
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java32
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java64
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java46
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java284
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java96
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java122
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java126
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java356
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java186
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java227
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java255
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java30
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java30
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java30
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java28
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java27
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt8
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml118
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml126
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml97
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties27
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties4
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml45
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml577
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml400
-rw-r--r--UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml78
-rw-r--r--UI source code/dns-dev-2.0/pom.xml266
-rw-r--r--UI source code/dns-dev-2.0/sql/DiamondV.sql1059
-rw-r--r--UI source code/dns-dev-2.0/sql/eladmin.sql825
-rw-r--r--UI source code/dns-dev-2.0/sql/tool_picture.sql2
-rw-r--r--UI source code/dns-dev-2.0/sql/脚本如何选择.md11
213 files changed, 20032 insertions, 0 deletions
diff --git a/UI source code/dns-dev-2.0/.gitignore b/UI source code/dns-dev-2.0/.gitignore
new file mode 100644
index 0000000..9acb04a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/.gitignore
@@ -0,0 +1,7 @@
+### IDEA ###
+.idea/*
+*.iml
+*/target/*
+*/*.iml
+/.gradle/
+/application.pid \ No newline at end of file
diff --git a/UI source code/dns-dev-2.0/LICENSE b/UI source code/dns-dev-2.0/LICENSE
new file mode 100644
index 0000000..ca38718
--- /dev/null
+++ b/UI source code/dns-dev-2.0/LICENSE
@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "{}" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+ Copyright 2019-2020 Zheng Jie
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License. \ No newline at end of file
diff --git a/UI source code/dns-dev-2.0/README.md b/UI source code/dns-dev-2.0/README.md
new file mode 100644
index 0000000..6284064
--- /dev/null
+++ b/UI source code/dns-dev-2.0/README.md
@@ -0,0 +1,72 @@
+<h1 style="text-align: center">DiamondV
+
+</div>
+
+#### 项目简介
+
+一个基于 Spring Boot 2.1.0 、 Spring Boot Jpa、mybatis-plus、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统
+
+**账号密码:** `admin / 123456`
+
+**打包:** `mvn clean install`
+
+#### 项目源码
+
+| | 后端源码 | 前端源码 |
+| ---- | ------------------------------ | ----------------------------------------- |
+| 地址 | http://192.168.40.125/kjch/dns | http://192.168.40.125/kjch/dns_mapping_ui |
+
+#### 主要特性
+
+- 使用最新技术栈,社区资源丰富。
+- 高效率开发,代码生成器可一键生成前后端代码
+- 支持数据字典,可方便地对一些状态进行管理
+- 支持接口限流,避免恶意请求导致服务层压力过大
+- 支持接口级别的功能权限与数据权限,可自定义操作
+- 自定义权限注解与匿名接口注解,可快速对接口拦截与放行
+- 对一些常用地前端组件封装:表格数据请求、数据字典等
+- 前后端统一异常拦截处理,统一输出异常,避免繁琐的判断
+- 支持在线用户管理与服务器性能监控,支持限制单用户登录
+- 支持运维管理,可方便地对远程服务器的应用进行部署与管理
+
+#### 系统功能
+
+- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456
+- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
+- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
+- 部门管理:可配置系统组织架构,树形表格展示
+- 岗位管理:配置各个部门的职位
+- 字典管理:可维护常用一些固定的数据,如:状态,性别等
+- 系统日志:记录用户操作日志与异常日志,方便开发人员定位排错
+- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456
+- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然
+- 代码生成:高灵活度生成前后端代码,减少大量重复的工作任务
+- 邮件工具:配合富文本,发送html格式的邮件
+- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据
+- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
+- 服务监控:监控服务器的负载情况
+- 运维管理:一键部署你的应用
+
+#### 项目结构
+
+项目采用按功能分模块的开发方式,结构如下
+
+- `dns-common` 为系统的公共模块,各种工具类,公共配置存在该模块
+- `dns-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
+- `dns-logging` 为系统的日志模块,其他模块如果需要记录日志需要引入该模块
+- 详细结构
+
+```
+- dns-common 公共模块
+ - annotation 为系统自定义注解
+ - aspect 自定义注解的切面
+ - base 提供了Entity、DTO基类和mapstruct的通用mapper
+ - config 自定义权限实现、redis配置、swagger配置、Rsa配置等
+ - exception 项目统一异常的处理
+ - utils 系统通用工具类
+- dns-system 系统核心模块(系统启动入口)
+ - config 配置跨域与静态资源,与数据权限
+ - thread 线程池相关
+ - modules 系统相关模块(登录授权、系统监控、定时任务、运维管理,测绘等)
+- dns-logging 系统日志模块
+```
diff --git a/UI source code/dns-dev-2.0/dns-common/pom.xml b/UI source code/dns-dev-2.0/dns-common/pom.xml
new file mode 100644
index 0000000..33734bb
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/pom.xml
@@ -0,0 +1,26 @@
+<?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>dns</artifactId>
+ <groupId>com.example</groupId>
+ <version>2.6</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <properties>
+ <hutool.version>5.3.4</hutool.version>
+ </properties>
+
+ <artifactId>dns-common</artifactId>
+ <name>dns-common</name>
+
+ <dependencies>
+ <!--工具包-->
+ <dependency>
+ <groupId>cn.hutool</groupId>
+ <artifactId>hutool-all</artifactId>
+ <version>${hutool.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java
new file mode 100644
index 0000000..9cffb51
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @author jacky
+ * 用于标记匿名访问方法
+ */
+@Inherited
+@Documented
+@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnonymousAccess {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java
new file mode 100644
index 0000000..7fa3e3f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * 用于判断是否过滤数据权限
+ * 1、如果没有用到 @OneToOne 这种关联关系,只需要填写 fieldName [参考:DeptQueryCriteria.class]
+ * 2、如果用到了 @OneToOne ,fieldName 和 joinName 都需要填写,拿UserQueryCriteria.class举例:
+ * 应该是 @DataPermission(joinName = "dept", fieldName = "id")
+ * </p>
+ *
+ * @website https://el-admin.vip
+ * 2020-05-07
+ **/
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DataPermission {
+
+ /**
+ * Entity 中的字段名称
+ */
+ String fieldName() default "";
+
+ /**
+ * Entity 中与部门关联的字段名称
+ */
+ String joinName() default "";
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java
new file mode 100644
index 0000000..ee285de
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.annotation;
+
+import com.example.aspect.LimitType;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author jacky
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Limit {
+
+ // 资源名称,用于描述接口功能
+ String name() default "";
+
+ // 资源 key
+ String key() default "";
+
+ // key prefix
+ String prefix() default "";
+
+ // 时间的,单位秒
+ int period();
+
+ // 限制访问次数
+ int count();
+
+ // 限制类型
+ LimitType limitType() default LimitType.CUSTOMER;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java
new file mode 100644
index 0000000..e21d60b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Query {
+
+ // Dong ZhaoYang 2017/8/7 基本对象的属性名
+ String propName() default "";
+ // Dong ZhaoYang 2017/8/7 查询方式
+ Type type() default Type.EQUAL;
+
+ /**
+ * 连接查询的属性名,如User类中的dept
+ */
+ String joinName() default "";
+
+ /**
+ * 默认左连接
+ */
+ Join join() default Join.LEFT;
+
+ /**
+ * 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
+ */
+ String blurry() default "";
+
+ enum Type {
+ // jie 2019/6/4 相等
+ EQUAL
+ // Dong ZhaoYang 2017/8/7 大于等于
+ , GREATER_THAN
+ // Dong ZhaoYang 2017/8/7 小于等于
+ , LESS_THAN
+ // Dong ZhaoYang 2017/8/7 中模糊查询
+ , INNER_LIKE
+ // Dong ZhaoYang 2017/8/7 左模糊查询
+ , LEFT_LIKE
+ // Dong ZhaoYang 2017/8/7 右模糊查询
+ , RIGHT_LIKE
+ // Dong ZhaoYang 2017/8/7 小于
+ , LESS_THAN_NQ
+ // jie 2019/6/4 包含
+ , IN
+ // 不包含
+ , NOT_IN
+ // 不等于
+ ,NOT_EQUAL
+ // between
+ ,BETWEEN
+ // 不为空
+ ,NOT_NULL
+ // 为空
+ ,IS_NULL
+ }
+
+ /**
+ *
+ * 适用于简单连接查询,复杂的请自定义该注解,或者使用sql查询
+ */
+ enum Join {
+ /** jie 2019-6-4 13:18:30 */
+ LEFT, RIGHT, INNER
+ }
+
+}
+
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java
new file mode 100644
index 0000000..10fbef4
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.annotation.rest;
+
+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.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code DELETE} requests onto specific handler
+ * methods.
+ * 支持匿名访问 DeleteMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousPatchMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.DELETE)
+public @interface AnonymousDeleteMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java
new file mode 100644
index 0000000..85d6a78
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.annotation.rest;
+
+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.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code GET} requests onto specific handler
+ * methods.
+ * <p>
+ * 支持匿名访问 GetMapping
+ *
+ * @author liaojinlong
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.GET)
+public @interface AnonymousGetMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ *
+ * @since 4.3.5
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java
new file mode 100644
index 0000000..3281a3b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.annotation.rest;
+
+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.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code PATCH} requests onto specific handler
+ * methods.
+ * * 支持匿名访问 PatchMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousDeleteMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.PATCH)
+public @interface AnonymousPatchMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java
new file mode 100644
index 0000000..977de6c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.annotation.rest;
+
+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.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code POST} requests onto specific handler
+ * methods.
+ * 支持匿名访问 PostMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousDeleteMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.POST)
+public @interface AnonymousPostMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java
new file mode 100644
index 0000000..6fc00b2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.annotation.rest;
+
+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.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code PUT} requests onto specific handler
+ * methods.
+ * * 支持匿名访问 PutMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousDeleteMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.PUT)
+public @interface AnonymousPutMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java
new file mode 100644
index 0000000..1e1856d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.aspect;
+
+import com.google.common.collect.ImmutableList;
+import com.example.annotation.Limit;
+import com.example.exception.BadRequestException;
+import com.example.utils.RequestHolder;
+import com.example.utils.StringUtils;
+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.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+
+/**
+ * @author /
+ */
+@Aspect
+@Component
+public class LimitAspect {
+
+ private final RedisTemplate<Object,Object> redisTemplate;
+ private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);
+
+ public LimitAspect(RedisTemplate<Object,Object> redisTemplate) {
+ this.redisTemplate = redisTemplate;
+ }
+
+ @Pointcut("@annotation(com.example.annotation.Limit)")
+ public void pointcut() {
+ }
+
+ @Around("pointcut()")
+ public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
+ HttpServletRequest request = RequestHolder.getHttpServletRequest();
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method signatureMethod = signature.getMethod();
+ Limit limit = signatureMethod.getAnnotation(Limit.class);
+ LimitType limitType = limit.limitType();
+ String key = limit.key();
+ if (StringUtils.isEmpty(key)) {
+ if (limitType == LimitType.IP) {
+ key = StringUtils.getIp(request);
+ } else {
+ key = signatureMethod.getName();
+ }
+ }
+
+ ImmutableList<Object> keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replace("/","_")));
+
+ String luaScript = buildLuaScript();
+ RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
+ Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
+ if (null != count && count.intValue() <= limit.count()) {
+ logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name());
+ return joinPoint.proceed();
+ } else {
+ throw new BadRequestException("访问次数受限制");
+ }
+ }
+
+ /**
+ * 限流脚本
+ */
+ private String buildLuaScript() {
+ return "local c" +
+ "\nc = redis.call('get',KEYS[1])" +
+ "\nif c and tonumber(c) > tonumber(ARGV[1]) then" +
+ "\nreturn c;" +
+ "\nend" +
+ "\nc = redis.call('incr',KEYS[1])" +
+ "\nif tonumber(c) == 1 then" +
+ "\nredis.call('expire',KEYS[1],ARGV[2])" +
+ "\nend" +
+ "\nreturn c;";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java
new file mode 100644
index 0000000..0a6deb6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.aspect;
+
+/**
+ * 限流枚举
+ * @author /
+ */
+public enum LimitType {
+ // 默认
+ CUSTOMER,
+ // by ip addr
+ IP
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java
new file mode 100644
index 0000000..7802007
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java
@@ -0,0 +1,40 @@
+package com.example.base;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.sql.Timestamp;
+
+/**
+ *
+ * 2019年10月24日20:48:53
+ */
+@Getter
+@Setter
+public class BaseDTO implements Serializable {
+
+ private String createBy;
+
+ private String updateBy;
+
+ private Timestamp createTime;
+
+ private Timestamp updateTime;
+
+ @Override
+ public String toString() {
+ ToStringBuilder builder = new ToStringBuilder(this);
+ Field[] fields = this.getClass().getDeclaredFields();
+ try {
+ for (Field f : fields) {
+ f.setAccessible(true);
+ builder.append(f.getName(), f.get(this)).append("\n");
+ }
+ } catch (Exception e) {
+ builder.append("toString builder encounter an error");
+ }
+ return builder.toString();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java
new file mode 100644
index 0000000..ba31ddf
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.sql.Timestamp;
+
+/**
+ * 通用字段, is_del 根据需求自行添加
+ *
+ * @Date 2019年10月24日20:46:32
+ */
+@Getter
+@Setter
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+public class BaseEntity implements Serializable {
+
+ @CreatedBy
+ @Column(name = "create_by", updatable = false)
+ @ApiModelProperty(value = "创建人", hidden = true)
+ private String createBy;
+
+ @LastModifiedBy
+ @Column(name = "update_by")
+ @ApiModelProperty(value = "更新人", hidden = true)
+ private String updateBy;
+
+ @CreationTimestamp
+ @Column(name = "create_time", updatable = false)
+ @ApiModelProperty(value = "创建时间", hidden = true)
+ private Timestamp createTime;
+
+ @UpdateTimestamp
+ @Column(name = "update_time")
+ @ApiModelProperty(value = "更新时间", hidden = true)
+ private Timestamp updateTime;
+
+ /* 分组校验 */
+ public @interface Create {}
+
+ /* 分组校验 */
+ public @interface Update {}
+
+ @Override
+ public String toString() {
+ ToStringBuilder builder = new ToStringBuilder(this);
+ Field[] fields = this.getClass().getDeclaredFields();
+ try {
+ for (Field f : fields) {
+ f.setAccessible(true);
+ builder.append(f.getName(), f.get(this)).append("\n");
+ }
+ } catch (Exception e) {
+ builder.append("toString builder encounter an error");
+ }
+ return builder.toString();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java
new file mode 100644
index 0000000..1c2d38a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.base;
+
+import java.util.List;
+
+
+public interface BaseMapper<D, E> {
+
+ /**
+ * DTO转Entity
+ * @param dto /
+ * @return /
+ */
+ E toEntity(D dto);
+
+ /**
+ * Entity转DTO
+ * @param entity /
+ * @return /
+ */
+ D toDto(E entity);
+
+ /**
+ * DTO集合转Entity集合
+ * @param dtoList /
+ * @return /
+ */
+ List <E> toEntity(List<D> dtoList);
+
+ /**
+ * Entity集合转DTO集合
+ * @param entityList /
+ * @return /
+ */
+ List <D> toDto(List<E> entityList);
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java
new file mode 100644
index 0000000..7d1dcbe
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import com.example.utils.SecurityUtils;
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+import java.util.Optional;
+
+/**
+ * @description : 设置审计
+ * @author : Dong ZhaoYang
+ * : 2019/10/28
+ */
+@Component("auditorAware")
+public class AuditorConfig implements AuditorAware<String> {
+
+ /**
+ * 返回操作员标志信息
+ *
+ * @return /
+ */
+ @Override
+ public Optional<String> getCurrentAuditor() {
+ try {
+ // 这里应根据实际业务情况获取具体信息
+ return Optional.of(SecurityUtils.getCurrentUsername());
+ }catch (Exception ignored){}
+ // 用户定时任务,或者无Token调用的情况
+ return Optional.of("System");
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java
new file mode 100644
index 0000000..b7670b3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @description
+ * 2021-11-22
+ **/
+@Data
+@Component
+public class ElAdminProperties {
+
+ public static Boolean ipLocal;
+
+ @Value("${ip.local-parsing}")
+ public void setIpLocal(Boolean ipLocal) {
+ ElAdminProperties.ipLocal = ipLocal;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java
new file mode 100644
index 0000000..7b7c1e7
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import com.example.utils.SecurityUtils;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.stereotype.Service;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ *
+ */
+@Service(value = "el")
+public class ElPermissionConfig {
+
+ public Boolean check(String ...permissions){
+ // 获取当前用户的所有权限
+ List<String> elPermissions = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
+ // 判断当前用户的所有权限是否包含接口上定义的权限
+ return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java
new file mode 100644
index 0000000..a1c3aff
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import lombok.Data;
+import com.example.utils.ElAdminConstant;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ *
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "file")
+public class FileProperties {
+
+ /** 文件大小限制 */
+ private Long maxSize;
+
+ /** 头像大小限制 */
+ private Long avatarMaxSize;
+
+ private ElPath mac;
+
+ private ElPath linux;
+
+ private ElPath windows;
+
+ public ElPath getPath(){
+ String os = System.getProperty("os.name");
+ if(os.toLowerCase().startsWith(ElAdminConstant.WIN)) {
+ return windows;
+ } else if(os.toLowerCase().startsWith(ElAdminConstant.MAC)){
+ return mac;
+ }
+ return linux;
+ }
+
+ @Data
+ public static class ElPath{
+
+ private String path;
+
+ private String avatar;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java
new file mode 100644
index 0000000..d482e83
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import cn.hutool.core.lang.Assert;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cache.Cache;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.CacheErrorHandler;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import reactor.util.annotation.Nullable;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ *
+ * 2018-11-24
+ */
+@Slf4j
+@Configuration
+@EnableCaching
+@ConditionalOnClass(RedisOperations.class)
+@EnableConfigurationProperties(RedisProperties.class)
+public class RedisConfig extends CachingConfigurerSupport {
+
+ /**
+ * 设置 redis 数据默认过期时间,默认2小时
+ * 设置@cacheable 序列化方式
+ */
+ @Bean
+ public RedisCacheConfiguration redisCacheConfiguration(){
+ FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
+ RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
+ configuration = configuration.serializeValuesWith(RedisSerializationContext.
+ SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2));
+ return configuration;
+ }
+
+ @SuppressWarnings("all")
+ @Bean(name = "redisTemplate")
+ @ConditionalOnMissingBean(name = "redisTemplate")
+ public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+ RedisTemplate<Object, Object> template = new RedisTemplate<>();
+ //序列化
+ FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
+ // value值的序列化采用fastJsonRedisSerializer
+ template.setValueSerializer(fastJsonRedisSerializer);
+ template.setHashValueSerializer(fastJsonRedisSerializer);
+ // 全局开启AutoType,这里方便开发,使用全局的方式
+ ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+ // 建议使用这种方式,小范围指定白名单
+ // ParserConfig.getGlobalInstance().addAccept("com.example.domain");
+ // key的序列化采用StringRedisSerializer
+ template.setKeySerializer(new StringRedisSerializer());
+ template.setHashKeySerializer(new StringRedisSerializer());
+ template.setConnectionFactory(redisConnectionFactory);
+ return template;
+ }
+
+ /**
+ * 自定义缓存key生成策略,默认将使用该策略
+ */
+ @Bean
+ @Override
+ public KeyGenerator keyGenerator() {
+ return (target, method, params) -> {
+ Map<String,Object> container = new HashMap<>(4);
+ Class<?> targetClassClass = target.getClass();
+ // 类地址
+ container.put("class",targetClassClass.toGenericString());
+ // 方法名称
+ container.put("methodName",method.getName());
+ // 包名称
+ container.put("package",targetClassClass.getPackage());
+ // 参数列表
+ for (int i = 0; i < params.length; i++) {
+ container.put(String.valueOf(i),params[i]);
+ }
+ // 转为JSON字符串
+ String jsonString = JSON.toJSONString(container);
+ // 做SHA256 Hash计算,得到一个SHA256摘要作为Key
+ return DigestUtils.sha256Hex(jsonString);
+ };
+ }
+
+ @Bean
+ @Override
+ public CacheErrorHandler errorHandler() {
+ // 异常处理,当Redis发生异常时,打印日志,但是程序正常走
+ log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
+ return new CacheErrorHandler() {
+ @Override
+ public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
+ log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
+ }
+
+ @Override
+ public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
+ log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
+ }
+
+ @Override
+ public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
+ log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
+ }
+
+ @Override
+ public void handleCacheClearError(RuntimeException e, Cache cache) {
+ log.error("Redis occur handleCacheClearError:", e);
+ }
+ };
+ }
+
+}
+
+/**
+ * Value 序列化
+ *
+ * @author /
+ * @param <T>
+ */
+ class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
+
+ private final Class<T> clazz;
+
+ FastJsonRedisSerializer(Class<T> clazz) {
+ super();
+ this.clazz = clazz;
+ }
+
+ @Override
+ public byte[] serialize(T t) {
+ if (t == null) {
+ return new byte[0];
+ }
+ return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public T deserialize(byte[] bytes) {
+ if (bytes == null || bytes.length <= 0) {
+ return null;
+ }
+ String str = new String(bytes, StandardCharsets.UTF_8);
+ return JSON.parseObject(str, clazz);
+ }
+
+}
+
+/**
+ * 重写序列化器
+ *
+ * @author /
+ */
+class StringRedisSerializer implements RedisSerializer<Object> {
+
+ private final Charset charset;
+
+ StringRedisSerializer() {
+ this(StandardCharsets.UTF_8);
+ }
+
+ private StringRedisSerializer(Charset charset) {
+ Assert.notNull(charset, "Charset must not be null!");
+ this.charset = charset;
+ }
+
+ @Override
+ public String deserialize(byte[] bytes) {
+ return (bytes == null ? null : new String(bytes, charset));
+ }
+
+ @Override
+ public @Nullable byte[] serialize(Object object) {
+ String string = JSON.toJSONString(object);
+
+ if (org.apache.commons.lang3.StringUtils.isBlank(string)) {
+ return null;
+ }
+ string = string.replace("\"", "");
+ return string.getBytes(charset);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java
new file mode 100644
index 0000000..7490f71
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description
+ * 2020-05-18
+ **/
+@Data
+@Component
+public class RsaProperties {
+
+ public static String privateKey;
+
+ @Value("${rsa.private_key}")
+ public void setPrivateKey(String privateKey) {
+ RsaProperties.privateKey = privateKey;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java
new file mode 100644
index 0000000..7d0b1c6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import com.fasterxml.classmate.TypeResolver;
+import com.google.common.base.Predicates;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.data.domain.Pageable;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.schema.AlternateTypeRule;
+import springfox.documentation.schema.AlternateTypeRuleConvention;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+import java.util.ArrayList;
+import java.util.List;
+import static com.google.common.collect.Lists.newArrayList;
+import static springfox.documentation.schema.AlternateTypeRules.newRule;
+
+/**
+ * api页面 /doc.html
+ *
+ * 2018-11-23
+ */
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+ @Value("${jwt.header}")
+ private String tokenHeader;
+
+ @Value("${swagger.enabled}")
+ private Boolean enabled;
+
+ @Bean
+ @SuppressWarnings("all")
+ public Docket createRestApi() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .enable(enabled)
+ .pathMapping("/")
+ .apiInfo(apiInfo())
+ .select()
+ .paths(Predicates.not(PathSelectors.regex("/error.*")))
+ .paths(PathSelectors.any())
+ .build()
+ //添加登陆认证
+ .securitySchemes(securitySchemes())
+ .securityContexts(securityContexts());
+ }
+
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .description("一个简单且易上手的 Spring boot 后台管理框架")
+ .title("DNS测绘 接口文档")
+ .version("2.6")
+ .build();
+ }
+
+ private List<SecurityScheme> securitySchemes() {
+ //设置请求头信息
+ List<SecurityScheme> securitySchemes = new ArrayList<>();
+ ApiKey apiKey = new ApiKey(tokenHeader, tokenHeader, "header");
+ securitySchemes.add(apiKey);
+ return securitySchemes;
+ }
+
+ private List<SecurityContext> securityContexts() {
+ //设置需要登录认证的路径
+ List<SecurityContext> securityContexts = new ArrayList<>();
+ // ^(?!auth).*$ 表示所有包含auth的接口不需要使用securitySchemes即不需要带token
+ // ^标识开始 ()里是一子表达式 ?!/auth表示匹配不是/auth的位置,匹配上则添加请求头,注意路径已/开头 .表示任意字符 *表示前面的字符匹配多次 $标识结束
+ securityContexts.add(getContextByPath());
+ return securityContexts;
+ }
+
+ private SecurityContext getContextByPath() {
+ return SecurityContext.builder()
+ .securityReferences(defaultAuth())
+ .forPaths(PathSelectors.regex("^(?!/auth).*$"))
+ .build();
+ }
+
+ private List<SecurityReference> defaultAuth() {
+ List<SecurityReference> securityReferences = new ArrayList<>();
+ AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+ AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+ authorizationScopes[0] = authorizationScope;
+ securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes));
+ return securityReferences;
+ }
+}
+
+/**
+ * 将Pageable转换展示在swagger中
+ */
+@Configuration
+class SwaggerDataConfig {
+
+ @Bean
+ public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
+ return new AlternateTypeRuleConvention() {
+ @Override
+ public int getOrder() {
+ return Ordered.HIGHEST_PRECEDENCE;
+ }
+
+ @Override
+ public List<AlternateTypeRule> rules() {
+ return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
+ }
+ };
+ }
+
+ @ApiModel
+ @Data
+ private static class Page {
+ @ApiModelProperty("页码 (0..N)")
+ private Integer page;
+
+ @ApiModelProperty("每页显示的数目")
+ private Integer size;
+
+ @ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
+ private List<String> sort;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java
new file mode 100644
index 0000000..0ca41ad
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.exception;
+
+/**
+ * 统一关于错误配置信息 异常
+ *
+ * @author: liaojinlong
+ * : 2020/6/10 18:06
+ */
+public class BadConfigurationException extends RuntimeException {
+ /**
+ * Constructs a new runtime exception with {@code null} as its
+ * detail message. The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause}.
+ */
+ public BadConfigurationException() {
+ super();
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail message.
+ * The cause is not initialized, and may subsequently be initialized by a
+ * call to {@link #initCause}.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public BadConfigurationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * {@code cause} is <i>not</i> automatically incorporated in
+ * this runtime exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public BadConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified cause and a
+ * detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}). This constructor is useful for runtime exceptions
+ * that are little more than wrappers for other throwables.
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public BadConfigurationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail
+ * message, cause, suppression enabled or disabled, and writable
+ * stack trace enabled or disabled.
+ *
+ * @param message the detail message.
+ * @param cause the cause. (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @param enableSuppression whether or not suppression is enabled
+ * or disabled
+ * @param writableStackTrace whether or not the stack trace should
+ * be writable
+ * @since 1.7
+ */
+ protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java
new file mode 100644
index 0000000..e8c7474
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.exception;
+
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+
+@Getter
+public class BadRequestException extends RuntimeException{
+
+ private Integer status = BAD_REQUEST.value();
+
+ public BadRequestException(String msg){
+ super(msg);
+ }
+
+ public BadRequestException(HttpStatus status,String msg){
+ super(msg);
+ this.status = status.value();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java
new file mode 100644
index 0000000..5af387f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.exception;
+
+import org.springframework.util.StringUtils;
+
+
+public class EntityExistException extends RuntimeException {
+
+ public EntityExistException(Class clazz, String field, String val) {
+ super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
+ }
+
+ private static String generateMessage(String entity, String field, String val) {
+ return StringUtils.capitalize(entity)
+ + " with " + field + " "+ val + " existed";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java
new file mode 100644
index 0000000..cdfd771
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.exception;
+
+import org.springframework.util.StringUtils;
+
+
+public class EntityNotFoundException extends RuntimeException {
+
+ public EntityNotFoundException(Class clazz, String field, String val) {
+ super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
+ }
+
+ private static String generateMessage(String entity, String field, String val) {
+ return StringUtils.capitalize(entity)
+ + " with " + field + " "+ val + " does not exist";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java
new file mode 100644
index 0000000..82ec628
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.exception.handler;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+
+@Data
+class ApiError {
+
+ private Integer status = 400;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime timestamp;
+ private String message;
+
+ private ApiError() {
+ timestamp = LocalDateTime.now();
+ }
+
+ public static ApiError error(String message){
+ ApiError apiError = new ApiError();
+ apiError.setMessage(message);
+ return apiError;
+ }
+
+ public static ApiError error(Integer status, String message){
+ ApiError apiError = new ApiError();
+ apiError.setStatus(status);
+ apiError.setMessage(message);
+ return apiError;
+ }
+}
+
+
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..ba044d1
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.exception.handler;
+
+import com.example.exception.BadRequestException;
+import com.example.exception.EntityExistException;
+import com.example.exception.EntityNotFoundException;
+import com.example.utils.ThrowableUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import java.util.Objects;
+import static org.springframework.http.HttpStatus.*;
+
+
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+ /**
+ * 处理所有不可知的异常
+ */
+ @ExceptionHandler(Throwable.class)
+ public ResponseEntity<ApiError> handleException(Throwable e){
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(e.getMessage()));
+ }
+
+ /**
+ * BadCredentialsException
+ */
+ @ExceptionHandler(BadCredentialsException.class)
+ public ResponseEntity<ApiError> badCredentialsException(BadCredentialsException e){
+ // 打印堆栈信息
+ String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();
+ log.error(message);
+ return buildResponseEntity(ApiError.error(message));
+ }
+
+ /**
+ * 处理自定义异常
+ */
+ @ExceptionHandler(value = BadRequestException.class)
+ public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
+ }
+
+ /**
+ * 处理 EntityExist
+ */
+ @ExceptionHandler(value = EntityExistException.class)
+ public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(e.getMessage()));
+ }
+
+ /**
+ * 处理 EntityNotFound
+ */
+ @ExceptionHandler(value = EntityNotFoundException.class)
+ public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
+ }
+
+ /**
+ * 处理所有接口数据验证异常
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
+ String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
+ String msg = "不能为空";
+ if(msg.equals(message)){
+ message = str[1] + ":" + message;
+ }
+ return buildResponseEntity(ApiError.error(message));
+ }
+
+ /**
+ * 统一返回
+ */
+ private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
+ return new ResponseEntity<>(apiError, valueOf(apiError.getStatus()));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java
new file mode 100644
index 0000000..8e93877
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/11 15:49
+ * @apiNote: 关于缓存的Key集合
+ */
+public interface CacheKey {
+
+ /**
+ * 用户
+ */
+ String USER_ID = "user::id:";
+ /**
+ * 数据
+ */
+ String DATA_USER = "data::user:";
+ /**
+ * 菜单
+ */
+ String MENU_ID = "menu::id:";
+ String MENU_USER = "menu::user:";
+ /**
+ * 角色授权
+ */
+ String ROLE_AUTH = "role::auth:";
+ /**
+ * 角色信息
+ */
+ String ROLE_ID = "role::id:";
+ /**
+ * 部门
+ */
+ String DEPT_ID = "dept::id:";
+ /**
+ * 岗位
+ */
+ String JOB_ID = "job::id:";
+ /**
+ * 数据字典
+ */
+ String DICT_NAME = "dict::name:";
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java
new file mode 100644
index 0000000..59a7d0b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.utils;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/9 17:02
+ * @since: 1.0
+ * @see {@link SpringContextHolder}
+ * 针对某些初始化方法,在SpringContextHolder 初始化前时,<br>
+ * 可提交一个 提交回调任务。<br>
+ * 在SpringContextHolder 初始化后,进行回调使用
+ */
+
+public interface CallBack {
+ /**
+ * 回调执行方法
+ */
+ void executor();
+
+ /**
+ * 本回调任务名称
+ * @return /
+ */
+ default String getCallBackName() {
+ return Thread.currentThread().getId() + ":" + this.getClass().getName();
+ }
+}
+
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java
new file mode 100644
index 0000000..cd515bc
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import java.io.Closeable;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description 用于关闭各种连接,缺啥补啥
+ * 2021-03-05
+ **/
+public class CloseUtil {
+
+ public static void close(Closeable closeable) {
+ if (null != closeable) {
+ try {
+ closeable.close();
+ } catch (Exception e) {
+ // 静默关闭
+ }
+ }
+ }
+
+ public static void close(AutoCloseable closeable) {
+ if (null != closeable) {
+ try {
+ closeable.close();
+ } catch (Exception e) {
+ // 静默关闭
+ }
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java
new file mode 100644
index 0000000..402403e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java
@@ -0,0 +1,62 @@
+package com.example.utils;
+
+/**
+ * 常量
+ */
+public class Constant {
+ public static final String DOH = "dns-doh";
+
+ public static final String DO53 = "dns-do53";
+
+ public static final String SERVICE = "service";
+
+ public static final String IP = "ip";
+
+ public static final String PORT = "port";
+
+ public static final Integer NONE = 0;
+
+ public static final Integer OPENRDNS = 1;
+
+ public static final Integer FORWARDER = 2;
+
+ public static final Integer FWDRDNS = 3;
+
+ public static final Integer EGRESSRDNS = 4;
+
+ public static final Integer NONSTANDARD = 5;
+
+ public static final String PORT8443 = "8443";
+
+ public static final String PORT443 = "443";
+
+ public static final String PORT53 = "53";
+
+ public static final String DNSTAG = "dns";
+
+ public static final String DOHTAG = "DNS-DoH";
+
+ public static final String DO53TAG = "DNS-Do53";
+
+ public static final String OPENRDNSTAG = "open-rdns";
+
+ public static final String FORWARDERTAG = "forwarder";
+
+ public static final String FWDRDNSTAG = "fwd/rdns";
+
+ public static final String EGRESSRDNSTAG = "egress-dns";
+
+ public static final String NONSTANDARDTAG = "nonstandard";
+
+ public static final String PROTOC_TCP = "tcp";
+
+ public static final String PROTOC_UDP = "udp";
+
+ public static final String IP_IPV4 = "ipv4";
+
+ public static final String IP_IPV6 = "ipv6";
+
+ public static final String POINT = ".";
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java
new file mode 100644
index 0000000..57e9408
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.utils;
+
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/11 16:28
+ * @apiNote: JDK 8 新日期类 格式化与字符串转换 工具类
+ */
+public class DateUtil {
+
+ public static final DateTimeFormatter DFY_MD_HMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ public static final DateTimeFormatter DFY_MD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ /**
+ * LocalDateTime 转时间戳
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static Long getTimeStamp(LocalDateTime localDateTime) {
+ return localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond();
+ }
+
+ /**
+ * 时间戳转LocalDateTime
+ *
+ * @param timeStamp /
+ * @return /
+ */
+ public static LocalDateTime fromTimeStamp(Long timeStamp) {
+ return LocalDateTime.ofEpochSecond(timeStamp, 0, OffsetDateTime.now().getOffset());
+ }
+
+ /**
+ * LocalDateTime 转 Date
+ * Jdk8 后 不推荐使用 {@link Date} Date
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static Date toDate(LocalDateTime localDateTime) {
+ return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+ }
+
+ /**
+ * LocalDate 转 Date
+ * Jdk8 后 不推荐使用 {@link Date} Date
+ *
+ * @param localDate /
+ * @return /
+ */
+ public static Date toDate(LocalDate localDate) {
+ return toDate(localDate.atTime(LocalTime.now(ZoneId.systemDefault())));
+ }
+
+
+ /**
+ * Date转 LocalDateTime
+ * Jdk8 后 不推荐使用 {@link Date} Date
+ *
+ * @param date /
+ * @return /
+ */
+ public static LocalDateTime toLocalDateTime(Date date) {
+ return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
+ }
+
+ /**
+ * 日期 格式化
+ *
+ * @param localDateTime /
+ * @param patten /
+ * @return /
+ */
+ public static String localDateTimeFormat(LocalDateTime localDateTime, String patten) {
+ DateTimeFormatter df = DateTimeFormatter.ofPattern(patten);
+ return df.format(localDateTime);
+ }
+
+ /**
+ * 日期 格式化
+ *
+ * @param localDateTime /
+ * @param df /
+ * @return /
+ */
+ public static String localDateTimeFormat(LocalDateTime localDateTime, DateTimeFormatter df) {
+ return df.format(localDateTime);
+ }
+
+ /**
+ * 日期格式化 yyyy-MM-dd HH:mm:ss
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static String localDateTimeFormatyMdHms(LocalDateTime localDateTime) {
+ return DFY_MD_HMS.format(localDateTime);
+ }
+
+ /**
+ * 日期格式化 yyyy-MM-dd
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public String localDateTimeFormatyMd(LocalDateTime localDateTime) {
+ return DFY_MD.format(localDateTime);
+ }
+
+ /**
+ * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, String pattern) {
+ DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
+ return LocalDateTime.from(dateTimeFormatter.parse(localDateTime));
+ }
+
+ /**
+ * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, DateTimeFormatter dateTimeFormatter) {
+ return LocalDateTime.from(dateTimeFormatter.parse(localDateTime));
+ }
+
+ /**
+ * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd HH:mm:ss
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static LocalDateTime parseLocalDateTimeFormatyMdHms(String localDateTime) {
+ return LocalDateTime.from(DFY_MD_HMS.parse(localDateTime));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java
new file mode 100644
index 0000000..f46ff3b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 常用静态常量
+ *
+ *
+ * 2018-12-26
+ */
+public class ElAdminConstant {
+
+ private ElAdminConstant() {
+ throw new IllegalStateException("Utility class");
+ }
+
+ /**
+ * 用于IP定位转换
+ */
+ public static final String REGION = "内网IP|内网IP";
+ /**
+ * win 系统
+ */
+ public static final String WIN = "win";
+
+ /**
+ * mac 系统
+ */
+ public static final String MAC = "mac";
+
+ public static final List<String> openRdnsLabels = Arrays.asList("DNS", "DNS-Do53", "open-rdns");
+
+ public static final List<String> forwarderLabels = Arrays.asList("DNS", "DNS-Do53", "forwarder");
+
+ public static final List<String> fwdRdnsLabels = Arrays.asList("DNS", "DNS-Do53", "fwd/rdns");
+
+ public static final List<String> egressDnsLabels = Arrays.asList("DNS", "DNS-Do53", "egress-dns");
+
+ public static final List<String> nonstandardLabels = Arrays.asList("DNS", "DNS-Do53", "nonstandard");
+
+ public static final List<String> dnsLabels = Arrays.asList("DNS");
+
+ public static final List<String> dohLabels = Arrays.asList("DNS","DNS-DoH");
+
+ public static final List<String> do53Labels = Arrays.asList(new String[]{"DNS","DNS-Do53"});
+
+ /**
+ * 常用接口
+ */
+ public static class Url {
+ // IP归属地查询
+ public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java
new file mode 100644
index 0000000..6ee5a49
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 加密
+ *
+ * 2018-11-23
+ */
+
+public class EncryptUtils {
+
+ private static final String STR_PARAM = "Passw0rd";
+
+ private static Cipher cipher;
+
+ private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8));
+
+ private static DESKeySpec getDesKeySpec(String source) throws Exception {
+ if (source == null || source.length() == 0){
+ return null;
+ }
+ cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ String strKey = "Passw0rd";
+ return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * 对称加密
+ */
+ public static String desEncrypt(String source) throws Exception {
+ DESKeySpec desKeySpec = getDesKeySpec(source);
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+ SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV);
+ return byte2hex(
+ cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
+ }
+
+ /**
+ * 对称解密
+ */
+ public static String desDecrypt(String source) throws Exception {
+ byte[] src = hex2byte(source.getBytes(StandardCharsets.UTF_8));
+ DESKeySpec desKeySpec = getDesKeySpec(source);
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+ SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, IV);
+ byte[] retByte = cipher.doFinal(src);
+ return new String(retByte);
+ }
+
+ private static String byte2hex(byte[] inStr) {
+ String stmp;
+ StringBuilder out = new StringBuilder(inStr.length * 2);
+ for (byte b : inStr) {
+ stmp = Integer.toHexString(b & 0xFF);
+ if (stmp.length() == 1) {
+ // 如果是0至F的单位字符串,则添加0
+ out.append("0").append(stmp);
+ } else {
+ out.append(stmp);
+ }
+ }
+ return out.toString();
+ }
+
+ private static byte[] hex2byte(byte[] b) {
+ int size = 2;
+ if ((b.length % size) != 0){
+ throw new IllegalArgumentException("长度不是偶数");
+ }
+ byte[] b2 = new byte[b.length / 2];
+ for (int n = 0; n < b.length; n += size) {
+ String item = new String(b, n, 2);
+ b2[n / 2] = (byte) Integer.parseInt(item, 16);
+ }
+ return b2;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java
new file mode 100644
index 0000000..dc209a9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.poi.excel.BigExcelWriter;
+import cn.hutool.poi.excel.ExcelUtil;
+import com.example.exception.BadRequestException;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.security.MessageDigest;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * File工具类,扩展 hutool 工具包
+ *
+ *
+ * 2018-12-27
+ */
+public class FileUtil extends cn.hutool.core.io.FileUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
+
+ /**
+ * 系统临时目录
+ * <br>
+ * windows 包含路径分割符,但Linux 不包含,
+ * 在windows \\==\ 前提下,
+ * 为安全起见 同意拼装 路径分割符,
+ * <pre>
+ * java.io.tmpdir
+ * windows : C:\Users/xxx\AppData\Local\Temp\
+ * linux: /temp
+ * </pre>
+ */
+ public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
+ /**
+ * 定义GB的计算常量
+ */
+ private static final int GB = 1024 * 1024 * 1024;
+ /**
+ * 定义MB的计算常量
+ */
+ private static final int MB = 1024 * 1024;
+ /**
+ * 定义KB的计算常量
+ */
+ private static final int KB = 1024;
+
+ /**
+ * 格式化小数
+ */
+ private static final DecimalFormat DF = new DecimalFormat("0.00");
+
+ public static final String IMAGE = "图片";
+ public static final String TXT = "文档";
+ public static final String MUSIC = "音乐";
+ public static final String VIDEO = "视频";
+ public static final String OTHER = "其他";
+
+
+ /**
+ * MultipartFile转File
+ */
+ public static File toFile(MultipartFile multipartFile) {
+ // 获取文件名
+ String fileName = multipartFile.getOriginalFilename();
+ // 获取文件后缀
+ String prefix = "." + getExtensionName(fileName);
+ File file = null;
+ try {
+ // 用uuid作为文件名,防止生成的临时文件重复
+ file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
+ // MultipartFile to File
+ multipartFile.transferTo(file);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ return file;
+ }
+
+ /**
+ * 获取文件扩展名,不带 .
+ */
+ public static String getExtensionName(String filename) {
+ if ((filename != null) && (filename.length() > 0)) {
+ int dot = filename.lastIndexOf('.');
+ if ((dot > -1) && (dot < (filename.length() - 1))) {
+ return filename.substring(dot + 1);
+ }
+ }
+ return filename;
+ }
+
+ /**
+ * Java文件操作 获取不带扩展名的文件名
+ */
+ public static String getFileNameNoEx(String filename) {
+ if ((filename != null) && (filename.length() > 0)) {
+ int dot = filename.lastIndexOf('.');
+ if ((dot > -1) && (dot < (filename.length()))) {
+ return filename.substring(0, dot);
+ }
+ }
+ return filename;
+ }
+
+ /**
+ * 文件大小转换
+ */
+ public static String getSize(long size) {
+ String resultSize;
+ if (size / GB >= 1) {
+ //如果当前Byte的值大于等于1GB
+ resultSize = DF.format(size / (float) GB) + "GB ";
+ } else if (size / MB >= 1) {
+ //如果当前Byte的值大于等于1MB
+ resultSize = DF.format(size / (float) MB) + "MB ";
+ } else if (size / KB >= 1) {
+ //如果当前Byte的值大于等于1KB
+ resultSize = DF.format(size / (float) KB) + "KB ";
+ } else {
+ resultSize = size + "B ";
+ }
+ return resultSize;
+ }
+
+ /**
+ * inputStream 转 File
+ */
+ static File inputStreamToFile(InputStream ins, String name){
+ File file = new File(SYS_TEM_DIR + name);
+ if (file.exists()) {
+ return file;
+ }
+ OutputStream os = null;
+ try {
+ os = new FileOutputStream(file);
+ int bytesRead;
+ int len = 8192;
+ byte[] buffer = new byte[len];
+ while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
+ os.write(buffer, 0, bytesRead);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ CloseUtil.close(os);
+ CloseUtil.close(ins);
+ }
+ return file;
+ }
+
+ /**
+ * 将文件名解析成文件的上传路径
+ */
+ public static File upload(MultipartFile file, String filePath) {
+ Date date = new Date();
+ SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
+ String name = getFileNameNoEx(file.getOriginalFilename());
+ String suffix = getExtensionName(file.getOriginalFilename());
+ String nowStr = "-" + format.format(date);
+ try {
+ String fileName = name + nowStr + "." + suffix;
+ String path = filePath + fileName;
+ // getCanonicalFile 可解析正确各种路径
+ File dest = new File(path).getCanonicalFile();
+ // 检测是否存在目录
+ if (!dest.getParentFile().exists()) {
+ if (!dest.getParentFile().mkdirs()) {
+ System.out.println("was not successful.");
+ }
+ }
+ // 文件写入
+ file.transferTo(dest);
+ return dest;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return null;
+ }
+
+ /**
+ * 导出excel
+ */
+ public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
+ String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
+ File file = new File(tempPath);
+ BigExcelWriter writer = ExcelUtil.getBigWriter(file);
+ // 一次性写出内容,使用默认样式,强制输出标题
+ writer.write(list, true);
+ SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
+ //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法
+ sheet.trackAllColumnsForAutoSizing();
+ //列宽自适应
+ writer.autoSizeColumnAll();
+ //response为HttpServletResponse对象
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
+ //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
+ response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
+ ServletOutputStream out = response.getOutputStream();
+ // 终止后删除临时文件
+ file.deleteOnExit();
+ writer.flush(out, true);
+ //此处记得关闭输出Servlet流
+ IoUtil.close(out);
+ }
+
+ public static String getFileType(String type) {
+ String documents = "txt doc pdf ppt pps xlsx xls docx";
+ String music = "mp3 wav wma mpa ram ra aac aif m4a";
+ String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
+ String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
+ if (image.contains(type)) {
+ return IMAGE;
+ } else if (documents.contains(type)) {
+ return TXT;
+ } else if (music.contains(type)) {
+ return MUSIC;
+ } else if (video.contains(type)) {
+ return VIDEO;
+ } else {
+ return OTHER;
+ }
+ }
+
+ public static void checkSize(long maxSize, long size) {
+ // 1M
+ int len = 1024 * 1024;
+ if (size > (maxSize * len)) {
+ throw new BadRequestException("文件超出规定大小:" + maxSize + "MB");
+ }
+ }
+
+ /**
+ * 判断两个文件是否相同
+ */
+ public static boolean check(File file1, File file2) {
+ String img1Md5 = getMd5(file1);
+ String img2Md5 = getMd5(file2);
+ if(img1Md5 != null){
+ return img1Md5.equals(img2Md5);
+ }
+ return false;
+ }
+
+ /**
+ * 判断两个文件是否相同
+ */
+ public static boolean check(String file1Md5, String file2Md5) {
+ return file1Md5.equals(file2Md5);
+ }
+
+ private static byte[] getByte(File file) {
+ // 得到文件长度
+ byte[] b = new byte[(int) file.length()];
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ try {
+ System.out.println(in.read(b));
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ } finally {
+ CloseUtil.close(in);
+ }
+ return b;
+ }
+
+ private static String getMd5(byte[] bytes) {
+ // 16进制字符
+ char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ try {
+ MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+ mdTemp.update(bytes);
+ byte[] md = mdTemp.digest();
+ int j = md.length;
+ char[] str = new char[j * 2];
+ int k = 0;
+ // 移位 输出字符串
+ for (byte byte0 : md) {
+ str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+ str[k++] = hexDigits[byte0 & 0xf];
+ }
+ return new String(str);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return null;
+ }
+
+ /**
+ * 下载文件
+ *
+ * @param request /
+ * @param response /
+ * @param file /
+ */
+ public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
+ response.setCharacterEncoding(request.getCharacterEncoding());
+ response.setContentType("application/octet-stream");
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(file);
+ response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
+ IOUtils.copy(fis, response.getOutputStream());
+ response.flushBuffer();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ if (deleteOnExit) {
+ file.deleteOnExit();
+ }
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ public static String getMd5(File file) {
+ return getMd5(getByte(file));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java
new file mode 100644
index 0000000..5bea120
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import org.springframework.data.domain.Page;
+import java.util.*;
+
+/**
+ * 分页工具
+ *
+ * 2018-12-10
+ */
+public class PageUtil extends cn.hutool.core.util.PageUtil {
+
+ /**
+ * List 分页
+ */
+ public static List toPage(int page, int size , List list) {
+ int fromIndex = page * size;
+ int toIndex = page * size + size;
+ if(fromIndex > list.size()){
+ return new ArrayList();
+ } else if(toIndex >= list.size()) {
+ return list.subList(fromIndex,list.size());
+ } else {
+ return list.subList(fromIndex,toIndex);
+ }
+ }
+
+ /**
+ * Page 数据处理,预防redis反序列化报错
+ */
+ public static Map<String,Object> toPage(Page page) {
+ Map<String,Object> map = new LinkedHashMap<>(2);
+ map.put("content",page.getContent());
+ map.put("totalElements",page.getTotalElements());
+ return map;
+ }
+
+ /**
+ * 自定义分页
+ */
+ public static Map<String,Object> toPage(Object object, Object totalElements) {
+ Map<String,Object> map = new LinkedHashMap<>(2);
+ map.put("content",object);
+ map.put("totalElements",totalElements);
+ return map;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java
new file mode 100644
index 0000000..e9cf239
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.extern.slf4j.Slf4j;
+import com.example.annotation.DataPermission;
+import com.example.annotation.Query;
+import javax.persistence.criteria.*;
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ *
+ * 2019-6-4 14:59:48
+ */
+@Slf4j
+@SuppressWarnings({"unchecked","all"})
+public class QueryHelp {
+
+ public static <R, Q> Predicate getPredicate(Root<R> root, Q query, CriteriaBuilder cb) {
+ List<Predicate> list = new ArrayList<>();
+ if(query == null){
+ return cb.and(list.toArray(new Predicate[0]));
+ }
+ // 数据权限验证
+ DataPermission permission = query.getClass().getAnnotation(DataPermission.class);
+ if(permission != null){
+ // 获取数据权限
+ List<Long> dataScopes = SecurityUtils.getCurrentUserDataScope();
+ if(CollectionUtil.isNotEmpty(dataScopes)){
+ if(StringUtils.isNotBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) {
+ Join join = root.join(permission.joinName(), JoinType.LEFT);
+ list.add(getExpression(permission.fieldName(),join, root).in(dataScopes));
+ } else if (StringUtils.isBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) {
+ list.add(getExpression(permission.fieldName(),null, root).in(dataScopes));
+ }
+ }
+ }
+ try {
+ List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
+ for (Field field : fields) {
+ boolean accessible = field.isAccessible();
+ // 设置对象的访问权限,保证对private的属性的访
+ field.setAccessible(true);
+ Query q = field.getAnnotation(Query.class);
+ if (q != null) {
+ String propName = q.propName();
+ String joinName = q.joinName();
+ String blurry = q.blurry();
+ String attributeName = isBlank(propName) ? field.getName() : propName;
+ Class<?> fieldType = field.getType();
+ Object val = field.get(query);
+ if (ObjectUtil.isNull(val) || "".equals(val)) {
+ continue;
+ }
+ Join join = null;
+ // 模糊多字段
+ if (ObjectUtil.isNotEmpty(blurry)) {
+ String[] blurrys = blurry.split(",");
+ List<Predicate> orPredicate = new ArrayList<>();
+ for (String s : blurrys) {
+ orPredicate.add(cb.like(root.get(s)
+ .as(String.class), "%" + val.toString() + "%"));
+ }
+ Predicate[] p = new Predicate[orPredicate.size()];
+ list.add(cb.or(orPredicate.toArray(p)));
+ continue;
+ }
+ if (ObjectUtil.isNotEmpty(joinName)) {
+ String[] joinNames = joinName.split(">");
+ for (String name : joinNames) {
+ switch (q.join()) {
+ case LEFT:
+ if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
+ join = join.join(name, JoinType.LEFT);
+ } else {
+ join = root.join(name, JoinType.LEFT);
+ }
+ break;
+ case RIGHT:
+ if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
+ join = join.join(name, JoinType.RIGHT);
+ } else {
+ join = root.join(name, JoinType.RIGHT);
+ }
+ break;
+ case INNER:
+ if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
+ join = join.join(name, JoinType.INNER);
+ } else {
+ join = root.join(name, JoinType.INNER);
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ switch (q.type()) {
+ case EQUAL:
+ list.add(cb.equal(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType),val));
+ break;
+ case GREATER_THAN:
+ list.add(cb.greaterThanOrEqualTo(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType), (Comparable) val));
+ break;
+ case LESS_THAN:
+ list.add(cb.lessThanOrEqualTo(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType), (Comparable) val));
+ break;
+ case LESS_THAN_NQ:
+ list.add(cb.lessThan(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType), (Comparable) val));
+ break;
+ case INNER_LIKE:
+ list.add(cb.like(getExpression(attributeName,join,root)
+ .as(String.class), "%" + val.toString() + "%"));
+ break;
+ case LEFT_LIKE:
+ list.add(cb.like(getExpression(attributeName,join,root)
+ .as(String.class), "%" + val.toString()));
+ break;
+ case RIGHT_LIKE:
+ list.add(cb.like(getExpression(attributeName,join,root)
+ .as(String.class), val.toString() + "%"));
+ break;
+ case IN:
+ if (CollUtil.isNotEmpty((Collection<Object>)val)) {
+ list.add(getExpression(attributeName,join,root).in((Collection<Object>) val));
+ }
+ break;
+ case NOT_IN:
+ if (CollUtil.isNotEmpty((Collection<Object>)val)) {
+ list.add(getExpression(attributeName,join,root).in((Collection<Object>) val).not());
+ }
+ break;
+ case NOT_EQUAL:
+ list.add(cb.notEqual(getExpression(attributeName,join,root), val));
+ break;
+ case NOT_NULL:
+ list.add(cb.isNotNull(getExpression(attributeName,join,root)));
+ break;
+ case IS_NULL:
+ list.add(cb.isNull(getExpression(attributeName,join,root)));
+ break;
+ case BETWEEN:
+ List<Object> between = new ArrayList<>((List<Object>)val);
+ list.add(cb.between(getExpression(attributeName, join, root).as((Class<? extends Comparable>) between.get(0).getClass()),
+ (Comparable) between.get(0), (Comparable) between.get(1)));
+ break;
+ default: break;
+ }
+ }
+ field.setAccessible(accessible);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ int size = list.size();
+ return cb.and(list.toArray(new Predicate[size]));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T, R> Expression<T> getExpression(String attributeName, Join join, Root<R> root) {
+ if (ObjectUtil.isNotEmpty(join)) {
+ return join.get(attributeName);
+ } else {
+ return root.get(attributeName);
+ }
+ }
+
+ private static boolean isBlank(final CharSequence cs) {
+ int strLen;
+ if (cs == null || (strLen = cs.length()) == 0) {
+ return true;
+ }
+ for (int i = 0; i < strLen; i++) {
+ if (!Character.isWhitespace(cs.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static List<Field> getAllFields(Class clazz, List<Field> fields) {
+ if (clazz != null) {
+ fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+ getAllFields(clazz.getSuperclass(), fields);
+ }
+ return fields;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java
new file mode 100644
index 0000000..4de0949
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java
@@ -0,0 +1,708 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author /
+ */
+@Component
+@SuppressWarnings({"unchecked", "all"})
+public class RedisUtils {
+ private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);
+ private RedisTemplate<Object, Object> redisTemplate;
+ @Value("${jwt.online-key}")
+ private String onlineKey;
+
+ public RedisUtils(RedisTemplate<Object, Object> redisTemplate) {
+ this.redisTemplate = redisTemplate;
+ }
+
+ /**
+ * 指定缓存失效时间
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ */
+ public boolean expire(String key, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.expire(key, time, TimeUnit.SECONDS);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 指定缓存失效时间
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ * @param timeUnit 单位
+ */
+ public boolean expire(String key, long time, TimeUnit timeUnit) {
+ try {
+ if (time > 0) {
+ redisTemplate.expire(key, time, timeUnit);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 根据 key 获取过期时间
+ *
+ * @param key 键 不能为null
+ * @return 时间(秒) 返回0代表为永久有效
+ */
+ public long getExpire(Object key) {
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 查找匹配key
+ *
+ * @param pattern key
+ * @return /
+ */
+ public List<String> scan(String pattern) {
+ ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
+ RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
+ RedisConnection rc = Objects.requireNonNull(factory).getConnection();
+ Cursor<byte[]> cursor = rc.scan(options);
+ List<String> result = new ArrayList<>();
+ while (cursor.hasNext()) {
+ result.add(new String(cursor.next()));
+ }
+ try {
+ RedisConnectionUtils.releaseConnection(rc, factory);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return result;
+ }
+
+ /**
+ * 分页查询 key
+ *
+ * @param patternKey key
+ * @param page 页码
+ * @param size 每页数目
+ * @return /
+ */
+ public List<String> findKeysForPage(String patternKey, int page, int size) {
+ ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
+ RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
+ RedisConnection rc = Objects.requireNonNull(factory).getConnection();
+ Cursor<byte[]> cursor = rc.scan(options);
+ List<String> result = new ArrayList<>(size);
+ int tmpIndex = 0;
+ int fromIndex = page * size;
+ int toIndex = page * size + size;
+ while (cursor.hasNext()) {
+ if (tmpIndex >= fromIndex && tmpIndex < toIndex) {
+ result.add(new String(cursor.next()));
+ tmpIndex++;
+ continue;
+ }
+ // 获取到满足条件的数据后,就可以退出了
+ if (tmpIndex >= toIndex) {
+ break;
+ }
+ tmpIndex++;
+ cursor.next();
+ }
+ try {
+ RedisConnectionUtils.releaseConnection(rc, factory);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return result;
+ }
+
+ /**
+ * 判断key是否存在
+ *
+ * @param key 键
+ * @return true 存在 false不存在
+ */
+ public boolean hasKey(String key) {
+ try {
+ return redisTemplate.hasKey(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 删除缓存
+ *
+ * @param key 可以传一个值 或多个
+ */
+ public void del(String... keys) {
+ if (keys != null && keys.length > 0) {
+ if (keys.length == 1) {
+ boolean result = redisTemplate.delete(keys[0]);
+ log.debug("--------------------------------------------");
+ log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString());
+ log.debug("--------------------------------------------");
+ } else {
+ Set<Object> keySet = new HashSet<>();
+ for (String key : keys) {
+ keySet.addAll(redisTemplate.keys(key));
+ }
+ long count = redisTemplate.delete(keySet);
+ log.debug("--------------------------------------------");
+ log.debug("成功删除缓存:" + keySet.toString());
+ log.debug("缓存删除数量:" + count + "个");
+ log.debug("--------------------------------------------");
+ }
+ }
+ }
+
+ // ============================String=============================
+
+ /**
+ * 普通缓存获取
+ *
+ * @param key 键
+ * @return 值
+ */
+ public Object get(String key) {
+ return key == null ? null : redisTemplate.opsForValue().get(key);
+ }
+
+ /**
+ * 批量获取
+ *
+ * @param keys
+ * @return
+ */
+ public List<Object> multiGet(List<String> keys) {
+ List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys));
+ List resultList = Lists.newArrayList();
+ Optional.ofNullable(list).ifPresent(e-> list.forEach(ele-> Optional.ofNullable(ele).ifPresent(resultList::add)));
+ return resultList;
+ }
+
+ /**
+ * 普通缓存放入
+ *
+ * @param key 键
+ * @param value 值
+ * @return true成功 false失败
+ */
+ public boolean set(String key, Object value) {
+ try {
+ redisTemplate.opsForValue().set(key, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 普通缓存放入并设置时间
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
+ * @return true成功 false 失败
+ */
+ public boolean set(String key, Object value, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+ } else {
+ set(key, value);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 普通缓存放入并设置时间
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间
+ * @param timeUnit 类型
+ * @return true成功 false 失败
+ */
+ public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
+ try {
+ if (time > 0) {
+ redisTemplate.opsForValue().set(key, value, time, timeUnit);
+ } else {
+ set(key, value);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ // ================================Map=================================
+
+ /**
+ * HashGet
+ *
+ * @param key 键 不能为null
+ * @param item 项 不能为null
+ * @return 值
+ */
+ public Object hget(String key, String item) {
+ return redisTemplate.opsForHash().get(key, item);
+ }
+
+ /**
+ * 获取hashKey对应的所有键值
+ *
+ * @param key 键
+ * @return 对应的多个键值
+ */
+ public Map<Object, Object> hmget(String key) {
+ return redisTemplate.opsForHash().entries(key);
+
+ }
+
+ /**
+ * HashSet
+ *
+ * @param key 键
+ * @param map 对应多个键值
+ * @return true 成功 false 失败
+ */
+ public boolean hmset(String key, Map<String, Object> map) {
+ try {
+ redisTemplate.opsForHash().putAll(key, map);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * HashSet 并设置时间
+ *
+ * @param key 键
+ * @param map 对应多个键值
+ * @param time 时间(秒)
+ * @return true成功 false失败
+ */
+ public boolean hmset(String key, Map<String, Object> map, long time) {
+ try {
+ redisTemplate.opsForHash().putAll(key, map);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 向一张hash表中放入数据,如果不存在将创建
+ *
+ * @param key 键
+ * @param item 项
+ * @param value 值
+ * @return true 成功 false失败
+ */
+ public boolean hset(String key, String item, Object value) {
+ try {
+ redisTemplate.opsForHash().put(key, item, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 向一张hash表中放入数据,如果不存在将创建
+ *
+ * @param key 键
+ * @param item 项
+ * @param value 值
+ * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
+ * @return true 成功 false失败
+ */
+ public boolean hset(String key, String item, Object value, long time) {
+ try {
+ redisTemplate.opsForHash().put(key, item, value);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 删除hash表中的值
+ *
+ * @param key 键 不能为null
+ * @param item 项 可以使多个 不能为null
+ */
+ public void hdel(String key, Object... item) {
+ redisTemplate.opsForHash().delete(key, item);
+ }
+
+ /**
+ * 判断hash表中是否有该项的值
+ *
+ * @param key 键 不能为null
+ * @param item 项 不能为null
+ * @return true 存在 false不存在
+ */
+ public boolean hHasKey(String key, String item) {
+ return redisTemplate.opsForHash().hasKey(key, item);
+ }
+
+ /**
+ * hash递增 如果不存在,就会创建一个 并把新增后的值返回
+ *
+ * @param key 键
+ * @param item 项
+ * @param by 要增加几(大于0)
+ * @return
+ */
+ public double hincr(String key, String item, double by) {
+ return redisTemplate.opsForHash().increment(key, item, by);
+ }
+
+ /**
+ * hash递减
+ *
+ * @param key 键
+ * @param item 项
+ * @param by 要减少记(小于0)
+ * @return
+ */
+ public double hdecr(String key, String item, double by) {
+ return redisTemplate.opsForHash().increment(key, item, -by);
+ }
+
+ // ============================set=============================
+
+ /**
+ * 根据key获取Set中的所有值
+ *
+ * @param key 键
+ * @return
+ */
+ public Set<Object> sGet(String key) {
+ try {
+ return redisTemplate.opsForSet().members(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 根据value从一个set中查询,是否存在
+ *
+ * @param key 键
+ * @param value 值
+ * @return true 存在 false不存在
+ */
+ public boolean sHasKey(String key, Object value) {
+ try {
+ return redisTemplate.opsForSet().isMember(key, value);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将数据放入set缓存
+ *
+ * @param key 键
+ * @param values 值 可以是多个
+ * @return 成功个数
+ */
+ public long sSet(String key, Object... values) {
+ try {
+ return redisTemplate.opsForSet().add(key, values);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 将set数据放入缓存
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ * @param values 值 可以是多个
+ * @return 成功个数
+ */
+ public long sSetAndTime(String key, long time, Object... values) {
+ try {
+ Long count = redisTemplate.opsForSet().add(key, values);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return count;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 获取set缓存的长度
+ *
+ * @param key 键
+ * @return
+ */
+ public long sGetSetSize(String key) {
+ try {
+ return redisTemplate.opsForSet().size(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 移除值为value的
+ *
+ * @param key 键
+ * @param values 值 可以是多个
+ * @return 移除的个数
+ */
+ public long setRemove(String key, Object... values) {
+ try {
+ Long count = redisTemplate.opsForSet().remove(key, values);
+ return count;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ // ===============================list=================================
+
+ /**
+ * 获取list缓存的内容
+ *
+ * @param key 键
+ * @param start 开始
+ * @param end 结束 0 到 -1代表所有值
+ * @return
+ */
+ public List<Object> lGet(String key, long start, long end) {
+ try {
+ return redisTemplate.opsForList().range(key, start, end);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 获取list缓存的长度
+ *
+ * @param key 键
+ * @return
+ */
+ public long lGetListSize(String key) {
+ try {
+ return redisTemplate.opsForList().size(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 通过索引 获取list中的值
+ *
+ * @param key 键
+ * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
+ * @return
+ */
+ public Object lGetIndex(String key, long index) {
+ try {
+ return redisTemplate.opsForList().index(key, index);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @return
+ */
+ public boolean lSet(String key, Object value) {
+ try {
+ redisTemplate.opsForList().rightPush(key, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒)
+ * @return
+ */
+ public boolean lSet(String key, Object value, long time) {
+ try {
+ redisTemplate.opsForList().rightPush(key, value);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @return
+ */
+ public boolean lSet(String key, List<Object> value) {
+ try {
+ redisTemplate.opsForList().rightPushAll(key, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒)
+ * @return
+ */
+ public boolean lSet(String key, List<Object> value, long time) {
+ try {
+ redisTemplate.opsForList().rightPushAll(key, value);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 根据索引修改list中的某条数据
+ *
+ * @param key 键
+ * @param index 索引
+ * @param value 值
+ * @return /
+ */
+ public boolean lUpdateIndex(String key, long index, Object value) {
+ try {
+ redisTemplate.opsForList().set(key, index, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 移除N个值为value
+ *
+ * @param key 键
+ * @param count 移除多少个
+ * @param value 值
+ * @return 移除的个数
+ */
+ public long lRemove(String key, long count, Object value) {
+ try {
+ return redisTemplate.opsForList().remove(key, count, value);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * @param prefix 前缀
+ * @param ids id
+ */
+ public void delByKeys(String prefix, Set<Long> ids) {
+ Set<Object> keys = new HashSet<>();
+ for (Long id : ids) {
+ keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString()));
+ }
+ long count = redisTemplate.delete(keys);
+ // 此处提示可自行删除
+ log.debug("--------------------------------------------");
+ log.debug("成功删除缓存:" + keys.toString());
+ log.debug("缓存删除数量:" + count + "个");
+ log.debug("--------------------------------------------");
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java
new file mode 100644
index 0000000..09764e4
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Objects;
+
+/**
+ * 获取 HttpServletRequest
+ *
+ * 2018-11-24
+ */
+public class RequestHolder {
+
+ public static HttpServletRequest getHttpServletRequest() {
+ return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java
new file mode 100644
index 0000000..4611a15
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java
@@ -0,0 +1,198 @@
+package com.example.utils;
+
+import org.apache.commons.codec.binary.Base64;
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * @author https://www.cnblogs.com/nihaorz/p/10690643.html
+ * @description Rsa 工具类,公钥私钥生成,加解密
+ * 2020-05-18
+ **/
+public class RsaUtils {
+
+ private static final String SRC = "123456";
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("\n");
+ RsaKeyPair keyPair = generateKeyPair();
+ System.out.println("公钥:" + keyPair.getPublicKey());
+ System.out.println("私钥:" + keyPair.getPrivateKey());
+ System.out.println("\n");
+ test1(keyPair);
+ System.out.println("\n");
+ test2(keyPair);
+ System.out.println("\n");
+ }
+
+ /**
+ * 公钥加密私钥解密
+ */
+ private static void test1(RsaKeyPair keyPair) throws Exception {
+ System.out.println("***************** 公钥加密私钥解密开始 *****************");
+ String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);
+ String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
+ System.out.println("加密前:" + RsaUtils.SRC);
+ System.out.println("加密后:" + text1);
+ System.out.println("解密后:" + text2);
+ if (RsaUtils.SRC.equals(text2)) {
+ System.out.println("解密字符串和原始字符串一致,解密成功");
+ } else {
+ System.out.println("解密字符串和原始字符串不一致,解密失败");
+ }
+ System.out.println("***************** 公钥加密私钥解密结束 *****************");
+ }
+
+ /**
+ * 私钥加密公钥解密
+ * @throws Exception /
+ */
+ private static void test2(RsaKeyPair keyPair) throws Exception {
+ System.out.println("***************** 私钥加密公钥解密开始 *****************");
+ String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);
+ String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
+ System.out.println("加密前:" + RsaUtils.SRC);
+ System.out.println("加密后:" + text1);
+ System.out.println("解密后:" + text2);
+ if (RsaUtils.SRC.equals(text2)) {
+ System.out.println("解密字符串和原始字符串一致,解密成功");
+ } else {
+ System.out.println("解密字符串和原始字符串不一致,解密失败");
+ }
+ System.out.println("***************** 私钥加密公钥解密结束 *****************");
+ }
+
+ /**
+ * 公钥解密
+ *
+ * @param publicKeyText 公钥
+ * @param text 待解密的信息
+ * @return /
+ * @throws Exception /
+ */
+ public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
+ X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, publicKey);
+ byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));
+ return new String(result);
+ }
+
+ /**
+ * 私钥加密
+ *
+ * @param privateKeyText 私钥
+ * @param text 待加密的信息
+ * @return /
+ * @throws Exception /
+ */
+ public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+ byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());
+ return Base64.encodeBase64String(result);
+ }
+
+ /**
+ * 私钥解密
+ *
+ * @param privateKeyText 私钥
+ * @param text 待解密的文本
+ * @return /
+ * @throws Exception /
+ */
+ public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
+ byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));
+ return new String(result);
+ }
+
+ /**
+ * 公钥加密
+ *
+ * @param publicKeyText 公钥
+ * @param text 待加密的文本
+ * @return /
+ */
+ public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
+ X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());
+ return Base64.encodeBase64String(result);
+ }
+
+ private static byte[] doLongerCipherFinal(int opMode,Cipher cipher, byte[] source) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (opMode == Cipher.DECRYPT_MODE) {
+ out.write(cipher.doFinal(source));
+ } else {
+ int offset = 0;
+ int totalSize = source.length;
+ while (totalSize - offset > 0) {
+ int size = Math.min(cipher.getOutputSize(0) - 11, totalSize - offset);
+ out.write(cipher.doFinal(source, offset, size));
+ offset += size;
+ }
+ }
+ out.close();
+ return out.toByteArray();
+ }
+
+ /**
+ * 构建RSA密钥对
+ *
+ * @return /
+ * @throws NoSuchAlgorithmException /
+ */
+ public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(1024);
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
+ RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
+ String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
+ String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
+ return new RsaKeyPair(publicKeyString, privateKeyString);
+ }
+
+
+ /**
+ * RSA密钥对对象
+ */
+ public static class RsaKeyPair {
+
+ private final String publicKey;
+ private final String privateKey;
+
+ public RsaKeyPair(String publicKey, String privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java
new file mode 100644
index 0000000..e263130
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.example.utils.enums.DataScopeEnum;
+import lombok.extern.slf4j.Slf4j;
+import com.example.exception.BadRequestException;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import java.util.List;
+
+/**
+ * 获取当前登录的用户
+ *
+ * 2019-01-17
+ */
+@Slf4j
+public class SecurityUtils {
+
+ /**
+ * 获取当前登录的用户
+ * @return UserDetails
+ */
+ public static UserDetails getCurrentUser() {
+ UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class);
+ return userDetailsService.loadUserByUsername(getCurrentUsername());
+ }
+
+ /**
+ * 获取系统用户名称
+ *
+ * @return 系统用户名称
+ */
+ public static String getCurrentUsername() {
+ final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null) {
+ throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期");
+ }
+ if (authentication.getPrincipal() instanceof UserDetails) {
+ UserDetails userDetails = (UserDetails) authentication.getPrincipal();
+ return userDetails.getUsername();
+ }
+ throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息");
+ }
+
+ /**
+ * 获取系统用户ID
+ * @return 系统用户ID
+ */
+ public static Long getCurrentUserId() {
+ UserDetails userDetails = getCurrentUser();
+ return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class);
+ }
+
+ /**
+ * 获取当前用户的数据权限
+ * @return /
+ */
+ public static List<Long> getCurrentUserDataScope(){
+ UserDetails userDetails = getCurrentUser();
+ JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes"));
+ return JSONUtil.toList(array,Long.class);
+ }
+
+ /**
+ * 获取数据权限级别
+ * @return 级别
+ */
+ public static String getDataScopeType() {
+ List<Long> dataScopes = getCurrentUserDataScope();
+ if(dataScopes.size() != 0){
+ return "";
+ }
+ return DataScopeEnum.ALL.getValue();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java
new file mode 100644
index 0000000..454b7c8
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.env.Environment;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Jie
+ * 2019-01-07
+ */
+@Slf4j
+public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
+
+ private static ApplicationContext applicationContext = null;
+ private static final List<CallBack> CALL_BACKS = new ArrayList<>();
+ private static boolean addCallback = true;
+
+ /**
+ * 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。
+ * 在SpringContextHolder 初始化后,进行回调使用
+ *
+ * @param callBack 回调函数
+ */
+ public synchronized static void addCallBacks(CallBack callBack) {
+ if (addCallback) {
+ SpringContextHolder.CALL_BACKS.add(callBack);
+ } else {
+ log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName());
+ callBack.executor();
+ }
+ }
+
+ /**
+ * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getBean(String name) {
+ assertContextInjected();
+ return (T) applicationContext.getBean(name);
+ }
+
+ /**
+ * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+ */
+ public static <T> T getBean(Class<T> requiredType) {
+ assertContextInjected();
+ return applicationContext.getBean(requiredType);
+ }
+
+ /**
+ * 获取SpringBoot 配置信息
+ *
+ * @param property 属性key
+ * @param defaultValue 默认值
+ * @param requiredType 返回类型
+ * @return /
+ */
+ public static <T> T getProperties(String property, T defaultValue, Class<T> requiredType) {
+ T result = defaultValue;
+ try {
+ result = getBean(Environment.class).getProperty(property, requiredType);
+ } catch (Exception ignored) {}
+ return result;
+ }
+
+ /**
+ * 获取SpringBoot 配置信息
+ *
+ * @param property 属性key
+ * @return /
+ */
+ public static String getProperties(String property) {
+ return getProperties(property, null, String.class);
+ }
+
+ /**
+ * 获取SpringBoot 配置信息
+ *
+ * @param property 属性key
+ * @param requiredType 返回类型
+ * @return /
+ */
+ public static <T> T getProperties(String property, Class<T> requiredType) {
+ return getProperties(property, null, requiredType);
+ }
+
+ /**
+ * 检查ApplicationContext不为空.
+ */
+ private static void assertContextInjected() {
+ if (applicationContext == null) {
+ throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
+ ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
+ }
+ }
+
+ /**
+ * 清除SpringContextHolder中的ApplicationContext为Null.
+ */
+ private static void clearHolder() {
+ log.debug("清除SpringContextHolder中的ApplicationContext:"
+ + applicationContext);
+ applicationContext = null;
+ }
+
+ @Override
+ public void destroy() {
+ SpringContextHolder.clearHolder();
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ if (SpringContextHolder.applicationContext != null) {
+ log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
+ }
+ SpringContextHolder.applicationContext = applicationContext;
+ if (addCallback) {
+ for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
+ callBack.executor();
+ }
+ CALL_BACKS.clear();
+ }
+ SpringContextHolder.addCallback = false;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java
new file mode 100644
index 0000000..a5fd454
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import com.example.config.ElAdminProperties;
+import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
+import net.dreamlu.mica.ip2region.core.IpInfo;
+import nl.basjes.parse.useragent.UserAgent;
+import nl.basjes.parse.useragent.UserAgentAnalyzer;
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Enumeration;
+
+/**
+ *
+ * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
+ */
+@Slf4j
+public class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+ private static final char SEPARATOR = '_';
+ private static final String UNKNOWN = "unknown";
+
+ /**
+ * 注入bean
+ */
+ private final static Ip2regionSearcher IP_SEARCHER = SpringContextHolder.getBean(Ip2regionSearcher.class);
+
+
+ private static final UserAgentAnalyzer USER_AGENT_ANALYZER = UserAgentAnalyzer
+ .newBuilder()
+ .hideMatcherLoadStats()
+ .withCache(10000)
+ .withField(UserAgent.AGENT_NAME_VERSION)
+ .build();
+
+ /**
+ * 驼峰命名法工具
+ *
+ * @return toCamelCase(" hello_world ") == "helloWorld"
+ * toCapitalizeCamelCase("hello_world") == "HelloWorld"
+ * toUnderScoreCase("helloWorld") = "hello_world"
+ */
+ public static String toCamelCase(String s) {
+ if (s == null) {
+ return null;
+ }
+
+ 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();
+ }
+
+ /**
+ * 驼峰命名法工具
+ *
+ * @return toCamelCase(" hello_world ") == "helloWorld"
+ * toCapitalizeCamelCase("hello_world") == "HelloWorld"
+ * toUnderScoreCase("helloWorld") = "hello_world"
+ */
+ public static String toCapitalizeCamelCase(String s) {
+ if (s == null) {
+ return null;
+ }
+ s = toCamelCase(s);
+ return s.substring(0, 1).toUpperCase() + s.substring(1);
+ }
+
+ /**
+ * 驼峰命名法工具
+ *
+ * @return toCamelCase(" hello_world ") == "helloWorld"
+ * toCapitalizeCamelCase("hello_world") == "HelloWorld"
+ * toUnderScoreCase("helloWorld") = "hello_world"
+ */
+ static String toUnderScoreCase(String s) {
+ if (s == null) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ boolean upperCase = false;
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+
+ boolean nextUpperCase = true;
+
+ if (i < (s.length() - 1)) {
+ nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
+ }
+
+ if ((i > 0) && Character.isUpperCase(c)) {
+ if (!upperCase || !nextUpperCase) {
+ sb.append(SEPARATOR);
+ }
+ upperCase = true;
+ } else {
+ upperCase = false;
+ }
+
+ sb.append(Character.toLowerCase(c));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 获取ip地址
+ */
+ public static String getIp(HttpServletRequest request) {
+ 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("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ String comma = ",";
+ String localhost = "127.0.0.1";
+ if (ip.contains(comma)) {
+ ip = ip.split(",")[0];
+ }
+ if (localhost.equals(ip)) {
+ // 获取本机真正的ip地址
+ try {
+ ip = InetAddress.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ return ip;
+ }
+
+ /**
+ * 根据ip获取详细地址
+ */
+ public static String getCityInfo(String ip) {
+ if (ElAdminProperties.ipLocal) {
+ return getLocalCityInfo(ip);
+ } else {
+ return getHttpCityInfo(ip);
+ }
+ }
+
+ /**
+ * 根据ip获取详细地址
+ */
+ public static String getHttpCityInfo(String ip) {
+ String api = String.format(ElAdminConstant.Url.IP_URL, ip);
+ JSONObject object = JSONUtil.parseObj(HttpUtil.get(api));
+ return object.get("addr", String.class);
+ }
+
+ /**
+ * 根据ip获取详细地址
+ */
+ public static String getLocalCityInfo(String ip) {
+ IpInfo ipInfo = IP_SEARCHER.memorySearch(ip);
+ if(ipInfo != null){
+ return ipInfo.getAddress();
+ }
+ return null;
+
+ }
+
+ public static String getBrowser(HttpServletRequest request) {
+ UserAgent.ImmutableUserAgent userAgent = USER_AGENT_ANALYZER.parse(request.getHeader("User-Agent"));
+ return userAgent.get(UserAgent.AGENT_NAME_VERSION).getValue();
+ }
+
+ /**
+ * 获得当天是周几
+ */
+ public static String getWeekDay() {
+ String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(new Date());
+
+ int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+ if (w < 0) {
+ w = 0;
+ }
+ return weekDays[w];
+ }
+
+ /**
+ * 获取当前机器的IP
+ *
+ * @return /
+ */
+ public static String getLocalIp() {
+ try {
+ InetAddress candidateAddress = null;
+ // 遍历所有的网络接口
+ for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) {
+ NetworkInterface anInterface = interfaces.nextElement();
+ // 在所有的接口下再遍历IP
+ for (Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) {
+ InetAddress inetAddr = inetAddresses.nextElement();
+ // 排除loopback类型地址
+ if (!inetAddr.isLoopbackAddress()) {
+ if (inetAddr.isSiteLocalAddress()) {
+ // 如果是site-local地址,就是它了
+ return inetAddr.getHostAddress();
+ } else if (candidateAddress == null) {
+ // site-local类型的地址未被发现,先记录候选地址
+ candidateAddress = inetAddr;
+ }
+ }
+ }
+ }
+ if (candidateAddress != null) {
+ return candidateAddress.getHostAddress();
+ }
+ // 如果没有发现 non-loopback地址.只能用最次选的方案
+ InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
+ if (jdkSuppliedAddress == null) {
+ return "";
+ }
+ return jdkSuppliedAddress.getHostAddress();
+ } catch (Exception e) {
+ return "";
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java
new file mode 100644
index 0000000..0ea7da7
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * 异常工具 2019-01-06
+ *
+ */
+public class ThrowableUtil {
+
+ /**
+ * 获取堆栈信息
+ */
+ public static String getStackTrace(Throwable throwable){
+ StringWriter sw = new StringWriter();
+ try (PrintWriter pw = new PrintWriter(sw)) {
+ throwable.printStackTrace(pw);
+ return sw.toString();
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java
new file mode 100644
index 0000000..7d7087d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import cn.hutool.json.JSONArray;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+
+/**
+ *
+ * 翻译工具类
+ */
+public class TranslatorUtil {
+
+ public static String translate(String word){
+ try {
+ String url = "https://translate.googleapis.com/translate_a/single?" +
+ "client=gtx&" +
+ "sl=en" +
+ "&tl=zh-CN" +
+ "&dt=t&q=" + URLEncoder.encode(word, "UTF-8");
+
+ URL obj = new URL(url);
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+ con.setRequestProperty("User-Agent", "Mozilla/5.0");
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ StringBuilder response = new StringBuilder();
+
+ while ((inputLine = in.readLine()) != null) {
+ response.append(inputLine);
+ }
+ in.close();
+ return parseResult(response.toString());
+ }catch (Exception e){
+ return word;
+ }
+ }
+
+ private static String parseResult(String inputJson){
+ JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0);
+ StringBuilder result = new StringBuilder();
+ for (Object o : jsonArray2) {
+ result.append(((JSONArray) o).get(0).toString());
+ }
+ return result.toString();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java
new file mode 100644
index 0000000..689ec6f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.example.exception.BadRequestException;
+import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
+
+/**
+ * 验证工具
+ *
+ * 2018-11-23
+ */
+public class ValidationUtil{
+
+ /**
+ * 验证空
+ */
+ public static void isNull(Object obj, String entity, String parameter , Object value){
+ if(ObjectUtil.isNull(obj)){
+ String msg = entity + " 不存在: "+ parameter +" is "+ value;
+ throw new BadRequestException(msg);
+ }
+ }
+
+ /**
+ * 验证是否为邮箱
+ */
+ public static boolean isEmail(String email) {
+ return new EmailValidator().isValid(email, null);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java
new file mode 100644
index 0000000..4f0147e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * <p>
+ * 验证码业务场景
+ * </p>
+ *
+ * 2020-05-02
+ */
+@Getter
+@AllArgsConstructor
+public enum CodeBiEnum {
+
+ /* 旧邮箱修改邮箱 */
+ ONE(1, "旧邮箱修改邮箱"),
+
+ /* 通过邮箱修改密码 */
+ TWO(2, "通过邮箱修改密码");
+
+ private final Integer code;
+ private final String description;
+
+ public static CodeBiEnum find(Integer code) {
+ for (CodeBiEnum value : CodeBiEnum.values()) {
+ if (value.getCode().equals(code)) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java
new file mode 100644
index 0000000..17a1b2d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * <p>
+ * 验证码业务场景对应的 Redis 中的 key
+ * </p>
+ *
+ * 2020-05-02
+ */
+@Getter
+@AllArgsConstructor
+public enum CodeEnum {
+
+ /* 通过手机号码重置邮箱 */
+ PHONE_RESET_EMAIL_CODE("phone_reset_email_code_", "通过手机号码重置邮箱"),
+
+ /* 通过旧邮箱重置邮箱 */
+ EMAIL_RESET_EMAIL_CODE("email_reset_email_code_", "通过旧邮箱重置邮箱"),
+
+ /* 通过手机号码重置密码 */
+ PHONE_RESET_PWD_CODE("phone_reset_pwd_code_", "通过手机号码重置密码"),
+
+ /* 通过邮箱重置密码 */
+ EMAIL_RESET_PWD_CODE("email_reset_pwd_code_", "通过邮箱重置密码");
+
+ private final String key;
+ private final String description;
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java
new file mode 100644
index 0000000..18330f2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * <p>
+ * 数据权限枚举
+ * </p>
+ *
+ * 2020-05-07
+ */
+@Getter
+@AllArgsConstructor
+public enum DataScopeEnum {
+
+ /* 全部的数据权限 */
+ ALL("全部", "全部的数据权限"),
+
+ /* 自己部门的数据权限 */
+ THIS_LEVEL("本级", "自己部门的数据权限"),
+
+ /* 自定义的数据权限 */
+ CUSTOMIZE("自定义", "自定义的数据权限");
+
+ private final String value;
+ private final String description;
+
+ public static DataScopeEnum find(String val) {
+ for (DataScopeEnum dataScopeEnum : DataScopeEnum.values()) {
+ if (dataScopeEnum.getValue().equals(val)) {
+ return dataScopeEnum;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java
new file mode 100644
index 0000000..2edd703
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description
+ * 2020-06-10
+ **/
+@Getter
+@AllArgsConstructor
+public enum RequestMethodEnum {
+
+ /**
+ * 搜寻 @AnonymousGetMapping
+ */
+ GET("GET"),
+
+ /**
+ * 搜寻 @AnonymousPostMapping
+ */
+ POST("POST"),
+
+ /**
+ * 搜寻 @AnonymousPutMapping
+ */
+ PUT("PUT"),
+
+ /**
+ * 搜寻 @AnonymousPatchMapping
+ */
+ PATCH("PATCH"),
+
+ /**
+ * 搜寻 @AnonymousDeleteMapping
+ */
+ DELETE("DELETE"),
+
+ /**
+ * 否则就是所有 Request 接口都放行
+ */
+ ALL("All");
+
+ /**
+ * Request 类型
+ */
+ private final String type;
+
+ public static RequestMethodEnum find(String type) {
+ for (RequestMethodEnum value : RequestMethodEnum.values()) {
+ if (value.getType().equals(type)) {
+ return value;
+ }
+ }
+ return ALL;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java
new file mode 100644
index 0000000..7f02b02
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java
@@ -0,0 +1,145 @@
+/**
+
+ *
+
+ *
+ *
+ */
+
+package com.example.utils.page;
+
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分页工具类
+ *
+ * @author Mark [email protected]
+ */
+public class PageUtils implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 总记录数
+ */
+ private int total;
+ /**
+ * 每页记录数
+ */
+ private int size;
+ /**
+ * 总页数
+ */
+ private int pages;
+ /**
+ * 当前页数
+ */
+ private int page;
+ /**
+ * 列表数据
+ */
+ private List<?> list;
+
+ private double totalTime;
+
+ private Object independentIpNum;
+
+ private int resultTotal;
+
+ public int getResultTotal() {
+ return resultTotal;
+ }
+
+ public void setResultTotal(int resultTotal) {
+ this.resultTotal = resultTotal;
+ }
+
+ /**
+ * 分页
+ * @param list 列表数据
+ * @param total 总记录数
+ * @param size 每页记录数
+ * @param page 当前页数
+ */
+ public PageUtils(List<?> list, int total, int size, int page ,double totalTime,int independentIpNum ,int resultTotal) {
+ this.list = list;
+ this.total = total;
+ this.size = size;
+ this.page = page;
+ this.totalTime = totalTime;
+ this.independentIpNum = independentIpNum;
+ this.resultTotal = resultTotal;
+ this.pages = (int)Math.ceil((double)total/size);
+ }
+
+ /**
+ * 分页
+ */
+ public PageUtils(IPage<?> page) {
+ this.list = page.getRecords();
+ this.total = (int)page.getTotal();
+ this.size = (int)page.getSize();
+ this.page = (int)page.getCurrent();
+ this.pages = (int)page.getPages();
+ }
+
+
+ public Object getIndependentIpNum() {
+ return independentIpNum;
+ }
+
+ public void setIndependentIpNum(Object independentIpNum) {
+ this.independentIpNum = independentIpNum;
+ }
+
+ public int getTotal() {
+ return total;
+ }
+
+ public void setTotal(int total) {
+ this.total = total;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ public int getPages() {
+ return pages;
+ }
+
+ public void setPages(int pages) {
+ this.pages = pages;
+ }
+
+ public int getPage() {
+ return page;
+ }
+
+ public double getTotalTime() {
+ return totalTime;
+ }
+
+ public void setTotalTime(double totalTime) {
+ this.totalTime = totalTime;
+ }
+
+ public void setPage(int page) {
+ this.page = page;
+ }
+
+ public List<?> getList() {
+ return list;
+ }
+
+ public void setList(List<?> list) {
+ this.list = list;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java
new file mode 100644
index 0000000..765f2f6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java
@@ -0,0 +1,64 @@
+package com.example.utils.page;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import java.util.Map;
+
+/**
+ * 查询参数
+ */
+public class Query {
+
+ private Class clz;
+
+ public Class<? extends Object> getClz() {
+ return clz;
+ }
+
+ public void setClz(Class clz) {
+ this.clz = clz;
+ }
+
+ public Query(Class clz) {
+ this.clz = clz;
+ }
+
+ public IPage getPage(Map<String, Object> params) {
+ return this.getPage(params, null, false);
+ }
+
+ public IPage getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
+ //分页参数
+ long curPage = 1;
+ long limit = 10;
+
+ if(params.get("page") != null && !"".equals(params.get("page"))){
+ curPage = Long.parseLong((String)params.get("page"));
+ }
+ if(params.get("size") != null && !"".equals(params.get("size"))){
+ limit = Long.parseLong((String)params.get("size"));
+ if(limit == -1){
+ limit = Long.MAX_VALUE;
+ curPage = 0;
+ }
+ }
+
+ //分页对象
+ Page page = new Page(curPage, limit);
+
+ //分页参数
+ params.put("page", page);
+
+
+ // 默认排序
+ if(isAsc) {
+ page.setAsc(defaultOrderField);
+ }else {
+ page.setDesc(defaultOrderField);
+ }
+
+ return page;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java
new file mode 100644
index 0000000..92db65a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java
@@ -0,0 +1,40 @@
+package com.example.utils.page;
+
+import cn.hutool.core.date.DateUtil;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class R extends HashMap<String, Object> {
+ private static final long serialVersionUID = 1L;
+
+ public R() {
+ put("status", 200);
+ put("message", "success");
+ put("timestamp", new Date());
+ }
+
+ public static R ok(String message) {
+ R r = new R();
+ r.put("message", message);
+ r.put("timestamp", new Date());
+ return r;
+ }
+
+ public static R ok() {
+ return new R();
+ }
+
+ public static R ok(Object data) {
+ R r = new R();
+ r.put("data", data);
+ r.put("timestamp", new Date());
+ return r;
+ }
+
+
+}
+
+
diff --git a/UI source code/dns-dev-2.0/dns-logging/pom.xml b/UI source code/dns-dev-2.0/dns-logging/pom.xml
new file mode 100644
index 0000000..f3c2cc9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/pom.xml
@@ -0,0 +1,22 @@
+<?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>dns</artifactId>
+ <groupId>com.example</groupId>
+ <version>2.6</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dns-logging</artifactId>
+ <name>dns-logging</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.example</groupId>
+ <artifactId>dns-common</artifactId>
+ <version>2.6</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/annotation/Log.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/annotation/Log.java
new file mode 100644
index 0000000..566b555
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/annotation/Log.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * 2018-11-24
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Log {
+ String value() default "";
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/aspect/LogAspect.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/aspect/LogAspect.java
new file mode 100644
index 0000000..aaed973
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/aspect/LogAspect.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.aspect;
+
+import com.example.utils.RequestHolder;
+import com.example.utils.SecurityUtils;
+import com.example.utils.StringUtils;
+import com.example.utils.ThrowableUtil;
+import lombok.extern.slf4j.Slf4j;
+import com.example.domain.Log;
+import com.example.service.LogService;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * 2018-11-24
+ */
+@Component
+@Aspect
+@Slf4j
+public class LogAspect {
+
+ private final LogService logService;
+
+ ThreadLocal<Long> currentTime = new ThreadLocal<>();
+
+ public LogAspect(LogService logService) {
+ this.logService = logService;
+ }
+
+ /**
+ * 配置切入点
+ */
+ @Pointcut("@annotation(com.example.annotation.Log)")
+ public void logPointcut() {
+ // 该方法无方法体,主要为了让同类中其他方法使用此切入点
+ }
+
+ /**
+ * 配置环绕通知,使用在方法logPointcut()上注册的切入点
+ *
+ * @param joinPoint join point for advice
+ */
+ @Around("logPointcut()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ Object result;
+ currentTime.set(System.currentTimeMillis());
+ result = joinPoint.proceed();
+ Log log = new Log("INFO",System.currentTimeMillis() - currentTime.get());
+ currentTime.remove();
+ HttpServletRequest request = RequestHolder.getHttpServletRequest();
+ logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log);
+ return result;
+ }
+
+ /**
+ * 配置异常通知
+ *
+ * @param joinPoint join point for advice
+ * @param e exception
+ */
+ @AfterThrowing(pointcut = "logPointcut()", throwing = "e")
+ public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
+ Log log = new Log("ERROR",System.currentTimeMillis() - currentTime.get());
+ currentTime.remove();
+ log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes());
+ HttpServletRequest request = RequestHolder.getHttpServletRequest();
+ logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log);
+ }
+
+ public String getUsername() {
+ try {
+ return SecurityUtils.getCurrentUsername();
+ }catch (Exception e){
+ return "";
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/domain/Log.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/domain/Log.java
new file mode 100644
index 0000000..21529a6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/domain/Log.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.domain;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+ *
+ * 2018-11-24
+ */
+@Entity
+@Getter
+@Setter
+@Table(name = "sys_log")
+@NoArgsConstructor
+public class Log implements Serializable {
+
+ @Id
+ @Column(name = "log_id")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ /** 操作用户 */
+ private String username;
+
+ /** 描述 */
+ private String description;
+
+ /** 方法名 */
+ private String method;
+
+ /** 参数 */
+ private String params;
+
+ /** 日志类型 */
+ private String logType;
+
+ /** 请求ip */
+ private String requestIp;
+
+ /** 地址 */
+ private String address;
+
+ /** 浏览器 */
+ private String browser;
+
+ /** 请求耗时 */
+ private Long time;
+
+ /** 异常详细 */
+ private byte[] exceptionDetail;
+
+ /** 创建日期 */
+ @CreationTimestamp
+ private Timestamp createTime;
+
+ public Log(String logType, Long time) {
+ this.logType = logType;
+ this.time = time;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/repository/LogRepository.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/repository/LogRepository.java
new file mode 100644
index 0000000..d689cfe
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/repository/LogRepository.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.repository;
+
+import com.example.domain.Log;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+/**
+ *
+ * 2018-11-24
+ */
+@Repository
+public interface LogRepository extends JpaRepository<Log,Long>, JpaSpecificationExecutor<Log> {
+
+ /**
+ * 根据日志类型删除信息
+ * @param logType 日志类型
+ */
+ @Modifying
+ @Query(value = "delete from sys_log where log_type = ?1", nativeQuery = true)
+ void deleteByLogType(String logType);
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/rest/LogController.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/rest/LogController.java
new file mode 100644
index 0000000..305f2bb
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/rest/LogController.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.rest;
+
+import com.example.utils.SecurityUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.service.LogService;
+import com.example.service.dto.LogQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ *
+ * 2018-11-24
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/logs")
+@Api(tags = "系统:日志管理")
+public class LogController {
+
+ private final LogService logService;
+
+ @Log("导出数据")
+ @ApiOperation("导出数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check()")
+ public void exportLog(HttpServletResponse response, LogQueryCriteria criteria) throws IOException {
+ criteria.setLogType("INFO");
+ logService.download(logService.queryAll(criteria), response);
+ }
+
+ @Log("导出错误数据")
+ @ApiOperation("导出错误数据")
+ @GetMapping(value = "/error/download")
+ @PreAuthorize("@el.check()")
+ public void exportErrorLog(HttpServletResponse response, LogQueryCriteria criteria) throws IOException {
+ criteria.setLogType("ERROR");
+ logService.download(logService.queryAll(criteria), response);
+ }
+ @GetMapping
+ @ApiOperation("日志查询")
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> queryLog(LogQueryCriteria criteria, Pageable pageable){
+ criteria.setLogType("INFO");
+ return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/user")
+ @ApiOperation("用户日志查询")
+ public ResponseEntity<Object> queryUserLog(LogQueryCriteria criteria, Pageable pageable){
+ criteria.setLogType("INFO");
+ criteria.setBlurry(SecurityUtils.getCurrentUsername());
+ return new ResponseEntity<>(logService.queryAllByUser(criteria,pageable), HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/error")
+ @ApiOperation("错误日志查询")
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> queryErrorLog(LogQueryCriteria criteria, Pageable pageable){
+ criteria.setLogType("ERROR");
+ return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/error/{id}")
+ @ApiOperation("日志异常详情查询")
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> queryErrorLogDetail(@PathVariable Long id){
+ return new ResponseEntity<>(logService.findByErrDetail(id), HttpStatus.OK);
+ }
+ @DeleteMapping(value = "/del/error")
+ @Log("删除所有ERROR日志")
+ @ApiOperation("删除所有ERROR日志")
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> delAllErrorLog(){
+ logService.delAllByError();
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ @DeleteMapping(value = "/del/info")
+ @Log("删除所有INFO日志")
+ @ApiOperation("删除所有INFO日志")
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> delAllInfoLog(){
+ logService.delAllByInfo();
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/LogService.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/LogService.java
new file mode 100644
index 0000000..b640559
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/LogService.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service;
+
+import com.example.domain.Log;
+import com.example.service.dto.LogQueryCriteria;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.springframework.data.domain.Pageable;
+import org.springframework.scheduling.annotation.Async;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ *
+ * 2018-11-24
+ */
+public interface LogService {
+
+ /**
+ * 分页查询
+ * @param criteria 查询条件
+ * @param pageable 分页参数
+ * @return /
+ */
+ Object queryAll(LogQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 查询全部数据
+ * @param criteria 查询条件
+ * @return /
+ */
+ List<Log> queryAll(LogQueryCriteria criteria);
+
+ /**
+ * 查询用户日志
+ * @param criteria 查询条件
+ * @param pageable 分页参数
+ * @return -
+ */
+ Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 保存日志数据
+ * @param username 用户
+ * @param browser 浏览器
+ * @param ip 请求IP
+ * @param joinPoint /
+ * @param log 日志实体
+ */
+ @Async
+ void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log);
+
+ /**
+ * 查询异常详情
+ * @param id 日志ID
+ * @return Object
+ */
+ Object findByErrDetail(Long id);
+
+ /**
+ * 导出日志
+ * @param logs 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<Log> logs, HttpServletResponse response) throws IOException;
+
+ /**
+ * 删除所有错误日志
+ */
+ void delAllByError();
+
+ /**
+ * 删除所有INFO日志
+ */
+ void delAllByInfo();
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogErrorDTO.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogErrorDTO.java
new file mode 100644
index 0000000..734bda3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogErrorDTO.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+*
+* 2019-5-22
+*/
+@Data
+public class LogErrorDTO implements Serializable {
+
+ private Long id;
+
+ private String username;
+
+ private String description;
+
+ private String method;
+
+ private String params;
+
+ private String browser;
+
+ private String requestIp;
+
+ private String address;
+
+ private Timestamp createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogQueryCriteria.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogQueryCriteria.java
new file mode 100644
index 0000000..9611dfb
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogQueryCriteria.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service.dto;
+
+import lombok.Data;
+import com.example.annotation.Query;
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+ * 日志查询类
+ *
+ * 2019-6-4 09:23:07
+ */
+@Data
+public class LogQueryCriteria {
+
+ @Query(blurry = "username,description,address,requestIp,method,params")
+ private String blurry;
+
+ @Query
+ private String logType;
+
+ @Query(type = Query.Type.BETWEEN)
+ private List<Timestamp> createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogSmallDTO.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogSmallDTO.java
new file mode 100644
index 0000000..d78f9d9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/dto/LogSmallDTO.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+ *
+ * 2019-5-22
+ */
+@Data
+public class LogSmallDTO implements Serializable {
+
+ private String description;
+
+ private String requestIp;
+
+ private Long time;
+
+ private String address;
+
+ private String browser;
+
+ private Timestamp createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/impl/LogServiceImpl.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/impl/LogServiceImpl.java
new file mode 100644
index 0000000..43b94b8
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/impl/LogServiceImpl.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service.impl;
+
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
+import com.example.domain.Log;
+import com.example.service.LogService;
+import com.example.service.dto.LogQueryCriteria;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.repository.LogRepository;
+import com.example.service.mapstruct.LogErrorMapper;
+import com.example.service.mapstruct.LogSmallMapper;
+import com.example.utils.*;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.*;
+
+/**
+ *
+ * 2018-11-24
+ */
+@Service
+@RequiredArgsConstructor
+public class LogServiceImpl implements LogService {
+ private final LogRepository logRepository;
+ private final LogErrorMapper logErrorMapper;
+ private final LogSmallMapper logSmallMapper;
+
+ @Override
+ public Object queryAll(LogQueryCriteria criteria, Pageable pageable) {
+ Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
+ String status = "ERROR";
+ if (status.equals(criteria.getLogType())) {
+ return PageUtil.toPage(page.map(logErrorMapper::toDto));
+ }
+ return page;
+ }
+
+ @Override
+ public List<Log> queryAll(LogQueryCriteria criteria) {
+ return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)));
+ }
+
+ @Override
+ public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) {
+ Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
+ return PageUtil.toPage(page.map(logSmallMapper::toDto));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log) {
+ if (log == null) {
+ throw new IllegalArgumentException("Log 不能为 null!");
+ }
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method method = signature.getMethod();
+ com.example.annotation.Log aopLog = method.getAnnotation(com.example.annotation.Log.class);
+
+ // 方法路径
+ String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
+
+ // 描述
+ log.setDescription(aopLog.value());
+
+ log.setRequestIp(ip);
+ log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
+ log.setMethod(methodName);
+ log.setUsername(username);
+ log.setParams(getParameter(method, joinPoint.getArgs()));
+ log.setBrowser(browser);
+ logRepository.save(log);
+ }
+
+ /**
+ * 根据方法和传入的参数获取请求参数
+ */
+ private String getParameter(Method method, Object[] args) {
+ List<Object> argList = new ArrayList<>();
+ Parameter[] parameters = method.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ //将RequestBody注解修饰的参数作为请求参数
+ RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
+ if (requestBody != null) {
+ argList.add(args[i]);
+ }
+ //将RequestParam注解修饰的参数作为请求参数
+ RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
+ if (requestParam != null) {
+ Map<String, Object> map = new HashMap<>(4);
+ String key = parameters[i].getName();
+ if (!StringUtils.isEmpty(requestParam.value())) {
+ key = requestParam.value();
+ }
+ map.put(key, args[i]);
+ argList.add(map);
+ }
+ }
+ if (argList.isEmpty()) {
+ return "";
+ }
+ return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : JSONUtil.toJsonStr(argList);
+ }
+
+ @Override
+ public Object findByErrDetail(Long id) {
+ Log log = logRepository.findById(id).orElseGet(Log::new);
+ ValidationUtil.isNull(log.getId(), "Log", "id", id);
+ byte[] details = log.getExceptionDetail();
+ return Dict.create().set("exception", new String(ObjectUtil.isNotNull(details) ? details : "".getBytes()));
+ }
+
+ @Override
+ public void download(List<Log> logs, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (Log log : logs) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("用户名", log.getUsername());
+ map.put("IP", log.getRequestIp());
+ map.put("IP来源", log.getAddress());
+ map.put("描述", log.getDescription());
+ map.put("浏览器", log.getBrowser());
+ map.put("请求耗时/毫秒", log.getTime());
+ map.put("异常详情", new String(ObjectUtil.isNotNull(log.getExceptionDetail()) ? log.getExceptionDetail() : "".getBytes()));
+ map.put("创建日期", log.getCreateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delAllByError() {
+ logRepository.deleteByLogType("ERROR");
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delAllByInfo() {
+ logRepository.deleteByLogType("INFO");
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogErrorMapper.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogErrorMapper.java
new file mode 100644
index 0000000..8a19a28
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogErrorMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service.mapstruct;
+
+import com.example.base.BaseMapper;
+import com.example.domain.Log;
+import com.example.service.dto.LogErrorDTO;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+ *
+ * 2019-5-22
+ */
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface LogErrorMapper extends BaseMapper<LogErrorDTO, Log> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogSmallMapper.java b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogSmallMapper.java
new file mode 100644
index 0000000..8c06ba4
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-logging/src/main/java/com/example/service/mapstruct/LogSmallMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.service.mapstruct;
+
+import com.example.base.BaseMapper;
+import com.example.domain.Log;
+import com.example.service.dto.LogSmallDTO;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+ *
+ * 2019-5-22
+ */
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface LogSmallMapper extends BaseMapper<LogSmallDTO, Log> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/pom.xml b/UI source code/dns-dev-2.0/dns-system/pom.xml
new file mode 100644
index 0000000..ea50602
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/pom.xml
@@ -0,0 +1,103 @@
+<?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>dns</artifactId>
+ <groupId>com.example</groupId>
+ <version>2.6</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dns-system</artifactId>
+ <name>dns-system</name>
+
+ <properties>
+ <jjwt.version>0.11.1</jjwt.version>
+ <!-- oshi监控需要指定jna版本, 问题详见 https://github.com/oshi/oshi/issues/1040 -->
+ <jna.version>5.8.0</jna.version>
+
+ </properties>
+
+ <dependencies>
+
+ <!-- tools 模块包含了 common 和 logging 模块 -->
+ <dependency>
+ <groupId>com.example</groupId>
+ <artifactId>dns-common</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>com.example</groupId>
+ <artifactId>dns-logging</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+ <!-- Spring boot websocket -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
+
+
+ <!-- jwt -->
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-api</artifactId>
+ <version>${jjwt.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-impl</artifactId>
+ <version>${jjwt.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-jackson</artifactId>
+ <version>${jjwt.version}</version>
+ </dependency>
+
+ <!-- quartz -->
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ </dependency>
+
+ <!-- linux的管理 -->
+ <dependency>
+ <groupId>ch.ethz.ganymed</groupId>
+ <artifactId>ganymed-ssh2</artifactId>
+ <version>build210</version>
+ </dependency>
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
+ <version>0.1.55</version>
+ </dependency>
+
+ <!-- 获取系统信息 -->
+ <dependency>
+ <groupId>com.github.oshi</groupId>
+ <artifactId>oshi-core</artifactId>
+ <version>5.7.1</version>
+ </dependency>
+ </dependencies>
+
+ <!-- 打包 -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+ <!-- 跳过单元测试 -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java
new file mode 100644
index 0000000..521f939
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example;
+
+import com.example.utils.SpringContextHolder;
+import io.swagger.annotations.Api;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.ApplicationPidFileWriter;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 开启审计功能 -> @EnableJpaAuditing
+ *
+ * 2018/11/15 9:20:19
+ */
+@EnableAsync
+@RestController
+@Api(hidden = true)
+@SpringBootApplication
+@EnableTransactionManagement
+@EnableJpaAuditing(auditorAwareRef = "auditorAware")
+public class AppRun {
+
+ public static void main(String[] args) {
+ SpringApplication springApplication = new SpringApplication(AppRun.class);
+ // 监控应用的PID,启动时可指定PID路径:--spring.pid.file=/home/dns/app.pid
+ // 或者在 application.yml 添加文件路径,方便 kill,kill `cat /home/dns/app.pid`
+ springApplication.addListeners(new ApplicationPidFileWriter());
+ springApplication.run(args);
+ }
+
+ @Bean
+ public SpringContextHolder springContextHolder() {
+ return new SpringContextHolder();
+ }
+
+ @Bean
+ public ServletWebServerFactory webServerFactory() {
+ TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory();
+ fa.addConnectorCustomizers(connector -> connector.setProperty("relaxedQueryChars", "[]{}"));
+ return fa;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java
new file mode 100644
index 0000000..b2bcf86
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+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.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * WebMvcConfigurer
+ *
+ *
+ * 2018-11-30
+ */
+@Configuration
+@EnableWebMvc
+public class ConfigurerAdapter implements WebMvcConfigurer {
+
+ /** 文件配置 */
+ private final FileProperties properties;
+
+ public ConfigurerAdapter(FileProperties properties) {
+ this.properties = properties;
+ }
+
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ config.addAllowedOrigin("*");
+ config.addAllowedHeader("*");
+ config.addAllowedMethod("*");
+ source.registerCorsConfiguration("/**", config);
+ return new CorsFilter(source);
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ FileProperties.ElPath path = properties.getPath();
+ String avatarUtl = "file:" + path.getAvatar().replace("\\","/");
+ String pathUtl = "file:" + path.getPath().replace("\\","/");
+ registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
+ registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0);
+ registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
+ }
+
+ @Override
+ public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
+ // 使用 fastjson 序列化,会导致 @JsonIgnore 失效,可以使用 @JSONField(serialize = false) 替换
+ FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
+ List<MediaType> supportMediaTypeList = new ArrayList<>();
+ supportMediaTypeList.add(MediaType.APPLICATION_JSON);
+ FastJsonConfig config = new FastJsonConfig();
+ config.setDateFormat("yyyy-MM-dd HH:mm:ss");
+ config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
+ converter.setFastJsonConfig(config);
+ converter.setSupportedMediaTypes(supportMediaTypeList);
+ converter.setDefaultCharset(StandardCharsets.UTF_8);
+ converters.add(converter);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..87e8cbf
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java
@@ -0,0 +1,236 @@
+package com.example.config;
+
+import cn.hutool.log.Log;
+import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
+import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
+import com.baomidou.mybatisplus.core.injector.ISqlInjector;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.mapping.DatabaseIdProvider;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.mapper.ClassPathMapperScanner;
+import org.mybatis.spring.mapper.MapperFactoryBean;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.context.annotation.*;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+import java.util.List;
+
+/**
+ * mybatis-plus 初始化配置
+ */
+@Configuration
+@EnableConfigurationProperties(MybatisPlusProperties.class)
+public class MybatisPlusConfig {
+
+ public MybatisPlusConfig(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider,
+ ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider,
+ ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider,
+ ApplicationContext applicationContext) {
+ this.properties = properties;
+ this.interceptors = interceptorsProvider.getIfAvailable();
+ this.resourceLoader = resourceLoader;
+ this.databaseIdProvider = databaseIdProvider.getIfAvailable();
+ this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
+ this.applicationContext = applicationContext;
+ }
+
+ private static final Log logger = Log.get();
+
+ private final MybatisPlusProperties properties;
+
+ private final Interceptor[] interceptors;
+
+ private final ResourceLoader resourceLoader;
+
+ private final DatabaseIdProvider databaseIdProvider;
+
+ private final List<ConfigurationCustomizer> configurationCustomizers;
+
+ private final ApplicationContext applicationContext;
+
+ @PostConstruct
+ public void checkConfigFileExists() {
+ if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
+ Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
+ Assert.state(resource.exists(), "Cannot find config location: " + resource
+ + " (please add config file or check your Mybatis configuration)");
+ }
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+ MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
+ factory.setDataSource(dataSource);
+ factory.setVfs(SpringBootVFS.class);
+ if (StringUtils.hasText(this.properties.getConfigLocation())) {
+ factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
+ }
+ applyConfiguration(factory);
+ if (this.properties.getConfigurationProperties() != null) {
+ factory.setConfigurationProperties(this.properties.getConfigurationProperties());
+ }
+ if (!ObjectUtils.isEmpty(this.interceptors)) {
+ factory.setPlugins(this.interceptors);
+ }
+ if (this.databaseIdProvider != null) {
+ factory.setDatabaseIdProvider(this.databaseIdProvider);
+ }
+ if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
+ factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
+ }
+ // TODO 自定义枚举包
+ if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
+ factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
+ }
+ if (this.properties.getTypeAliasesSuperType() != null) {
+ factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
+ }
+ if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
+ factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
+ }
+ if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
+ factory.setMapperLocations(this.properties.resolveMapperLocations());
+ }
+ // TODO 此处必为非 NULL
+ GlobalConfig globalConfig = this.properties.getGlobalConfig();
+ // 注入填充器
+ if (this.applicationContext.getBeanNamesForType(MetaObjectHandler.class, false, false).length > 0) {
+ MetaObjectHandler metaObjectHandler = this.applicationContext.getBean(MetaObjectHandler.class);
+ globalConfig.setMetaObjectHandler(metaObjectHandler);
+ }
+ // 注入主键生成器
+ if (this.applicationContext.getBeanNamesForType(IKeyGenerator.class, false, false).length > 0) {
+ IKeyGenerator keyGenerator = this.applicationContext.getBean(IKeyGenerator.class);
+ globalConfig.getDbConfig().setKeyGenerator(keyGenerator);
+ }
+ // 注入sql注入器
+ if (this.applicationContext.getBeanNamesForType(ISqlInjector.class, false, false).length > 0) {
+ ISqlInjector iSqlInjector = this.applicationContext.getBean(ISqlInjector.class);
+ globalConfig.setSqlInjector(iSqlInjector);
+ }
+ factory.setGlobalConfig(globalConfig);
+ return factory.getObject();
+ }
+
+ private void applyConfiguration(MybatisSqlSessionFactoryBean factory) {
+ MybatisConfiguration configuration = this.properties.getConfiguration();
+ if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
+ configuration = new MybatisConfiguration();
+ }
+ if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
+ for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
+ customizer.customize(configuration);
+ }
+ }
+ factory.setConfiguration(configuration);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
+ ExecutorType executorType = this.properties.getExecutorType();
+ if (executorType != null) {
+ return new SqlSessionTemplate(sqlSessionFactory, executorType);
+ } else {
+ return new SqlSessionTemplate(sqlSessionFactory);
+ }
+ }
+
+ /**
+ * This will just scan the same base package as Spring Boot does. If you want
+ * more power, you can explicitly use
+ * {@link org.mybatis.spring.annotation.MapperScan} but this will get typed
+ * mappers working correctly, out-of-the-box, similar to using Spring Data JPA
+ * repositories.
+ */
+ public static class AutoConfiguredMapperScannerRegistrar
+ implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
+
+ private BeanFactory beanFactory;
+
+ private ResourceLoader resourceLoader;
+
+ @Override
+ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
+ BeanDefinitionRegistry registry) {
+
+ logger.debug("Searching for mappers annotated with @Mapper");
+
+ ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
+
+ try {
+ if (this.resourceLoader != null) {
+ scanner.setResourceLoader(this.resourceLoader);
+ }
+
+ List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
+ if (logger.isDebugEnabled()) {
+ packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
+ }
+
+ scanner.setAnnotationClass(Mapper.class);
+ scanner.registerFilters();
+ scanner.doScan(StringUtils.toStringArray(packages));
+ } catch (IllegalStateException ex) {
+ logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
+ }
+ }
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.beanFactory = beanFactory;
+ }
+
+ @Override
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+ }
+
+ /**
+ * {@link org.mybatis.spring.annotation.MapperScan} ultimately ends up creating
+ * instances of {@link MapperFactoryBean}. If
+ * {@link org.mybatis.spring.annotation.MapperScan} is used then this
+ * auto-configuration is not needed. If it is _not_ used, however, then this
+ * will bring in a bean registrar and automatically register components based on
+ * the same component-scanning path as Spring Boot itself.
+ */
+ @Configuration
+ @Import({ AutoConfiguredMapperScannerRegistrar.class })
+ @ConditionalOnMissingBean(MapperFactoryBean.class)
+ public static class MapperScannerRegistrarNotFoundConfiguration {
+
+ @PostConstruct
+ public void afterPropertiesSet() {
+ logger.debug("No {} found.", MapperFactoryBean.class.getName());
+ }
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java
new file mode 100644
index 0000000..cc9739c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java
@@ -0,0 +1,36 @@
+package com.example.config;
+
+import cn.hutool.log.Log;
+import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
+import com.baomidou.mybatisplus.core.injector.ISqlInjector;
+import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+/**
+ * mybatis-plus 插件配置
+ */
+@Configuration
+public class MybatisPlusPluginsConfig {
+
+ private static final Log logger = Log.get();
+
+ /**
+ * 分页插件
+ */
+ @Bean
+ public PaginationInterceptor paginationInterceptor() {
+ return new PaginationInterceptor();
+ }
+
+
+ @Bean
+ public ISqlInjector sqlInjector() {
+ return new LogicSqlInjector();
+ }
+
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java
new file mode 100644
index 0000000..906021c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * @author ZhangHouYing
+ * 2019-08-24 15:44
+ */
+@Configuration
+public class WebSocketConfig {
+
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter() {
+ return new ServerEndpointExporter();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java
new file mode 100644
index 0000000..44abd3d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config.thread;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 异步任务线程池装配类
+ * @author https://juejin.im/entry/5abb8f6951882555677e9da2
+ * 2019年10月31日15:06:18
+ */
+@Slf4j
+@Configuration
+public class AsyncTaskExecutePool implements AsyncConfigurer {
+
+ @Override
+ public Executor getAsyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ //核心线程池大小
+ executor.setCorePoolSize(AsyncTaskProperties.corePoolSize);
+ //最大线程数
+ executor.setMaxPoolSize(AsyncTaskProperties.maxPoolSize);
+ //队列容量
+ executor.setQueueCapacity(AsyncTaskProperties.queueCapacity);
+ //活跃时间
+ executor.setKeepAliveSeconds(AsyncTaskProperties.keepAliveSeconds);
+ //线程名字前缀
+ executor.setThreadNamePrefix("el-async-");
+ // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
+ // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ executor.initialize();
+ return executor;
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return (throwable, method, objects) -> {
+ log.error("===="+throwable.getMessage()+"====", throwable);
+ log.error("exception method:"+method.getName());
+ };
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java
new file mode 100644
index 0000000..012a127
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config.thread;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * 线程池配置属性类
+ * @author https://juejin.im/entry/5abb8f6951882555677e9da2
+ * 2019年10月31日14:58:18
+ */
+@Data
+@Component
+public class AsyncTaskProperties {
+
+ public static int corePoolSize;
+
+ public static int maxPoolSize;
+
+ public static int keepAliveSeconds;
+
+ public static int queueCapacity;
+
+ @Value("${task.pool.core-pool-size}")
+ public void setCorePoolSize(int corePoolSize) {
+ AsyncTaskProperties.corePoolSize = corePoolSize;
+ }
+
+ @Value("${task.pool.max-pool-size}")
+ public void setMaxPoolSize(int maxPoolSize) {
+ AsyncTaskProperties.maxPoolSize = maxPoolSize;
+ }
+
+ @Value("${task.pool.keep-alive-seconds}")
+ public void setKeepAliveSeconds(int keepAliveSeconds) {
+ AsyncTaskProperties.keepAliveSeconds = keepAliveSeconds;
+ }
+
+ @Value("${task.pool.queue-capacity}")
+ public void setQueueCapacity(int queueCapacity) {
+ AsyncTaskProperties.queueCapacity = queueCapacity;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java
new file mode 100644
index 0000000..b06a723
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config.thread;
+
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 自定义线程名称
+ *
+ * 2019年10月31日17:49:55
+ */
+@Component
+public class TheadFactoryName implements ThreadFactory {
+
+ private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
+ private final ThreadGroup group;
+ private final AtomicInteger threadNumber = new AtomicInteger(1);
+ private final String namePrefix;
+
+ public TheadFactoryName() {
+ this("el-pool");
+ }
+
+ private TheadFactoryName(String name){
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null) ? s.getThreadGroup() :
+ Thread.currentThread().getThreadGroup();
+ //此时namePrefix就是 name + 第几个用这个工厂创建线程池的
+ this.namePrefix = name +
+ POOL_NUMBER.getAndIncrement();
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ //此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程
+ Thread t = new Thread(group, r,
+ namePrefix + "-thread-"+threadNumber.getAndIncrement(),
+ 0);
+ if (t.isDaemon()) {
+ t.setDaemon(false);
+ }
+ if (t.getPriority() != Thread.NORM_PRIORITY) {
+ t.setPriority(Thread.NORM_PRIORITY);
+ }
+ return t;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java
new file mode 100644
index 0000000..db542cf
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.config.thread;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 用于获取自定义线程池
+ *
+ * 2019年10月31日18:16:47
+ */
+public class ThreadPoolExecutorUtil {
+
+ public static ThreadPoolExecutor getPoll(){
+ return new ThreadPoolExecutor(
+ AsyncTaskProperties.corePoolSize,
+ AsyncTaskProperties.maxPoolSize,
+ AsyncTaskProperties.keepAliveSeconds,
+ TimeUnit.SECONDS,
+ new ArrayBlockingQueue<>(AsyncTaskProperties.queueCapacity),
+ new TheadFactoryName()
+ );
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java
new file mode 100644
index 0000000..581a46b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java
@@ -0,0 +1,48 @@
+package com.example.modules.dns.controller;
+
+import com.example.modules.dns.service.DnsService;
+import com.example.utils.page.PageUtils;
+import com.example.utils.page.R;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.text.DecimalFormat;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/dns")
+public class DnsController {
+ @Autowired
+ private DnsService dnsService;
+
+ @GetMapping
+ public R queryPage(@RequestParam Map<String, Object> params) {
+ long startTime = System.currentTimeMillis();
+ PageUtils page =dnsService.queryPage(params);
+ long endTime = System.currentTimeMillis();
+ DecimalFormat df = new DecimalFormat("0.000");
+ String totalTime = df.format((float) (endTime - startTime) / 1000);
+ page.setTotalTime(Double.parseDouble(totalTime));
+ return R.ok(page);
+ }
+
+
+ //区域数据统计
+ @GetMapping("/dataCount")
+ public R dataCount(@RequestParam Map<String, Object> params) {
+ return R.ok(dnsService.dataCount(params));
+ }
+
+ //区域数据统计
+ @GetMapping("/mapData")
+ public R mapData() {
+ return R.ok(dnsService.mapData());
+ }
+
+
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java
new file mode 100644
index 0000000..983c2ee
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java
@@ -0,0 +1,24 @@
+
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+@TableName("dns_type")
+public class DnsType implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String ip;
+
+ private String type;
+
+ private int epoch;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java
new file mode 100644
index 0000000..5a772e2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@TableName("doh_attribute")
+public class DohAttribute implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+ private String ip;
+ private Integer port;
+ private String host;
+ private String path;
+ private String method;
+ private Integer connectType;
+ private Integer statusCode;
+ private String repHeader;
+ private String repBody;
+ private Date timestamp;
+
+ private String component;
+
+ private int rounds;
+
+ @TableField(exist = false)
+ private List<String> pathList;
+
+ @TableField(exist = false)
+ private List<String> componentList;
+
+ @TableField(exist = false)
+ private List<IpCert> ipCert;
+
+ @TableField(exist = false)
+ private List<IpInformation> ipInformation;
+
+ @TableField(exist = false)
+ private List<List<Vulnerability>> vulnerability;
+ @TableField(exist = false)
+ private List<String> tags;
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java
new file mode 100644
index 0000000..5823a34
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java
@@ -0,0 +1,24 @@
+
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+@TableName("forward_dns")
+public class ForwardDns implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String forwarder;
+
+ private String upstream;
+
+ private int epoch;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java
new file mode 100644
index 0000000..a7f88af
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.domain.Job;
+import com.example.modules.system.domain.Role;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Set;
+
+/**
+ * 2018-11-22
+ */
+@Data
+@TableName("ip_cert")
+public class IpCert implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String ip;
+
+ private String port;
+
+ private String certificate;
+
+ private String ca;
+
+ private Date timestamp;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java
new file mode 100644
index 0000000..1c61eb5
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ *
+ * 2018-11-22
+ */
+@Data
+@TableName("ip_information")
+public class IpInformation implements Serializable {
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String ip;
+
+ private String country;
+
+ private String province;
+
+ private String city;
+ private String district;
+ private String provider;
+ private String isp;
+ private Integer asnumber;
+ private Date timestamp;
+ private String zipcode;
+ private String timezone;
+
+ @TableField(exist = false)
+ private List<IpCert> ipCert;
+
+ @TableField(exist = false)
+ private List<NonstandardDns> nonstandardDns;
+
+
+ @TableField(exist = false)
+ private DnsType dnsType;
+
+ @TableField(exist = false)
+ private List<DohAttribute> dohAttribute;
+
+ @TableField(exist = false)
+ private List<ForwardDns> forwardDns;
+
+ @TableField(exist = false)
+ private ScanResult scanResult;
+
+ @TableField(exist = false)
+ private Integer dnsTypeValue;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java
new file mode 100644
index 0000000..11badef
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java
@@ -0,0 +1,28 @@
+
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+
+
+/**
+ *
+ * 直接响DNS表
+ */
+@Data
+ @TableName("nonstandard_dns")
+public class NonstandardDns implements Serializable {
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String ip;
+
+ private String record;
+
+ private int epoch;
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java
new file mode 100644
index 0000000..6047df6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java
@@ -0,0 +1,71 @@
+package com.example.modules.dns.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class Result implements Serializable {
+
+ private Long id;
+ private String ip;
+
+ private String protocolType;
+ private String ipType;
+
+ private Integer port;
+ private String host;
+ private String path;
+ private String method;
+ private Integer connectType;
+ private Integer statusCode;
+ private String repHeader;
+ private String repBody;
+ private Date timestamp;
+ private String component;
+
+
+ private Integer flags;
+ private Integer opcode;
+ private Integer qr;
+ //权威标志位
+ private Integer aa;
+ //递归标志位
+ private Integer ra;
+ private Integer rcode;
+ private String queryName;
+ private String queryResponse;
+
+ //(预留)ipv4,ipv6,dnssec,tcp,udp等
+ private Integer scanType;
+
+ private Date time;
+
+ private Integer epoch;
+
+ private Integer rounds;
+
+
+ private Integer dnsType;
+
+ private String uuid;
+
+ private List<String> pathList;
+
+ private List<String> componentList;
+
+ private List<IpCert> ipCert;
+
+ private List<Vulnerability> vulnerability;
+
+ private List<String> tags;
+
+ private IpInformation ipInformation;
+
+ private List<? extends Object> banner;
+
+ private List<? extends Object> httpContent;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java
new file mode 100644
index 0000000..8d479dc
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 2018-11-22
+ */
+@Data
+@TableName("scan_result")
+public class ScanResult implements Serializable {
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String ip;
+
+ private Integer flags;
+
+ private Integer opcode;
+
+ private Integer qr;
+ //权威标志位
+ private Integer aa;
+ //递归标志位
+ private Integer ra;
+
+ private Integer rcode;
+
+ private String queryName;
+
+ private String queryResponse;
+
+ private String component;
+
+ private int epoch;
+
+ private List<String> componentList;
+ //(预留)ipv4,ipv6,dnssec,tcp,udp等
+ private Integer scanType;
+
+ private Date time;
+ @TableField(exist = false)
+ private IpInformation IpInformation;
+ @TableField(exist = false)
+ private List<IpInformation> forwarderBanner;
+ @TableField(exist = false)
+ private Integer dnsType;
+ @TableField(exist = false)
+ private List<NonstandardDns> nonstandardBanner;
+
+ @TableField(exist = false)
+ private List<String> tags;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java
new file mode 100644
index 0000000..b31ba3e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java
@@ -0,0 +1,24 @@
+package com.example.modules.dns.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("vulnerability")
+public class Vulnerability implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String component;
+
+ private String vulnerability;
+
+ private Date timestamp;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java
new file mode 100644
index 0000000..0d1eee5
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java
@@ -0,0 +1,76 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.Result;
+import com.example.modules.dns.domain.ScanResult;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface DnsDo53Dao extends BaseMapper<ScanResult> {
+
+ List<Result> queryDo53Page(IPage page, @Param("params") Map<String, Object> params);
+
+ int do53IpCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> do53ServiceCategoryCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> do53ProvinceCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> do53ProviderCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> do53ComponentCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> do53VulnerabilityCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> do53CountryCount();
+
+ List<Map<String, Object>> do53CountryMapCount();
+
+
+ List<Map<String, Object>> do53WorldMapCount();
+
+ List<Map<String, Object>> do53ChinaMapCount();
+
+ int pageCount(@Param("params") Map<String, Object> params);
+
+ List<Result> queryOpenRdns(@Param("params")Map<String, Object> params);
+
+ int getCountByDnsType(@Param("dnsType")Integer dnsType,@Param("params") Map<String, Object> params);
+
+ int getIndependentIpNum(@Param("dnsType")Integer dnsType, @Param("params")Map<String, Object> params);
+
+ List<Result> selectScanResultByUnion(IPage page, @Param("params") Map<String, Object> params);
+
+ Integer selectScanResultCountByUnion(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> getDohAndDo53SrvCategoryCount(@Param("params") Map<String, Object> params);
+
+ /**
+ * 根据dnsType和其他参数统计ip省份分布
+ * @param dnsType
+ * @param params
+ * @return
+ */
+ List<Map<String, Object>> getDo53ProvinceCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
+
+ /**
+ * 根据dnsType和其他参数统计ip运营商分布
+ * @param dnsType
+ * @param params
+ * @return
+ */
+ List<Map<String, Object>> getDo53ProviderCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> getDo53ComponentCountByDnsType(@Param("dnsType") Integer dnsType, Map<String, Object> params);
+
+ Integer getDo53SrvCategoryCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> getDo53VulnerabCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java
new file mode 100644
index 0000000..29018e6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java
@@ -0,0 +1,93 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.DohAttribute;
+import com.example.modules.dns.domain.IpInformation;
+import com.example.modules.dns.domain.Result;
+import com.example.modules.dns.domain.ScanResult;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface DnsDohDao extends BaseMapper<DohAttribute> {
+
+ List<Result> queryDohPage(IPage page, @Param("params") Map<String, Object> params);
+
+ //省份数据统计
+ List<Map<String, Object>> dohProvinceCount(@Param("params") Map<String, Object> params);
+
+ int dohIpCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohPortCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohAndDo53ProvinceCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohProviderCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohAndDo53ProviderCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohComponentCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohAndDo53ComponentCount(@Param("params") Map<String, Object> params);
+
+ Map<String, Object> dohServiceCategoryCount(@Param("params") Map<String, Object> params);
+
+ int dohResultTotalCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohVulnerabilityCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohAndDo53VulnerabilityCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> dohCountryCount();
+
+ List<Map<String, Object>> dohChinaMapCount();
+
+ List<Result> getDohRepBody(String ip, Integer port, String host, Integer rounds);
+
+ List<Result> selectDohInfoByUnion(@Param("params") Map<String, Object> params);
+
+ Integer selectDohCountByUnion(@Param("params") Map<String, Object> params);
+
+ /**
+ * 查询 doh 和 do53 交集下的port ip数量
+ * @param params
+ * @return
+ */
+ List<Map<String, Object>> countDohPortUnion(@Param("params") Map<String, Object> params);
+
+ /**
+ * 统计 doh和do53公共ip的省份分布
+ * @param params
+ * @return
+ */
+ List<Map<String, Object>> getDohAndDo53ProvinceCount(@Param("params") Map<String, Object> params);
+
+ /**
+ * 统计 doh和do53公共ip的运营商分布
+ * @param params
+ * @return
+ */
+ List<Map<String, Object>> getDohAndDo53ProviderCount(@Param("params") Map<String, Object> params);
+
+ /**
+ * 统计 doh和do53公共ip的组件分布
+ * @param params
+ * @return
+ */
+ List<Map<String, Object>> getDohAndDo53ComponentCount(@Param("params") Map<String, Object> params);
+
+ /**
+ * 统计 doh 和 do53公共ip 服务类别统计
+ * @param params
+ * @return
+ */
+ Map<String, Object> getDohServiceCategoryCount(@Param("params") Map<String, Object> params);
+
+ List<Map<String, Object>> getDohAndDo53VulnerabilityCount(@Param("params") Map<String, Object> params);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java
new file mode 100644
index 0000000..e5193e6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java
@@ -0,0 +1,20 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.DnsType;
+import com.example.modules.dns.domain.DohAttribute;
+import com.example.modules.dns.domain.IpCert;
+import com.example.modules.dns.domain.ScanResult;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface DnsTypeDao extends BaseMapper<DnsType> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java
new file mode 100644
index 0000000..2986981
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java
@@ -0,0 +1,20 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.ForwardDns;
+import com.example.modules.dns.domain.ScanResult;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface ForwardDnsDao extends BaseMapper<ForwardDns> {
+
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java
new file mode 100644
index 0000000..01939f6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java
@@ -0,0 +1,32 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.DohAttribute;
+import com.example.modules.dns.domain.IpCert;
+import com.example.modules.dns.domain.ScanResult;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface IpCertDao extends BaseMapper<IpCert> {
+
+ List<DohAttribute> queryDohPage(IPage page, @Param("params") Map<String, Object> params);
+
+ // 国家数据统计
+ List<Map<String, Object>> countryCount();
+
+ //省份数据统计
+ List<Map<String, Object>> provinceCount();
+
+ // 城市数据统计
+ List<Map<String, Object>> cityCount();
+
+
+ List<ScanResult> queryDo53Page(IPage page, @Param("params") Map<String, Object> params);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java
new file mode 100644
index 0000000..2ed80e3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java
@@ -0,0 +1,27 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.IpInformation;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface IpInformationDao extends BaseMapper<IpInformation> {
+
+
+ List<IpInformation> queryIpPage(IPage page, @Param("params") Map<String, Object> params);
+
+ /**
+ * 根据 forward_dns中的 forwarder查询ip信息
+ * @param ip
+ * @return
+ */
+ List<IpInformation> getIpInfoByFwd(@Param("ip")String ip,@Param("epoch")Integer epoch);
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java
new file mode 100644
index 0000000..7c050ef
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java
@@ -0,0 +1,15 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.modules.dns.domain.ForwardDns;
+import com.example.modules.dns.domain.NonstandardDns;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface NonstandardDnsDao extends BaseMapper<NonstandardDns> {
+
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java
new file mode 100644
index 0000000..5d1c06f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java
@@ -0,0 +1,20 @@
+package com.example.modules.dns.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.example.modules.dns.domain.DohAttribute;
+import com.example.modules.dns.domain.ScanResult;
+import com.example.modules.dns.domain.Vulnerability;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+@Repository
+public interface VulnerabilityDao extends BaseMapper<Vulnerability> {
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java
new file mode 100644
index 0000000..3aad1ca
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java
@@ -0,0 +1,19 @@
+package com.example.modules.dns.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.modules.dns.domain.DohAttribute;
+import com.example.modules.dns.domain.IpInformation;
+import com.example.utils.page.PageUtils;
+
+import java.util.List;
+import java.util.Map;
+
+public interface DnsService extends IService<DohAttribute> {
+
+
+ PageUtils queryPage(Map<String, Object> params);
+
+ Map<String, Object> dataCount(Map<String, Object> params);
+
+ Map<String, List<Map<String, Object>>> mapData();
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java
new file mode 100644
index 0000000..f9cb1c6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java
@@ -0,0 +1,13 @@
+package com.example.modules.dns.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.modules.dns.domain.DnsType;
+import com.example.modules.dns.domain.DohAttribute;
+import com.example.utils.page.PageUtils;
+
+import java.util.List;
+import java.util.Map;
+
+public interface DnsTypeService extends IService<DnsType> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java
new file mode 100644
index 0000000..3dcd9dd
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java
@@ -0,0 +1,13 @@
+package com.example.modules.dns.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.modules.dns.domain.ScanResult;
+
+import java.util.Map;
+
+public interface ScanResultService extends IService<ScanResult> {
+
+
+ Map<String, Object> queryDo53DataCountByDnsType(Map<String,Object> params,Integer dnsType);
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java
new file mode 100644
index 0000000..089a514
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java
@@ -0,0 +1,108 @@
+package com.example.modules.dns.service.impl;
+
+import com.example.utils.Constant;
+import com.example.utils.ElAdminConstant;
+
+import java.util.List;
+
+/**
+ * @author Lihe
+ * @version 1
+ * @description 查询分类
+ * @date 2022/6/22
+ */
+public enum DnsQueryEnum {
+
+ OPEN_RDNS(Constant.OPENRDNSTAG, ElAdminConstant.openRdnsLabels, "openRdns", 1),
+
+ FORWARDER(Constant.FORWARDERTAG, ElAdminConstant.forwarderLabels, "forwarder", 2),
+
+ FWD_RDNS(Constant.FWDRDNSTAG, ElAdminConstant.fwdRdnsLabels, "fwdRdns", 3),
+
+ EGRESS_DNS(Constant.EGRESSRDNSTAG, ElAdminConstant.egressDnsLabels, "egressDns", 4),
+
+ NON_STANDARD(Constant.NONSTANDARDTAG, ElAdminConstant.nonstandardLabels, "nonstandard", 5),
+
+ DNS(Constant.DNSTAG, ElAdminConstant.dnsLabels, "queryDnsInfo", 0),
+
+ DOH(Constant.DOH, ElAdminConstant.dohLabels, "queryDohInfo", 0),
+
+ DO53(Constant.DO53, ElAdminConstant.do53Labels, "queryDo53Info", 0),
+
+ DOH_AND_DO53("dohAndDo53", null, "queryDohAndDo53Info", 0),
+
+ IP(Constant.IP, null, "queryPageByIp", 0),
+ ;
+
+ private final String service;
+
+ private final List<String> labels;
+
+ private final String methodName;
+
+ private final Integer dnsType;
+
+ public static DnsQueryEnum getQueryInfo(String serviceName) {
+ for (DnsQueryEnum value : DnsQueryEnum.values()) {
+ if (value.getService().equals(serviceName)) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+
+ public String getMethodName() {
+ return methodName;
+ }
+
+ public String getService() {
+ return service;
+ }
+
+ public List<String> getLabels() {
+ return labels;
+ }
+
+ public Integer getDnsType() {
+ return dnsType;
+ }
+
+ DnsQueryEnum(String service, List<String> labels, String methodName, Integer dnsType) {
+ this.service = service;
+ this.labels = labels;
+ this.methodName = methodName;
+ this.dnsType = dnsType;
+ }
+
+ public static List<String> getLabels(String key) {
+ for (DnsQueryEnum value : DnsQueryEnum.values()) {
+ if (value.getService().equals(key)) {
+ return value.getLabels();
+ }
+ }
+ return null;
+ }
+
+ public static Integer getDnsType(String key) {
+ for (DnsQueryEnum value : DnsQueryEnum.values()) {
+ if (value.getService().equals(key)) {
+ return value.getDnsType();
+ }
+ }
+ return null;
+ }
+
+ public static String getDnsType(Integer type) {
+ for (DnsQueryEnum value : DnsQueryEnum.values()) {
+ if (value.getDnsType().equals(type)) {
+ return value.getService();
+ }
+ }
+ return null;
+ }
+
+}
+
+
+
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java
new file mode 100644
index 0000000..09cab1a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java
@@ -0,0 +1,631 @@
+package com.example.modules.dns.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.modules.dns.domain.*;
+import com.example.modules.dns.mapper.*;
+import com.example.modules.dns.service.DnsService;
+import com.example.modules.dns.service.ScanResultService;
+import com.example.utils.Constant;
+import com.example.utils.page.PageUtils;
+import com.example.utils.page.Query;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class DnsServiceImpl extends ServiceImpl<DnsDohDao, DohAttribute> implements DnsService {
+ @Autowired
+ private DnsDohDao dnsDohDao;
+
+ @Autowired
+ private DnsDo53Dao dnsDo53Dao;
+
+ @Autowired
+ private IpCertDao ipCertDao;
+
+ @Autowired
+ private IpInformationDao ipInformationDao;
+
+ @Autowired
+ private NonstandardDnsDao nonstandardDnsDao;
+
+ @Autowired
+ private ScanResultService scanResultService;
+
+
+ /**
+ * 添加新service查询逻辑时:
+ * 1. 在本类中实现该service的查询逻辑
+ * 2. DnsQueryEnum 添加该查询逻辑的枚举,包括serviceName,方法名,标签和dnsType可根据需要设置
+ * and 查询逻辑需要单独实现
+ * @param params
+ * @return
+ */
+ @Override
+ public PageUtils queryPage(Map<String, Object> params) {
+ String service = (String) params.get(Constant.SERVICE);
+ String port = (String) params.get(Constant.PORT);
+ String ip = (String) params.get(Constant.IP);
+ IPage page = new Query(IpInformation.class).getPage(params);
+ params.put("n", (page.getCurrent() - 1) * page.getSize()); //用作doh查询的分页
+ params.put("m", page.getSize()); //用作doh查询的分页
+ if(StringUtils.isBlank(service) && StringUtils.isBlank(ip) && StringUtils.isBlank(port)){
+ return new PageUtils(page);
+ }
+ if(StringUtils.isNotBlank(port)){
+ if(Constant.PORT53.equals(port)){
+ service = Constant.DO53;
+ }else if(Constant.PORT443.equals(port) || Constant.PORT8443.equals(port)){
+ service = Constant.DOH;
+ }
+ }
+ if(StringUtils.isBlank(port) && StringUtils.isBlank(service) && StringUtils.isNotBlank(ip)){
+ service = Constant.IP;
+ }
+ if(StringUtils.isNotBlank(service)) {
+ if(service.toLowerCase().contains("and")){
+ return queryDohAndDo53Info(page,params);
+ }else {
+ // DnsQueryEnum 枚举类获取service对应的方法名,并通过反射调用
+ DnsQueryEnum serviceEnum = DnsQueryEnum.getQueryInfo(service.toLowerCase());
+ Class<? extends DnsServiceImpl> aClass = this.getClass();
+ try {
+ Method method = aClass.getDeclaredMethod(serviceEnum.getMethodName(), IPage.class, Map.class);
+ return (PageUtils) method.invoke(this, page, params);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return new PageUtils(page);
+ }
+
+ @Override
+ public Map<String, Object> dataCount(Map<String, Object> params) {
+ String service = (String) params.get(Constant.SERVICE);
+ String port = (String) params.get(Constant.PORT);
+ String ip = (String) params.get(Constant.IP);
+ Map<String, Object> resultMap = new HashMap(8);
+ if(StringUtils.isBlank(service) && StringUtils.isBlank(ip) && StringUtils.isBlank(port)){
+ return resultMap;
+ }
+ List<Map<String, Object>> portList = new ArrayList<>();
+ List<Map<String, Object>> regionList ;
+ List<Map<String, Object>> providerList ;
+ List<Map<String, Object>> componentList ;
+ List<Map<String, Object>> serviceCategoryList = new ArrayList<>();
+ List<Map<String, Object>> do53serviceCategoryList ;
+ List<Map<String, Object>> vulnerabilityCountList ;
+ if (Constant.DOH.equals(service) || Constant.PORT8443.equals(port) || Constant.PORT443.equals(port)) {
+ //端口
+ portList = dnsDohDao.dohPortCount(params);
+ //地域
+ regionList = dnsDohDao.dohProvinceCount(params);
+ //运营商
+ providerList = dnsDohDao.dohProviderCount(params);
+ //服务组件
+ componentList = dnsDohDao.dohComponentCount(params);
+ //服务类别
+ Map<String, Object> map = dnsDohDao.dohServiceCategoryCount(params);
+ map.put("key", Constant.DOHTAG);
+ serviceCategoryList.add(map);
+ //漏洞威胁
+ vulnerabilityCountList = dnsDohDao.dohVulnerabilityCount(params);
+
+ } else if (Constant.DO53.equals(service) || Constant.PORT53.equals(port)) {
+ //端口
+ Map<String, Object> portMap = new HashMap<>();
+ int do53PortCount = dnsDo53Dao.do53IpCount(params);
+ portMap.put("port", Constant.PORT53);
+ portMap.put("count", do53PortCount);
+ portList.add(portMap);
+ //地域
+ regionList = dnsDo53Dao.do53ProvinceCount(params);
+ //运营商
+ providerList = dnsDo53Dao.do53ProviderCount(params);
+ //服务组件
+ componentList = dnsDo53Dao.do53ComponentCount(params);
+ //服务类别
+ do53serviceCategoryList = dnsDo53Dao.do53ServiceCategoryCount(params);
+ serviceCategoryList = transformDo53serviceCategory(do53serviceCategoryList);
+ //漏洞威胁
+ vulnerabilityCountList = dnsDo53Dao.do53VulnerabilityCount(params);
+
+ }else if ("dns".equalsIgnoreCase(service) || StringUtils.isNotBlank(ip)) {
+ //端口
+ portList = dnsDohDao.dohPortCount(params);
+ Map<String, Object> portMap = new HashMap<>();
+ Integer do53PortCount = dnsDo53Dao.do53IpCount(params);
+ portMap.put("port", Constant.PORT53);
+ portMap.put("count", do53PortCount);
+ portList.add(portMap);
+ //地域
+ regionList = dnsDohDao.dohAndDo53ProvinceCount(params);
+ //运营商
+ providerList = dnsDohDao.dohAndDo53ProviderCount(params);
+ //服务组件
+ componentList = dnsDohDao.dohAndDo53ComponentCount(params);
+ //服务类别
+ do53serviceCategoryList = dnsDo53Dao.do53ServiceCategoryCount(params);
+ serviceCategoryList = transformDo53serviceCategory(do53serviceCategoryList);
+ Map<String, Object> map = dnsDohDao.dohServiceCategoryCount(params);
+ map.put("key", Constant.DOHTAG);
+ serviceCategoryList.add(map);
+ //漏洞威胁
+ vulnerabilityCountList = dnsDohDao.dohAndDo53VulnerabilityCount(params);
+ }else if(service.toLowerCase().contains("and")){
+ // 目前只有 doh AND do53其余条件未实现
+ //端口
+ portList = dnsDohDao.countDohPortUnion(params);
+
+ //地域
+ regionList = dnsDohDao.getDohAndDo53ProvinceCount(params);
+ //运营商
+ providerList = dnsDohDao.getDohAndDo53ProviderCount(params);
+ //服务组件
+ componentList = dnsDohDao.getDohAndDo53ComponentCount(params);
+ //服务类别
+ do53serviceCategoryList = dnsDo53Dao.getDohAndDo53SrvCategoryCount(params);
+ serviceCategoryList = transformDo53serviceCategory(do53serviceCategoryList);
+ Map<String, Object> map = dnsDohDao.getDohServiceCategoryCount(params);
+ map.put("key", Constant.DOHTAG);
+ map.put("count", dnsDo53Dao.selectScanResultCountByUnion(params));
+ serviceCategoryList.add(map);
+ //漏洞威胁
+ vulnerabilityCountList = dnsDohDao.getDohAndDo53VulnerabilityCount(params);
+ }else{
+ // dn53下5种 dns_type 统计
+ return scanResultService.queryDo53DataCountByDnsType(params,DnsQueryEnum.getDnsType(service));
+ }
+ resultMap.put("portList", portList);
+ resultMap.put("regionList", regionList);
+ resultMap.put("providerList", providerList);
+ resultMap.put("componentList", componentList);
+ resultMap.put("serviceCategoryList", serviceCategoryList);
+ resultMap.put("vulnerabilityCountList", vulnerabilityCountList);
+ return resultMap;
+ }
+
+ @Override
+ public Map<String, List<Map<String, Object>>> mapData() {
+ Map<String, List<Map<String, Object>>> resultMap = new HashMap<>();
+ List<Map<String, Object>> dohChinaMapList ;
+ List<Map<String, Object>> dohWorldMapDataList ;
+ List<Map<String, Object>> do53CountryMapCountList ;
+ List<Map<String, Object>> do53OpenRdnsList = new ArrayList<>();
+ List<Map<String, Object>> do53ForwarderList = new ArrayList<>();
+ List<Map<String, Object>> do53FwdRdnsList = new ArrayList<>();
+ List<Map<String, Object>> do53EgressDnsList = new ArrayList<>();
+ List<Map<String, Object>> do53NonstandardList = new ArrayList<>();
+ List<Map<String, Object>> do53WorldMapList ;
+ List<Map<String, Object>> do53ChinaMapList ;
+ dohChinaMapList = dnsDohDao.dohChinaMapCount();
+ dohWorldMapDataList = dnsDohDao.dohCountryCount();
+ do53WorldMapList = dnsDo53Dao.do53WorldMapCount();
+ do53ChinaMapList = dnsDo53Dao.do53ChinaMapCount();
+ do53CountryMapCountList = dnsDo53Dao.do53CountryMapCount();
+ for (Map<String, Object> map : do53CountryMapCountList) {
+ if (Constant.OPENRDNS == map.get("type")) {
+ do53OpenRdnsList.add(map);
+ } else if (Constant.FORWARDER == map.get("type")) {
+ do53ForwarderList.add(map);
+ } else if (Constant.FWDRDNS == map.get("type")) {
+ do53FwdRdnsList.add(map);
+ } else if (Constant.EGRESSRDNS == map.get("type")) {
+ do53EgressDnsList.add(map);
+ } else if (Constant.NONSTANDARD == map.get("type")) {
+ do53NonstandardList.add(map);
+ }
+ }
+ resultMap.put("dohChinaMapList", dohChinaMapList);
+ resultMap.put("dohWorldMapDataList", dohWorldMapDataList);
+ resultMap.put("do53WorldMapDataList", do53WorldMapList);
+ resultMap.put("do53ChinaMapList", do53ChinaMapList);
+ resultMap.put("do53OpenRdnsList", do53OpenRdnsList);
+ resultMap.put("do53ForwarderList", do53ForwarderList);
+ resultMap.put("do53FwdRdnsList", do53FwdRdnsList);
+ resultMap.put("do53EgressDnsList", do53EgressDnsList);
+ resultMap.put("do53NonstandardList", do53NonstandardList);
+ return resultMap;
+ }
+
+ public List<Map<String, Object>> transformDo53serviceCategory(List<Map<String, Object>> do53serviceCategoryList) {
+ List<Map<String, Object>> serviceCategoryList = new ArrayList<>();
+ long do53Count = 0;
+ for (Map<String, Object> map : do53serviceCategoryList) {
+ Map<String, Object> do53ServiceMap = new HashMap<>();
+ long count = (long) map.get("count");
+ int dnsType = (int) map.get("type");
+ if (Constant.FORWARDER == dnsType) { //2
+ do53ServiceMap.put("key", Constant.FORWARDERTAG);
+ do53ServiceMap.put("count", count);
+ } else if (Constant.FWDRDNS == dnsType) {//3
+ do53ServiceMap.put("key", Constant.FWDRDNSTAG);
+ do53ServiceMap.put("count", count);
+ } else if (Constant.EGRESSRDNS == dnsType) { //4
+ do53ServiceMap.put("key", Constant.EGRESSRDNSTAG);
+ do53ServiceMap.put("count", count);
+ } else if (Constant.NONSTANDARD == dnsType) { //5
+ do53ServiceMap.put("key", Constant.NONSTANDARDTAG);
+ do53ServiceMap.put("count", count);
+ } else if (Constant.OPENRDNS == dnsType) { //1
+ do53ServiceMap.put("key", Constant.OPENRDNSTAG);
+ do53ServiceMap.put("count", count);
+ }
+ do53Count += count;
+ serviceCategoryList.add(do53ServiceMap);
+ }
+ HashMap<String, Object> do53Map = new HashMap<>();
+ do53Map.put("key", Constant.DO53TAG);
+ do53Map.put("count", do53Count);
+ serviceCategoryList.add(do53Map);
+ return serviceCategoryList;
+
+ }
+
+ /**
+ * 设置doh属性
+ * @param dohAttributes
+ */
+ public void setDohData(List<Result> dohAttributes) {
+ for (Result dohAttribute : dohAttributes) {
+ String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
+ dohAttribute.setUuid(uuid);
+ String dohIp = dohAttribute.getIp();
+ Integer port = dohAttribute.getPort();
+ String component = dohAttribute.getComponent();
+ String path = dohAttribute.getPath();
+ dohAttribute.setProtocolType(Constant.PROTOC_TCP);
+ dohAttribute.setIpType(getIpType(dohIp));
+ if (component != null)
+ dohAttribute.setComponentList(new ArrayList<>(Arrays.stream(component.split(",")).collect(Collectors.toSet())));
+ if (path != null)
+ dohAttribute.setPathList(new ArrayList<>(Arrays.stream(path.split(",")).collect(Collectors.toSet())));
+ ArrayList<String> tagList = new ArrayList<>(); //添加服务类别标签
+ tagList.add(Constant.DOHTAG);
+ List<Object> banner = new ArrayList<>();
+ List<Object> httpHeader = new ArrayList<>();
+ // 根据ip,port,host,rounds查询doh_attribute rep_body repHeader信息
+ List<Result> repList = this.baseMapper.getDohRepBody(dohIp, port, dohAttribute.getHost(), dohAttribute.getRounds());
+ for (int i = 0; i < repList.size(); i++) {
+ Result result = repList.get(i);
+ if (StringUtils.isNotBlank(result.getRepBody())) {
+ banner.add(result.getRepBody());
+ }
+ if (StringUtils.isNotBlank(result.getRepHeader())) {
+ httpHeader.add(result.getRepHeader());
+ }
+ }
+ dohAttribute.setBanner(banner);
+ dohAttribute.setHttpContent(httpHeader);
+ //根据ip和端口查询证书库,获取证书数据
+ List<IpCert> ipCertList = ipCertDao.selectList(new LambdaQueryWrapper<IpCert>().eq(IpCert::getIp, dohIp).eq(IpCert::getPort, port));
+ dohAttribute.setIpCert(ipCertList);
+ dohAttribute.setTags(tagList);
+ }
+ }
+
+ /**
+ * 设置do53标签,根据dnsType设置banner
+ * type = 1 banner list.get(0)为rep
+ * type = 2,3 banner中的 list.get(0)为 query_rep,列表其余数据为ip信息
+ * type = 5 banner list.get(0)为rep,其余为NonstandardDns列表
+ * @param scanResultList
+ */
+ public void setdo53Data(List<Result> scanResultList) {
+ for (Result scanResult : scanResultList) {
+ String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
+ scanResult.setUuid(uuid);
+ String do53Ip = scanResult.getIp();
+ Integer epoch = scanResult.getEpoch();
+ Integer dnsType = scanResult.getDnsType();
+ ArrayList<String> tagList = new ArrayList<>(); //添加服务类别标签
+ tagList.add(Constant.DO53TAG);
+ scanResult.setIpType(getIpType(do53Ip));
+ scanResult.setProtocolType(getProtocolType(scanResult.getScanType()));
+ List<Object> bannerList = new ArrayList<>();
+ if (Constant.FORWARDER.equals(dnsType) || Constant.FWDRDNS.equals(dnsType)) { //2、3
+ if (Constant.FWDRDNS.equals(dnsType)) { //3
+ tagList.add(Constant.FORWARDERTAG);
+ } else {
+ tagList.add(Constant.FWDRDNSTAG);
+ }
+ bannerList.add(scanResult.getQueryResponse());
+ List<IpInformation> forwardDnsList = ipInformationDao.getIpInfoByFwd(do53Ip, epoch);
+ bannerList.addAll(forwardDnsList);
+ } else if (Constant.EGRESSRDNS.equals(dnsType)) { //4
+ tagList.add(Constant.EGRESSRDNSTAG);
+
+ } else if (Constant.NONSTANDARD.equals(dnsType)) { //5
+ bannerList.add(scanResult.getQueryResponse());
+ tagList.add(Constant.NONSTANDARDTAG);
+ List<NonstandardDns> nonstandardDnsList = nonstandardDnsDao.selectList(new LambdaQueryWrapper<NonstandardDns>().eq(NonstandardDns::getIp, do53Ip).eq(NonstandardDns::getEpoch, epoch));
+ bannerList.addAll((List<JSONObject>) JSONObject.toJSON(nonstandardDnsList));
+ } else if (Constant.OPENRDNS.equals(dnsType)) { //1
+ tagList.add(Constant.OPENRDNSTAG);
+ if(StringUtils.isNotBlank(scanResult.getQueryResponse())){
+ bannerList.add(scanResult.getQueryResponse());
+ }
+ }
+ scanResult.setBanner(bannerList);
+ scanResult.setTags(tagList);
+ }
+ }
+
+ /**
+ * @param dataList 目标list
+ * @param pageSize 当前页大小
+ * @param currentPage 当前页
+ * @return 返回当前页的数据集
+ * @deprecated 对list进行分页
+ */
+ public List<Result> getPage(List<Result> dataList, int pageSize, int currentPage) {
+ List<Result> currentPageList = new ArrayList<>();
+ if (!dataList.isEmpty()) {
+ int currIdx = (currentPage > 1 ? (currentPage - 1) * pageSize : 0);
+ for (int i = 0; i < pageSize && i < dataList.size() - currIdx; i++) {
+ Result data = dataList.get(currIdx + i);
+ currentPageList.add(data);
+ }
+ }
+ return currentPageList;
+ }
+
+
+ /**
+ * 查询dns信息,dnh和do53(scan_result)结果并集
+ *
+ * @param page
+ * @param params
+ * @return
+ */
+ private PageUtils queryDnsInfo(IPage page, Map<String, Object> params) {
+ Map<String, Object> indepentIpMap = new HashMap<>(4);
+ int resultTotal = 0;
+ long pageSize = page.getSize();
+ params.put("n", 0); //用作doh查询的分页偏移量
+ params.put("m", page.getCurrent() * page.getSize()); //用作查询的分页大小
+ // 查询doh信息
+ //同一轮次,相同ip合并path和component,漏洞信息
+ List<Result> dohAttributes = dnsDohDao.queryDohPage(null, params);
+ setDohData(dohAttributes);
+ int dohResultTotal = dnsDohDao.dohResultTotalCount(params);
+ indepentIpMap.put("dns-doh", dnsDohDao.dohIpCount(params));
+ // 查询do53信息
+ List<Result> scanResultList = dnsDo53Dao.queryDo53Page(null, params);
+ setdo53Data(scanResultList);
+ indepentIpMap.put("dns-do53", dnsDo53Dao.do53IpCount(params));
+ int do53ResultTotal = dnsDo53Dao.pageCount(params);
+
+ List<Result> resultList = new ArrayList<>();
+ resultList.addAll(dohAttributes);
+ resultList.addAll(scanResultList);
+ List<Result> collect = resultList.stream().sorted(Comparator.comparing(Result::getTimestamp).reversed()).collect(Collectors.toList());
+
+ page.setTotal(do53ResultTotal + dohResultTotal);
+ page.setRecords(getPage(collect, (int) pageSize, (int) page.getCurrent()));
+
+ return buildResult(page,indepentIpMap,(do53ResultTotal + dohResultTotal));
+ }
+
+ /**
+ * 查询 do53信息
+ * @param page
+ * @param params
+ * @return
+ */
+ private PageUtils queryDo53Info(IPage page, Map<String, Object> params){
+ // 根据 service=dns-do53, port为53查询 scan_result表 参数:ip,port
+ List<Result> scanResultList = dnsDo53Dao.queryDo53Page(null, params);
+ setdo53Data(scanResultList);
+
+ int independentIpNum = dnsDo53Dao.do53IpCount(params);
+ int resultTotal = dnsDo53Dao.pageCount(params);
+ page.setRecords(scanResultList);
+ return buildResult(page,independentIpNum,resultTotal);
+ }
+
+ /**
+ * 查询doh信息
+ * @param page
+ * @param params
+ * @return
+ */
+ private PageUtils queryDohInfo(IPage page, Map<String, Object> params){
+ // 根据 service=dns-do53, port为53查询 scan_result表 参数:ip,port
+ List<Result> scanResultList = dnsDohDao.queryDohPage(null, params);
+ setDohData(scanResultList);
+
+ int independentIpNum = dnsDohDao.dohIpCount(params);
+ int resultTotal = dnsDohDao.dohResultTotalCount(params);
+ page.setRecords(scanResultList);
+ return buildResult(page,independentIpNum,resultTotal);
+ }
+
+ /**
+ * 只根据ip查询
+ * @param page
+ * @param params
+ * @return
+ */
+ private PageUtils queryPageByIp(IPage page, Map<String, Object> params){
+ // 只根据ip查询
+ int independentIpNum = 0;
+ params.put("n", 0); //用作doh查询的分页
+ params.put("m", page.getCurrent() * page.getSize()); //用作doh查询的分页
+ long pageSize = page.getSize();
+ List<Result> dohAttributesList = dnsDohDao.queryDohPage(null, params);
+ setDohData(dohAttributesList);
+ List<Result> scanResultList = dnsDo53Dao.queryDo53Page(null, params);
+ setdo53Data(scanResultList);
+ List<Result> resultList = new ArrayList<>();
+ resultList.addAll(dohAttributesList);
+ resultList.addAll(scanResultList);
+ int resultTotal = resultList.size();
+ List<Result> collect = resultList.stream().sorted(Comparator.comparing(Result::getTimestamp).reversed()).collect(Collectors.toList());
+ if (!collect.isEmpty()) {
+ independentIpNum = 1;
+ }
+ page.setTotal(collect.size());
+ page.setRecords(getPage(collect, (int) pageSize, (int) page.getCurrent()));
+ return buildResult(page,independentIpNum,resultTotal);
+ }
+
+ /**
+ * 查询 dnh和do53(scan_result)结果交集 service = dns-doh AND dns-do53
+ *
+ * @param page
+ * @param params
+ * @return
+ */
+ private PageUtils queryDohAndDo53Info(IPage page, Map<String, Object> params) {
+ params.put("offset", 0); //用作doh查询的分页偏移量
+ params.put("limit", page.getCurrent() * page.getSize()); //用作查询的分页大小
+ Map<String, Object> indepentIpMap = new HashMap<>(4);
+
+ // 查询doh信息
+ List<Result> dohAttributes = dnsDohDao.selectDohInfoByUnion(params);
+ Integer dohCount = dnsDohDao.selectDohCountByUnion(params);
+ setDohData(dohAttributes);
+ // 查询do53(scan_result)信息
+ List<Result> do53Infos = dnsDo53Dao.selectScanResultByUnion(null,params);
+ Integer do53Count = dnsDo53Dao.selectScanResultCountByUnion(params);
+ setdo53Data(do53Infos);
+ do53Infos.addAll(dohAttributes);
+
+ page.setTotal(dohCount + do53Count);
+ page.setRecords(getPage(do53Infos, (int) page.getSize(), (int) page.getCurrent()));
+ indepentIpMap.put("dns-doh",do53Count);
+ indepentIpMap.put("dns-do53",do53Count);
+
+ return buildResult(page,indepentIpMap,(dohCount + do53Count));
+
+ }
+
+ private String getIpType(String ip){
+ if(ip.contains(Constant.POINT)){
+ return Constant.IP_IPV4;
+ }
+ return Constant.IP_IPV6;
+ }
+
+ private String getProtocolType(Integer scanType){
+ // dnsType 为2为udp,1或者空为tcp
+ if(scanType == null || scanType < 2){
+ return Constant.PROTOC_TCP;
+ }
+ return Constant.PROTOC_UDP;
+ }
+
+ private PageUtils buildResult(IPage page,Object independentIpNum,Integer resultTotal ){
+ PageUtils pageUtils = new PageUtils(page);
+ // 添加独立IP个数
+ pageUtils.setIndependentIpNum(independentIpNum);
+ pageUtils.setResultTotal(resultTotal);
+ return pageUtils;
+ }
+
+
+ private PageUtils openRdns(IPage page, Map<String, Object> params) {
+ List<Result> results = dnsDo53Dao.queryOpenRdns(params);
+ int totalCount = dnsDo53Dao.getCountByDnsType(Constant.OPENRDNS, params);
+ setDo53Label(results, Constant.OPENRDNSTAG);
+ page.setRecords(results);
+ // 添加独立IP个数
+ Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.OPENRDNS, params);
+
+ return buildResult(page,independentIpNum,totalCount);
+ }
+
+ private PageUtils forwarder(IPage page, Map<String, Object> params) {
+ int totalCount = dnsDo53Dao.getCountByDnsType(Constant.FORWARDER, params);
+ List<Result> results = dnsDo53Dao.queryOpenRdns(params);
+ for (Result result : results) {
+ List<IpInformation> ipInfos = ipInformationDao.getIpInfoByFwd(result.getIp(),null);
+ result.setBanner(ipInfos);
+ result.setProtocolType(getProtocolType(result.getScanType()));
+ result.setIpType(getIpType(result.getIp()));
+ addLabels(result, Constant.FORWARDERTAG);
+ }
+
+ page.setRecords(results);
+ // 添加独立IP个数
+ Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.FORWARDER, params);
+
+ return buildResult(page,independentIpNum,totalCount);
+ }
+
+ private PageUtils fwdRdns(IPage page, Map<String, Object> params) {
+ int totalCount = dnsDo53Dao.getCountByDnsType(Constant.FWDRDNS, params);
+ List<Result> results = dnsDo53Dao.queryOpenRdns(params);
+ for (Result result : results) {
+ List<IpInformation> ipInfos = ipInformationDao.getIpInfoByFwd(result.getIp(),null);
+ result.setBanner(ipInfos);
+ result.setProtocolType(getProtocolType(result.getScanType()));
+ result.setIpType(getIpType(result.getIp()));
+ addLabels(result, Constant.FWDRDNSTAG);
+ }
+ page.setRecords(results);
+ // 添加独立IP个数
+ Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.FWDRDNS, params);
+
+ return buildResult(page,independentIpNum,totalCount);
+ }
+
+ private PageUtils egressDns(IPage page, Map<String, Object> params) {
+ int totalCount = dnsDo53Dao.getCountByDnsType(Constant.EGRESSRDNS, params);
+ List<Result> results = dnsDo53Dao.queryOpenRdns(params);
+ setDo53Label(results, Constant.EGRESSRDNSTAG);
+ page.setRecords(results);
+ // 添加独立IP个数
+ Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.EGRESSRDNS, params);
+
+ return buildResult(page,independentIpNum,totalCount);
+ }
+
+ private PageUtils nonstandard(IPage page, Map<String, Object> params) {
+ int totalCount = dnsDo53Dao.getCountByDnsType(Constant.NONSTANDARD, params);
+ List<Result> results = dnsDo53Dao.queryOpenRdns(params);
+ for (Result result : results) {
+ List<IpInformation> ipInfos = ipInformationDao.getIpInfoByFwd(result.getIp(),null);
+ result.setBanner(ipInfos);
+ result.setProtocolType(getProtocolType(result.getScanType()));
+ result.setIpType(getIpType(result.getIp()));
+ addLabels(result, Constant.NONSTANDARDTAG);
+ }
+
+ page.setRecords(results);
+ // 添加独立IP个数
+ Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.NONSTANDARD, params);
+
+ return buildResult(page,independentIpNum,totalCount);
+ }
+
+
+
+ private void setDo53Label(List<Result> results, String serviceType) {
+ List<String> labels = DnsQueryEnum.getLabels(serviceType);
+ for (Result result : results) {
+ // result.setBanner(result.getQueryResponse());
+ result.setProtocolType(getProtocolType(result.getScanType()));
+ result.setIpType(getIpType(result.getIp()));
+ result.setTags(labels);
+ }
+ }
+
+ private void addLabels(Result result, String serviceType) {
+ List<String> labels = DnsQueryEnum.getLabels(serviceType);
+ result.setTags(labels);
+ }
+
+}
+
+
+
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java
new file mode 100644
index 0000000..8bd6d89
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java
@@ -0,0 +1,15 @@
+package com.example.modules.dns.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.modules.dns.domain.DnsType;
+import com.example.modules.dns.mapper.DnsTypeDao;
+import com.example.modules.dns.service.DnsTypeService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DnsTypeServiceImpl extends ServiceImpl<DnsTypeDao, DnsType> implements DnsTypeService {
+
+}
+
+
+
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java
new file mode 100644
index 0000000..5b832c9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java
@@ -0,0 +1,66 @@
+package com.example.modules.dns.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.modules.dns.domain.ScanResult;
+import com.example.modules.dns.mapper.DnsDo53Dao;
+import com.example.modules.dns.service.ScanResultService;
+import com.example.utils.Constant;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Lihe
+ * @version 1
+ * @description
+ * @date 2022/6/8
+ */
+@Service
+public class ScanResultServiceImpl extends ServiceImpl<DnsDo53Dao, ScanResult> implements ScanResultService {
+
+
+ @Override
+ public Map<String, Object> queryDo53DataCountByDnsType(Map<String, Object> params, Integer dnsType) {
+
+ Map<String, Object> resultMap = new HashMap(8);
+ List<Map<String, Object>> portList = new ArrayList<>();
+
+ List<Map<String, Object>> serviceCategoryList = new ArrayList<>();
+ //端口
+ Map<String, Object> portMap = new HashMap<>();
+ int count = this.baseMapper.getCountByDnsType(dnsType,params);
+ portMap.put("port", Constant.PORT53);
+ portMap.put("count", count);
+ portList.add(portMap);
+ resultMap.put("portList", portList);
+
+ //地域
+ resultMap.put("regionList", this.baseMapper.getDo53ProvinceCountByDnsType(dnsType,params));
+
+ //运营商
+ resultMap.put("providerList", this.baseMapper.getDo53ProviderCountByDnsType(dnsType,params));
+
+ //服务组件
+ resultMap.put("componentList", this.baseMapper.getDo53ComponentCountByDnsType(dnsType,params));
+
+ //服务类别
+ Integer serviceCount = this.baseMapper.getDo53SrvCategoryCountByDnsType(dnsType,params);
+ Map<String,Object> dnsTypeMap = new HashMap<>(2);
+ dnsTypeMap.put("key",DnsQueryEnum.getDnsType(dnsType));
+ dnsTypeMap.put("count",serviceCount);
+ serviceCategoryList.add(dnsTypeMap);
+ Map<String,Object> do53ServiceMap = new HashMap<>(2);
+ do53ServiceMap.put("key",Constant.DO53TAG);
+ do53ServiceMap.put("count",serviceCount);
+ serviceCategoryList.add(do53ServiceMap);
+ resultMap.put("serviceCategoryList", serviceCategoryList);
+
+ //漏洞威胁
+ resultMap.put("vulnerabilityCountList", this.baseMapper.getDo53VulnerabCountByDnsType(dnsType,params));
+
+ return resultMap;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java
new file mode 100644
index 0000000..1c01c10
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.config;
+
+import com.example.modules.security.config.bean.LoginProperties;
+import com.example.modules.security.config.bean.SecurityProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @apiNote 配置文件转换Pojo类的 统一配置 类
+ * @author: liaojinlong
+ * : 2020/6/10 19:04
+ */
+@Configuration
+public class ConfigBeanConfiguration {
+
+ @Bean
+ @ConfigurationProperties(prefix = "login")
+ public LoginProperties loginProperties() {
+ return new LoginProperties();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "jwt")
+ public SecurityProperties securityProperties() {
+ return new SecurityProperties();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java
new file mode 100644
index 0000000..aa9fddf
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.config;
+
+import com.example.modules.security.security.JwtAccessDeniedHandler;
+import com.example.modules.security.security.JwtAuthenticationEntryPoint;
+import com.example.modules.security.security.TokenConfigurer;
+import com.example.modules.security.security.TokenProvider;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.AnonymousAccess;
+import com.example.modules.security.config.bean.SecurityProperties;
+import com.example.modules.security.security.*;
+import com.example.modules.security.service.OnlineUserService;
+import com.example.modules.security.service.UserCacheClean;
+import com.example.utils.enums.RequestMethodEnum;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+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.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.core.GrantedAuthorityDefaults;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+import java.util.*;
+
+/**
+ *
+ */
+@Configuration
+@EnableWebSecurity
+@RequiredArgsConstructor
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ private final TokenProvider tokenProvider;
+ private final CorsFilter corsFilter;
+ private final JwtAuthenticationEntryPoint authenticationErrorHandler;
+ private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
+ private final ApplicationContext applicationContext;
+ private final SecurityProperties properties;
+ private final OnlineUserService onlineUserService;
+ private final UserCacheClean userCacheClean;
+
+ @Bean
+ GrantedAuthorityDefaults grantedAuthorityDefaults() {
+ // 去除 ROLE_ 前缀
+ return new GrantedAuthorityDefaults("");
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ // 密码加密方式
+ return new BCryptPasswordEncoder();
+ }
+
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ // 搜寻匿名标记 url: @AnonymousAccess
+ RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
+ Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
+ // 获取匿名标记
+ Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap);
+ httpSecurity
+ // 禁用 CSRF
+ .csrf().disable()
+ .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
+ // 授权异常
+ .exceptionHandling()
+ .authenticationEntryPoint(authenticationErrorHandler)
+ .accessDeniedHandler(jwtAccessDeniedHandler)
+ // 防止iframe 造成跨域
+ .and()
+ .headers()
+ .frameOptions()
+ .disable()
+ // 不创建会话
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .authorizeRequests()
+ // 静态资源等等
+ .antMatchers(
+ HttpMethod.GET,
+ "/*.html",
+ "/**/*.html",
+ "/**/*.css",
+ "/**/*.js",
+ "/webSocket/**"
+ ).permitAll()
+ // swagger 文档
+ .antMatchers("/swagger-ui.html").permitAll()
+ .antMatchers("/swagger-resources/**").permitAll()
+ .antMatchers("/webjars/**").permitAll()
+ .antMatchers("/*/api-docs").permitAll()
+ // 文件
+ .antMatchers("/avatar/**").permitAll()
+ .antMatchers("/file/**").permitAll()
+ // 阿里巴巴 druid
+ .antMatchers("/druid/**").permitAll()
+ // 放行OPTIONS请求
+ .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
+ // 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
+ // GET
+ .antMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()
+ // POST
+ .antMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()
+ // PUT
+ .antMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()
+ // PATCH
+ .antMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()
+ // DELETE
+ .antMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()
+ // 所有类型的接口都放行
+ .antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()
+ // 所有请求都需要认证
+ .anyRequest().authenticated()
+ .and().apply(securityConfigurerAdapter());
+ }
+
+ private TokenConfigurer securityConfigurerAdapter() {
+ return new TokenConfigurer(tokenProvider, properties, onlineUserService, userCacheClean);
+ }
+
+ private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {
+ Map<String, Set<String>> anonymousUrls = new HashMap<>(8);
+ Set<String> get = new HashSet<>();
+ Set<String> post = new HashSet<>();
+ Set<String> put = new HashSet<>();
+ Set<String> patch = new HashSet<>();
+ Set<String> delete = new HashSet<>();
+ Set<String> all = new HashSet<>();
+ for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
+ HandlerMethod handlerMethod = infoEntry.getValue();
+ AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
+ if (null != anonymousAccess) {
+ List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
+ RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
+ switch (Objects.requireNonNull(request)) {
+ case GET:
+ get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ break;
+ case POST:
+ post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ break;
+ case PUT:
+ put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ break;
+ case PATCH:
+ patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ break;
+ case DELETE:
+ delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ break;
+ default:
+ all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
+ break;
+ }
+ }
+ }
+ anonymousUrls.put(RequestMethodEnum.GET.getType(), get);
+ anonymousUrls.put(RequestMethodEnum.POST.getType(), post);
+ anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);
+ anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);
+ anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);
+ anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);
+ return anonymousUrls;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java
new file mode 100644
index 0000000..02fbc23
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.config.bean;
+
+import lombok.Data;
+
+/**
+ * 登录验证码配置信息
+ *
+ * @author liaojinlong
+ * 2020/6/10 18:53
+ */
+@Data
+public class LoginCode {
+
+ /**
+ * 验证码配置
+ */
+ private LoginCodeEnum codeType;
+ /**
+ * 验证码有效期 分钟
+ */
+ private Long expiration = 2L;
+ /**
+ * 验证码内容长度
+ */
+ private int length = 2;
+ /**
+ * 验证码宽度
+ */
+ private int width = 111;
+ /**
+ * 验证码高度
+ */
+ private int height = 36;
+ /**
+ * 验证码字体
+ */
+ private String fontName;
+ /**
+ * 字体大小
+ */
+ private int fontSize = 25;
+
+ public LoginCodeEnum getCodeType() {
+ return codeType;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java
new file mode 100644
index 0000000..d9fe369
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.config.bean;
+
+/**
+ * 验证码配置枚举
+ *
+ * @author: liaojinlong
+ * : 2020/6/10 17:40
+ */
+
+public enum LoginCodeEnum {
+ /**
+ * 算数
+ */
+ ARITHMETIC,
+ /**
+ * 中文
+ */
+ CHINESE,
+ /**
+ * 中文闪图
+ */
+ CHINESE_GIF,
+ /**
+ * 闪图
+ */
+ GIF,
+ SPEC
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java
new file mode 100644
index 0000000..f4b6754
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version loginCode.length.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-loginCode.length.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.config.bean;
+
+import com.wf.captcha.*;
+import com.wf.captcha.base.Captcha;
+import lombok.Data;
+import com.example.exception.BadConfigurationException;
+import com.example.utils.StringUtils;
+
+import java.awt.*;
+import java.util.Objects;
+
+/**
+ * 配置文件读取
+ *
+ * @author liaojinlong
+ * loginCode.length0loginCode.length0/6/10 17:loginCode.length6
+ */
+@Data
+public class LoginProperties {
+
+ /**
+ * 账号单用户 登录
+ */
+ private boolean singleLogin = false;
+
+ private LoginCode loginCode;
+
+ /**
+ * 用户登录信息缓存
+ */
+ private boolean cacheEnable;
+
+ public boolean isSingleLogin() {
+ return singleLogin;
+ }
+
+ public boolean isCacheEnable() {
+ return cacheEnable;
+ }
+
+ /**
+ * 获取验证码生产类
+ *
+ * @return /
+ */
+ public Captcha getCaptcha() {
+ if (Objects.isNull(loginCode)) {
+ loginCode = new LoginCode();
+ if (Objects.isNull(loginCode.getCodeType())) {
+ loginCode.setCodeType(LoginCodeEnum.ARITHMETIC);
+ }
+ }
+ return switchCaptcha(loginCode);
+ }
+
+ /**
+ * 依据配置信息生产验证码
+ *
+ * @param loginCode 验证码配置信息
+ * @return /
+ */
+ private Captcha switchCaptcha(LoginCode loginCode) {
+ Captcha captcha;
+ synchronized (this) {
+ switch (loginCode.getCodeType()) {
+ case ARITHMETIC:
+ // 算术类型 https://gitee.com/whvse/EasyCaptcha
+ captcha = new FixedArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ // 几位数运算,默认是两位
+ captcha.setLen(loginCode.getLength());
+ break;
+ case CHINESE:
+ captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ case CHINESE_GIF:
+ captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ case GIF:
+ captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ case SPEC:
+ captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ default:
+ throw new BadConfigurationException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
+ }
+ }
+ if(StringUtils.isNotBlank(loginCode.getFontName())){
+ captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize()));
+ }
+ return captcha;
+ }
+
+ static class FixedArithmeticCaptcha extends ArithmeticCaptcha {
+ public FixedArithmeticCaptcha(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ protected char[] alphas() {
+ // 生成随机数字和运算符
+ int n1 = num(1, 10), n2 = num(1, 10);
+ int opt = num(3);
+
+ // 计算结果
+ int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
+ // 转换为字符运算符
+ char optChar = "+-x".charAt(opt);
+
+ this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
+ this.chars = String.valueOf(res);
+
+ return chars.toCharArray();
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java
new file mode 100644
index 0000000..f341003
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.config.bean;
+
+import lombok.Data;
+
+/**
+ * Jwt参数配置
+ *
+ *
+ * 2019年11月28日
+ */
+@Data
+public class SecurityProperties {
+
+ /**
+ * Request Headers : Authorization
+ */
+ private String header;
+
+ /**
+ * 令牌前缀,最后留个空格 Bearer
+ */
+ private String tokenStartWith;
+
+ /**
+ * 必须使用最少88位的Base64对该令牌进行编码
+ */
+ private String base64Secret;
+
+ /**
+ * 令牌过期时间 此处单位/毫秒
+ */
+ private Long tokenValidityInSeconds;
+
+ /**
+ * 在线用户 key,根据 key 查询 redis 中在线用户的数据
+ */
+ private String onlineKey;
+
+ /**
+ * 验证码 key
+ */
+ private String codeKey;
+
+ /**
+ * token 续期检查
+ */
+ private Long detect;
+
+ /**
+ * 续期时间
+ */
+ private Long renew;
+
+ public String getTokenStartWith() {
+ return tokenStartWith + " ";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java
new file mode 100644
index 0000000..7e2148b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.rest;
+
+import cn.hutool.core.util.IdUtil;
+import com.wf.captcha.base.Captcha;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import com.example.annotation.rest.AnonymousDeleteMapping;
+import com.example.annotation.rest.AnonymousGetMapping;
+import com.example.annotation.rest.AnonymousPostMapping;
+import com.example.config.RsaProperties;
+import com.example.exception.BadRequestException;
+import com.example.modules.security.config.bean.LoginCodeEnum;
+import com.example.modules.security.config.bean.LoginProperties;
+import com.example.modules.security.config.bean.SecurityProperties;
+import com.example.modules.security.security.TokenProvider;
+import com.example.modules.security.service.dto.AuthUserDto;
+import com.example.modules.security.service.dto.JwtUserDto;
+import com.example.modules.security.service.OnlineUserService;
+import com.example.utils.RsaUtils;
+import com.example.utils.RedisUtils;
+import com.example.utils.SecurityUtils;
+import com.example.utils.StringUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * 2018-11-23
+ * 授权、根据token获取用户详细信息
+ */
+@Slf4j
+@RestController
+@RequestMapping("/auth")
+@RequiredArgsConstructor
+@Api(tags = "系统:系统授权接口")
+public class AuthorizationController {
+ private final SecurityProperties properties;
+ private final RedisUtils redisUtils;
+ private final OnlineUserService onlineUserService;
+ private final TokenProvider tokenProvider;
+ private final AuthenticationManagerBuilder authenticationManagerBuilder;
+ @Resource
+ private LoginProperties loginProperties;
+
+ @ApiOperation("登录授权")
+ @AnonymousPostMapping(value = "/login")
+ public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
+ // 密码解密
+ String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
+ //去除验证码功能
+/* // 查询验证码
+ String code = (String) redisUtils.get(authUser.getUuid());
+ // 清除验证码
+ redisUtils.del(authUser.getUuid());
+ if (StringUtils.isBlank(code)) {
+ throw new BadRequestException("验证码不存在或已过期");
+ }
+ if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {
+ throw new BadRequestException("验证码错误");
+ }*/
+ UsernamePasswordAuthenticationToken authenticationToken =
+ new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
+ Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ // 生成令牌与第三方系统获取令牌方式
+ // UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername());
+ // Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+ // SecurityContextHolder.getContext().setAuthentication(authentication);
+ String token = tokenProvider.createToken(authentication);
+ final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
+ // 保存在线信息
+ onlineUserService.save(jwtUserDto, token, request);
+ // 返回 token 与 用户信息
+ Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
+ put("token", properties.getTokenStartWith() + token);
+ put("user", jwtUserDto);
+ }};
+ if (loginProperties.isSingleLogin()) {
+ //踢掉之前已经登录的token
+ onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
+ }
+ return ResponseEntity.ok(authInfo);
+ }
+
+ @ApiOperation("获取用户信息")
+ @GetMapping(value = "/info")
+ public ResponseEntity<Object> getUserInfo() {
+ return ResponseEntity.ok(SecurityUtils.getCurrentUser());
+ }
+
+ @ApiOperation("获取验证码")
+ @AnonymousGetMapping(value = "/code")
+ public ResponseEntity<Object> getCode() {
+ // 获取运算的结果
+ Captcha captcha = loginProperties.getCaptcha();
+ String uuid = properties.getCodeKey() + IdUtil.simpleUUID();
+ //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
+ String captchaValue = captcha.text();
+ if (captcha.getCharType() - 1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")) {
+ captchaValue = captchaValue.split("\\.")[0];
+ }
+ // 保存
+ redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
+ // 验证码信息
+ Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
+ put("img", captcha.toBase64());
+ put("uuid", uuid);
+ }};
+ return ResponseEntity.ok(imgResult);
+ }
+
+ @ApiOperation("退出登录")
+ @AnonymousDeleteMapping(value = "/logout")
+ public ResponseEntity<Object> logout(HttpServletRequest request) {
+ onlineUserService.logout(tokenProvider.getToken(request));
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java
new file mode 100644
index 0000000..c4962a3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.rest;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.modules.security.service.OnlineUserService;
+import com.example.utils.EncryptUtils;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ *
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/auth/online")
+@Api(tags = "系统:在线用户管理")
+public class OnlineController {
+
+ private final OnlineUserService onlineUserService;
+
+ @ApiOperation("查询在线用户")
+ @GetMapping
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> queryOnlineUser(String filter, Pageable pageable){
+ return new ResponseEntity<>(onlineUserService.getAll(filter, pageable),HttpStatus.OK);
+ }
+
+ @ApiOperation("导出数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check()")
+ public void exportOnlineUser(HttpServletResponse response, String filter) throws IOException {
+ onlineUserService.download(onlineUserService.getAll(filter), response);
+ }
+
+ @ApiOperation("踢出用户")
+ @DeleteMapping
+ @PreAuthorize("@el.check()")
+ public ResponseEntity<Object> deleteOnlineUser(@RequestBody Set<String> keys) throws Exception {
+ for (String key : keys) {
+ // 解密Key
+ key = EncryptUtils.desDecrypt(key);
+ onlineUserService.kickOut(key);
+ }
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java
new file mode 100644
index 0000000..c0b6f86
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.security;
+
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ *
+ */
+@Component
+public class JwtAccessDeniedHandler implements AccessDeniedHandler {
+
+ @Override
+ public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
+ //当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
+ response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java
new file mode 100644
index 0000000..9fa256e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.security;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ *
+ */
+@Component
+public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request,
+ HttpServletResponse response,
+ AuthenticationException authException) throws IOException {
+ // 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java
new file mode 100644
index 0000000..2a1ad1c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.security;
+
+import com.example.modules.security.config.bean.SecurityProperties;
+import com.example.modules.security.service.OnlineUserService;
+import com.example.modules.security.service.UserCacheClean;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.DefaultSecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * @author /
+ */
+@RequiredArgsConstructor
+public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
+
+ private final TokenProvider tokenProvider;
+ private final SecurityProperties properties;
+ private final OnlineUserService onlineUserService;
+ private final UserCacheClean userCacheClean;
+
+ @Override
+ public void configure(HttpSecurity http) {
+ TokenFilter customFilter = new TokenFilter(tokenProvider, properties, onlineUserService, userCacheClean);
+ http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java
new file mode 100644
index 0000000..dc1369e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.security;
+
+import cn.hutool.core.util.StrUtil;
+import com.example.modules.security.config.bean.SecurityProperties;
+import com.example.modules.security.service.OnlineUserService;
+import com.example.modules.security.service.UserCacheClean;
+import com.example.modules.security.service.dto.OnlineUserDto;
+import io.jsonwebtoken.ExpiredJwtException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.GenericFilterBean;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * @author /
+ */
+public class TokenFilter extends GenericFilterBean {
+ private static final Logger log = LoggerFactory.getLogger(TokenFilter.class);
+
+
+ private final TokenProvider tokenProvider;
+ private final SecurityProperties properties;
+ private final OnlineUserService onlineUserService;
+ private final UserCacheClean userCacheClean;
+
+ /**
+ * @param tokenProvider Token
+ * @param properties JWT
+ * @param onlineUserService 用户在线
+ * @param userCacheClean 用户缓存清理工具
+ */
+ public TokenFilter(TokenProvider tokenProvider, SecurityProperties properties, OnlineUserService onlineUserService, UserCacheClean userCacheClean) {
+ this.properties = properties;
+ this.onlineUserService = onlineUserService;
+ this.tokenProvider = tokenProvider;
+ this.userCacheClean = userCacheClean;
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ String token = resolveToken(httpServletRequest);
+ // 对于 Token 为空的不需要去查 Redis
+ if (StrUtil.isNotBlank(token)) {
+ OnlineUserDto onlineUserDto = null;
+ boolean cleanUserCache = false;
+ try {
+ onlineUserDto = onlineUserService.getOne(properties.getOnlineKey() + token);
+ } catch (ExpiredJwtException e) {
+ log.error(e.getMessage());
+ cleanUserCache = true;
+ } finally {
+ if (cleanUserCache || Objects.isNull(onlineUserDto)) {
+ userCacheClean.cleanUserCache(String.valueOf(tokenProvider.getClaims(token).get(TokenProvider.AUTHORITIES_KEY)));
+ }
+ }
+ if (onlineUserDto != null && StringUtils.hasText(token)) {
+ Authentication authentication = tokenProvider.getAuthentication(token);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ // Token 续期
+ tokenProvider.checkRenewal(token);
+ }
+ }
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+
+ /**
+ * 初步检测Token
+ *
+ * @param request /
+ * @return /
+ */
+ private String resolveToken(HttpServletRequest request) {
+ String bearerToken = request.getHeader(properties.getHeader());
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
+ // 去掉令牌前缀
+ return bearerToken.replace(properties.getTokenStartWith(), "");
+ } else {
+ log.debug("非法Token:{}", bearerToken);
+ }
+ return null;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java
new file mode 100644
index 0000000..dfe2134
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.security;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import com.example.modules.security.config.bean.SecurityProperties;
+import com.example.utils.RedisUtils;
+import io.jsonwebtoken.*;
+import io.jsonwebtoken.io.Decoders;
+import io.jsonwebtoken.security.Keys;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import java.security.Key;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author /
+ */
+@Slf4j
+@Component
+public class TokenProvider implements InitializingBean {
+
+ private final SecurityProperties properties;
+ private final RedisUtils redisUtils;
+ public static final String AUTHORITIES_KEY = "user";
+ private JwtParser jwtParser;
+ private JwtBuilder jwtBuilder;
+
+ public TokenProvider(SecurityProperties properties, RedisUtils redisUtils) {
+ this.properties = properties;
+ this.redisUtils = redisUtils;
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
+ Key key = Keys.hmacShaKeyFor(keyBytes);
+ jwtParser = Jwts.parserBuilder()
+ .setSigningKey(key)
+ .build();
+ jwtBuilder = Jwts.builder()
+ .signWith(key, SignatureAlgorithm.HS512);
+ }
+
+ /**
+ * 创建Token 设置永不过期,
+ * Token 的时间有效性转到Redis 维护
+ *
+ * @param authentication /
+ * @return /
+ */
+ public String createToken(Authentication authentication) {
+ return jwtBuilder
+ // 加入ID确保生成的 Token 都不一致
+ .setId(IdUtil.simpleUUID())
+ .claim(AUTHORITIES_KEY, authentication.getName())
+ .setSubject(authentication.getName())
+ .compact();
+ }
+
+ /**
+ * 依据Token 获取鉴权信息
+ *
+ * @param token /
+ * @return /
+ */
+ Authentication getAuthentication(String token) {
+ Claims claims = getClaims(token);
+ User principal = new User(claims.getSubject(), "******", new ArrayList<>());
+ return new UsernamePasswordAuthenticationToken(principal, token, new ArrayList<>());
+ }
+
+ public Claims getClaims(String token) {
+ return jwtParser
+ .parseClaimsJws(token)
+ .getBody();
+ }
+
+ /**
+ * @param token 需要检查的token
+ */
+ public void checkRenewal(String token) {
+ // 判断是否续期token,计算token的过期时间
+ long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
+ Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
+ // 判断当前时间与过期时间的时间差
+ long differ = expireDate.getTime() - System.currentTimeMillis();
+ // 如果在续期检查的范围内,则续期
+ if (differ <= properties.getDetect()) {
+ long renew = time + properties.getRenew();
+ redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ public String getToken(HttpServletRequest request) {
+ final String requestHeader = request.getHeader(properties.getHeader());
+ if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) {
+ return requestHeader.substring(7);
+ }
+ return null;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java
new file mode 100644
index 0000000..9cfda04
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.service;
+
+import com.example.modules.security.config.bean.SecurityProperties;
+import com.example.utils.*;
+import lombok.extern.slf4j.Slf4j;
+import com.example.modules.security.service.dto.JwtUserDto;
+import com.example.modules.security.service.dto.OnlineUserDto;
+import com.example.utils.*;
+import org.springframework.data.domain.Pageable;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ *
+ * 2019年10月26日21:56:27
+ */
+@Service
+@Slf4j
+public class OnlineUserService {
+
+ private final SecurityProperties properties;
+ private final RedisUtils redisUtils;
+
+ public OnlineUserService(SecurityProperties properties, RedisUtils redisUtils) {
+ this.properties = properties;
+ this.redisUtils = redisUtils;
+ }
+
+ /**
+ * 保存在线用户信息
+ * @param jwtUserDto /
+ * @param token /
+ * @param request /
+ */
+ public void save(JwtUserDto jwtUserDto, String token, HttpServletRequest request){
+ String dept = jwtUserDto.getUser().getDept().getName();
+ String ip = StringUtils.getIp(request);
+ String browser = StringUtils.getBrowser(request);
+ String address = StringUtils.getCityInfo(ip);
+ OnlineUserDto onlineUserDto = null;
+ try {
+ onlineUserDto = new OnlineUserDto(jwtUserDto.getUsername(), jwtUserDto.getUser().getNickName(), dept, browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
+ } catch (Exception e) {
+ log.error(e.getMessage(),e);
+ }
+ redisUtils.set(properties.getOnlineKey() + token, onlineUserDto, properties.getTokenValidityInSeconds()/1000);
+ }
+
+ /**
+ * 查询全部数据
+ * @param filter /
+ * @param pageable /
+ * @return /
+ */
+ public Map<String,Object> getAll(String filter, Pageable pageable){
+ List<OnlineUserDto> onlineUserDtos = getAll(filter);
+ return PageUtil.toPage(
+ PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(), onlineUserDtos),
+ onlineUserDtos.size()
+ );
+ }
+
+ /**
+ * 查询全部数据,不分页
+ * @param filter /
+ * @return /
+ */
+ public List<OnlineUserDto> getAll(String filter){
+ List<String> keys = redisUtils.scan(properties.getOnlineKey() + "*");
+ Collections.reverse(keys);
+ List<OnlineUserDto> onlineUserDtos = new ArrayList<>();
+ for (String key : keys) {
+ OnlineUserDto onlineUserDto = (OnlineUserDto) redisUtils.get(key);
+ if(StringUtils.isNotBlank(filter)){
+ if(onlineUserDto.toString().contains(filter)){
+ onlineUserDtos.add(onlineUserDto);
+ }
+ } else {
+ onlineUserDtos.add(onlineUserDto);
+ }
+ }
+ onlineUserDtos.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
+ return onlineUserDtos;
+ }
+
+ /**
+ * 踢出用户
+ * @param key /
+ */
+ public void kickOut(String key){
+ key = properties.getOnlineKey() + key;
+ redisUtils.del(key);
+ }
+
+ /**
+ * 退出登录
+ * @param token /
+ */
+ public void logout(String token) {
+ String key = properties.getOnlineKey() + token;
+ redisUtils.del(key);
+ }
+
+ /**
+ * 导出
+ * @param all /
+ * @param response /
+ * @throws IOException /
+ */
+ public void download(List<OnlineUserDto> all, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (OnlineUserDto user : all) {
+ Map<String,Object> map = new LinkedHashMap<>();
+ map.put("用户名", user.getUserName());
+ map.put("部门", user.getDept());
+ map.put("登录IP", user.getIp());
+ map.put("登录地点", user.getAddress());
+ map.put("浏览器", user.getBrowser());
+ map.put("登录日期", user.getLoginTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ /**
+ * 查询用户
+ * @param key /
+ * @return /
+ */
+ public OnlineUserDto getOne(String key) {
+ return (OnlineUserDto)redisUtils.get(key);
+ }
+
+ /**
+ * 检测用户是否在之前已经登录,已经登录踢下线
+ * @param userName 用户名
+ */
+ public void checkLoginOnUser(String userName, String igoreToken){
+ List<OnlineUserDto> onlineUserDtos = getAll(userName);
+ if(onlineUserDtos ==null || onlineUserDtos.isEmpty()){
+ return;
+ }
+ for(OnlineUserDto onlineUserDto : onlineUserDtos){
+ if(onlineUserDto.getUserName().equals(userName)){
+ try {
+ String token =EncryptUtils.desDecrypt(onlineUserDto.getKey());
+ if(StringUtils.isNotBlank(igoreToken)&&!igoreToken.equals(token)){
+ this.kickOut(token);
+ }else if(StringUtils.isBlank(igoreToken)){
+ this.kickOut(token);
+ }
+ } catch (Exception e) {
+ log.error("checkUser is error",e);
+ }
+ }
+ }
+ }
+
+ /**
+ * 根据用户名强退用户
+ * @param username /
+ */
+ @Async
+ public void kickOutForUsername(String username) throws Exception {
+ List<OnlineUserDto> onlineUsers = getAll(username);
+ for (OnlineUserDto onlineUser : onlineUsers) {
+ if (onlineUser.getUserName().equals(username)) {
+ String token =EncryptUtils.desDecrypt(onlineUser.getKey());
+ kickOut(token);
+ }
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java
new file mode 100644
index 0000000..aa1ef9c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.modules.security.service;
+
+import lombok.AllArgsConstructor;
+import com.example.utils.StringUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/11 18:01
+ * @apiNote: 用于清理 用户登录信息缓存,为防止Spring循环依赖与安全考虑 ,单独构成工具类
+ */
+@Component
+@AllArgsConstructor
+public class UserCacheClean {
+
+ private final UserCacheManager userCacheManager;
+
+ /**
+ * 清理特定用户缓存信息<br>
+ * 用户信息变更时
+ *
+ * @param userName /
+ */
+ public void cleanUserCache(String userName) {
+ if (StringUtils.isNotEmpty(userName)) {
+ userCacheManager.remove(userName);
+ }
+ }
+
+ /**
+ * 清理所有用户的缓存信息<br>
+ * ,如发生角色授权信息变化,可以简便的全部失效缓存
+ */
+ public void cleanAll() {
+ userCacheManager.clear();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java
new file mode 100644
index 0000000..9c1f60b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java
@@ -0,0 +1,110 @@
+package com.example.modules.security.service;
+
+import lombok.extern.slf4j.Slf4j;
+import com.example.modules.security.service.dto.JwtUserDto;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 用户缓存
+ *
+ * @author TikiWong
+ * 2022/1/27 8:23
+ **/
+@Slf4j
+@Component
+public class UserCacheManager {
+
+ @Value("${user-cache.min-evictable-size}")
+ private int minEvictableSize;
+ @Value("${user-cache.min-evictable-interval}")
+ private long minEvictableInterval;
+ @Value("${user-cache.min-idle-time}")
+ private long minIdleTime;
+
+ private final Map<String, Node> cache = new ConcurrentHashMap<>();
+ private final AtomicBoolean expelLock = new AtomicBoolean(true);
+ private long nextMinEvictableTime = 0;
+
+ public Future<JwtUserDto> putIfAbsent(String username, Future<JwtUserDto> ft) {
+ Node tryNode = new Node(ft);
+ Node node = cache.putIfAbsent(username, tryNode);
+ expel();
+ return nodeToDate(node);
+ }
+
+ /**
+ * 缓存回收
+ * 为避免超过边界后回收热点数据设置了最小生存时间
+ * 回收时会保留在最小生存时间内的数据
+ **/
+ public void expel() {
+ long now = System.currentTimeMillis();
+ if (cache.size() < minEvictableSize ||
+ now < nextMinEvictableTime ||
+ !expelLock.compareAndSet(true, false)) {
+ return;
+ }
+ long oldestTime = now;
+ int evictedCount = 0;
+ try {
+ Iterator<Map.Entry<String, Node>> iterator = cache.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry<String, Node> entry = iterator.next();
+ long nodeTime = entry.getValue().getTime();
+ if (nodeTime + minIdleTime < now) {
+ iterator.remove();
+ evictedCount++;
+ }
+ oldestTime = Math.min(oldestTime, nodeTime);
+ }
+ } finally {
+ this.nextMinEvictableTime = Math.max(now + minEvictableInterval, oldestTime);
+ expelLock.set(true);
+ log.info("回收掉【{}】条用户缓存, 剩余缓存数为【{}】,下次可回收时间为【{}】秒后",
+ evictedCount,
+ cache.size(),
+ (this.nextMinEvictableTime - now) / 1000);
+ }
+ }
+
+ public Future<JwtUserDto> get(String username) {
+ return nodeToDate(cache.get(username));
+ }
+
+ public void clear() {
+ cache.clear();
+ }
+
+ public void remove(String username) {
+ cache.remove(username);
+ }
+
+ private Future<JwtUserDto> nodeToDate(Node node) {
+ return node == null ? null : node.getData();
+ }
+
+ private static class Node {
+ private final Future<JwtUserDto> data;
+ private final long time;
+
+ public Node(Future<JwtUserDto> data) {
+ this.data = data;
+ this.time = System.currentTimeMillis();
+ }
+
+ public Future<JwtUserDto> getData() {
+ return data;
+ }
+
+ public long getTime() {
+ return time;
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..8d368f2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.service;
+
+import com.example.modules.security.config.bean.LoginProperties;
+import com.example.modules.system.service.DataService;
+import com.example.modules.system.service.RoleService;
+import com.example.modules.system.service.UserService;
+import com.example.modules.system.service.dto.UserDto;
+import lombok.RequiredArgsConstructor;
+import com.example.exception.BadRequestException;
+import com.example.exception.EntityNotFoundException;
+import com.example.modules.security.service.dto.JwtUserDto;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ *
+ * 2018-11-22
+ */
+@RequiredArgsConstructor
+@Service("userDetailsService")
+public class UserDetailsServiceImpl implements UserDetailsService {
+ private final UserService userService;
+ private final RoleService roleService;
+ private final DataService dataService;
+ private final LoginProperties loginProperties;
+
+ private final UserCacheManager USER_DTO_CACHE;
+
+ public void setEnableCache(boolean enableCache) {
+ this.loginProperties.setCacheEnable(enableCache);
+ }
+
+ public static ExecutorService executor = newThreadPool();
+
+ @Override
+ public JwtUserDto loadUserByUsername(String username) {
+ JwtUserDto jwtUserDto = null;
+ Future<JwtUserDto> future = USER_DTO_CACHE.get(username);
+ if (!loginProperties.isCacheEnable()) {
+ UserDto user;
+ try {
+ user = userService.findByName(username);
+ } catch (EntityNotFoundException e) {
+ // SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException
+ throw new UsernameNotFoundException(username, e);
+ }
+ if (user == null) {
+ throw new UsernameNotFoundException("");
+ } else {
+ if (!user.getEnabled()) {
+ throw new BadRequestException("账号未激活!");
+ }
+ jwtUserDto = new JwtUserDto(
+ user,
+ dataService.getDeptIds(user),
+ roleService.mapToGrantedAuthorities(user)
+ );
+ }
+ return jwtUserDto;
+ }
+
+ if (future == null) {
+ Callable<JwtUserDto> call = () -> getJwtBySearchDb(username);
+ FutureTask<JwtUserDto> ft = new FutureTask<>(call);
+ future = USER_DTO_CACHE.putIfAbsent(username, ft);
+ if (future == null) {
+ future = ft;
+ executor.submit(ft);
+ }
+ try {
+ return future.get();
+ } catch (CancellationException e) {
+ USER_DTO_CACHE.remove(username);
+ System.out.println("error" + Thread.currentThread().getName());
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ } else {
+ try {
+ jwtUserDto = future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ // 检查dataScope是否修改
+ List<Long> dataScopes = jwtUserDto.getDataScopes();
+ dataScopes.clear();
+ dataScopes.addAll(dataService.getDeptIds(jwtUserDto.getUser()));
+
+ }
+ return jwtUserDto;
+
+ }
+
+ private JwtUserDto getJwtBySearchDb(String username) {
+ UserDto user;
+ try {
+ user = userService.findByName(username);
+ } catch (EntityNotFoundException e) {
+ // SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException
+ throw new UsernameNotFoundException("", e);
+ }
+ if (user == null) {
+ throw new UsernameNotFoundException("");
+ } else {
+ if (!user.getEnabled()) {
+ throw new BadRequestException("账号未激活!");
+ }
+ return new JwtUserDto(
+ user,
+ dataService.getDeptIds(user),
+ roleService.mapToGrantedAuthorities(user)
+ );
+ }
+
+ }
+
+ public static ExecutorService newThreadPool() {
+ ThreadFactory namedThreadFactory = new ThreadFactory() {
+ final AtomicInteger sequence = new AtomicInteger(1);
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r);
+ int seq = this.sequence.getAndIncrement();
+ thread.setName("future-task-thread" + (seq > 1 ? "-" + seq : ""));
+ if (!thread.isDaemon()) {
+ thread.setDaemon(true);
+ }
+
+ return thread;
+ }
+ };
+ return new ThreadPoolExecutor(10, 200,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>(1024),
+ namedThreadFactory,
+ new ThreadPoolExecutor.AbortPolicy());
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java
new file mode 100644
index 0000000..983d690
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.service.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import javax.validation.constraints.NotBlank;
+
+/**
+ *
+ * 2018-11-30
+ */
+@Getter
+@Setter
+public class AuthUserDto {
+
+ @NotBlank
+ private String username;
+
+ @NotBlank
+ private String password;
+
+ private String code;
+
+ private String uuid = "";
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java
new file mode 100644
index 0000000..20e1bc6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.service.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.example.modules.system.service.dto.UserDto;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+
+@Getter
+@AllArgsConstructor
+public class JwtUserDto implements UserDetails {
+
+ private final UserDto user;
+
+ private final List<Long> dataScopes;
+
+ @JSONField(serialize = false)
+ private final List<GrantedAuthority> authorities;
+
+ public Set<String> getRoles() {
+ return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
+ }
+
+ @Override
+ @JSONField(serialize = false)
+ public String getPassword() {
+ return user.getPassword();
+ }
+
+ @Override
+ @JSONField(serialize = false)
+ public String getUsername() {
+ return user.getUsername();
+ }
+
+ @JSONField(serialize = false)
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @JSONField(serialize = false)
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @JSONField(serialize = false)
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ @JSONField(serialize = false)
+ public boolean isEnabled() {
+ return user.getEnabled();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java
new file mode 100644
index 0000000..77ba3bc
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.security.service.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.util.Date;
+
+/**
+ * 在线用户
+ *
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OnlineUserDto {
+
+ /**
+ * 用户名
+ */
+ private String userName;
+
+ /**
+ * 昵称
+ */
+ private String nickName;
+
+ /**
+ * 岗位
+ */
+ private String dept;
+
+ /**
+ * 浏览器
+ */
+ private String browser;
+
+ /**
+ * IP
+ */
+ private String ip;
+
+ /**
+ * 地址
+ */
+ private String address;
+
+ /**
+ * token
+ */
+ private String key;
+
+ /**
+ * 登录时间
+ */
+ private Date loginTime;
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java
new file mode 100644
index 0000000..0bef112
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.service.DeptService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.dto.DeptDto;
+import com.example.modules.system.service.dto.DeptQueryCriteria;
+import com.example.utils.PageUtil;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+/**
+*
+* 2019-03-25
+*/
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统:部门管理")
+@RequestMapping("/api/dept")
+public class DeptController {
+
+ private final DeptService deptService;
+ private static final String ENTITY_NAME = "dept";
+
+ @ApiOperation("导出部门数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('dept:list')")
+ public void exportDept(HttpServletResponse response, DeptQueryCriteria criteria) throws Exception {
+ deptService.download(deptService.queryAll(criteria, false), response);
+ }
+
+ @ApiOperation("查询部门")
+ @GetMapping
+ @PreAuthorize("@el.check('user:list','dept:list')")
+ public ResponseEntity<Object> queryDept(DeptQueryCriteria criteria) throws Exception {
+ List<DeptDto> deptDtos = deptService.queryAll(criteria, true);
+ return new ResponseEntity<>(PageUtil.toPage(deptDtos, deptDtos.size()),HttpStatus.OK);
+ }
+
+ @ApiOperation("查询部门:根据ID获取同级与上级数据")
+ @PostMapping("/superior")
+ @PreAuthorize("@el.check('user:list','dept:list')")
+ public ResponseEntity<Object> getDeptSuperior(@RequestBody List<Long> ids) {
+ Set<DeptDto> deptDtos = new LinkedHashSet<>();
+ for (Long id : ids) {
+ DeptDto deptDto = deptService.findById(id);
+ List<DeptDto> depts = deptService.getSuperior(deptDto, new ArrayList<>());
+ deptDtos.addAll(depts);
+ }
+ return new ResponseEntity<>(deptService.buildTree(new ArrayList<>(deptDtos)),HttpStatus.OK);
+ }
+
+ @Log("新增部门")
+ @ApiOperation("新增部门")
+ @PostMapping
+ @PreAuthorize("@el.check('dept:add')")
+ public ResponseEntity<Object> createDept(@Validated @RequestBody Dept resources){
+ if (resources.getId() != null) {
+ throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
+ }
+ deptService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改部门")
+ @ApiOperation("修改部门")
+ @PutMapping
+ @PreAuthorize("@el.check('dept:edit')")
+ public ResponseEntity<Object> updateDept(@Validated(Dept.Update.class) @RequestBody Dept resources){
+ deptService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除部门")
+ @ApiOperation("删除部门")
+ @DeleteMapping
+ @PreAuthorize("@el.check('dept:del')")
+ public ResponseEntity<Object> deleteDept(@RequestBody Set<Long> ids){
+ Set<DeptDto> deptDtos = new HashSet<>();
+ for (Long id : ids) {
+ List<Dept> deptList = deptService.findByPid(id);
+ deptDtos.add(deptService.findById(id));
+ if(CollectionUtil.isNotEmpty(deptList)){
+ deptDtos = deptService.getDeleteDepts(deptList, deptDtos);
+ }
+ }
+ // 验证是否被角色或用户关联
+ deptService.verification(deptDtos);
+ deptService.delete(deptDtos);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java
new file mode 100644
index 0000000..8f4dec7
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import com.example.modules.system.domain.Dict;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.DictService;
+import com.example.modules.system.service.dto.DictQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+*
+* 2019-04-10
+*/
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统:字典管理")
+@RequestMapping("/api/dict")
+public class DictController {
+
+ private final DictService dictService;
+ private static final String ENTITY_NAME = "dict";
+
+ @ApiOperation("导出字典数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('dict:list')")
+ public void exportDict(HttpServletResponse response, DictQueryCriteria criteria) throws IOException {
+ dictService.download(dictService.queryAll(criteria), response);
+ }
+
+ @ApiOperation("查询字典")
+ @GetMapping(value = "/all")
+ @PreAuthorize("@el.check('dict:list')")
+ public ResponseEntity<Object> queryAllDict(){
+ return new ResponseEntity<>(dictService.queryAll(new DictQueryCriteria()),HttpStatus.OK);
+ }
+
+ @ApiOperation("查询字典")
+ @GetMapping
+ @PreAuthorize("@el.check('dict:list')")
+ public ResponseEntity<Object> queryDict(DictQueryCriteria resources, Pageable pageable){
+ return new ResponseEntity<>(dictService.queryAll(resources,pageable),HttpStatus.OK);
+ }
+
+ @Log("新增字典")
+ @ApiOperation("新增字典")
+ @PostMapping
+ @PreAuthorize("@el.check('dict:add')")
+ public ResponseEntity<Object> createDict(@Validated @RequestBody Dict resources){
+ if (resources.getId() != null) {
+ throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
+ }
+ dictService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改字典")
+ @ApiOperation("修改字典")
+ @PutMapping
+ @PreAuthorize("@el.check('dict:edit')")
+ public ResponseEntity<Object> updateDict(@Validated(Dict.Update.class) @RequestBody Dict resources){
+ dictService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除字典")
+ @ApiOperation("删除字典")
+ @DeleteMapping
+ @PreAuthorize("@el.check('dict:del')")
+ public ResponseEntity<Object> deleteDict(@RequestBody Set<Long> ids){
+ dictService.delete(ids);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java
new file mode 100644
index 0000000..e3c5891
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import com.example.modules.system.domain.DictDetail;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.DictDetailService;
+import com.example.modules.system.service.dto.DictDetailDto;
+import com.example.modules.system.service.dto.DictDetailQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+*
+* 2019-04-10
+*/
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统:字典详情管理")
+@RequestMapping("/api/dictDetail")
+public class DictDetailController {
+
+ private final DictDetailService dictDetailService;
+ private static final String ENTITY_NAME = "dictDetail";
+
+ @ApiOperation("查询字典详情")
+ @GetMapping
+ public ResponseEntity<Object> queryDictDetail(DictDetailQueryCriteria criteria,
+ @PageableDefault(sort = {"dictSort"}, direction = Sort.Direction.ASC) Pageable pageable){
+ return new ResponseEntity<>(dictDetailService.queryAll(criteria,pageable),HttpStatus.OK);
+ }
+
+ @ApiOperation("查询多个字典详情")
+ @GetMapping(value = "/map")
+ public ResponseEntity<Object> getDictDetailMaps(@RequestParam String dictName){
+ String[] names = dictName.split("[,,]");
+ Map<String, List<DictDetailDto>> dictMap = new HashMap<>(16);
+ for (String name : names) {
+ dictMap.put(name, dictDetailService.getDictByName(name));
+ }
+ return new ResponseEntity<>(dictMap, HttpStatus.OK);
+ }
+
+ @Log("新增字典详情")
+ @ApiOperation("新增字典详情")
+ @PostMapping
+ @PreAuthorize("@el.check('dict:add')")
+ public ResponseEntity<Object> createDictDetail(@Validated @RequestBody DictDetail resources){
+ if (resources.getId() != null) {
+ throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
+ }
+ dictDetailService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改字典详情")
+ @ApiOperation("修改字典详情")
+ @PutMapping
+ @PreAuthorize("@el.check('dict:edit')")
+ public ResponseEntity<Object> updateDictDetail(@Validated(DictDetail.Update.class) @RequestBody DictDetail resources){
+ dictDetailService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除字典详情")
+ @ApiOperation("删除字典详情")
+ @DeleteMapping(value = "/{id}")
+ @PreAuthorize("@el.check('dict:del')")
+ public ResponseEntity<Object> deleteDictDetail(@PathVariable Long id){
+ dictDetailService.delete(id);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java
new file mode 100644
index 0000000..6106f0d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import com.example.modules.system.domain.Job;
+import com.example.modules.system.service.JobService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.dto.JobQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+*
+* 2019-03-29
+*/
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统:岗位管理")
+@RequestMapping("/api/job")
+public class JobController {
+
+ private final JobService jobService;
+ private static final String ENTITY_NAME = "job";
+
+ @ApiOperation("导出岗位数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('job:list')")
+ public void exportJob(HttpServletResponse response, JobQueryCriteria criteria) throws IOException {
+ jobService.download(jobService.queryAll(criteria), response);
+ }
+
+ @ApiOperation("查询岗位")
+ @GetMapping
+ @PreAuthorize("@el.check('job:list','user:list')")
+ public ResponseEntity<Object> queryJob(JobQueryCriteria criteria, Pageable pageable){
+ return new ResponseEntity<>(jobService.queryAll(criteria, pageable),HttpStatus.OK);
+ }
+
+ @Log("新增岗位")
+ @ApiOperation("新增岗位")
+ @PostMapping
+ @PreAuthorize("@el.check('job:add')")
+ public ResponseEntity<Object> createJob(@Validated @RequestBody Job resources){
+ if (resources.getId() != null) {
+ throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
+ }
+ jobService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改岗位")
+ @ApiOperation("修改岗位")
+ @PutMapping
+ @PreAuthorize("@el.check('job:edit')")
+ public ResponseEntity<Object> updateJob(@Validated(Job.Update.class) @RequestBody Job resources){
+ jobService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除岗位")
+ @ApiOperation("删除岗位")
+ @DeleteMapping
+ @PreAuthorize("@el.check('job:del')")
+ public ResponseEntity<Object> deleteJob(@RequestBody Set<Long> ids){
+ // 验证是否被用户关联
+ jobService.verification(ids);
+ jobService.delete(ids);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java
new file mode 100644
index 0000000..636ec91
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import com.example.annotation.Limit;
+import com.example.annotation.rest.AnonymousGetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author /
+ * 接口限流测试类
+ */
+@RestController
+@RequestMapping("/api/limit")
+@Api(tags = "系统:限流测试管理")
+public class LimitController {
+
+ private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
+
+ /**
+ * 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test,
+ */
+ @AnonymousGetMapping
+ @ApiOperation("测试")
+ @Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit")
+ public int testLimit() {
+ return ATOMIC_INTEGER.incrementAndGet();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java
new file mode 100644
index 0000000..26a2f1a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.example.modules.system.domain.Menu;
+import com.example.modules.system.service.MenuService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.dto.MenuDto;
+import com.example.modules.system.service.dto.MenuQueryCriteria;
+import com.example.modules.system.service.mapstruct.MenuMapper;
+import com.example.utils.PageUtil;
+import com.example.utils.SecurityUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * 2018-12-03
+ */
+
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统:菜单管理")
+@RequestMapping("/api/menus")
+public class MenuController {
+
+ private final MenuService menuService;
+ private final MenuMapper menuMapper;
+ private static final String ENTITY_NAME = "menu";
+
+ @ApiOperation("导出菜单数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('menu:list')")
+ public void exportMenu(HttpServletResponse response, MenuQueryCriteria criteria) throws Exception {
+ menuService.download(menuService.queryAll(criteria, false), response);
+ }
+
+ @GetMapping(value = "/build")
+ @ApiOperation("获取前端所需菜单")
+ public ResponseEntity<Object> buildMenus(){
+ List<MenuDto> menuDtoList = menuService.findByUser(SecurityUtils.getCurrentUserId());
+ List<MenuDto> menuDtos = menuService.buildTree(menuDtoList);
+ return new ResponseEntity<>(menuService.buildMenus(menuDtos),HttpStatus.OK);
+ }
+
+ @ApiOperation("返回全部的菜单")
+ @GetMapping(value = "/lazy")
+ @PreAuthorize("@el.check('menu:list','roles:list')")
+ public ResponseEntity<Object> queryAllMenu(@RequestParam Long pid){
+ return new ResponseEntity<>(menuService.getMenus(pid),HttpStatus.OK);
+ }
+
+ @ApiOperation("根据菜单ID返回所有子节点ID,包含自身ID")
+ @GetMapping(value = "/child")
+ @PreAuthorize("@el.check('menu:list','roles:list')")
+ public ResponseEntity<Object> childMenu(@RequestParam Long id){
+ Set<Menu> menuSet = new HashSet<>();
+ List<MenuDto> menuList = menuService.getMenus(id);
+ menuSet.add(menuService.findOne(id));
+ menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet);
+ Set<Long> ids = menuSet.stream().map(Menu::getId).collect(Collectors.toSet());
+ return new ResponseEntity<>(ids,HttpStatus.OK);
+ }
+
+ @GetMapping
+ @ApiOperation("查询菜单")
+ @PreAuthorize("@el.check('menu:list')")
+ public ResponseEntity<Object> queryMenu(MenuQueryCriteria criteria) throws Exception {
+ List<MenuDto> menuDtoList = menuService.queryAll(criteria, true);
+ return new ResponseEntity<>(PageUtil.toPage(menuDtoList, menuDtoList.size()),HttpStatus.OK);
+ }
+
+ @ApiOperation("查询菜单:根据ID获取同级与上级数据")
+ @PostMapping("/superior")
+ @PreAuthorize("@el.check('menu:list')")
+ public ResponseEntity<Object> getMenuSuperior(@RequestBody List<Long> ids) {
+ Set<MenuDto> menuDtos = new LinkedHashSet<>();
+ if(CollectionUtil.isNotEmpty(ids)){
+ for (Long id : ids) {
+ MenuDto menuDto = menuService.findById(id);
+ menuDtos.addAll(menuService.getSuperior(menuDto, new ArrayList<>()));
+ }
+ return new ResponseEntity<>(menuService.buildTree(new ArrayList<>(menuDtos)),HttpStatus.OK);
+ }
+ return new ResponseEntity<>(menuService.getMenus(null),HttpStatus.OK);
+ }
+
+ @Log("新增菜单")
+ @ApiOperation("新增菜单")
+ @PostMapping
+ @PreAuthorize("@el.check('menu:add')")
+ public ResponseEntity<Object> createMenu(@Validated @RequestBody Menu resources){
+ if (resources.getId() != null) {
+ throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
+ }
+ menuService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改菜单")
+ @ApiOperation("修改菜单")
+ @PutMapping
+ @PreAuthorize("@el.check('menu:edit')")
+ public ResponseEntity<Object> updateMenu(@Validated(Menu.Update.class) @RequestBody Menu resources){
+ menuService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除菜单")
+ @ApiOperation("删除菜单")
+ @DeleteMapping
+ @PreAuthorize("@el.check('menu:del')")
+ public ResponseEntity<Object> deleteMenu(@RequestBody Set<Long> ids){
+ Set<Menu> menuSet = new HashSet<>();
+ for (Long id : ids) {
+ List<MenuDto> menuList = menuService.getMenus(id);
+ menuSet.add(menuService.findOne(id));
+ menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet);
+ }
+ menuService.delete(menuSet);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java
new file mode 100644
index 0000000..bb7bf02
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.modules.system.service.MonitorService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ *
+ * 2020-05-02
+ */
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统-服务监控管理")
+@RequestMapping("/api/monitor")
+public class MonitorController {
+
+ private final MonitorService serverService;
+
+ @GetMapping
+ @ApiOperation("查询服务监控")
+ @PreAuthorize("@el.check('monitor:list')")
+ public ResponseEntity<Object> queryMonitor(){
+ return new ResponseEntity<>(serverService.getServers(),HttpStatus.OK);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java
new file mode 100644
index 0000000..8f4fae8
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import cn.hutool.core.lang.Dict;
+import com.example.modules.system.domain.Role;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.RoleService;
+import com.example.modules.system.service.dto.RoleDto;
+import com.example.modules.system.service.dto.RoleQueryCriteria;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.utils.SecurityUtils;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * 2018-12-03
+ */
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "系统:角色管理")
+@RequestMapping("/api/roles")
+public class RoleController {
+
+ private final RoleService roleService;
+
+ private static final String ENTITY_NAME = "role";
+
+ @ApiOperation("获取单个role")
+ @GetMapping(value = "/{id}")
+ @PreAuthorize("@el.check('roles:list')")
+ public ResponseEntity<Object> findRoleById(@PathVariable Long id){
+ return new ResponseEntity<>(roleService.findById(id), HttpStatus.OK);
+ }
+
+ @ApiOperation("导出角色数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('role:list')")
+ public void exportRole(HttpServletResponse response, RoleQueryCriteria criteria) throws IOException {
+ roleService.download(roleService.queryAll(criteria), response);
+ }
+
+ @ApiOperation("返回全部的角色")
+ @GetMapping(value = "/all")
+ @PreAuthorize("@el.check('roles:list','user:add','user:edit')")
+ public ResponseEntity<Object> queryAllRole(){
+ return new ResponseEntity<>(roleService.queryAll(),HttpStatus.OK);
+ }
+
+ @ApiOperation("查询角色")
+ @GetMapping
+ @PreAuthorize("@el.check('roles:list')")
+ public ResponseEntity<Object> queryRole(RoleQueryCriteria criteria, Pageable pageable){
+ return new ResponseEntity<>(roleService.queryAll(criteria,pageable),HttpStatus.OK);
+ }
+
+ @ApiOperation("获取用户级别")
+ @GetMapping(value = "/level")
+ public ResponseEntity<Object> getRoleLevel(){
+ return new ResponseEntity<>(Dict.create().set("level", getLevels(null)),HttpStatus.OK);
+ }
+
+ @Log("新增角色")
+ @ApiOperation("新增角色")
+ @PostMapping
+ @PreAuthorize("@el.check('roles:add')")
+ public ResponseEntity<Object> createRole(@Validated @RequestBody Role resources){
+ if (resources.getId() != null) {
+ throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
+ }
+ getLevels(resources.getLevel());
+ roleService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改角色")
+ @ApiOperation("修改角色")
+ @PutMapping
+ @PreAuthorize("@el.check('roles:edit')")
+ public ResponseEntity<Object> updateRole(@Validated(Role.Update.class) @RequestBody Role resources){
+ getLevels(resources.getLevel());
+ roleService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("修改角色菜单")
+ @ApiOperation("修改角色菜单")
+ @PutMapping(value = "/menu")
+ @PreAuthorize("@el.check('roles:edit')")
+ public ResponseEntity<Object> updateRoleMenu(@RequestBody Role resources){
+ RoleDto role = roleService.findById(resources.getId());
+ getLevels(role.getLevel());
+ roleService.updateMenu(resources,role);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除角色")
+ @ApiOperation("删除角色")
+ @DeleteMapping
+ @PreAuthorize("@el.check('roles:del')")
+ public ResponseEntity<Object> deleteRole(@RequestBody Set<Long> ids){
+ for (Long id : ids) {
+ RoleDto role = roleService.findById(id);
+ getLevels(role.getLevel());
+ }
+ // 验证是否被用户关联
+ roleService.verification(ids);
+ roleService.delete(ids);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ /**
+ * 获取用户的角色级别
+ * @return /
+ */
+ private int getLevels(Integer level){
+ List<Integer> levels = roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList());
+ int min = Collections.min(levels);
+ if(level != null){
+ if(level < min){
+ throw new BadRequestException("权限不足,你的角色级别:" + min + ",低于操作的角色级别:" + level);
+ }
+ }
+ return min;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java
new file mode 100644
index 0000000..393a878
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.domain.vo.UserPassVo;
+import com.example.modules.system.service.DataService;
+import com.example.modules.system.service.DeptService;
+import com.example.modules.system.service.UserService;
+import com.example.utils.PageUtil;
+import com.example.utils.RsaUtils;
+import com.example.utils.SecurityUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import com.example.annotation.Log;
+import com.example.config.RsaProperties;
+import com.example.modules.system.domain.User;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.service.RoleService;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.modules.system.service.dto.UserDto;
+import com.example.modules.system.service.dto.UserQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+@Api(tags = "系统:用户管理")
+@RestController
+@RequestMapping("/api/users")
+@RequiredArgsConstructor
+public class UserController {
+
+ private final PasswordEncoder passwordEncoder;
+ private final UserService userService;
+ private final DataService dataService;
+ private final DeptService deptService;
+ private final RoleService roleService;
+
+ @ApiOperation("导出用户数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('user:list')")
+ public void exportUser(HttpServletResponse response, UserQueryCriteria criteria) throws IOException {
+ userService.download(userService.queryAll(criteria), response);
+ }
+
+ @ApiOperation("查询用户")
+ @GetMapping
+ @PreAuthorize("@el.check('user:list')")
+ public ResponseEntity<Object> queryUser(UserQueryCriteria criteria, Pageable pageable){
+ if (!ObjectUtils.isEmpty(criteria.getDeptId())) {
+ criteria.getDeptIds().add(criteria.getDeptId());
+ // 先查找是否存在子节点
+ List<Dept> data = deptService.findByPid(criteria.getDeptId());
+ // 然后把子节点的ID都加入到集合中
+ criteria.getDeptIds().addAll(deptService.getDeptChildren(data));
+ }
+ // 数据权限
+ List<Long> dataScopes = dataService.getDeptIds(userService.findByName(SecurityUtils.getCurrentUsername()));
+ // criteria.getDeptIds() 不为空并且数据权限不为空则取交集
+ if (!CollectionUtils.isEmpty(criteria.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)){
+ // 取交集
+ criteria.getDeptIds().retainAll(dataScopes);
+ if(!CollectionUtil.isEmpty(criteria.getDeptIds())){
+ return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK);
+ }
+ } else {
+ // 否则取并集
+ criteria.getDeptIds().addAll(dataScopes);
+ return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK);
+ }
+ return new ResponseEntity<>(PageUtil.toPage(null,0),HttpStatus.OK);
+ }
+
+ @Log("新增用户")
+ @ApiOperation("新增用户")
+ @PostMapping
+ @PreAuthorize("@el.check('user:add')")
+ public ResponseEntity<Object> createUser(@Validated @RequestBody User resources){
+// checkLevel(resources);
+ // 默认密码 123456
+ resources.setPassword(passwordEncoder.encode("123456"));
+ userService.create(resources);
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+
+ @Log("修改用户")
+ @ApiOperation("修改用户")
+ @PutMapping
+ @PreAuthorize("@el.check('user:edit')")
+ public ResponseEntity<Object> updateUser(@Validated(User.Update.class) @RequestBody User resources) throws Exception {
+ checkLevel(resources);
+ userService.update(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("修改用户:个人中心")
+ @ApiOperation("修改用户:个人中心")
+ @PutMapping(value = "center")
+ public ResponseEntity<Object> centerUser(@Validated(User.Update.class) @RequestBody User resources){
+ if(!resources.getId().equals(SecurityUtils.getCurrentUserId())){
+ throw new BadRequestException("不能修改他人资料");
+ }
+ userService.updateCenter(resources);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @Log("删除用户")
+ @ApiOperation("删除用户")
+ @DeleteMapping
+ @PreAuthorize("@el.check('user:del')")
+ public ResponseEntity<Object> deleteUser(@RequestBody Set<Long> ids){
+ for (Long id : ids) {
+ Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
+ Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
+ if (currentLevel > optLevel) {
+ throw new BadRequestException("角色权限不足,不能删除:" + userService.findById(id).getUsername());
+ }
+ }
+ userService.delete(ids);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ @ApiOperation("修改密码")
+ @PostMapping(value = "/updatePass")
+ public ResponseEntity<Object> updateUserPass(@RequestBody UserPassVo passVo) throws Exception {
+ String oldPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getOldPass());
+ String newPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getNewPass());
+ UserDto user = userService.findByName(SecurityUtils.getCurrentUsername());
+ if(!passwordEncoder.matches(oldPass, user.getPassword())){
+ throw new BadRequestException("修改失败,旧密码错误");
+ }
+ if(passwordEncoder.matches(newPass, user.getPassword())){
+ throw new BadRequestException("新密码不能与旧密码相同");
+ }
+ userService.updatePass(user.getUsername(),passwordEncoder.encode(newPass));
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ @ApiOperation("修改头像")
+ @PostMapping(value = "/updateAvatar")
+ public ResponseEntity<Object> updateUserAvatar(@RequestParam MultipartFile avatar){
+ return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK);
+ }
+
+ @Log("修改邮箱")
+ @ApiOperation("修改邮箱")
+ @PostMapping(value = "/updateEmail/{code}")
+ public ResponseEntity<Object> updateUserEmail(@PathVariable String code,@RequestBody User user) throws Exception {
+ String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,user.getPassword());
+ UserDto userDto = userService.findByName(SecurityUtils.getCurrentUsername());
+ if(!passwordEncoder.matches(password, userDto.getPassword())){
+ throw new BadRequestException("密码错误");
+ }
+ userService.updateEmail(userDto.getUsername(),user.getEmail());
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ /**
+ * 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误
+ * @param resources /
+ */
+ private void checkLevel(User resources) {
+ Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
+ Integer optLevel = roleService.findByRoles(resources.getRoles());
+ if (currentLevel > optLevel) {
+ throw new BadRequestException("角色权限不足");
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java
new file mode 100644
index 0000000..4ef6ac1
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+import javax.persistence.*;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+*
+* 2019-03-25
+*/
+@Entity
+@Getter
+@Setter
+@Table(name="sys_dept")
+public class Dept extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "dept_id")
+ @NotNull(groups = Update.class)
+ @ApiModelProperty(value = "ID", hidden = true)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @JSONField(serialize = false)
+ @ManyToMany(mappedBy = "depts")
+ @ApiModelProperty(value = "角色")
+ private Set<Role> roles;
+
+ @ApiModelProperty(value = "排序")
+ private Integer deptSort;
+
+ @NotBlank
+ @ApiModelProperty(value = "部门名称")
+ private String name;
+
+ @NotNull
+ @ApiModelProperty(value = "是否启用")
+ private Boolean enabled;
+
+ @ApiModelProperty(value = "上级部门")
+ private Long pid;
+
+ @ApiModelProperty(value = "子节点数目", hidden = true)
+ private Integer subCount = 0;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Dept dept = (Dept) o;
+ return Objects.equals(id, dept.id) &&
+ Objects.equals(name, dept.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java
new file mode 100644
index 0000000..de65392
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+import javax.persistence.*;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+*
+* 2019-04-10
+*/
+@Entity
+@Getter
+@Setter
+@Table(name="sys_dict")
+public class Dict extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "dict_id")
+ @NotNull(groups = Update.class)
+ @ApiModelProperty(value = "ID", hidden = true)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @OneToMany(mappedBy = "dict",cascade={CascadeType.PERSIST,CascadeType.REMOVE})
+ private List<DictDetail> dictDetails;
+
+ @NotBlank
+ @ApiModelProperty(value = "名称")
+ private String name;
+
+ @ApiModelProperty(value = "描述")
+ private String description;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java
new file mode 100644
index 0000000..538743e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+*
+* 2019-04-10
+*/
+@Entity
+@Getter
+@Setter
+@Table(name="sys_dict_detail")
+public class DictDetail extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "detail_id")
+ @NotNull(groups = Update.class)
+ @ApiModelProperty(value = "ID", hidden = true)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @JoinColumn(name = "dict_id")
+ @ManyToOne(fetch=FetchType.LAZY)
+ @ApiModelProperty(value = "字典", hidden = true)
+ private Dict dict;
+
+ @ApiModelProperty(value = "字典标签")
+ private String label;
+
+ @ApiModelProperty(value = "字典值")
+ private String value;
+
+ @ApiModelProperty(value = "排序")
+ private Integer dictSort = 999;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java
new file mode 100644
index 0000000..f3f47b3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+import javax.persistence.*;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+*
+* 2019-03-29
+*/
+@Entity
+@Getter
+@Setter
+@Table(name="sys_job")
+public class Job extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "job_id")
+ @NotNull(groups = Update.class)
+ @ApiModelProperty(value = "ID", hidden = true)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @NotBlank
+ @ApiModelProperty(value = "岗位名称")
+ private String name;
+
+ @NotNull
+ @ApiModelProperty(value = "岗位排序")
+ private Long jobSort;
+
+ @NotNull
+ @ApiModelProperty(value = "是否启用")
+ private Boolean enabled;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Job job = (Job) o;
+ return Objects.equals(id, job.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java
new file mode 100644
index 0000000..0989055
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ *
+ * 2018-12-17
+ */
+@Entity
+@Getter
+@Setter
+@Table(name = "sys_menu")
+public class Menu extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "menu_id")
+ @NotNull(groups = {Update.class})
+ @ApiModelProperty(value = "ID", hidden = true)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @JSONField(serialize = false)
+ @ManyToMany(mappedBy = "menus")
+ @ApiModelProperty(value = "菜单角色")
+ private Set<Role> roles;
+
+ @ApiModelProperty(value = "菜单标题")
+ private String title;
+
+ @Column(name = "name")
+ @ApiModelProperty(value = "菜单组件名称")
+ private String componentName;
+
+ @ApiModelProperty(value = "排序")
+ private Integer menuSort = 999;
+
+ @ApiModelProperty(value = "组件路径")
+ private String component;
+
+ @ApiModelProperty(value = "路由地址")
+ private String path;
+
+ @ApiModelProperty(value = "菜单类型,目录、菜单、按钮")
+ private Integer type;
+
+ @ApiModelProperty(value = "权限标识")
+ private String permission;
+
+ @ApiModelProperty(value = "菜单图标")
+ private String icon;
+
+ @Column(columnDefinition = "bit(1) default 0")
+ @ApiModelProperty(value = "缓存")
+ private Boolean cache;
+
+ @Column(columnDefinition = "bit(1) default 0")
+ @ApiModelProperty(value = "是否隐藏")
+ private Boolean hidden;
+
+ @ApiModelProperty(value = "上级菜单")
+ private Long pid;
+
+ @ApiModelProperty(value = "子节点数目", hidden = true)
+ private Integer subCount = 0;
+
+ @ApiModelProperty(value = "外链菜单")
+ private Boolean iFrame;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Menu menu = (Menu) o;
+ return Objects.equals(id, menu.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java
new file mode 100644
index 0000000..b600f46
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+import com.example.utils.enums.DataScopeEnum;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * 角色
+ *
+ * 2018-11-22
+ */
+@Getter
+@Setter
+@Entity
+@Table(name = "sys_role")
+public class Role extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "role_id")
+ @NotNull(groups = {Update.class})
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @ApiModelProperty(value = "ID", hidden = true)
+ private Long id;
+
+ @JSONField(serialize = false)
+ @ManyToMany(mappedBy = "roles")
+ @ApiModelProperty(value = "用户", hidden = true)
+ private Set<User> users;
+
+ @ManyToMany(fetch = FetchType.EAGER)
+ @JoinTable(name = "sys_roles_menus",
+ joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")},
+ inverseJoinColumns = {@JoinColumn(name = "menu_id",referencedColumnName = "menu_id")})
+ @ApiModelProperty(value = "菜单", hidden = true)
+ private Set<Menu> menus;
+
+ @ManyToMany
+ @JoinTable(name = "sys_roles_depts",
+ joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")},
+ inverseJoinColumns = {@JoinColumn(name = "dept_id",referencedColumnName = "dept_id")})
+ @ApiModelProperty(value = "部门", hidden = true)
+ private Set<Dept> depts;
+
+ @NotBlank
+ @ApiModelProperty(value = "名称", hidden = true)
+ private String name;
+
+ @ApiModelProperty(value = "数据权限,全部 、 本级 、 自定义")
+ private String dataScope = DataScopeEnum.THIS_LEVEL.getValue();
+
+ @Column(name = "level")
+ @ApiModelProperty(value = "级别,数值越小,级别越大")
+ private Integer level = 3;
+
+ @ApiModelProperty(value = "描述")
+ private String description;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Role role = (Role) o;
+ return Objects.equals(id, role.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java
new file mode 100644
index 0000000..fcbba83
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseEntity;
+import javax.persistence.*;
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ *
+ * 2018-11-22
+ */
+@Entity
+@Getter
+@Setter
+@Table(name="sys_user")
+public class User extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "user_id")
+ @NotNull(groups = Update.class)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @ApiModelProperty(value = "ID", hidden = true)
+ private Long id;
+
+ @ManyToMany(fetch = FetchType.EAGER)
+ @ApiModelProperty(value = "用户角色")
+ @JoinTable(name = "sys_users_roles",
+ joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")},
+ inverseJoinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")})
+ private Set<Role> roles;
+
+ @ManyToMany(fetch = FetchType.EAGER)
+ @ApiModelProperty(value = "用户岗位")
+ @JoinTable(name = "sys_users_jobs",
+ joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")},
+ inverseJoinColumns = {@JoinColumn(name = "job_id",referencedColumnName = "job_id")})
+ private Set<Job> jobs;
+
+ @OneToOne
+ @JoinColumn(name = "dept_id")
+ @ApiModelProperty(value = "用户部门")
+ private Dept dept;
+
+ @NotBlank
+ @Column(unique = true)
+ @ApiModelProperty(value = "用户名称")
+ private String username;
+
+ @NotBlank
+ @ApiModelProperty(value = "用户昵称")
+ private String nickName;
+
+ @Email
+ @NotBlank
+ @ApiModelProperty(value = "邮箱")
+ private String email;
+
+ @NotBlank
+ @ApiModelProperty(value = "电话号码")
+ private String phone;
+
+ @ApiModelProperty(value = "用户性别")
+ private String gender;
+
+ @ApiModelProperty(value = "头像真实名称",hidden = true)
+ private String avatarName;
+
+ @ApiModelProperty(value = "头像存储的路径", hidden = true)
+ private String avatarPath;
+
+ @ApiModelProperty(value = "密码")
+ private String password;
+
+ @NotNull
+ @ApiModelProperty(value = "是否启用")
+ private Boolean enabled;
+
+ @ApiModelProperty(value = "是否为admin账号", hidden = true)
+ private Boolean isAdmin = false;
+
+ @Column(name = "pwd_reset_time")
+ @ApiModelProperty(value = "最后修改密码的时间", hidden = true)
+ private Date pwdResetTime;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ User user = (User) o;
+ return Objects.equals(id, user.id) &&
+ Objects.equals(username, user.username);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, username);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java
new file mode 100644
index 0000000..68944cc
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ *
+ * 2018-12-20
+ */
+@Data
+@AllArgsConstructor
+public class MenuMetaVo implements Serializable {
+
+ private String title;
+
+ private String icon;
+
+ private Boolean noCache;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java
new file mode 100644
index 0000000..71c6161
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 构建前端路由时用到
+ *
+ * 2018-12-20
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class MenuVo implements Serializable {
+
+ private String name;
+
+ private String path;
+
+ private Boolean hidden;
+
+ private String redirect;
+
+ private String component;
+
+ private Boolean alwaysShow;
+
+ private MenuMetaVo meta;
+
+ private List<MenuVo> children;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java
new file mode 100644
index 0000000..66869b2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 修改密码的 Vo 类
+ *
+ * 2019年7月11日13:59:49
+ */
+@Data
+public class UserPassVo {
+
+ private String oldPass;
+
+ private String newPass;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java
new file mode 100644
index 0000000..5952659
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.Dept;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import java.util.List;
+import java.util.Set;
+
+/**
+*
+* 2019-03-25
+*/
+public interface DeptRepository extends JpaRepository<Dept, Long>, JpaSpecificationExecutor<Dept> {
+
+ /**
+ * 根据 PID 查询
+ * @param id pid
+ * @return /
+ */
+ List<Dept> findByPid(Long id);
+
+ /**
+ * 获取顶级部门
+ * @return /
+ */
+ List<Dept> findByPidIsNull();
+
+ /**
+ * 根据角色ID 查询
+ * @param roleId 角色ID
+ * @return /
+ */
+ @Query(value = "select d.* from sys_dept d, sys_roles_depts r where " +
+ "d.dept_id = r.dept_id and r.role_id = ?1", nativeQuery = true)
+ Set<Dept> findByRoleId(Long roleId);
+
+ /**
+ * 判断是否存在子节点
+ * @param pid /
+ * @return /
+ */
+ int countByPid(Long pid);
+
+ /**
+ * 根据ID更新sub_count
+ * @param count /
+ * @param id /
+ */
+ @Modifying
+ @Query(value = " update sys_dept set sub_count = ?1 where dept_id = ?2 ",nativeQuery = true)
+ void updateSubCntById(Integer count, Long id);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java
new file mode 100644
index 0000000..315be98
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.DictDetail;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.util.List;
+
+/**
+*
+* 2019-04-10
+*/
+public interface DictDetailRepository extends JpaRepository<DictDetail, Long>, JpaSpecificationExecutor<DictDetail> {
+
+ /**
+ * 根据字典名称查询
+ * @param name /
+ * @return /
+ */
+ List<DictDetail> findByDictName(String name);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java
new file mode 100644
index 0000000..c2d1a49
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.Dict;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+*
+* 2019-04-10
+*/
+public interface DictRepository extends JpaRepository<Dict, Long>, JpaSpecificationExecutor<Dict> {
+
+ /**
+ * 删除
+ * @param ids /
+ */
+ void deleteByIdIn(Set<Long> ids);
+
+ /**
+ * 查询
+ * @param ids /
+ * @return /
+ */
+ List<Dict> findByIdIn(Set<Long> ids);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java
new file mode 100644
index 0000000..d804309
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.Job;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.util.Set;
+
+/**
+*
+* 2019-03-29
+*/
+public interface JobRepository extends JpaRepository<Job, Long>, JpaSpecificationExecutor<Job> {
+
+ /**
+ * 根据名称查询
+ * @param name 名称
+ * @return /
+ */
+ Job findByName(String name);
+
+ /**
+ * 根据Id删除
+ * @param ids /
+ */
+ void deleteAllByIdIn(Set<Long> ids);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java
new file mode 100644
index 0000000..ac1e524
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.Menu;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 2018-12-17
+ */
+public interface MenuRepository extends JpaRepository<Menu, Long>, JpaSpecificationExecutor<Menu> {
+
+ /**
+ * 根据菜单标题查询
+ * @param title 菜单标题
+ * @return /
+ */
+ Menu findByTitle(String title);
+
+ /**
+ * 根据组件名称查询
+ * @param name 组件名称
+ * @return /
+ */
+ Menu findByComponentName(String name);
+
+ /**
+ * 根据菜单的 PID 查询
+ * @param pid /
+ * @return /
+ */
+ List<Menu> findByPid(long pid);
+
+ /**
+ * 查询顶级菜单
+ * @return /
+ */
+ List<Menu> findByPidIsNull();
+
+ /**
+ * 根据角色ID与菜单类型查询菜单
+ * @param roleIds roleIDs
+ * @param type 类型
+ * @return /
+ */
+ @Query(value = "SELECT m.* FROM sys_menu m, sys_roles_menus r WHERE " +
+ "m.menu_id = r.menu_id AND r.role_id IN ?1 AND type != ?2 order by m.menu_sort asc",nativeQuery = true)
+ LinkedHashSet<Menu> findByRoleIdsAndTypeNot(Set<Long> roleIds, int type);
+
+ /**
+ * 获取节点数量
+ * @param id /
+ * @return /
+ */
+ int countByPid(Long id);
+
+ /**
+ * 更新节点数目
+ * @param count /
+ * @param menuId /
+ */
+ @Modifying
+ @Query(value = " update sys_menu set sub_count = ?1 where menu_id = ?2 ",nativeQuery = true)
+ void updateSubCntById(int count, Long menuId);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java
new file mode 100644
index 0000000..dd6e48b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.Role;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 2018-12-03
+ */
+public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> {
+
+ /**
+ * 根据名称查询
+ * @param name /
+ * @return /
+ */
+ Role findByName(String name);
+
+ /**
+ * 删除多个角色
+ * @param ids /
+ */
+ void deleteAllByIdIn(Set<Long> ids);
+
+ /**
+ * 根据用户ID查询
+ * @param id 用户ID
+ * @return /
+ */
+ @Query(value = "SELECT r.* FROM sys_role r, sys_users_roles u WHERE " +
+ "r.role_id = u.role_id AND u.user_id = ?1",nativeQuery = true)
+ Set<Role> findByUserId(Long id);
+
+ /**
+ * 解绑角色菜单
+ * @param id 菜单ID
+ */
+ @Modifying
+ @Query(value = "delete from sys_roles_menus where menu_id = ?1",nativeQuery = true)
+ void untiedMenu(Long id);
+
+ /**
+ * 根据部门查询
+ * @param deptIds /
+ * @return /
+ */
+ @Query(value = "select count(1) from sys_role r, sys_roles_depts d where " +
+ "r.role_id = d.role_id and d.dept_id in ?1",nativeQuery = true)
+ int countByDepts(Set<Long> deptIds);
+
+ /**
+ * 根据菜单Id查询
+ * @param menuIds /
+ * @return /
+ */
+ @Query(value = "SELECT r.* FROM sys_role r, sys_roles_menus m WHERE " +
+ "r.role_id = m.role_id AND m.menu_id in ?1",nativeQuery = true)
+ List<Role> findInMenuId(List<Long> menuIds);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java
new file mode 100644
index 0000000..620b247
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.repository;
+
+import com.example.modules.system.domain.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 2018-11-22
+ */
+public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
+
+ /**
+ * 根据用户名查询
+ * @param username 用户名
+ * @return /
+ */
+ User findByUsername(String username);
+
+ /**
+ * 根据邮箱查询
+ * @param email 邮箱
+ * @return /
+ */
+ User findByEmail(String email);
+
+ /**
+ * 根据手机号查询
+ * @param phone 手机号
+ * @return /
+ */
+ User findByPhone(String phone);
+
+ /**
+ * 修改密码
+ * @param username 用户名
+ * @param pass 密码
+ * @param lastPasswordResetTime /
+ */
+ @Modifying
+ @Query(value = "update sys_user set password = ?2 , pwd_reset_time = ?3 where username = ?1",nativeQuery = true)
+ void updatePass(String username, String pass, Date lastPasswordResetTime);
+
+ /**
+ * 修改邮箱
+ * @param username 用户名
+ * @param email 邮箱
+ */
+ @Modifying
+ @Query(value = "update sys_user set email = ?2 where username = ?1",nativeQuery = true)
+ void updateEmail(String username, String email);
+
+ /**
+ * 根据角色查询用户
+ * @param roleId /
+ * @return /
+ */
+ @Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r WHERE" +
+ " u.user_id = r.user_id AND r.role_id = ?1", nativeQuery = true)
+ List<User> findByRoleId(Long roleId);
+
+ /**
+ * 根据角色中的部门查询
+ * @param deptId /
+ * @return /
+ */
+ @Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r, sys_roles_depts d WHERE " +
+ "u.user_id = r.user_id AND r.role_id = d.role_id AND d.dept_id = ?1 group by u.user_id", nativeQuery = true)
+ List<User> findByRoleDeptId(Long deptId);
+
+ /**
+ * 根据菜单查询
+ * @param id 菜单ID
+ * @return /
+ */
+ @Query(value = "SELECT u.* FROM sys_user u, sys_users_roles ur, sys_roles_menus rm WHERE\n" +
+ "u.user_id = ur.user_id AND ur.role_id = rm.role_id AND rm.menu_id = ?1 group by u.user_id", nativeQuery = true)
+ List<User> findByMenuId(Long id);
+
+ /**
+ * 根据Id删除
+ * @param ids /
+ */
+ void deleteAllByIdIn(Set<Long> ids);
+
+ /**
+ * 根据岗位查询
+ * @param ids /
+ * @return /
+ */
+ @Query(value = "SELECT count(1) FROM sys_user u, sys_users_jobs j WHERE u.user_id = j.user_id AND j.job_id IN ?1", nativeQuery = true)
+ int countByJobs(Set<Long> ids);
+
+ /**
+ * 根据部门查询
+ * @param deptIds /
+ * @return /
+ */
+ @Query(value = "SELECT count(1) FROM sys_user u WHERE u.dept_id IN ?1", nativeQuery = true)
+ int countByDepts(Set<Long> deptIds);
+
+ /**
+ * 根据角色查询
+ * @param ids /
+ * @return /
+ */
+ @Query(value = "SELECT count(1) FROM sys_user u, sys_users_roles r WHERE " +
+ "u.user_id = r.user_id AND r.role_id in ?1", nativeQuery = true)
+ int countByRoles(Set<Long> ids);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java
new file mode 100644
index 0000000..de01bd9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.service.dto.UserDto;
+import java.util.List;
+
+/**
+ * 数据权限服务类
+ *
+ * 2020-05-07
+ */
+public interface DataService {
+
+ /**
+ * 获取数据权限
+ * @param user /
+ * @return /
+ */
+ List<Long> getDeptIds(UserDto user);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java
new file mode 100644
index 0000000..24f6138
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.service.dto.DeptDto;
+import com.example.modules.system.service.dto.DeptQueryCriteria;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+*
+* 2019-03-25
+*/
+public interface DeptService {
+
+ /**
+ * 查询所有数据
+ * @param criteria 条件
+ * @param isQuery /
+ * @throws Exception /
+ * @return /
+ */
+ List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception;
+
+ /**
+ * 根据ID查询
+ * @param id /
+ * @return /
+ */
+ DeptDto findById(Long id);
+
+ /**
+ * 创建
+ * @param resources /
+ */
+ void create(Dept resources);
+
+ /**
+ * 编辑
+ * @param resources /
+ */
+ void update(Dept resources);
+
+ /**
+ * 删除
+ * @param deptDtos /
+ *
+ */
+ void delete(Set<DeptDto> deptDtos);
+
+ /**
+ * 根据PID查询
+ * @param pid /
+ * @return /
+ */
+ List<Dept> findByPid(long pid);
+
+ /**
+ * 根据角色ID查询
+ * @param id /
+ * @return /
+ */
+ Set<Dept> findByRoleId(Long id);
+
+ /**
+ * 导出数据
+ * @param queryAll 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<DeptDto> queryAll, HttpServletResponse response) throws IOException;
+
+ /**
+ * 获取待删除的部门
+ * @param deptList /
+ * @param deptDtos /
+ * @return /
+ */
+ Set<DeptDto> getDeleteDepts(List<Dept> deptList, Set<DeptDto> deptDtos);
+
+ /**
+ * 根据ID获取同级与上级数据
+ * @param deptDto /
+ * @param depts /
+ * @return /
+ */
+ List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts);
+
+ /**
+ * 构建树形数据
+ * @param deptDtos /
+ * @return /
+ */
+ Object buildTree(List<DeptDto> deptDtos);
+
+ /**
+ * 获取
+ * @param deptList
+ * @return
+ */
+ List<Long> getDeptChildren(List<Dept> deptList);
+
+ /**
+ * 验证是否被角色或用户关联
+ * @param deptDtos /
+ */
+ void verification(Set<DeptDto> deptDtos);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java
new file mode 100644
index 0000000..57e5a7f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.DictDetail;
+import com.example.modules.system.service.dto.DictDetailDto;
+import com.example.modules.system.service.dto.DictDetailQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import java.util.List;
+import java.util.Map;
+
+/**
+*
+* 2019-04-10
+*/
+public interface DictDetailService {
+
+ /**
+ * 创建
+ * @param resources /
+ */
+ void create(DictDetail resources);
+
+ /**
+ * 编辑
+ * @param resources /
+ */
+ void update(DictDetail resources);
+
+ /**
+ * 删除
+ * @param id /
+ */
+ void delete(Long id);
+
+ /**
+ * 分页查询
+ * @param criteria 条件
+ * @param pageable 分页参数
+ * @return /
+ */
+ Map<String,Object> queryAll(DictDetailQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 根据字典名称获取字典详情
+ * @param name 字典名称
+ * @return /
+ */
+ List<DictDetailDto> getDictByName(String name);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java
new file mode 100644
index 0000000..8cf7e9c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.Dict;
+import com.example.modules.system.service.dto.DictDto;
+import com.example.modules.system.service.dto.DictQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+*
+* 2019-04-10
+*/
+public interface DictService {
+
+ /**
+ * 分页查询
+ * @param criteria 条件
+ * @param pageable 分页参数
+ * @return /
+ */
+ Map<String,Object> queryAll(DictQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 查询全部数据
+ * @param dict /
+ * @return /
+ */
+ List<DictDto> queryAll(DictQueryCriteria dict);
+
+ /**
+ * 创建
+ * @param resources /
+ * @return /
+ */
+ void create(Dict resources);
+
+ /**
+ * 编辑
+ * @param resources /
+ */
+ void update(Dict resources);
+
+ /**
+ * 删除
+ * @param ids /
+ */
+ void delete(Set<Long> ids);
+
+ /**
+ * 导出数据
+ * @param queryAll 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<DictDto> queryAll, HttpServletResponse response) throws IOException;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java
new file mode 100644
index 0000000..2fc99b6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.Job;
+import com.example.modules.system.service.dto.JobDto;
+import com.example.modules.system.service.dto.JobQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+*
+* 2019-03-29
+*/
+public interface JobService {
+
+ /**
+ * 根据ID查询
+ * @param id /
+ * @return /
+ */
+ JobDto findById(Long id);
+
+ /**
+ * 创建
+ * @param resources /
+ * @return /
+ */
+ void create(Job resources);
+
+ /**
+ * 编辑
+ * @param resources /
+ */
+ void update(Job resources);
+
+ /**
+ * 删除
+ * @param ids /
+ */
+ void delete(Set<Long> ids);
+
+ /**
+ * 分页查询
+ * @param criteria 条件
+ * @param pageable 分页参数
+ * @return /
+ */
+ Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 查询全部数据
+ * @param criteria /
+ * @return /
+ */
+ List<JobDto> queryAll(JobQueryCriteria criteria);
+
+ /**
+ * 导出数据
+ * @param queryAll 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<JobDto> queryAll, HttpServletResponse response) throws IOException;
+
+ /**
+ * 验证是否被用户关联
+ * @param ids /
+ */
+ void verification(Set<Long> ids);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java
new file mode 100644
index 0000000..4706705
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.Menu;
+import com.example.modules.system.service.dto.MenuDto;
+import com.example.modules.system.service.dto.MenuQueryCriteria;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 2018-12-17
+ */
+public interface MenuService {
+
+ /**
+ * 查询全部数据
+ * @param criteria 条件
+ * @param isQuery /
+ * @throws Exception /
+ * @return /
+ */
+ List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception;
+
+ /**
+ * 根据ID查询
+ * @param id /
+ * @return /
+ */
+ MenuDto findById(long id);
+
+ /**
+ * 创建
+ * @param resources /
+ */
+ void create(Menu resources);
+
+ /**
+ * 编辑
+ * @param resources /
+ */
+ void update(Menu resources);
+
+ /**
+ * 获取所有子节点,包含自身ID
+ * @param menuList /
+ * @param menuSet /
+ * @return /
+ */
+ Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet);
+
+ /**
+ * 构建菜单树
+ * @param menuDtos 原始数据
+ * @return /
+ */
+ List<MenuDto> buildTree(List<MenuDto> menuDtos);
+
+ /**
+ * 构建菜单树
+ * @param menuDtos /
+ * @return /
+ */
+ Object buildMenus(List<MenuDto> menuDtos);
+
+ /**
+ * 根据ID查询
+ * @param id /
+ * @return /
+ */
+ Menu findOne(Long id);
+
+ /**
+ * 删除
+ * @param menuSet /
+ */
+ void delete(Set<Menu> menuSet);
+
+ /**
+ * 导出
+ * @param queryAll 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<MenuDto> queryAll, HttpServletResponse response) throws IOException;
+
+ /**
+ * 懒加载菜单数据
+ * @param pid /
+ * @return /
+ */
+ List<MenuDto> getMenus(Long pid);
+
+ /**
+ * 根据ID获取同级与上级数据
+ * @param menuDto /
+ * @param objects /
+ * @return /
+ */
+ List<MenuDto> getSuperior(MenuDto menuDto, List<Menu> objects);
+
+ /**
+ * 根据当前用户获取菜单
+ * @param currentUserId /
+ * @return /
+ */
+ List<MenuDto> findByUser(Long currentUserId);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java
new file mode 100644
index 0000000..d9f87f9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import java.util.Map;
+
+/**
+ *
+ * 2020-05-02
+ */
+public interface MonitorService {
+
+ /**
+ * 查询数据分页
+ * @return Map<String,Object>
+ */
+ Map<String,Object> getServers();
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java
new file mode 100644
index 0000000..5fa13ca
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.Role;
+import com.example.modules.system.service.dto.RoleDto;
+import com.example.modules.system.service.dto.RoleQueryCriteria;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.modules.system.service.dto.UserDto;
+import org.springframework.data.domain.Pageable;
+import org.springframework.security.core.GrantedAuthority;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 2018-12-03
+ */
+public interface RoleService {
+
+ /**
+ * 查询全部数据
+ * @return /
+ */
+ List<RoleDto> queryAll();
+
+ /**
+ * 根据ID查询
+ * @param id /
+ * @return /
+ */
+ RoleDto findById(long id);
+
+ /**
+ * 创建
+ * @param resources /
+ */
+ void create(Role resources);
+
+ /**
+ * 编辑
+ * @param resources /
+ */
+ void update(Role resources);
+
+ /**
+ * 删除
+ * @param ids /
+ */
+ void delete(Set<Long> ids);
+
+ /**
+ * 根据用户ID查询
+ * @param id 用户ID
+ * @return /
+ */
+ List<RoleSmallDto> findByUsersId(Long id);
+
+ /**
+ * 根据角色查询角色级别
+ * @param roles /
+ * @return /
+ */
+ Integer findByRoles(Set<Role> roles);
+
+ /**
+ * 修改绑定的菜单
+ * @param resources /
+ * @param roleDTO /
+ */
+ void updateMenu(Role resources, RoleDto roleDTO);
+
+ /**
+ * 解绑菜单
+ * @param id /
+ */
+ void untiedMenu(Long id);
+
+ /**
+ * 待条件分页查询
+ * @param criteria 条件
+ * @param pageable 分页参数
+ * @return /
+ */
+ Object queryAll(RoleQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 查询全部
+ * @param criteria 条件
+ * @return /
+ */
+ List<RoleDto> queryAll(RoleQueryCriteria criteria);
+
+ /**
+ * 导出数据
+ * @param queryAll 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<RoleDto> queryAll, HttpServletResponse response) throws IOException;
+
+ /**
+ * 获取用户权限信息
+ * @param user 用户信息
+ * @return 权限信息
+ */
+ List<GrantedAuthority> mapToGrantedAuthorities(UserDto user);
+
+ /**
+ * 验证是否被用户关联
+ * @param ids /
+ */
+ void verification(Set<Long> ids);
+
+ /**
+ * 根据菜单Id查询
+ * @param menuIds /
+ * @return /
+ */
+ List<Role> findInMenuId(List<Long> menuIds);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java
new file mode 100644
index 0000000..10fba88
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service;
+
+import com.example.modules.system.domain.User;
+import com.example.modules.system.service.dto.UserDto;
+import com.example.modules.system.service.dto.UserQueryCriteria;
+import org.springframework.data.domain.Pageable;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+public interface UserService {
+
+ /**
+ * 根据ID查询
+ * @param id ID
+ * @return /
+ */
+ UserDto findById(long id);
+
+ /**
+ * 新增用户
+ * @param resources /
+ */
+ void create(User resources);
+
+ /**
+ * 编辑用户
+ * @param resources /
+ * @throws Exception /
+ */
+ void update(User resources) throws Exception;
+
+ /**
+ * 删除用户
+ * @param ids /
+ */
+ void delete(Set<Long> ids);
+
+ /**
+ * 根据用户名查询
+ * @param userName /
+ * @return /
+ */
+ UserDto findByName(String userName);
+
+ /**
+ * 修改密码
+ * @param username 用户名
+ * @param encryptPassword 密码
+ */
+ void updatePass(String username, String encryptPassword);
+
+ /**
+ * 修改头像
+ * @param file 文件
+ * @return /
+ */
+ Map<String, String> updateAvatar(MultipartFile file);
+
+ /**
+ * 修改邮箱
+ * @param username 用户名
+ * @param email 邮箱
+ */
+ void updateEmail(String username, String email);
+
+ /**
+ * 查询全部
+ * @param criteria 条件
+ * @param pageable 分页参数
+ * @return /
+ */
+ Object queryAll(UserQueryCriteria criteria, Pageable pageable);
+
+ /**
+ * 查询全部不分页
+ * @param criteria 条件
+ * @return /
+ */
+ List<UserDto> queryAll(UserQueryCriteria criteria);
+
+ /**
+ * 导出数据
+ * @param queryAll 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<UserDto> queryAll, HttpServletResponse response) throws IOException;
+
+ /**
+ * 用户自助修改资料
+ * @param resources /
+ */
+ void updateCenter(User resources);
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java
new file mode 100644
index 0000000..02ec1ea
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+/**
+*
+* 2019-03-25
+*/
+@Getter
+@Setter
+public class DeptDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private String name;
+
+ private Boolean enabled;
+
+ private Integer deptSort;
+
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private List<DeptDto> children;
+
+ private Long pid;
+
+ private Integer subCount;
+
+ public Boolean getHasChildren() {
+ return subCount > 0;
+ }
+
+ public Boolean getLeaf() {
+ return subCount <= 0;
+ }
+
+ public String getLabel() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DeptDto deptDto = (DeptDto) o;
+ return Objects.equals(id, deptDto.id) &&
+ Objects.equals(name, deptDto.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java
new file mode 100644
index 0000000..8f8c56b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import com.example.annotation.DataPermission;
+import com.example.annotation.Query;
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+*
+* 2019-03-25
+*/
+@Data
+@DataPermission(fieldName = "id")
+public class DeptQueryCriteria{
+
+ @Query(type = Query.Type.INNER_LIKE)
+ private String name;
+
+ @Query
+ private Boolean enabled;
+
+ @Query
+ private Long pid;
+
+ @Query(type = Query.Type.IS_NULL, propName = "pid")
+ private Boolean pidIsNull;
+
+ @Query(type = Query.Type.BETWEEN)
+ private List<Timestamp> createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java
new file mode 100644
index 0000000..503762b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+*
+* 2019-6-10 16:32:18
+*/
+@Data
+public class DeptSmallDto implements Serializable {
+
+ private Long id;
+
+ private String name;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java
new file mode 100644
index 0000000..58e826b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+import java.io.Serializable;
+
+/**
+*
+* 2019-04-10
+*/
+@Getter
+@Setter
+public class DictDetailDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private DictSmallDto dict;
+
+ private String label;
+
+ private String value;
+
+ private Integer dictSort;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java
new file mode 100644
index 0000000..2f12c80
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import com.example.annotation.Query;
+
+/**
+*
+* 2019-04-10
+*/
+@Data
+public class DictDetailQueryCriteria {
+
+ @Query(type = Query.Type.INNER_LIKE)
+ private String label;
+
+ @Query(propName = "name",joinName = "dict")
+ private String dictName;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java
new file mode 100644
index 0000000..72f704e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+*
+* 2019-04-10
+*/
+@Getter
+@Setter
+public class DictDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private List<DictDetailDto> dictDetails;
+
+ private String name;
+
+ private String description;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java
new file mode 100644
index 0000000..3a5da52
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import com.example.annotation.Query;
+
+/**
+ *
+ * 公共查询类
+ */
+@Data
+public class DictQueryCriteria {
+
+ @Query(blurry = "name,description")
+ private String blurry;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java
new file mode 100644
index 0000000..a0ed61f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import java.io.Serializable;
+
+/**
+*
+* 2019-04-10
+*/
+@Getter
+@Setter
+public class DictSmallDto implements Serializable {
+
+ private Long id;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java
new file mode 100644
index 0000000..502176b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+
+import java.io.Serializable;
+
+/**
+*
+* 2019-03-29
+*/
+@Getter
+@Setter
+@NoArgsConstructor
+public class JobDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private Integer jobSort;
+
+ private String name;
+
+ private Boolean enabled;
+
+ public JobDto(String name, Boolean enabled) {
+ this.name = name;
+ this.enabled = enabled;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java
new file mode 100644
index 0000000..215d721
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import com.example.annotation.Query;
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+*
+* 2019-6-4 14:49:34
+*/
+@Data
+@NoArgsConstructor
+public class JobQueryCriteria {
+
+ @Query(type = Query.Type.INNER_LIKE)
+ private String name;
+
+ @Query
+ private Boolean enabled;
+
+ @Query(type = Query.Type.BETWEEN)
+ private List<Timestamp> createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java
new file mode 100644
index 0000000..af9f8a6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.io.Serializable;
+
+/**
+*
+* 2019-6-10 16:32:18
+*/
+@Data
+@NoArgsConstructor
+public class JobSmallDto implements Serializable {
+
+ private Long id;
+
+ private String name;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java
new file mode 100644
index 0000000..8500654
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ *
+ * 2018-12-17
+ */
+@Getter
+@Setter
+public class MenuDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private List<MenuDto> children;
+
+ private Integer type;
+
+ private String permission;
+
+ private String title;
+
+ private Integer menuSort;
+
+ private String path;
+
+ private String component;
+
+ private Long pid;
+
+ private Integer subCount;
+
+ private Boolean iFrame;
+
+ private Boolean cache;
+
+ private Boolean hidden;
+
+ private String componentName;
+
+ private String icon;
+
+ public Boolean getHasChildren() {
+ return subCount > 0;
+ }
+
+ public Boolean getLeaf() {
+ return subCount <= 0;
+ }
+
+ public String getLabel() {
+ return title;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ MenuDto menuDto = (MenuDto) o;
+ return Objects.equals(id, menuDto.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java
new file mode 100644
index 0000000..1d03860
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import com.example.annotation.Query;
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+ *
+ * 公共查询类
+ */
+@Data
+public class MenuQueryCriteria {
+
+ @Query(blurry = "title,component,permission")
+ private String blurry;
+
+ @Query(type = Query.Type.BETWEEN)
+ private List<Timestamp> createTime;
+
+ @Query(type = Query.Type.IS_NULL, propName = "pid")
+ private Boolean pidIsNull;
+
+ @Query
+ private Long pid;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java
new file mode 100644
index 0000000..1373b7f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.Set;
+
+
+@Getter
+@Setter
+public class RoleDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private Set<MenuDto> menus;
+
+ private Set<DeptDto> depts;
+
+ private String name;
+
+ private String dataScope;
+
+ private Integer level;
+
+ private String description;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ RoleDto roleDto = (RoleDto) o;
+ return Objects.equals(id, roleDto.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java
new file mode 100644
index 0000000..afe3a4e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import com.example.annotation.Query;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+/**
+ *
+ * 公共查询类
+ */
+@Data
+public class RoleQueryCriteria {
+
+ @Query(blurry = "name,description")
+ private String blurry;
+
+ @Query(type = Query.Type.BETWEEN)
+ private List<Timestamp> createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java
new file mode 100644
index 0000000..5c7f184
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class RoleSmallDto implements Serializable {
+
+ private Long id;
+
+ private String name;
+
+ private Integer level;
+
+ private String dataScope;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java
new file mode 100644
index 0000000..a1ecd96
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Getter;
+import lombok.Setter;
+import com.example.base.BaseDTO;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Set;
+
+
+@Getter
+@Setter
+public class UserDto extends BaseDTO implements Serializable {
+
+ private Long id;
+
+ private Set<RoleSmallDto> roles;
+
+ private Set<JobSmallDto> jobs;
+
+ private DeptSmallDto dept;
+
+ private Long deptId;
+
+ private String username;
+
+ private String nickName;
+
+ private String email;
+
+ private String phone;
+
+ private String gender;
+
+ private String avatarName;
+
+ private String avatarPath;
+
+ @JSONField(serialize = false)
+ private String password;
+
+ private Boolean enabled;
+
+ @JSONField(serialize = false)
+ private Boolean isAdmin = false;
+
+ private Date pwdResetTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java
new file mode 100644
index 0000000..1f862cf
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.dto;
+
+import lombok.Data;
+import com.example.annotation.Query;
+import java.io.Serializable;
+import java.sql.Timestamp;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+
+@Data
+public class UserQueryCriteria implements Serializable {
+
+ @Query
+ private Long id;
+
+ @Query(propName = "id", type = Query.Type.IN, joinName = "dept")
+ private Set<Long> deptIds = new HashSet<>();
+
+ @Query(blurry = "email,username,nickName")
+ private String blurry;
+
+ @Query
+ private Boolean enabled;
+
+ private Long deptId;
+
+ @Query(type = Query.Type.BETWEEN)
+ private List<Timestamp> createTime;
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java
new file mode 100644
index 0000000..e31f26b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.service.DataService;
+import com.example.modules.system.service.DeptService;
+import lombok.RequiredArgsConstructor;
+import com.example.modules.system.service.RoleService;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.modules.system.service.dto.UserDto;
+import com.example.utils.enums.DataScopeEnum;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import java.util.*;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description 数据权限服务实现
+ * 2020-05-07
+ **/
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "data")
+public class DataServiceImpl implements DataService {
+
+ private final RoleService roleService;
+ private final DeptService deptService;
+
+ /**
+ * 用户角色改变时需清理缓存
+ * @param user /
+ * @return /
+ */
+ @Override
+ @Cacheable(key = "'user:' + #p0.id")
+ public List<Long> getDeptIds(UserDto user) {
+ // 用于存储部门id
+ Set<Long> deptIds = new HashSet<>();
+ // 查询用户角色
+ List<RoleSmallDto> roleSet = roleService.findByUsersId(user.getId());
+ // 获取对应的部门ID
+ for (RoleSmallDto role : roleSet) {
+ DataScopeEnum dataScopeEnum = DataScopeEnum.find(role.getDataScope());
+ switch (Objects.requireNonNull(dataScopeEnum)) {
+ case THIS_LEVEL:
+ deptIds.add(user.getDept().getId());
+ break;
+ case CUSTOMIZE:
+ deptIds.addAll(getCustomize(deptIds, role));
+ break;
+ default:
+ return new ArrayList<>(deptIds);
+ }
+ }
+ return new ArrayList<>(deptIds);
+ }
+
+ /**
+ * 获取自定义的数据权限
+ * @param deptIds 部门ID
+ * @param role 角色
+ * @return 数据权限ID
+ */
+ public Set<Long> getCustomize(Set<Long> deptIds, RoleSmallDto role){
+ Set<Dept> depts = deptService.findByRoleId(role.getId());
+ for (Dept dept : depts) {
+ deptIds.add(dept.getId());
+ List<Dept> deptChildren = deptService.findByPid(dept.getId());
+ if (deptChildren != null && deptChildren.size() != 0) {
+ deptIds.addAll(deptService.getDeptChildren(deptChildren));
+ }
+ }
+ return deptIds;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java
new file mode 100644
index 0000000..e777319
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.domain.User;
+import com.example.modules.system.repository.DeptRepository;
+import com.example.modules.system.repository.RoleRepository;
+import com.example.modules.system.service.DeptService;
+import com.example.modules.system.service.dto.DeptDto;
+import com.example.modules.system.service.dto.DeptQueryCriteria;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.exception.BadRequestException;
+import com.example.modules.system.repository.UserRepository;
+import com.example.utils.*;
+import com.example.modules.system.service.mapstruct.DeptMapper;
+import com.example.utils.enums.DataScopeEnum;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+*
+* 2019-03-25
+*/
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "dept")
+public class DeptServiceImpl implements DeptService {
+
+ private final DeptRepository deptRepository;
+ private final DeptMapper deptMapper;
+ private final UserRepository userRepository;
+ private final RedisUtils redisUtils;
+ private final RoleRepository roleRepository;
+
+ @Override
+ public List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception {
+ Sort sort = Sort.by(Sort.Direction.ASC, "deptSort");
+ String dataScopeType = SecurityUtils.getDataScopeType();
+ if (isQuery) {
+ if(dataScopeType.equals(DataScopeEnum.ALL.getValue())){
+ criteria.setPidIsNull(true);
+ }
+ List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>());
+ List<String> fieldNames = new ArrayList<String>(){{ add("pidIsNull");add("enabled");}};
+ for (Field field : fields) {
+ //设置对象的访问权限,保证对private的属性的访问
+ field.setAccessible(true);
+ Object val = field.get(criteria);
+ if(fieldNames.contains(field.getName())){
+ continue;
+ }
+ if (ObjectUtil.isNotNull(val)) {
+ criteria.setPidIsNull(null);
+ break;
+ }
+ }
+ }
+ List<DeptDto> list = deptMapper.toDto(deptRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort));
+ // 如果为空,就代表为自定义权限或者本级权限,就需要去重,不理解可以注释掉,看查询结果
+ if(StringUtils.isBlank(dataScopeType)){
+ return deduplication(list);
+ }
+ return list;
+ }
+
+ @Override
+ @Cacheable(key = "'id:' + #p0")
+ public DeptDto findById(Long id) {
+ Dept dept = deptRepository.findById(id).orElseGet(Dept::new);
+ ValidationUtil.isNull(dept.getId(),"Dept","id",id);
+ return deptMapper.toDto(dept);
+ }
+
+ @Override
+ public List<Dept> findByPid(long pid) {
+ return deptRepository.findByPid(pid);
+ }
+
+ @Override
+ public Set<Dept> findByRoleId(Long id) {
+ return deptRepository.findByRoleId(id);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(Dept resources) {
+ deptRepository.save(resources);
+ // 计算子节点数目
+ resources.setSubCount(0);
+ // 清理缓存
+ updateSubCnt(resources.getPid());
+ // 清理自定义角色权限的datascope缓存
+ delCaches(resources.getPid());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(Dept resources) {
+ // 旧的部门
+ Long oldPid = findById(resources.getId()).getPid();
+ Long newPid = resources.getPid();
+ if(resources.getPid() != null && resources.getId().equals(resources.getPid())) {
+ throw new BadRequestException("上级不能为自己");
+ }
+ Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new);
+ ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId());
+ resources.setId(dept.getId());
+ deptRepository.save(resources);
+ // 更新父节点中子节点数目
+ updateSubCnt(oldPid);
+ updateSubCnt(newPid);
+ // 清理缓存
+ delCaches(resources.getId());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Set<DeptDto> deptDtos) {
+ for (DeptDto deptDto : deptDtos) {
+ // 清理缓存
+ delCaches(deptDto.getId());
+ deptRepository.deleteById(deptDto.getId());
+ updateSubCnt(deptDto.getPid());
+ }
+ }
+
+ @Override
+ public void download(List<DeptDto> deptDtos, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (DeptDto deptDTO : deptDtos) {
+ Map<String,Object> map = new LinkedHashMap<>();
+ map.put("部门名称", deptDTO.getName());
+ map.put("部门状态", deptDTO.getEnabled() ? "启用" : "停用");
+ map.put("创建日期", deptDTO.getCreateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ @Override
+ public Set<DeptDto> getDeleteDepts(List<Dept> menuList, Set<DeptDto> deptDtos) {
+ for (Dept dept : menuList) {
+ deptDtos.add(deptMapper.toDto(dept));
+ List<Dept> depts = deptRepository.findByPid(dept.getId());
+ if(depts!=null && depts.size()!=0){
+ getDeleteDepts(depts, deptDtos);
+ }
+ }
+ return deptDtos;
+ }
+
+ @Override
+ public List<Long> getDeptChildren(List<Dept> deptList) {
+ List<Long> list = new ArrayList<>();
+ deptList.forEach(dept -> {
+ if (dept!=null && dept.getEnabled()) {
+ List<Dept> depts = deptRepository.findByPid(dept.getId());
+ if (depts.size() != 0) {
+ list.addAll(getDeptChildren(depts));
+ }
+ list.add(dept.getId());
+ }
+ }
+ );
+ return list;
+ }
+
+ @Override
+ public List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts) {
+ if(deptDto.getPid() == null){
+ depts.addAll(deptRepository.findByPidIsNull());
+ return deptMapper.toDto(depts);
+ }
+ depts.addAll(deptRepository.findByPid(deptDto.getPid()));
+ return getSuperior(findById(deptDto.getPid()), depts);
+ }
+
+ @Override
+ public Object buildTree(List<DeptDto> deptDtos) {
+ Set<DeptDto> trees = new LinkedHashSet<>();
+ Set<DeptDto> depts= new LinkedHashSet<>();
+ List<String> deptNames = deptDtos.stream().map(DeptDto::getName).collect(Collectors.toList());
+ boolean isChild;
+ for (DeptDto deptDTO : deptDtos) {
+ isChild = false;
+ if (deptDTO.getPid() == null) {
+ trees.add(deptDTO);
+ }
+ for (DeptDto it : deptDtos) {
+ if (it.getPid() != null && deptDTO.getId().equals(it.getPid())) {
+ isChild = true;
+ if (deptDTO.getChildren() == null) {
+ deptDTO.setChildren(new ArrayList<>());
+ }
+ deptDTO.getChildren().add(it);
+ }
+ }
+ if(isChild) {
+ depts.add(deptDTO);
+ } else if(deptDTO.getPid() != null && !deptNames.contains(findById(deptDTO.getPid()).getName())) {
+ depts.add(deptDTO);
+ }
+ }
+
+ if (CollectionUtil.isEmpty(trees)) {
+ trees = depts;
+ }
+ Map<String,Object> map = new HashMap<>(2);
+ map.put("totalElements",deptDtos.size());
+ map.put("content",CollectionUtil.isEmpty(trees)? deptDtos :trees);
+ return map;
+ }
+
+ @Override
+ public void verification(Set<DeptDto> deptDtos) {
+ Set<Long> deptIds = deptDtos.stream().map(DeptDto::getId).collect(Collectors.toSet());
+ if(userRepository.countByDepts(deptIds) > 0){
+ throw new BadRequestException("所选部门存在用户关联,请解除后再试!");
+ }
+ if(roleRepository.countByDepts(deptIds) > 0){
+ throw new BadRequestException("所选部门存在角色关联,请解除后再试!");
+ }
+ }
+
+ private void updateSubCnt(Long deptId){
+ if(deptId != null){
+ int count = deptRepository.countByPid(deptId);
+ deptRepository.updateSubCntById(count, deptId);
+ }
+ }
+
+ private List<DeptDto> deduplication(List<DeptDto> list) {
+ List<DeptDto> deptDtos = new ArrayList<>();
+ for (DeptDto deptDto : list) {
+ boolean flag = true;
+ for (DeptDto dto : list) {
+ if (dto.getId().equals(deptDto.getPid())) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag){
+ deptDtos.add(deptDto);
+ }
+ }
+ return deptDtos;
+ }
+
+ /**
+ * 清理缓存
+ * @param id /
+ */
+ public void delCaches(Long id){
+ List<User> users = userRepository.findByRoleDeptId(id);
+ // 删除数据权限
+ redisUtils.delByKeys(CacheKey.DATA_USER, users.stream().map(User::getId).collect(Collectors.toSet()));
+ redisUtils.del(CacheKey.DEPT_ID + id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java
new file mode 100644
index 0000000..672a31a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import com.example.modules.system.domain.Dict;
+import com.example.modules.system.domain.DictDetail;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.modules.system.repository.DictRepository;
+import com.example.modules.system.service.dto.DictDetailQueryCriteria;
+import com.example.utils.*;
+import com.example.modules.system.repository.DictDetailRepository;
+import com.example.modules.system.service.DictDetailService;
+import com.example.modules.system.service.dto.DictDetailDto;
+import com.example.modules.system.service.mapstruct.DictDetailMapper;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import java.util.List;
+import java.util.Map;
+
+/**
+*
+* 2019-04-10
+*/
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "dict")
+public class DictDetailServiceImpl implements DictDetailService {
+
+ private final DictRepository dictRepository;
+ private final DictDetailRepository dictDetailRepository;
+ private final DictDetailMapper dictDetailMapper;
+ private final RedisUtils redisUtils;
+
+ @Override
+ public Map<String,Object> queryAll(DictDetailQueryCriteria criteria, Pageable pageable) {
+ Page<DictDetail> page = dictDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
+ return PageUtil.toPage(page.map(dictDetailMapper::toDto));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(DictDetail resources) {
+ dictDetailRepository.save(resources);
+ // 清理缓存
+ delCaches(resources);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(DictDetail resources) {
+ DictDetail dictDetail = dictDetailRepository.findById(resources.getId()).orElseGet(DictDetail::new);
+ ValidationUtil.isNull( dictDetail.getId(),"DictDetail","id",resources.getId());
+ resources.setId(dictDetail.getId());
+ dictDetailRepository.save(resources);
+ // 清理缓存
+ delCaches(resources);
+ }
+
+ @Override
+ @Cacheable(key = "'name:' + #p0")
+ public List<DictDetailDto> getDictByName(String name) {
+ return dictDetailMapper.toDto(dictDetailRepository.findByDictName(name));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Long id) {
+ DictDetail dictDetail = dictDetailRepository.findById(id).orElseGet(DictDetail::new);
+ // 清理缓存
+ delCaches(dictDetail);
+ dictDetailRepository.deleteById(id);
+ }
+
+ public void delCaches(DictDetail dictDetail){
+ Dict dict = dictRepository.findById(dictDetail.getDict().getId()).orElseGet(Dict::new);
+ redisUtils.del(CacheKey.DICT_NAME + dict.getName());
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java
new file mode 100644
index 0000000..79cd9e3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.example.modules.system.domain.Dict;
+import com.example.modules.system.service.dto.DictDto;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.modules.system.service.dto.DictDetailDto;
+import com.example.modules.system.service.dto.DictQueryCriteria;
+import com.example.utils.*;
+import com.example.modules.system.repository.DictRepository;
+import com.example.modules.system.service.DictService;
+import com.example.modules.system.service.mapstruct.DictMapper;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+
+/**
+*
+* 2019-04-10
+*/
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "dict")
+public class DictServiceImpl implements DictService {
+
+ private final DictRepository dictRepository;
+ private final DictMapper dictMapper;
+ private final RedisUtils redisUtils;
+
+ @Override
+ public Map<String, Object> queryAll(DictQueryCriteria dict, Pageable pageable){
+ Page<Dict> page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable);
+ return PageUtil.toPage(page.map(dictMapper::toDto));
+ }
+
+ @Override
+ public List<DictDto> queryAll(DictQueryCriteria dict) {
+ List<Dict> list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb));
+ return dictMapper.toDto(list);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(Dict resources) {
+ dictRepository.save(resources);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(Dict resources) {
+ // 清理缓存
+ delCaches(resources);
+ Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new);
+ ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId());
+ dict.setName(resources.getName());
+ dict.setDescription(resources.getDescription());
+ dictRepository.save(dict);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Set<Long> ids) {
+ // 清理缓存
+ List<Dict> dicts = dictRepository.findByIdIn(ids);
+ for (Dict dict : dicts) {
+ delCaches(dict);
+ }
+ dictRepository.deleteByIdIn(ids);
+ }
+
+ @Override
+ public void download(List<DictDto> dictDtos, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (DictDto dictDTO : dictDtos) {
+ if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){
+ for (DictDetailDto dictDetail : dictDTO.getDictDetails()) {
+ Map<String,Object> map = new LinkedHashMap<>();
+ map.put("字典名称", dictDTO.getName());
+ map.put("字典描述", dictDTO.getDescription());
+ map.put("字典标签", dictDetail.getLabel());
+ map.put("字典值", dictDetail.getValue());
+ map.put("创建日期", dictDetail.getCreateTime());
+ list.add(map);
+ }
+ } else {
+ Map<String,Object> map = new LinkedHashMap<>();
+ map.put("字典名称", dictDTO.getName());
+ map.put("字典描述", dictDTO.getDescription());
+ map.put("字典标签", null);
+ map.put("字典值", null);
+ map.put("创建日期", dictDTO.getCreateTime());
+ list.add(map);
+ }
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ public void delCaches(Dict dict){
+ redisUtils.del(CacheKey.DICT_NAME + dict.getName());
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java
new file mode 100644
index 0000000..73c93c5
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import com.example.modules.system.domain.Job;
+import com.example.modules.system.service.JobService;
+import com.example.modules.system.service.dto.JobDto;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.exception.BadRequestException;
+import com.example.exception.EntityExistException;
+import com.example.modules.system.repository.UserRepository;
+import com.example.modules.system.service.dto.JobQueryCriteria;
+import com.example.utils.*;
+import com.example.modules.system.repository.JobRepository;
+import com.example.modules.system.service.mapstruct.JobMapper;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+
+/**
+*
+* 2019-03-29
+*/
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "job")
+public class JobServiceImpl implements JobService {
+
+ private final JobRepository jobRepository;
+ private final JobMapper jobMapper;
+ private final RedisUtils redisUtils;
+ private final UserRepository userRepository;
+
+ @Override
+ public Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable) {
+ Page<Job> page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
+ return PageUtil.toPage(page.map(jobMapper::toDto).getContent(),page.getTotalElements());
+ }
+
+ @Override
+ public List<JobDto> queryAll(JobQueryCriteria criteria) {
+ List<Job> list = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
+ return jobMapper.toDto(list);
+ }
+
+ @Override
+ @Cacheable(key = "'id:' + #p0")
+ public JobDto findById(Long id) {
+ Job job = jobRepository.findById(id).orElseGet(Job::new);
+ ValidationUtil.isNull(job.getId(),"Job","id",id);
+ return jobMapper.toDto(job);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(Job resources) {
+ Job job = jobRepository.findByName(resources.getName());
+ if(job != null){
+ throw new EntityExistException(Job.class,"name",resources.getName());
+ }
+ jobRepository.save(resources);
+ }
+
+ @Override
+ @CacheEvict(key = "'id:' + #p0.id")
+ @Transactional(rollbackFor = Exception.class)
+ public void update(Job resources) {
+ Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new);
+ Job old = jobRepository.findByName(resources.getName());
+ if(old != null && !old.getId().equals(resources.getId())){
+ throw new EntityExistException(Job.class,"name",resources.getName());
+ }
+ ValidationUtil.isNull( job.getId(),"Job","id",resources.getId());
+ resources.setId(job.getId());
+ jobRepository.save(resources);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Set<Long> ids) {
+ jobRepository.deleteAllByIdIn(ids);
+ // 删除缓存
+ redisUtils.delByKeys(CacheKey.JOB_ID, ids);
+ }
+
+ @Override
+ public void download(List<JobDto> jobDtos, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (JobDto jobDTO : jobDtos) {
+ Map<String,Object> map = new LinkedHashMap<>();
+ map.put("岗位名称", jobDTO.getName());
+ map.put("岗位状态", jobDTO.getEnabled() ? "启用" : "停用");
+ map.put("创建日期", jobDTO.getCreateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ @Override
+ public void verification(Set<Long> ids) {
+ if(userRepository.countByJobs(ids) > 0){
+ throw new BadRequestException("所选的岗位中存在用户关联,请解除关联再试!");
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java
new file mode 100644
index 0000000..ceacddb
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.example.modules.system.domain.Menu;
+import com.example.modules.system.domain.Role;
+import com.example.modules.system.domain.User;
+import com.example.modules.system.domain.vo.MenuMetaVo;
+import com.example.modules.system.domain.vo.MenuVo;
+import com.example.modules.system.repository.MenuRepository;
+import com.example.modules.system.service.MenuService;
+import com.example.modules.system.service.RoleService;
+import com.example.modules.system.service.dto.MenuDto;
+import com.example.modules.system.service.dto.MenuQueryCriteria;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.exception.BadRequestException;
+import com.example.exception.EntityExistException;
+import com.example.modules.system.repository.UserRepository;
+import com.example.modules.system.service.mapstruct.MenuMapper;
+import com.example.utils.*;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ */
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "menu")
+public class MenuServiceImpl implements MenuService {
+
+ private final MenuRepository menuRepository;
+ private final UserRepository userRepository;
+ private final MenuMapper menuMapper;
+ private final RoleService roleService;
+ private final RedisUtils redisUtils;
+
+ @Override
+ public List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception {
+ Sort sort = Sort.by(Sort.Direction.ASC, "menuSort");
+ if(Boolean.TRUE.equals(isQuery)){
+ criteria.setPidIsNull(true);
+ List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>());
+ for (Field field : fields) {
+ //设置对象的访问权限,保证对private的属性的访问
+ field.setAccessible(true);
+ Object val = field.get(criteria);
+ if("pidIsNull".equals(field.getName())){
+ continue;
+ }
+ if (ObjectUtil.isNotNull(val)) {
+ criteria.setPidIsNull(null);
+ break;
+ }
+ }
+ }
+ return menuMapper.toDto(menuRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort));
+ }
+
+ @Override
+ @Cacheable(key = "'id:' + #p0")
+ public MenuDto findById(long id) {
+ Menu menu = menuRepository.findById(id).orElseGet(Menu::new);
+ ValidationUtil.isNull(menu.getId(),"Menu","id",id);
+ return menuMapper.toDto(menu);
+ }
+
+ /**
+ * 用户角色改变时需清理缓存
+ * @param currentUserId /
+ * @return /
+ */
+ @Override
+ @Cacheable(key = "'user:' + #p0")
+ public List<MenuDto> findByUser(Long currentUserId) {
+ List<RoleSmallDto> roles = roleService.findByUsersId(currentUserId);
+ Set<Long> roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet());
+ LinkedHashSet<Menu> menus = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2);
+ return menus.stream().map(menuMapper::toDto).collect(Collectors.toList());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(Menu resources) {
+ if(menuRepository.findByTitle(resources.getTitle()) != null){
+ throw new EntityExistException(Menu.class,"title",resources.getTitle());
+ }
+ if(StringUtils.isNotBlank(resources.getComponentName())){
+ if(menuRepository.findByComponentName(resources.getComponentName()) != null){
+ throw new EntityExistException(Menu.class,"componentName",resources.getComponentName());
+ }
+ }
+ if(resources.getPid().equals(0L)){
+ resources.setPid(null);
+ }
+ if(resources.getIFrame()){
+ String http = "http://", https = "https://";
+ if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) {
+ throw new BadRequestException("外链必须以http://或者https://开头");
+ }
+ }
+ menuRepository.save(resources);
+ // 计算子节点数目
+ resources.setSubCount(0);
+ // 更新父节点菜单数目
+ updateSubCnt(resources.getPid());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(Menu resources) {
+ if(resources.getId().equals(resources.getPid())) {
+ throw new BadRequestException("上级不能为自己");
+ }
+ Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new);
+ ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId());
+
+ if(resources.getIFrame()){
+ String http = "http://", https = "https://";
+ if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) {
+ throw new BadRequestException("外链必须以http://或者https://开头");
+ }
+ }
+ Menu menu1 = menuRepository.findByTitle(resources.getTitle());
+
+ if(menu1 != null && !menu1.getId().equals(menu.getId())){
+ throw new EntityExistException(Menu.class,"title",resources.getTitle());
+ }
+
+ if(resources.getPid().equals(0L)){
+ resources.setPid(null);
+ }
+
+ // 记录的父节点ID
+ Long oldPid = menu.getPid();
+ Long newPid = resources.getPid();
+
+ if(StringUtils.isNotBlank(resources.getComponentName())){
+ menu1 = menuRepository.findByComponentName(resources.getComponentName());
+ if(menu1 != null && !menu1.getId().equals(menu.getId())){
+ throw new EntityExistException(Menu.class,"componentName",resources.getComponentName());
+ }
+ }
+ menu.setTitle(resources.getTitle());
+ menu.setComponent(resources.getComponent());
+ menu.setPath(resources.getPath());
+ menu.setIcon(resources.getIcon());
+ menu.setIFrame(resources.getIFrame());
+ menu.setPid(resources.getPid());
+ menu.setMenuSort(resources.getMenuSort());
+ menu.setCache(resources.getCache());
+ menu.setHidden(resources.getHidden());
+ menu.setComponentName(resources.getComponentName());
+ menu.setPermission(resources.getPermission());
+ menu.setType(resources.getType());
+ menuRepository.save(menu);
+ // 计算父级菜单节点数目
+ updateSubCnt(oldPid);
+ updateSubCnt(newPid);
+ // 清理缓存
+ delCaches(resources.getId());
+ }
+
+ @Override
+ public Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet) {
+ for (Menu menu : menuList) {
+ menuSet.add(menu);
+ List<Menu> menus = menuRepository.findByPid(menu.getId());
+ if(menus!=null && menus.size()!=0){
+ getChildMenus(menus, menuSet);
+ }
+ }
+ return menuSet;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Set<Menu> menuSet) {
+ for (Menu menu : menuSet) {
+ // 清理缓存
+ delCaches(menu.getId());
+ roleService.untiedMenu(menu.getId());
+ menuRepository.deleteById(menu.getId());
+ updateSubCnt(menu.getPid());
+ }
+ }
+
+ @Override
+ public List<MenuDto> getMenus(Long pid) {
+ List<Menu> menus;
+ if(pid != null && !pid.equals(0L)){
+ menus = menuRepository.findByPid(pid);
+ } else {
+ menus = menuRepository.findByPidIsNull();
+ }
+ return menuMapper.toDto(menus);
+ }
+
+ @Override
+ public List<MenuDto> getSuperior(MenuDto menuDto, List<Menu> menus) {
+ if(menuDto.getPid() == null){
+ menus.addAll(menuRepository.findByPidIsNull());
+ return menuMapper.toDto(menus);
+ }
+ menus.addAll(menuRepository.findByPid(menuDto.getPid()));
+ return getSuperior(findById(menuDto.getPid()), menus);
+ }
+
+ @Override
+ public List<MenuDto> buildTree(List<MenuDto> menuDtos) {
+ List<MenuDto> trees = new ArrayList<>();
+ Set<Long> ids = new HashSet<>();
+ for (MenuDto menuDTO : menuDtos) {
+ if (menuDTO.getPid() == null) {
+ trees.add(menuDTO);
+ }
+ for (MenuDto it : menuDtos) {
+ if (menuDTO.getId().equals(it.getPid())) {
+ if (menuDTO.getChildren() == null) {
+ menuDTO.setChildren(new ArrayList<>());
+ }
+ menuDTO.getChildren().add(it);
+ ids.add(it.getId());
+ }
+ }
+ }
+ if(trees.size() == 0){
+ trees = menuDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
+ }
+ return trees;
+ }
+
+ @Override
+ public List<MenuVo> buildMenus(List<MenuDto> menuDtos) {
+ List<MenuVo> list = new LinkedList<>();
+ menuDtos.forEach(menuDTO -> {
+ if (menuDTO!=null){
+ List<MenuDto> menuDtoList = menuDTO.getChildren();
+ MenuVo menuVo = new MenuVo();
+ menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponentName()) ? menuDTO.getComponentName() : menuDTO.getTitle());
+ // 一级目录需要加斜杠,不然会报警告
+ menuVo.setPath(menuDTO.getPid() == null ? "/" + menuDTO.getPath() :menuDTO.getPath());
+ menuVo.setHidden(menuDTO.getHidden());
+ // 如果不是外链
+ if(!menuDTO.getIFrame()){
+ if(menuDTO.getPid() == null){
+ menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent());
+ // 如果不是一级菜单,并且菜单类型为目录,则代表是多级菜单
+ }else if(menuDTO.getType() == 0){
+ menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"ParentView":menuDTO.getComponent());
+ }else if(StringUtils.isNoneBlank(menuDTO.getComponent())){
+ menuVo.setComponent(menuDTO.getComponent());
+ }
+ }
+ menuVo.setMeta(new MenuMetaVo(menuDTO.getTitle(),menuDTO.getIcon(),!menuDTO.getCache()));
+ if(CollectionUtil.isNotEmpty(menuDtoList)){
+ menuVo.setAlwaysShow(true);
+ menuVo.setRedirect("noredirect");
+ menuVo.setChildren(buildMenus(menuDtoList));
+ // 处理是一级菜单并且没有子菜单的情况
+ } else if(menuDTO.getPid() == null){
+ MenuVo menuVo1 = new MenuVo();
+ menuVo1.setMeta(menuVo.getMeta());
+ // 非外链
+ if(!menuDTO.getIFrame()){
+ menuVo1.setPath("index");
+ menuVo1.setName(menuVo.getName());
+ menuVo1.setComponent(menuVo.getComponent());
+ } else {
+ menuVo1.setPath(menuDTO.getPath());
+ }
+ menuVo.setName(null);
+ menuVo.setMeta(null);
+ menuVo.setComponent("Layout");
+ List<MenuVo> list1 = new ArrayList<>();
+ list1.add(menuVo1);
+ menuVo.setChildren(list1);
+ }
+ list.add(menuVo);
+ }
+ }
+ );
+ return list;
+ }
+
+ @Override
+ public Menu findOne(Long id) {
+ Menu menu = menuRepository.findById(id).orElseGet(Menu::new);
+ ValidationUtil.isNull(menu.getId(),"Menu","id",id);
+ return menu;
+ }
+
+ @Override
+ public void download(List<MenuDto> menuDtos, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (MenuDto menuDTO : menuDtos) {
+ Map<String,Object> map = new LinkedHashMap<>();
+ map.put("菜单标题", menuDTO.getTitle());
+ map.put("菜单类型", menuDTO.getType() == null ? "目录" : menuDTO.getType() == 1 ? "菜单" : "按钮");
+ map.put("权限标识", menuDTO.getPermission());
+ map.put("外链菜单", menuDTO.getIFrame() ? "是" : "否");
+ map.put("菜单可见", menuDTO.getHidden() ? "否" : "是");
+ map.put("是否缓存", menuDTO.getCache() ? "是" : "否");
+ map.put("创建日期", menuDTO.getCreateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ private void updateSubCnt(Long menuId){
+ if(menuId != null){
+ int count = menuRepository.countByPid(menuId);
+ menuRepository.updateSubCntById(count, menuId);
+ }
+ }
+
+ /**
+ * 清理缓存
+ * @param id 菜单ID
+ */
+ public void delCaches(Long id){
+ List<User> users = userRepository.findByMenuId(id);
+ redisUtils.del(CacheKey.MENU_ID + id);
+ redisUtils.delByKeys(CacheKey.MENU_USER, users.stream().map(User::getId).collect(Collectors.toSet()));
+ // 清除 Role 缓存
+ List<Role> roles = roleService.findInMenuId(new ArrayList<Long>(){{
+ add(id);
+ }});
+ redisUtils.delByKeys(CacheKey.ROLE_ID, roles.stream().map(Role::getId).collect(Collectors.toSet()));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java
new file mode 100644
index 0000000..c279293
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import cn.hutool.core.date.BetweenFormater;
+import cn.hutool.core.date.DateUtil;
+import com.example.modules.system.service.MonitorService;
+import com.example.utils.ElAdminConstant;
+import com.example.utils.FileUtil;
+import com.example.utils.StringUtils;
+import org.springframework.stereotype.Service;
+import oshi.SystemInfo;
+import oshi.hardware.*;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.FormatUtil;
+import oshi.util.Util;
+import java.lang.management.ManagementFactory;
+import java.text.DecimalFormat;
+import java.util.*;
+
+/**
+*
+* 2020-05-02
+*/
+@Service
+public class MonitorServiceImpl implements MonitorService {
+
+ private final DecimalFormat df = new DecimalFormat("0.00");
+
+ @Override
+ public Map<String,Object> getServers(){
+ Map<String, Object> resultMap = new LinkedHashMap<>(8);
+ try {
+ SystemInfo si = new SystemInfo();
+ OperatingSystem os = si.getOperatingSystem();
+ HardwareAbstractionLayer hal = si.getHardware();
+ // 系统信息
+ resultMap.put("sys", getSystemInfo(os));
+ // cpu 信息
+ resultMap.put("cpu", getCpuInfo(hal.getProcessor()));
+ // 内存信息
+ resultMap.put("memory", getMemoryInfo(hal.getMemory()));
+ // 交换区信息
+ resultMap.put("swap", getSwapInfo(hal.getMemory()));
+ // 磁盘
+ resultMap.put("disk", getDiskInfo(os));
+ resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return resultMap;
+ }
+
+ /**
+ * 获取磁盘信息
+ * @return /
+ */
+ private Map<String,Object> getDiskInfo(OperatingSystem os) {
+ Map<String,Object> diskInfo = new LinkedHashMap<>();
+ FileSystem fileSystem = os.getFileSystem();
+ List<OSFileStore> fsArray = fileSystem.getFileStores();
+ String osName = System.getProperty("os.name");
+ long available = 0, total = 0;
+ for (OSFileStore fs : fsArray){
+ // windows 需要将所有磁盘分区累加,linux 和 mac 直接累加会出现磁盘重复的问题,待修复
+ if(osName.toLowerCase().startsWith(ElAdminConstant.WIN)) {
+ available += fs.getUsableSpace();
+ total += fs.getTotalSpace();
+ } else {
+ available = fs.getUsableSpace();
+ total = fs.getTotalSpace();
+ break;
+ }
+ }
+ long used = total - available;
+ diskInfo.put("total", total > 0 ? FileUtil.getSize(total) : "?");
+ diskInfo.put("available", FileUtil.getSize(available));
+ diskInfo.put("used", FileUtil.getSize(used));
+ if(total != 0){
+ diskInfo.put("usageRate", df.format(used/(double)total * 100));
+ } else {
+ diskInfo.put("usageRate", 0);
+ }
+ return diskInfo;
+ }
+
+ /**
+ * 获取交换区信息
+ * @param memory /
+ * @return /
+ */
+ private Map<String,Object> getSwapInfo(GlobalMemory memory) {
+ Map<String,Object> swapInfo = new LinkedHashMap<>();
+ VirtualMemory virtualMemory = memory.getVirtualMemory();
+ long total = virtualMemory.getSwapTotal();
+ long used = virtualMemory.getSwapUsed();
+ swapInfo.put("total", FormatUtil.formatBytes(total));
+ swapInfo.put("used", FormatUtil.formatBytes(used));
+ swapInfo.put("available", FormatUtil.formatBytes(total - used));
+ if(used == 0){
+ swapInfo.put("usageRate", 0);
+ } else {
+ swapInfo.put("usageRate", df.format(used/(double)total * 100));
+ }
+ return swapInfo;
+ }
+
+ /**
+ * 获取内存信息
+ * @param memory /
+ * @return /
+ */
+ private Map<String,Object> getMemoryInfo(GlobalMemory memory) {
+ Map<String,Object> memoryInfo = new LinkedHashMap<>();
+ memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal()));
+ memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable()));
+ memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable()));
+ memoryInfo.put("usageRate", df.format((memory.getTotal() - memory.getAvailable())/(double)memory.getTotal() * 100));
+ return memoryInfo;
+ }
+
+ /**
+ * 获取Cpu相关信息
+ * @param processor /
+ * @return /
+ */
+ private Map<String,Object> getCpuInfo(CentralProcessor processor) {
+ Map<String,Object> cpuInfo = new LinkedHashMap<>();
+ cpuInfo.put("name", processor.getProcessorIdentifier().getName());
+ cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU");
+ cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心");
+ cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount());
+ cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU");
+ // CPU信息
+ long[] prevTicks = processor.getSystemCpuLoadTicks();
+ // 等待1秒...
+ Util.sleep(1000);
+ long[] ticks = processor.getSystemCpuLoadTicks();
+ long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
+ long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
+ long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
+ long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
+ long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
+ long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
+ long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
+ long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
+ long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;
+ cpuInfo.put("used", df.format(100d * user / totalCpu + 100d * sys / totalCpu));
+ cpuInfo.put("idle", df.format(100d * idle / totalCpu));
+ return cpuInfo;
+ }
+
+ /**
+ * 获取系统相关信息,系统、运行天数、系统IP
+ * @param os /
+ * @return /
+ */
+ private Map<String,Object> getSystemInfo(OperatingSystem os){
+ Map<String,Object> systemInfo = new LinkedHashMap<>();
+ // jvm 运行时间
+ long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+ Date date = new Date(time);
+ // 计算项目运行时间
+ String formatBetween = DateUtil.formatBetween(date, new Date(),BetweenFormater.Level.HOUR);
+ // 系统信息
+ systemInfo.put("os", os.toString());
+ systemInfo.put("day", formatBetween);
+ systemInfo.put("ip", StringUtils.getLocalIp());
+ return systemInfo;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java
new file mode 100644
index 0000000..4a54a8c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.example.modules.system.domain.Menu;
+import com.example.modules.system.domain.Role;
+import com.example.modules.system.domain.User;
+import com.example.modules.system.service.dto.RoleDto;
+import com.example.modules.system.service.dto.RoleQueryCriteria;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.exception.BadRequestException;
+import com.example.modules.security.service.UserCacheClean;
+import com.example.exception.EntityExistException;
+import com.example.modules.system.repository.RoleRepository;
+import com.example.modules.system.repository.UserRepository;
+import com.example.modules.system.service.RoleService;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.modules.system.service.dto.UserDto;
+import com.example.modules.system.service.mapstruct.RoleMapper;
+import com.example.modules.system.service.mapstruct.RoleSmallMapper;
+import com.example.utils.*;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * 2018-12-03
+ */
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "role")
+public class RoleServiceImpl implements RoleService {
+
+ private final RoleRepository roleRepository;
+ private final RoleMapper roleMapper;
+ private final RoleSmallMapper roleSmallMapper;
+ private final RedisUtils redisUtils;
+ private final UserRepository userRepository;
+ private final UserCacheClean userCacheClean;
+
+ @Override
+ public List<RoleDto> queryAll() {
+ Sort sort = Sort.by(Sort.Direction.ASC, "level");
+ return roleMapper.toDto(roleRepository.findAll(sort));
+ }
+
+ @Override
+ public List<RoleDto> queryAll(RoleQueryCriteria criteria) {
+ return roleMapper.toDto(roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
+ }
+
+ @Override
+ public Object queryAll(RoleQueryCriteria criteria, Pageable pageable) {
+ Page<Role> page = roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
+ return PageUtil.toPage(page.map(roleMapper::toDto));
+ }
+
+ @Override
+ @Cacheable(key = "'id:' + #p0")
+ @Transactional(rollbackFor = Exception.class)
+ public RoleDto findById(long id) {
+ Role role = roleRepository.findById(id).orElseGet(Role::new);
+ ValidationUtil.isNull(role.getId(), "Role", "id", id);
+ return roleMapper.toDto(role);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(Role resources) {
+ if (roleRepository.findByName(resources.getName()) != null) {
+ throw new EntityExistException(Role.class, "username", resources.getName());
+ }
+ roleRepository.save(resources);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(Role resources) {
+ Role role = roleRepository.findById(resources.getId()).orElseGet(Role::new);
+ ValidationUtil.isNull(role.getId(), "Role", "id", resources.getId());
+
+ Role role1 = roleRepository.findByName(resources.getName());
+
+ if (role1 != null && !role1.getId().equals(role.getId())) {
+ throw new EntityExistException(Role.class, "username", resources.getName());
+ }
+ role.setName(resources.getName());
+ role.setDescription(resources.getDescription());
+ role.setDataScope(resources.getDataScope());
+ role.setDepts(resources.getDepts());
+ role.setLevel(resources.getLevel());
+ roleRepository.save(role);
+ // 更新相关缓存
+ delCaches(role.getId(), null);
+ }
+
+ @Override
+ public void updateMenu(Role resources, RoleDto roleDTO) {
+ Role role = roleMapper.toEntity(roleDTO);
+ List<User> users = userRepository.findByRoleId(role.getId());
+ // 更新菜单
+ role.setMenus(resources.getMenus());
+ delCaches(resources.getId(), users);
+ roleRepository.save(role);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void untiedMenu(Long menuId) {
+ // 更新菜单
+ roleRepository.untiedMenu(menuId);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Set<Long> ids) {
+ for (Long id : ids) {
+ // 更新相关缓存
+ delCaches(id, null);
+ }
+ roleRepository.deleteAllByIdIn(ids);
+ }
+
+ @Override
+ public List<RoleSmallDto> findByUsersId(Long id) {
+ return roleSmallMapper.toDto(new ArrayList<>(roleRepository.findByUserId(id)));
+ }
+
+ @Override
+ public Integer findByRoles(Set<Role> roles) {
+ if (roles.size() == 0) {
+ return Integer.MAX_VALUE;
+ }
+ Set<RoleDto> roleDtos = new HashSet<>();
+ for (Role role : roles) {
+ roleDtos.add(findById(role.getId()));
+ }
+ return Collections.min(roleDtos.stream().map(RoleDto::getLevel).collect(Collectors.toList()));
+ }
+
+ @Override
+ @Cacheable(key = "'auth:' + #p0.id")
+ public List<GrantedAuthority> mapToGrantedAuthorities(UserDto user) {
+ Set<String> permissions = new HashSet<>();
+ // 如果是管理员直接返回
+ if (user.getIsAdmin()) {
+ permissions.add("admin");
+ return permissions.stream().map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toList());
+ }
+ Set<Role> roles = roleRepository.findByUserId(user.getId());
+ permissions = roles.stream().flatMap(role -> role.getMenus().stream())
+ .filter(menu -> StringUtils.isNotBlank(menu.getPermission()))
+ .map(Menu::getPermission).collect(Collectors.toSet());
+ return permissions.stream().map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void download(List<RoleDto> roles, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (RoleDto role : roles) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("角色名称", role.getName());
+ map.put("角色级别", role.getLevel());
+ map.put("描述", role.getDescription());
+ map.put("创建日期", role.getCreateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ @Override
+ public void verification(Set<Long> ids) {
+ if (userRepository.countByRoles(ids) > 0) {
+ throw new BadRequestException("所选角色存在用户关联,请解除关联再试!");
+ }
+ }
+
+ @Override
+ public List<Role> findInMenuId(List<Long> menuIds) {
+ return roleRepository.findInMenuId(menuIds);
+ }
+
+ /**
+ * 清理缓存
+ * @param id /
+ */
+ public void delCaches(Long id, List<User> users) {
+ users = CollectionUtil.isEmpty(users) ? userRepository.findByRoleId(id) : users;
+ if (CollectionUtil.isNotEmpty(users)) {
+ users.forEach(item -> userCacheClean.cleanUserCache(item.getUsername()));
+ Set<Long> userIds = users.stream().map(User::getId).collect(Collectors.toSet());
+ redisUtils.delByKeys(CacheKey.DATA_USER, userIds);
+ redisUtils.delByKeys(CacheKey.MENU_USER, userIds);
+ redisUtils.delByKeys(CacheKey.ROLE_AUTH, userIds);
+ }
+ redisUtils.del(CacheKey.ROLE_ID + id);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..6b86b77
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.impl;
+
+import com.example.modules.system.domain.User;
+import com.example.modules.system.service.UserService;
+import com.example.modules.system.service.dto.JobSmallDto;
+import com.example.modules.system.service.dto.UserQueryCriteria;
+import com.example.utils.*;
+import lombok.RequiredArgsConstructor;
+import com.example.config.FileProperties;
+import com.example.exception.BadRequestException;
+import com.example.modules.security.service.OnlineUserService;
+import com.example.modules.security.service.UserCacheClean;
+import com.example.exception.EntityExistException;
+import com.example.exception.EntityNotFoundException;
+import com.example.modules.system.repository.UserRepository;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.modules.system.service.dto.UserDto;
+import com.example.modules.system.service.mapstruct.UserMapper;
+import com.example.utils.*;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotBlank;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "user")
+public class UserServiceImpl implements UserService {
+
+ private final UserRepository userRepository;
+ private final UserMapper userMapper;
+ private final FileProperties properties;
+ private final RedisUtils redisUtils;
+ private final UserCacheClean userCacheClean;
+ private final OnlineUserService onlineUserService;
+
+ @Override
+ public Object queryAll(UserQueryCriteria criteria, Pageable pageable) {
+ Page<User> page = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
+ return PageUtil.toPage(page.map(userMapper::toDto));
+ }
+
+ @Override
+ public List<UserDto> queryAll(UserQueryCriteria criteria) {
+ List<User> users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder));
+ return userMapper.toDto(users);
+ }
+
+ @Override
+ @Cacheable(key = "'id:' + #p0")
+ @Transactional(rollbackFor = Exception.class)
+ public UserDto findById(long id) {
+ User user = userRepository.findById(id).orElseGet(User::new);
+ ValidationUtil.isNull(user.getId(), "User", "id", id);
+ return userMapper.toDto(user);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void create(User resources) {
+ if (userRepository.findByUsername(resources.getUsername()) != null) {
+ throw new EntityExistException(User.class, "username", resources.getUsername());
+ }
+ if (userRepository.findByEmail(resources.getEmail()) != null) {
+ throw new EntityExistException(User.class, "email", resources.getEmail());
+ }
+ if (userRepository.findByPhone(resources.getPhone()) != null) {
+ throw new EntityExistException(User.class, "phone", resources.getPhone());
+ }
+ userRepository.save(resources);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(User resources) throws Exception {
+ User user = userRepository.findById(resources.getId()).orElseGet(User::new);
+ ValidationUtil.isNull(user.getId(), "User", "id", resources.getId());
+ User user1 = userRepository.findByUsername(resources.getUsername());
+ User user2 = userRepository.findByEmail(resources.getEmail());
+ User user3 = userRepository.findByPhone(resources.getPhone());
+ if (user1 != null && !user.getId().equals(user1.getId())) {
+ throw new EntityExistException(User.class, "username", resources.getUsername());
+ }
+ if (user2 != null && !user.getId().equals(user2.getId())) {
+ throw new EntityExistException(User.class, "email", resources.getEmail());
+ }
+ if (user3 != null && !user.getId().equals(user3.getId())) {
+ throw new EntityExistException(User.class, "phone", resources.getPhone());
+ }
+ // 如果用户的角色改变
+ if (!resources.getRoles().equals(user.getRoles())) {
+ redisUtils.del(CacheKey.DATA_USER + resources.getId());
+ redisUtils.del(CacheKey.MENU_USER + resources.getId());
+ redisUtils.del(CacheKey.ROLE_AUTH + resources.getId());
+ }
+ // 如果用户被禁用,则清除用户登录信息
+ if(!resources.getEnabled()){
+ onlineUserService.kickOutForUsername(resources.getUsername());
+ }
+ user.setUsername(resources.getUsername());
+ user.setEmail(resources.getEmail());
+ user.setEnabled(resources.getEnabled());
+ user.setRoles(resources.getRoles());
+ user.setDept(resources.getDept());
+ user.setJobs(resources.getJobs());
+ user.setPhone(resources.getPhone());
+ user.setNickName(resources.getNickName());
+ user.setGender(resources.getGender());
+ userRepository.save(user);
+ // 清除缓存
+ delCaches(user.getId(), user.getUsername());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateCenter(User resources) {
+ User user = userRepository.findById(resources.getId()).orElseGet(User::new);
+ User user1 = userRepository.findByPhone(resources.getPhone());
+ if (user1 != null && !user.getId().equals(user1.getId())) {
+ throw new EntityExistException(User.class, "phone", resources.getPhone());
+ }
+ user.setNickName(resources.getNickName());
+ user.setPhone(resources.getPhone());
+ user.setGender(resources.getGender());
+ userRepository.save(user);
+ // 清理缓存
+ delCaches(user.getId(), user.getUsername());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void delete(Set<Long> ids) {
+ for (Long id : ids) {
+ // 清理缓存
+ UserDto user = findById(id);
+ delCaches(user.getId(), user.getUsername());
+ }
+ userRepository.deleteAllByIdIn(ids);
+ }
+
+ @Override
+ public UserDto findByName(String userName) {
+ User user = userRepository.findByUsername(userName);
+ if (user == null) {
+ throw new EntityNotFoundException(User.class, "name", userName);
+ } else {
+ return userMapper.toDto(user);
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updatePass(String username, String pass) {
+ userRepository.updatePass(username, pass, new Date());
+ flushCache(username);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Map<String, String> updateAvatar(MultipartFile multipartFile) {
+ // 文件大小验证
+ FileUtil.checkSize(properties.getAvatarMaxSize(), multipartFile.getSize());
+ // 验证文件上传的格式
+ String image = "gif jpg png jpeg";
+ String fileType = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
+ if(fileType != null && !image.contains(fileType)){
+ throw new BadRequestException("文件格式错误!, 仅支持 " + image +" 格式");
+ }
+ User user = userRepository.findByUsername(SecurityUtils.getCurrentUsername());
+ String oldPath = user.getAvatarPath();
+ File file = FileUtil.upload(multipartFile, properties.getPath().getAvatar());
+ user.setAvatarPath(Objects.requireNonNull(file).getPath());
+ user.setAvatarName(file.getName());
+ userRepository.save(user);
+ if (StringUtils.isNotBlank(oldPath)) {
+ FileUtil.del(oldPath);
+ }
+ @NotBlank String username = user.getUsername();
+ flushCache(username);
+ return new HashMap<String, String>(1) {{
+ put("avatar", file.getName());
+ }};
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateEmail(String username, String email) {
+ userRepository.updateEmail(username, email);
+ flushCache(username);
+ }
+
+ @Override
+ public void download(List<UserDto> queryAll, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (UserDto userDTO : queryAll) {
+ List<String> roles = userDTO.getRoles().stream().map(RoleSmallDto::getName).collect(Collectors.toList());
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("用户名", userDTO.getUsername());
+ map.put("角色", roles);
+ map.put("部门", userDTO.getDept().getName());
+ map.put("岗位", userDTO.getJobs().stream().map(JobSmallDto::getName).collect(Collectors.toList()));
+ map.put("邮箱", userDTO.getEmail());
+ map.put("状态", userDTO.getEnabled() ? "启用" : "禁用");
+ map.put("手机号码", userDTO.getPhone());
+ map.put("修改密码的时间", userDTO.getPwdResetTime());
+ map.put("创建日期", userDTO.getCreateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+
+ /**
+ * 清理缓存
+ *
+ * @param id /
+ */
+ public void delCaches(Long id, String username) {
+ redisUtils.del(CacheKey.USER_ID + id);
+ flushCache(username);
+ }
+
+ /**
+ * 清理 登陆时 用户缓存信息
+ *
+ * @param username /
+ */
+ private void flushCache(String username) {
+ userCacheClean.cleanUserCache(username);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java
new file mode 100644
index 0000000..25de23f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.service.dto.DeptDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-03-25
+*/
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface DeptMapper extends BaseMapper<DeptDto, Dept> {
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java
new file mode 100644
index 0000000..01b7c65
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Dept;
+import com.example.modules.system.service.dto.DeptSmallDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-03-25
+*/
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface DeptSmallMapper extends BaseMapper<DeptSmallDto, Dept> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java
new file mode 100644
index 0000000..42ad48c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.DictDetail;
+import com.example.modules.system.service.dto.DictDetailDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-04-10
+*/
+@Mapper(componentModel = "spring", uses = {DictSmallMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface DictDetailMapper extends BaseMapper<DictDetailDto, DictDetail> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java
new file mode 100644
index 0000000..24b763e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Dict;
+import com.example.modules.system.service.dto.DictDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-04-10
+*/
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface DictMapper extends BaseMapper<DictDto, Dict> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java
new file mode 100644
index 0000000..8f05535
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Dict;
+import com.example.modules.system.service.dto.DictSmallDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-04-10
+*/
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface DictSmallMapper extends BaseMapper<DictSmallDto, Dict> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java
new file mode 100644
index 0000000..90be895
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Job;
+import com.example.modules.system.service.dto.JobDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-03-29
+*/
+@Mapper(componentModel = "spring",uses = {DeptMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface JobMapper extends BaseMapper<JobDto, Job> {
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java
new file mode 100644
index 0000000..9a36c91
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Job;
+import com.example.modules.system.service.dto.JobSmallDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+*
+* 2019-03-29
+*/
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface JobSmallMapper extends BaseMapper<JobSmallDto, Job> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java
new file mode 100644
index 0000000..867cbf2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Menu;
+import com.example.modules.system.service.dto.MenuDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+ *
+ * 2018-12-17
+ */
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface MenuMapper extends BaseMapper<MenuDto, Menu> {
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java
new file mode 100644
index 0000000..929b14b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Role;
+import com.example.modules.system.service.dto.RoleDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+
+@Mapper(componentModel = "spring", uses = {MenuMapper.class, DeptMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface RoleMapper extends BaseMapper<RoleDto, Role> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java
new file mode 100644
index 0000000..4d4ecff
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.Role;
+import com.example.modules.system.service.dto.RoleSmallDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+/**
+ *
+ * 2019-5-23
+ */
+@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface RoleSmallMapper extends BaseMapper<RoleSmallDto, Role> {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java
new file mode 100644
index 0000000..68a45dd
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.modules.system.service.mapstruct;
+
+import com.example.modules.system.domain.User;
+import com.example.modules.system.service.dto.UserDto;
+import com.example.base.BaseMapper;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+
+@Mapper(componentModel = "spring",uses = {RoleMapper.class, DeptMapper.class, JobMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface UserMapper extends BaseMapper<UserDto, User> {
+}
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt b/UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt
new file mode 100644
index 0000000..d0f401a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt
@@ -0,0 +1,8 @@
+ _ _ _
+ | | | | (_)
+ ___| |______ __ _ __| |_ __ ___ _ _ __
+ / _ | |______/ _` |/ _` | '_ ` _ \| | '_ \
+ | __| | | (_| | (_| | | | | | | | | | |
+ \___|_| \__,_|\__,_|_| |_| |_|_|_| |_|
+
+ :: Spring Boot :: (v2.1.0.RELEASE) \ No newline at end of file
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml
new file mode 100644
index 0000000..983bf6d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml
@@ -0,0 +1,118 @@
+#配置数据源
+spring:
+ datasource:
+ druid:
+ db-type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
+ url: jdbc:log4jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:eladmin}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
+ username: ${DB_USER:root}
+ password: ${DB_PWD:root}
+ # 初始连接数
+ initial-size: 5
+ # 最小连接数
+ min-idle: 15
+ # 最大连接数
+ max-active: 30
+ # 超时时间(以秒数为单位)
+ remove-abandoned-timeout: 180
+ # 获取连接超时时间
+ max-wait: 3000
+ # 连接有效性检测时间
+ time-between-eviction-runs-millis: 60000
+ # 连接在池中最小生存的时间
+ min-evictable-idle-time-millis: 300000
+ # 连接在池中最大生存的时间
+ max-evictable-idle-time-millis: 900000
+ # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
+ test-while-idle: true
+ # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
+ test-on-borrow: true
+ # 是否在归还到池中前进行检验
+ test-on-return: false
+ # 检测连接是否有效
+ validation-query: select 1
+ # 配置监控统计
+ webStatFilter:
+ enabled: true
+ stat-view-servlet:
+ enabled: true
+ url-pattern: /druid/*
+ reset-enable: false
+ filter:
+ stat:
+ enabled: true
+ # 记录慢SQL
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
+
+# 登录相关配置
+login:
+ # 登录缓存
+ cache-enable: true
+ # 是否限制单用户登录
+ single-login: false
+ # 验证码
+ login-code:
+ # 验证码类型配置 查看 LoginProperties 类
+ code-type: arithmetic
+ # 登录图形验证码有效时间/分钟
+ expiration: 2
+ # 验证码高度
+ width: 111
+ # 验证码宽度
+ height: 36
+ # 内容长度
+ length: 2
+ # 字体名称,为空则使用默认字体
+ font-name:
+ # 字体大小
+ font-size: 25
+
+#jwt
+jwt:
+ header: Authorization
+ # 令牌前缀
+ token-start-with: Bearer
+ # 必须使用最少88位的Base64对该令牌进行编码
+ base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
+ # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
+ token-validity-in-seconds: 14400000
+ # 在线用户key
+ online-key: online-token-
+ # 验证码
+ code-key: code-key-
+ # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
+ detect: 1800000
+ # 续期时间范围,默认1小时,单位毫秒
+ renew: 3600000
+
+#是否允许生成代码,生产环境设置为false
+generator:
+ enabled: true
+
+#是否开启 swagger-ui
+swagger:
+ enabled: true
+
+# IP 本地解析
+ip:
+ local-parsing: true
+
+# 文件存储路径
+file:
+ mac:
+ path: ~/file/
+ avatar: ~/avatar/
+ linux:
+ path: /home/dns/file/
+ avatar: /home/dns/avatar/
+ windows:
+ path: C:\dns\file\
+ avatar: C:\dns\avatar\
+ # 文件大小 /M
+ maxSize: 100
+ avatarMaxSize: 5
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml
new file mode 100644
index 0000000..8e1993f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml
@@ -0,0 +1,126 @@
+#配置数据源
+spring:
+ datasource:
+ druid:
+ db-type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
+ url: jdbc:log4jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:eladmin}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
+ username: ${DB_USER:root}
+ password: ${DB_PWD:123456}
+ # 初始连接数
+ initial-size: 5
+ # 最小连接数
+ min-idle: 15
+ # 最大连接数
+ max-active: 30
+ # 获取连接超时时间
+ max-wait: 5000
+ # 连接有效性检测时间
+ time-between-eviction-runs-millis: 60000
+ # 连接在池中最小生存的时间
+ min-evictable-idle-time-millis: 300000
+ # 连接在池中最大生存的时间
+ max-evictable-idle-time-millis: 900000
+ # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
+ test-while-idle: true
+ # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
+ test-on-borrow: true
+ # 是否在归还到池中前进行检验
+ test-on-return: false
+ # 检测连接是否有效
+ validation-query: select 1
+ # 配置监控统计
+ webStatFilter:
+ enabled: true
+ stat-view-servlet:
+ enabled: true
+ # 控制台管理用户名和密码
+ url-pattern: /druid/*
+ reset-enable: false
+ login-username: admin
+ 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
+
+# 登录相关配置
+login:
+ # 登录缓存
+ cache-enable: true
+ # 是否限制单用户登录
+ single-login: false
+ # 验证码
+ login-code:
+ # 验证码类型配置 查看 LoginProperties 类
+ code-type: arithmetic
+ # 登录图形验证码有效时间/分钟
+ expiration: 2
+ # 验证码高度
+ width: 111
+ # 验证码宽度
+ height: 36
+ # 内容长度
+ length: 2
+ # 字体名称,为空则使用默认字体,如遇到线上乱码,设置其他字体即可
+ font-name:
+ # 字体大小
+ font-size: 25
+
+#jwt
+jwt:
+ header: Authorization
+ # 令牌前缀
+ token-start-with: Bearer
+ # 必须使用最少88位的Base64对该令牌进行编码
+ base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
+ # 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
+ token-validity-in-seconds: 7200000
+ # 在线用户key
+ online-key: online-token-
+ # 验证码
+ code-key: code-key-
+ # token 续期检查时间范围(默认30分钟,单位默认毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
+ detect: 1800000
+ # 续期时间范围,默认 1小时,这里单位毫秒
+ renew: 3600000
+
+# IP 本地解析
+ip:
+ local-parsing: false
+
+#是否允许生成代码,生产环境设置为false
+generator:
+ enabled: false
+
+#如果生产环境要开启swagger,需要配置请求地址
+#springfox:
+# documentation:
+# swagger:
+# v2:
+# host: # 接口域名或外网ip
+
+#是否开启 swagger-ui
+swagger:
+ enabled: false
+
+# 文件存储路径
+file:
+ mac:
+ path: ~/file/
+ avatar: ~/avatar/
+ linux:
+ path: /home/dns/file/
+ avatar: /home/dns/avatar/
+ windows:
+ path: C:\dns\file\
+ avatar: C:\dns\avatar\
+ # 文件大小 /M
+ maxSize: 100
+ avatarMaxSize: 5
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml
new file mode 100644
index 0000000..a43407b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml
@@ -0,0 +1,97 @@
+server:
+ port: 8888
+
+spring:
+ freemarker:
+ check-template-location: false
+ profiles:
+ active: dev
+ jackson:
+ time-zone: GMT+8
+ data:
+ redis:
+ repositories:
+ enabled: false
+# pid:
+# file: /自行指定位置/dns.pid
+
+ #配置 Jpa
+ jpa:
+ hibernate:
+ ddl-auto: none
+ open-in-view: true
+ properties:
+ hibernate:
+ dialect: org.hibernate.dialect.MySQL5InnoDBDialect
+
+ redis:
+ #数据库索引
+ database: ${REDIS_DB:0}
+ host: ${REDIS_HOST:127.0.0.1}
+ port: ${REDIS_PORT:6379}
+ password: ${REDIS_PWD:}
+ #连接超时时间
+ timeout: 5000
+
+task:
+ pool:
+ # 核心线程池大小
+ core-pool-size: 10
+ # 最大线程数
+ max-pool-size: 30
+ # 活跃时间
+ keep-alive-seconds: 60
+ # 队列容量
+ queue-capacity: 50
+
+#七牛云
+qiniu:
+ # 文件大小 /M
+ max-size: 15
+
+#邮箱验证码有效时间/秒
+code:
+ expiration: 300
+
+#密码加密传输,前端公钥加密,后端私钥解密
+rsa:
+ private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
+
+# 内存用户缓存配置
+user-cache:
+ # 最小回收数(当缓存数量达到此值时进行回收)
+ min-evictable-size: 512
+ # 最小回收间隔
+ min-evictable-interval: 1800000
+ # 最小存活时间 (ms)
+ min-idle-time: 3600000
+
+
+#mybatis
+mybatis-plus:
+ mapper-locations: classpath*:/mapper/**/*.xml
+ #实体扫描,多个package用逗号或者分号分隔
+ typeAliasesPackage: com.example.modules.*.domain
+ global-config:
+ #数据库相关配置
+ db-config:
+ #主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
+ id-type: AUTO
+ #字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
+ field-strategy: NOT_NULL
+ #驼峰下划线转换
+ column-underline: true
+ logic-delete-value: 1
+ logic-not-delete-value: 0
+ banner: false
+ #原生配置
+ configuration:
+ map-underscore-to-camel-case: true
+ cache-enabled: false
+ call-setters-on-nulls: true
+ jdbc-type-for-null: 'null'
+
+#showSql
+logging:
+ level:
+ com.example.modules.system.mapper: debug
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties b/UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties
new file mode 100644
index 0000000..2ed9370
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties
@@ -0,0 +1,27 @@
+#数据库类型转Java类型
+tinyint=Integer
+smallint=Integer
+mediumint=Integer
+int=Integer
+integer=Integer
+
+bigint=Long
+
+float=Float
+
+double=Double
+
+decimal=BigDecimal
+
+bit=Boolean
+
+char=String
+varchar=String
+tinytext=String
+text=String
+mediumtext=String
+longtext=String
+
+date=Timestamp
+datetime=Timestamp
+timestamp=Timestamp \ No newline at end of file
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties b/UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties
new file mode 100644
index 0000000..302525f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties
@@ -0,0 +1,4 @@
+# If you use SLF4J. First, you need to tell log4jdbc-log4j2 that you want to use the SLF4J logger
+log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
+log4jdbc.auto.load.popular.drivers=false
+log4jdbc.drivers=com.mysql.cj.jdbc.Driver \ No newline at end of file
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml
new file mode 100644
index 0000000..8a399c4
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="30 seconds" debug="false">
+ <contextName>DiamondV</contextName>
+ <property name="log.charset" value="utf-8" />
+ <property name="log.pattern" value="%contextName- %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n" />
+
+ <!--输出到控制台-->
+ <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>${log.pattern}</pattern>
+ <charset>${log.charset}</charset>
+ </encoder>
+ </appender>
+
+ <!--普通日志输出到控制台-->
+ <root level="info">
+ <appender-ref ref="console" />
+ </root>
+
+ <!--监控sql日志输出,如需监控 Sql 打印,请设置为 INFO -->
+ <logger name="jdbc.sqlonly" level="INFO" additivity="false">
+ <appender-ref ref="console" />
+ </logger>
+
+ <logger name="jdbc.resultset" level="ERROR" additivity="false">
+ <appender-ref ref="console" />
+ </logger>
+
+ <!-- 如想看到表格数据,将OFF改为INFO -->
+ <logger name="jdbc.resultsettable" level="OFF" additivity="false">
+ <appender-ref ref="console" />
+ </logger>
+
+ <logger name="jdbc.connection" level="OFF" additivity="false">
+ <appender-ref ref="console" />
+ </logger>
+
+ <logger name="jdbc.sqltiming" level="OFF" additivity="false">
+ <appender-ref ref="console" />
+ </logger>
+
+ <logger name="jdbc.audit" level="OFF" additivity="false">
+ <appender-ref ref="console" />
+ </logger>
+</configuration>
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml
new file mode 100644
index 0000000..37d8a3b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml
@@ -0,0 +1,577 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.example.modules.dns.mapper.DnsDohDao">
+
+ <resultMap id="dohMap" type="com.example.modules.dns.domain.Result">
+ <id property="id" column="id"/>
+ <id property="ip" column="ip"/>
+ <id property="host" column="host"/>
+ <id property="port" column="port"/>
+ <result property="path" column="path"/>
+ <result property="method" column="method"/>
+ <result property="connectType" column="connect_type"/>
+ <result property="statusCode" column="status_code"/>
+ <result property="repHeader" column="rep_header"/>
+ <result property="repBody" column="rep_body"/>
+ <result property="timestamp" column="timestamp"/>
+ <result property="component" column="component"/>
+ <result property="rounds" column="rounds"/>
+ <association property="ipInformation" columnPrefix="ii_"
+ javaType="com.example.modules.dns.domain.IpInformation">
+ <result property="id" column="id"/>
+ <result property="ip" column="ip"/>
+ <result property="country" column="country"/>
+ <result property="province" column="province"/>
+ <result property="city" column="city"/>
+ <result property="district" column="district"/>
+ <result property="provider" column="provider"/>
+ <result property="isp" column="isp"/>
+ <result property="asnumber" column="asnumber"/>
+ <result property="timestamp" column="timestamp"/>
+ <result property="zipcode" column="zipcode"/>
+ <result property="timezone" column="timezone"/>
+ </association>
+
+ <collection property="pathList" columnPrefix="da2_" ofType="String">
+ <result property="pathList" column="path"/>
+ </collection>
+
+ <collection property="componentList" columnPrefix="da2_" ofType="String">
+ <result property="component" column="component"/>
+ </collection>
+ <collection property="ipCert" columnPrefix="ic_" ofType="com.example.modules.dns.domain.IpCert">
+ <id property="id" column="id"/>
+ <result property="ip" column="ip"/>
+ <result property="port" column="port"/>
+ <result property="certificate" column="certificate"/>
+ <result property="ca" column="ca"/>
+ <result property="timestamp" column="timestamp"/>
+ </collection>
+
+ <collection property="vulnerability" columnPrefix="v_" ofType="com.example.modules.dns.domain.Vulnerability">
+ <id property="id" column="id"/>
+ <result property="component" column="component"/>
+ <result property="vulnerability" column="vulnerability"/>
+ <result property="timestamp" column="timestamp"/>
+ </collection>
+
+ </resultMap>
+
+ <select id="queryDohPage" resultMap="dohMap">
+ SELECT da.id,da.ip,da.`host`,da.`port`,da.rounds,da.`timestamp`
+ ,GROUP_CONCAT(concat(da.method,'',da.path)) path
+ ,GROUP_CONCAT(distinct da.component) component
+ ,ii.country ii_country,ii.provider ii_provider,ii.city ii_city ,ii.asnumber ii_asnumber,ii.isp ii_isp,
+ ii.province ii_province,ii.zipcode ii_zipcode,ii.district ii_district,
+ v.`vulnerability` v_vulnerability
+ FROM (SELECT da.* FROM doh_attribute da
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ AND da.`port` = #{params.port}
+ </if>
+ </where>
+ ) da
+ LEFT JOIN ip_information ii ON da.ip=ii.ip
+ LEFT JOIN `vulnerability` v ON v.`component` = da.`component`
+
+ GROUP BY da.ip,da.port,da.host,da.rounds
+ order by da.`timestamp` desc
+ LIMIT #{params.n},#{params.m}
+ </select>
+
+ <select id="dohProvinceCount" resultType="map">
+ SELECT
+ COUNT(distinct da.ip) count,ii.`province`
+ FROM (SELECT DISTINCT ip from doh_attribute
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and port = #{params.port}
+ </if>
+ </where>
+ ) da
+ JOIN `ip_information` ii
+ ON da.ip = ii.ip AND ii.province IS NOT NULL AND ii.province !=''
+ GROUP BY ii.province
+ </select>
+
+ <select id="dohChinaMapCount" resultType="map">
+ SELECT ii.`province`,
+ COUNT(distinct da.ip) count
+ FROM `doh_attribute` da
+ JOIN `ip_information` ii
+ ON da.ip = ii.ip
+ where ii.country = '中国'
+ and da.`rounds` = (select MAX(rounds) FROM doh_attribute)
+ and ii.province IS NOT NULL
+ AND ii.province != ''
+ GROUP BY ii.province
+
+ order by count desc
+ </select>
+
+ <select id="dohCountryCount" resultType="map">
+ SELECT ii.`country`,
+ COUNT(distinct da.ip) count
+ FROM `doh_attribute` da
+ JOIN `ip_information` ii
+ ON da.ip = ii.ip
+ where da.`rounds` = (SELECT DISTINCT MAX(rounds) FROM doh_attribute)
+ GROUP BY ii.country
+ order by count desc
+ </select>
+
+ <select id="dohAndDo53ProvinceCount" resultType="map">
+ SELECT province,SUM(count) count FROM (
+ SELECT
+ ii.`province`,COUNT(distinct da.ip) count,da.ip
+ FROM `doh_attribute` da
+ JOIN `ip_information` ii
+ ON da.ip = ii.ip
+ where ii.province IS NOT NULL AND ii.province !=''
+ <if test="params.ip != null and params.ip != ''">
+ and da.ip = #{params.ip}
+ </if>
+ GROUP BY ii.province
+
+ UNION ALL
+
+ SELECT
+ ii.`province`,COUNT(distinct s.ip) COUNT, s.ip
+ FROM `scan_result` s
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip
+ where ii.province IS NOT NULL AND ii.province !=''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ GROUP BY ii.province
+ ) a1
+
+ GROUP BY a1.province
+ </select>
+
+ <select id="dohProviderCount" resultType="map">
+ SELECT
+ COUNT(ip_attr.ip) count,ii.`provider`
+ from
+ (SELECT DISTINCT ip from doh_attribute
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and port = #{params.port}
+ </if>
+ </where>
+ ) ip_attr
+ JOIN `ip_information` ii on ip_attr.ip = ii.ip AND ii.provider IS NOT NULL AND ii.provider !=''
+
+ GROUP BY ii.provider
+ </select>
+
+ <select id="dohAndDo53ProviderCount" resultType="map">
+
+ SELECT provider,SUM(COUNT) count FROM(
+ SELECT
+ ii.`provider`,COUNT(da.ip) COUNT,da.ip
+ FROM (SELECT id, ip from doh_attribute
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ ip = #{params.ip}
+ </if>
+ </where>
+ ) da
+ JOIN `ip_information` ii ON da.ip = ii.ip
+ GROUP BY ii.provider
+
+ UNION ALL
+ SELECT
+ ii.`provider`,COUNT(distinct s.ip) COUNT,s.ip
+ FROM `scan_result` s
+ JOIN `ip_information` ii ON s.ip = ii.ip
+ GROUP BY ii.provider
+ ) a1
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ a1.ip = #{params.ip}
+ </if>
+ </where>
+ GROUP BY a1.provider
+ HAVING provider IS NOT NULL AND provider !=''
+ </select>
+
+ <select id="dohComponentCount" resultType="map">
+ SELECT
+ da.component,COUNT(distinct da.ip) count
+ FROM (SELECT DISTINCT ip,component from doh_attribute
+ where
+ component IS NOT NULL AND component !=''
+ <if test="params.ip != null and params.ip != ''">
+ and ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and port = #{params.port}
+ </if>
+ ) da
+ GROUP BY da.component
+
+ </select>
+
+ <select id="dohAndDo53ComponentCount" resultType="map">
+ SELECT component,SUM(COUNT) count FROM (
+ SELECT
+ da.component,COUNT(distinct da.ip) COUNT,da.ip
+ FROM `doh_attribute` da
+ <where>
+
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+
+ </where>
+ GROUP BY da.component,da.ip
+
+ UNION ALL
+
+ SELECT
+ s.component,COUNT(distinct s.ip) COUNT ,s.ip
+ FROM `scan_result` s
+ GROUP BY s.component,s.ip) a1
+ where component IS NOT NULL AND component !=''
+ <if test="params.ip != null and params.ip != ''">
+ and a1.ip = #{params.ip}
+ </if>
+
+ GROUP BY a1.component
+
+ </select>
+
+ <select id="dohServiceCategoryCount" resultType="map">
+ <!--SELECT IFNULL(SUM(count),0) count FROM (
+ SELECT da.ip,COUNT(distinct da.ip) count FROM `doh_attribute` da
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ and da.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and da.port = #{params.port}
+ </if>
+ </where>
+ GROUP BY ip) a1-->
+ SELECT count(1) count from (
+ SELECT distinct da.ip from `doh_attribute` da
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and da.port = #{params.port}
+ </if>
+ </where>
+ ) a
+
+ </select>
+
+ <select id="dohResultTotalCount" resultType="int">
+ SELECT COUNT(1) count FROM (
+ SELECT ip,PORT,HOST,rounds
+ FROM `doh_attribute` da
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and da.port = #{params.port}
+ </if>
+ </where>
+ GROUP BY ip,PORT,HOST,rounds
+ ) a1
+ </select>
+
+ <select id="dohVulnerabilityCount" resultType="map">
+ SELECT vulnerability,COUNT(distinct ip) count FROM (
+ SELECT da.ip,da.port,da.host,da.`component`
+ ,v.`vulnerability`
+ FROM `doh_attribute` da
+ JOIN `vulnerability` v ON v.`component` = da.`component` AND vulnerability IS NOT NULL AND vulnerability != ''
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and da.port = #{params.port}
+ </if>
+ </where>
+ ) a1
+
+ GROUP BY a1.vulnerability
+ </select>
+
+ <select id="dohAndDo53VulnerabilityCount" resultType="map">
+ SELECT vulnerability,COUNT(distinct ip) count FROM (
+ SELECT da.ip
+ ,v.`vulnerability`
+ FROM `doh_attribute` da
+ JOIN `vulnerability` v ON v.`component` = da.`component`
+ where vulnerability IS NOT NULL AND vulnerability !=''
+ <if test="params.ip != null and params.ip != ''">
+ and ip = #{params.ip}
+ </if>
+
+ UNION ALL
+
+ SELECT s.ip
+ ,v.`vulnerability`
+ FROM `scan_result` s
+ JOIN `vulnerability` v ON v.`component` = s.`component`
+ where vulnerability IS NOT NULL AND vulnerability !=''
+ <if test="params.ip != null and params.ip != ''">
+ and ip = #{params.ip}
+ </if>
+ ) a1
+
+ GROUP BY a1.vulnerability
+ </select>
+
+
+ <select id="dohPortCount" resultType="map">
+ SELECT COUNT(ip) count,`port` FROM
+ (SELECT DISTINCT ip,port from doh_attribute
+ where `port` is not null AND `port` != ''
+ <if test="params.ip != null and params.ip != ''">
+ and ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and port = #{params.port}
+ </if>
+ ) da
+ GROUP BY port
+ </select>
+
+
+ <select id="dohIpCount" resultType="int">
+ SELECT COUNT(distinct da.ip) FROM doh_attribute da
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+ </where>
+ </select>
+ <select id="getDohRepBody" resultMap="dohMap">
+ select da.rep_body, da.rep_header
+ from doh_attribute da
+ where da.ip = #{ip}
+ AND da.port = #{port}
+ AND da.host = #{host}
+ AND da.rounds = #{rounds}
+ </select>
+
+ <select id="selectDohInfoByUnion" resultMap="dohMap">
+ SELECT da.*,
+ GROUP_CONCAT(concat(da.method, '', da.path)) path,
+ ii.country ii_country,
+ ii.provider ii_provider,
+ ii.city ii_city,
+ ii.asnumber ii_asnumber,
+ ii.isp ii_isp,
+ ii.province ii_province,
+ ii.zipcode ii_zipcode,
+ ii.district ii_district,
+ v.`vulnerability` v_vulnerability
+ from (select da.ip
+ from (select count(1), d.ip from doh_attribute d
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ </where>
+ group by d.ip) da
+ JOIN scan_result s on da.ip = s.ip) dip
+ join doh_attribute da on da.ip = dip.ip
+ left join ip_information ii on ii.ip = dip.ip
+ left join vulnerability v on v.component = da.component
+
+ group by da.ip, da.host, da.`port`, da.rounds
+ order by da.`timestamp` desc
+ LIMIT #{params.offset},#{params.limit}
+ </select>
+
+ <select id="selectDohCountByUnion" resultType="integer">
+ select count(1)
+ from (SELECT da.id, da.ip, da.host, da.`port`, da.rounds
+ from (select da.ip
+ from (select count(1), d.ip from doh_attribute d
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ </where>
+ group by d.ip) da
+ JOIN scan_result s on da.ip = s.ip
+ ) dip
+ join doh_attribute da on da.ip = dip.ip
+ group by da.ip, da.host, da.`port`, da.rounds) total
+
+ </select>
+
+ <select id="countDohPortUnion" resultType="java.util.Map">
+
+ select count(distinct dh.ip) count ,dh.`port`
+ from (select distinct ip,`port` from doh_attribute
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and port = #{params.port}
+ </if>
+ </where>
+ ) dh
+ join scan_result sc on sc.ip = dh.ip
+ group by dh.`port`
+ having dh.`port` is not null AND dh.`port` != ''
+
+ UNION ALL
+
+ select count(distinct sc.ip) count,'53' as `port`
+ from (select distinct ip,`port` from doh_attribute da
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ da.ip = #{params.ip}
+ </if>
+ </where>
+ ) dh
+ join scan_result sc on sc.ip = dh.ip
+
+ </select>
+
+ <select id="getDohAndDo53ProvinceCount" resultType="java.util.Map">
+ SELECT
+ ii.`province`,COUNT(distinct s.ip) COUNT
+ FROM ( select sc.id,sc.ip from `scan_result` sc
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ sc.ip = #{ip}
+ </if>
+ </where>
+ )s
+ join `doh_attribute` da on da.ip = s.ip
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip
+ <where>
+ <if test="params.port != null and params.port != ''">
+ da.`port` = #{params.port}
+ </if>
+ </where>
+ GROUP BY ii.province
+ having ii.province IS NOT NULL AND ii.province !=''
+ </select>
+
+ <select id="getDohAndDo53ProviderCount" resultType="java.util.Map">
+ SELECT
+ ii.`provider`,COUNT(distinct s.ip) COUNT
+ FROM ( select sc.id,sc.ip from `scan_result` sc
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ sc.ip = #{ip}
+ </if>
+ </where>
+ )s
+ join `doh_attribute` da on da.ip = s.ip
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip
+ <where>
+ <if test="params.port != null and params.port != ''">
+ da.`port` = #{params.port}
+ </if>
+ </where>
+ GROUP BY ii.provider
+ having ii.provider IS NOT NULL AND ii.provider !=''
+ </select>
+
+ <select id="getDohAndDo53ComponentCount" resultType="java.util.Map">
+ SELECT
+ da.component component,count(distinct da.ip) count
+ FROM ( select count(1),d.ip,d.component from doh_attribute d
+ where d.component IS NOT NULL AND d.component !=''
+ <if test="params.ip != null and params.ip != ''">
+ AND d.ip = #{ip}
+ </if>
+ ) da
+ JOIN scan_result s on da.ip = s.ip
+ <where>
+ <if test="params.port != null and params.port != ''">
+ da.`port` = #{params.port}
+ </if>
+ </where>
+ GROUP BY da.component
+ having da.component IS NOT NULL AND da.component !=''
+ </select>
+
+ <select id="getDohServiceCategoryCount" resultType="java.util.Map">
+ SELECT count(DISTINCT da.ip)
+ from (select count(1),d.ip from doh_attribute d
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ </where>
+ group by d.ip) da
+ join scan_result sc on da.ip = sc.ip
+ </select>
+ <select id="getDohAndDo53VulnerabilityCount" resultType="java.util.Map">
+ SELECT vulnerability, COUNT(distinct ip) count
+ FROM (
+ select da.ip, dv.vulnerability
+ from (select count(1), d.ip, d.component
+ from doh_attribute d
+ where d.component is not null and d.component != ''
+ <if test="params.ip != null and params.ip != ''">
+ and d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ group by d.ip, d.component) da
+ join scan_result sc on da.ip = sc.ip
+ join (select distinct v.vulnerability, d.component, d.ip from doh_attribute d
+ JOIN `vulnerability` v ON v.`component` = d.`component`) dv
+ on da.ip = dv.ip
+ where dv.vulnerability is not null and dv.vulnerability != ''
+
+ union all
+
+ select s.ip, dv.vulnerability
+ from (select count(1), d.ip from doh_attribute d
+ group by d.ip
+ ) da
+ join scan_result s on da.ip = s.ip
+ join (select distinct v.vulnerability, sc.component, sc.ip
+ from scan_result sc
+ JOIN `vulnerability` v ON v.`component` = sc.`component`) dv
+ on s.ip = dv.ip
+ where dv.vulnerability is not null and dv.vulnerability != ''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ ) a1
+ GROUP BY a1.vulnerability
+ </select>
+
+</mapper>
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml
new file mode 100644
index 0000000..849fc64
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml
@@ -0,0 +1,400 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.example.modules.dns.mapper.DnsDo53Dao">
+
+ <resultMap id="do53Map" type="com.example.modules.dns.domain.Result">
+ <id property="id" column="id"/>
+ <result property="ip" column="ip"/>
+ <result property="flags" column="flags"/>
+ <result property="opcode" column="opcode"/>
+ <result property="qr" column="qr"/>
+ <result property="aa" column="aa"/>
+ <result property="ra" column="ra"/>
+ <result property="rcode" column="rcode"/>
+ <result property="queryName" column="queryName"/>
+ <result property="queryResponse" column="query_response"/>
+ <result property="component" column="component"/>
+ <result property="scanType" column="scanType"/>
+ <result property="timestamp" column="time"/>
+ <result property="dnsType" column="dnsType"/>
+ <result property="epoch" column="epoch"/>
+
+ <association property="ipInformation" columnPrefix="ii_"
+ javaType="com.example.modules.dns.domain.IpInformation">
+ <result property="id" column="id"/>
+ <result property="ip" column="ip"/>
+ <result property="country" column="country"/>
+ <result property="province" column="province"/>
+ <result property="city" column="city"/>
+ <result property="district" column="district"/>
+ <result property="provider" column="provider"/>
+ <result property="isp" column="isp"/>
+ <result property="asnumber" column="asnumber"/>
+ <result property="timestamp" column="timestamp"/>
+ <result property="zipcode" column="zipcode"/>
+ <result property="timezone" column="timezone"/>
+ </association>
+ <collection property="componentList" ofType="String">
+ <result property="component" column="component"/>
+ </collection>
+
+ <collection property="vulnerability" columnPrefix="v_" ofType="com.example.modules.dns.domain.Vulnerability">
+ <id property="id" column="id"/>
+ <result property="component" column="component"/>
+ <result property="vulnerability" column="vulnerability"/>
+ <result property="timestamp" column="timestamp"/>
+ </collection>
+
+
+ </resultMap>
+
+ <select id="queryDo53Page" resultMap="do53Map">
+ SELECT s.*,
+ ii.country ii_country,ii.provider ii_provider,
+ ii.city ii_city ,ii.asnumber ii_asnumber,ii.isp ii_isp,
+ ii.province ii_province,ii.zipcode ii_zipcode,ii.district ii_district,
+ dt.type dnsType,v.`vulnerability` v_vulnerability
+ FROM (select s.* from scan_result s
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ s.ip = #{params.ip}
+ </if>
+ </where>
+ order by s.time desc
+ LIMIT #{params.n},#{params.m}
+ ) s
+ LEFT JOIN ip_information ii ON ii.ip = s.ip
+ LEFT JOIN dns_type dt ON dt.ip = s.ip AND dt.`epoch` = s.`epoch`
+ LEFT JOIN `vulnerability` v ON v.`component` = s.`component`
+
+
+ </select>
+
+ <select id="do53IpCount" resultType="int">
+ SELECT COUNT(distinct ip) FROM `scan_result`
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ ip = #{params.ip}
+ </if>
+ </where>
+
+ </select>
+
+ <select id="do53ServiceCategoryCount" resultType="map">
+ SELECT TYPE,COUNT(distinct ip) count FROM (
+ SELECT s.ip,dt.type FROM `scan_result` s
+ JOIN `dns_type` dt ON s.ip=dt.ip
+ where type IS NOT NULL AND type !=''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ <if test="params.dnsType != null and params.dnsType != ''">
+ and dt.type = #{params.dnsType}
+ </if>
+ ) a1
+ GROUP BY a1.type
+ </select>
+
+ <select id="do53ProvinceCount" resultType="map">
+ SELECT
+ ii.`province`,COUNT(distinct s.ip) count
+ FROM `scan_result` s
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip AND ii.province IS NOT NULL AND ii.province !=''
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ </where>
+ GROUP BY ii.province
+ </select>
+
+ <select id="do53CountryCount" resultType="map">
+ SELECT ii.`country`,
+ COUNT(s.ip) count
+ FROM `scan_result` s
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip
+ GROUP BY ii.country
+ </select>
+
+ <select id="do53CountryMapCount" resultType="map">
+ SELECT ii.`country`,
+ COUNT(ii.`country`) count,
+ dt.type
+ FROM `dns_type` dt
+ JOIN `ip_information` ii ON dt.ip = ii.ip
+ WHERE dt.epoch = (SELECT MAX(epoch) FROM `dns_type`)
+ GROUP BY ii.`country`, dt.`type`
+ order by count desc
+ </select>
+
+ <select id="do53WorldMapCount" resultType="map">
+ SELECT ii.`country`,
+ COUNT(ii.`country`) count
+ FROM `dns_type` dt
+ JOIN `ip_information` ii ON dt.ip = ii.ip
+ WHERE dt.epoch = (SELECT MAX(epoch) FROM `dns_type`)
+ GROUP BY ii.`country`
+ order by count desc
+ </select>
+
+ <select id="do53ChinaMapCount" resultType="map">
+ SELECT ii.`province`,
+ COUNT(ii.`province`) count
+ FROM `dns_type` dt
+ JOIN `ip_information` ii ON dt.ip = ii.ip
+ WHERE ii.country = '中国'
+ and dt.epoch = (SELECT MAX(epoch) FROM `dns_type`)
+ GROUP BY ii.`province`
+ order by count desc
+ </select>
+
+ <select id="do53ProviderCount" resultType="map">
+ SELECT
+ ii.`provider`,COUNT(s.ip) count
+ FROM `scan_result` s
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip AND provider IS NOT NULL AND provider !=''
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ s.ip = #{params.ip}
+ </if>
+ </where>
+ GROUP BY ii.provider
+ </select>
+
+
+ <select id="do53ComponentCount" resultType="map">
+ SELECT
+ s.component,COUNT(distinct s.ip) count
+ FROM `scan_result` s
+ where
+ component IS NOT NULL AND component !=''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ GROUP BY s.component
+ </select>
+
+ <select id="do53VulnerabilityCount" resultType="map">
+
+ SELECT vulnerability,COUNT(ip) count FROM (
+ SELECT s.ip
+ ,v.`vulnerability`
+ FROM `scan_result` s
+ JOIN `vulnerability` v ON v.`component` = s.`component`
+ where vulnerability IS NOT NULL AND vulnerability !=''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ ) a1
+ GROUP BY a1.vulnerability
+ </select>
+
+ <select id="pageCount" resultType="java.lang.Integer">
+ select count(1) from scan_result s
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ s.ip = #{params.ip}
+ </if>
+ </where>
+ </select>
+
+ <select id="queryOpenRdns" resultType="result">
+ select sc.*,
+ dt.type dnsType,
+ ii.country ii_country,ii.provider ii_provider,ii.city ii_city ,ii.asnumber ii_asnumber,ii.isp ii_isp,
+ ii.province ii_province,ii.zipcode ii_zipcode,ii.district ii_district,
+ v.`vulnerability` v_vulnerability
+ from
+ (
+ select sc.* from
+ scan_result sc join (select ip,epoch from dns_type where type = 1) dt on dt.ip = sc.ip and dt.epoch = sc.epoch
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ sc.ip = #{params.ip}
+ </if>
+ </where>
+ order by sc.epoch desc,sc.`time` desc LIMIT #{params.offset},#{params.limit}
+ ) sc
+
+ left join ip_information ii on sc.ip = ii.ip
+ left join vulnerability v on sc.component = v.component
+ </select>
+
+ <select id="getCountByDnsType" resultType="java.lang.Integer">
+ select count(1) from
+ (select id,ip,epoch from scan_result sr
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ sr.ip = #{params.ip}
+ </if>
+ </where>
+ ) sc
+ join ( select d.id,d.ip,d.epoch from dns_type d where d.type = #{dnsType}) dt
+ on dt.ip = sc.ip AND dt.epoch = sc.epoch
+
+
+ </select>
+
+ <select id="getIndependentIpNum" resultType="java.lang.Integer">
+ select count(distinct sc.ip)
+ from ( select id,ip,epoch from scan_result sr
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ ip = #{params.ip}
+ </if>
+ </where>
+ ) sc
+ join (select ip, epoch from dns_type d where d.type = #{dnsType})
+ dt on dt.ip = sc.ip and dt.epoch = sc.epoch
+
+ </select>
+
+ <select id="selectScanResultCountByUnion" resultType="java.lang.Integer">
+ select count(1) count
+ from (
+ select da.ip
+ from (select count(1), d.ip from doh_attribute d
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ </where>
+ group by d.ip) da
+ JOIN scan_result s on da.ip = s.ip
+ ) dip
+ join scan_result sc on sc.ip = dip.ip
+ </select>
+
+ <select id="selectScanResultByUnion" resultMap="do53Map">
+ SELECT sc.*,
+ ii.country ii_country, ii.provider ii_provider,
+ ii.city ii_city, ii.asnumber ii_asnumber, ii.isp ii_isp,
+ ii.province ii_province,ii.zipcode ii_zipcode,
+ ii.district ii_district,
+ dt.type dnsType, v.`vulnerability` v_vulnerability
+ from (
+ select da.ip
+ from (select count(1), d.ip from doh_attribute d
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ </where>
+ group by d.ip) da
+ JOIN scan_result s on da.ip = s.ip
+ ) dip
+
+ join scan_result sc on sc.ip = dip.ip
+ left join ip_information ii on ii.ip = dip.ip
+ left join vulnerability v on v.component = sc.component
+ left join dns_type dt ON dt.ip = sc.ip AND dt.`epoch` = sc.`epoch`
+ order by sc.`time` desc
+ LIMIT #{params.offset},#{params.limit}
+ </select>
+
+ <select id="getDohAndDo53SrvCategoryCount" resultType="java.util.Map">
+ SELECT dt.type, COUNT(distinct da.ip) count
+ FROM (select count(1),d.ip from doh_attribute d
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ d.ip = #{params.ip}
+ </if>
+ <if test="params.port != null and params.port != ''">
+ and d.`port` = #{params.port}
+ </if>
+ </where>
+ group by d.ip
+ ) da
+ JOIN scan_result s on da.ip = s.ip
+ JOIN `dns_type` dt ON da.ip = dt.ip and dt.type > 0
+
+ GROUP BY dt.type
+ </select>
+
+ <select id="getDo53ProvinceCountByDnsType" resultType="java.util.Map">
+ select s.`province`,COUNT(distinct s.ip) count from
+ (SELECT s.ip,ii.province FROM `scan_result` s
+ JOIN `ip_information` ii ON s.ip = ii.ip
+ where ii.province IS NOT NULL AND ii.province !=''
+ <if test="params.ip != null and params.ip != ''">
+ AND s.ip = #{params.ip}
+ </if>
+ ) s
+ join dns_type dt on s.ip = dt.ip
+ where dt.type = #{dnsType}
+ GROUP BY s.province
+ </select>
+
+ <select id="getDo53ProviderCountByDnsType" resultType="java.util.Map">
+ SELECT
+ s.`provider`,COUNT(distinct s.ip) count
+ FROM ( SELECT ii.`provider`,s.ip
+ FROM `scan_result` s
+ JOIN `ip_information` ii
+ ON s.ip = ii.ip AND provider IS NOT NULL AND provider !=''
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ s.ip = #{params.ip}
+ </if>
+ </where>
+ ) s
+ JOIN dns_type dt on dt.ip = s.ip
+ <if test="dnsType != null and dnsType != ''">
+ AND dt.type = #{dnsType}
+ </if>
+ GROUP BY s.provider
+ </select>
+
+ <select id="getDo53ComponentCountByDnsType" resultType="java.util.Map">
+ select s.component,COUNT(distinct s.ip) count
+ from (
+ SELECT s.component, s.ip FROM `scan_result` s
+ where
+ component IS NOT NULL AND component !=''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ ) s
+ JOIN (SELECT ip from dns_type where type = #{dnsType}) dt on s.ip = dt.ip
+ GROUP BY s.component
+ </select>
+
+ <select id="getDo53SrvCategoryCountByDnsType" resultType="java.lang.Integer">
+ SELECT COUNT(a1.ip) count FROM (
+ SELECT s.ip,dt.type FROM `scan_result` s
+ JOIN `dns_type` dt ON s.ip=dt.ip
+ where dt.type = #{dnsType}
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ ) a1
+ GROUP BY a1.type
+ </select>
+
+ <select id="getDo53VulnerabCountByDnsType" resultType="java.util.Map">
+ SELECT vulnerability,COUNT(a1.ip) count FROM (
+ SELECT s.ip
+ ,v.`vulnerability`
+ FROM `scan_result` s
+ JOIN `vulnerability` v ON v.`component` = s.`component`
+ where vulnerability IS NOT NULL AND vulnerability !=''
+ <if test="params.ip != null and params.ip != ''">
+ and s.ip = #{params.ip}
+ </if>
+ ) a1
+ JOIN dns_type dt on a1.ip = dt.ip and dt.type = #{dnsType}
+ GROUP BY a1.vulnerability
+ </select>
+
+
+</mapper>
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml
new file mode 100644
index 0000000..f4a0047
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.example.modules.dns.mapper.IpInformationDao">
+
+ <resultMap id="ipMap" type="com.example.modules.dns.domain.IpInformation">
+ <id property="id" column="id"/>
+ <id property="ip" column="ip"/>
+ <result property="country" column="country"/>
+ <result property="province" column="province"/>
+ <result property="city" column="city"/>
+ <result property="district" column="district"/>
+ <result property="provider" column="provider"/>
+ <result property="isp" column="isp"/>
+ <result property="asnumber" column="asnumber"/>
+ <result property="timestamp" column="timestamp"/>
+ <result property="zipcode" column="zipcode"/>
+ <result property="timezone" column="timezone"/>
+
+ <association property="dnsType" columnPrefix="dt_" javaType="com.example.modules.dns.domain.DnsType">
+ <id property="id" column="id"/>
+ <id property="ip" column="ip"/>
+ <result property="type" column="type"/>
+ </association>
+
+ <collection property="ipCert" columnPrefix="ic_" ofType="com.example.modules.dns.domain.IpCert">
+ <id property="id" column="id"/>
+ <id property="ip" column="ip"/>
+ <result property="port" column="port"/>
+ <result property="certificate" column="certificate"/>
+ <result property="ca" column="ca"/>
+ <result property="timestamp" column="timestamp"/>
+ </collection>
+
+ <collection property="dohAttribute" columnPrefix="da_" ofType="com.example.modules.dns.domain.DohAttribute">
+ <id property="ip" column="ip"/>
+ <result property="host" column="host"/>
+ <result property="port" column="port"/>
+ <result property="path" column="path"/>
+ <result property="method" column="method"/>
+ <result property="connectType" column="connect_type"/>
+ <result property="statusCode" column="status_code"/>
+ <result property="repHeader" column="rep_header"/>
+ <result property="repBody" column="rep_body"/>
+ <result property="timestamp" column="timestamp"/>
+ <result property="component" column="component"/>
+ </collection>
+
+ </resultMap>
+
+
+
+ <select id="queryIpPage" resultMap="ipMap">
+ SELECT ii.*
+-- ,ic.certificate ic_certificate ,ic.ca ic_ca
+ ,da.host da_host , da.rep_body da_rep_body , da.status_code da_status_code ,da.component da_component,da.path da_path
+ FROM `ip_information` ii
+-- LEFT JOIN `ip_cert` ic ON ii.ip = ic.ip
+ left join doh_attribute da on ii.ip = da.ip
+
+ <where>
+ <if test="params.ip != null and params.ip != ''">
+ and ii.ip = #{params.ip}
+ </if>
+ </where>
+
+ </select>
+ <select id="getIpInfoByFwd" resultType="ipInformation">
+ select ii.* from ip_information ii
+ join (SELECT fd.upstream from forward_dns fd where fd.forwarder = #{ip}
+ <if test="epoch != '' and epoch != null ">
+ and fd.epoch = #{epoch}
+ </if>
+ ) fw
+ on fw.upstream = ii.ip
+ </select>
+
+</mapper>
diff --git a/UI source code/dns-dev-2.0/pom.xml b/UI source code/dns-dev-2.0/pom.xml
new file mode 100644
index 0000000..84d1b52
--- /dev/null
+++ b/UI source code/dns-dev-2.0/pom.xml
@@ -0,0 +1,266 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.example</groupId>
+ <artifactId>dns</artifactId>
+ <packaging>pom</packaging>
+ <version>2.6</version>
+
+ <modules>
+ <module>dns-common</module>
+ <module>dns-logging</module>
+ <module>dns-system</module>
+ </modules>
+
+ <name>DNS测绘</name>
+ <url>https://el-admin.vip</url>
+
+ <parent>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>2.2.10.RELEASE</version>
+ </parent>
+
+ <properties>
+ <log4j2.version>2.17.0</log4j2.version>
+ <logback.version>1.2.9</logback.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <java.version>1.8</java.version>
+ <log4jdbc.version>1.16</log4jdbc.version>
+ <swagger.version>2.9.2</swagger.version>
+ <fastjson.version>1.2.70</fastjson.version>
+ <druid.version>1.1.24</druid.version>
+ <commons-pool2.version>2.5.0</commons-pool2.version>
+ <mapstruct.version>1.3.1.Final</mapstruct.version>
+ <mybatisplus.version>3.0.7.1</mybatisplus.version>
+ </properties>
+
+ <dependencies>
+<!-- mybatis-plus-->
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>${mybatisplus.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-generator</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!--Spring boot 核心-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+
+ <!--Spring boot Web容器-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+
+ </dependency>
+
+ <!--Spring boot 测试-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!--Spring boot 安全框架-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+
+ <!-- spring boot 缓存 -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-cache</artifactId>
+ </dependency>
+
+ <!--Spring boot Redis-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+
+ <!--spring boot 集成redis所需common-pool2-->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>${commons-pool2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+
+ <!--监控sql日志-->
+ <dependency>
+ <groupId>org.bgee.log4jdbc-log4j2</groupId>
+ <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
+ <version>${log4jdbc.version}</version>
+ </dependency>
+
+ <!-- Swagger UI 相关 -->
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ <version>${swagger.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-models</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ <version>${swagger.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <version>1.5.21</version>
+ </dependency>
+ <dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-models</artifactId>
+ <version>1.5.21</version>
+ </dependency>
+
+ <!--Mysql依赖包-->
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!-- druid数据源驱动 -->
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>${druid.version}</version>
+ </dependency>
+
+ <!-- ip2region IP库 -->
+ <dependency>
+ <groupId>net.dreamlu</groupId>
+ <artifactId>mica-ip2region</artifactId>
+ <version>2.5.6</version>
+ </dependency>
+
+
+ <!--lombok插件-->
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <!-- excel工具 -->
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi</artifactId>
+ <version>3.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-ooxml</artifactId>
+ <version>3.17</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.12.2</version>
+ </dependency>
+
+ <!-- fastjson -->
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ <version>${fastjson.version}</version>
+ </dependency>
+
+ <!--mapStruct依赖-->
+ <dependency>
+ <groupId>org.mapstruct</groupId>
+ <artifactId>mapstruct</artifactId>
+ <version>${mapstruct.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mapstruct</groupId>
+ <artifactId>mapstruct-processor</artifactId>
+ <version>${mapstruct.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ <version>1</version>
+ </dependency>
+
+ <!-- Java图形验证码 -->
+ <dependency>
+ <groupId>com.github.whvcse</groupId>
+ <artifactId>easy-captcha</artifactId>
+ <version>1.6.2</version>
+ </dependency>
+
+ <!-- 解析客户端操作系统、浏览器信息 -->
+ <dependency>
+ <groupId>nl.basjes.parse.useragent</groupId>
+ <artifactId>yauaa</artifactId>
+ <version>5.23</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- 打包时跳过测试 -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>public</id>
+ <name>aliyun nexus</name>
+ <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </repository>
+ </repositories>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>public</id>
+ <name>aliyun nexus</name>
+ <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+</project>
diff --git a/UI source code/dns-dev-2.0/sql/DiamondV.sql b/UI source code/dns-dev-2.0/sql/DiamondV.sql
new file mode 100644
index 0000000..cfb1dea
--- /dev/null
+++ b/UI source code/dns-dev-2.0/sql/DiamondV.sql
@@ -0,0 +1,1059 @@
+/*
+SQLyog Ultimate v13.1.1 (64 bit)
+MySQL - 5.7.30-log : Database - eladmin
+*********************************************************************
+*/
+
+/*!40101 SET NAMES utf8 */;
+
+/*!40101 SET SQL_MODE=''*/;
+
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+CREATE DATABASE /*!32312 IF NOT EXISTS*/`diamondv` /*!40100 DEFAULT CHARACTER SET utf8 */;
+
+USE `diamondv`;
+
+
+/*Table structure for table `code_column_config` */
+
+DROP TABLE IF EXISTS `code_column_config`;
+
+CREATE TABLE `code_column_config` (
+ `column_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `table_name` varchar(255) DEFAULT NULL,
+ `column_name` varchar(255) DEFAULT NULL,
+ `column_type` varchar(255) DEFAULT NULL,
+ `dict_name` varchar(255) DEFAULT NULL,
+ `extra` varchar(255) DEFAULT NULL,
+ `form_show` bit(1) DEFAULT NULL,
+ `form_type` varchar(255) DEFAULT NULL,
+ `key_type` varchar(255) DEFAULT NULL,
+ `list_show` bit(1) DEFAULT NULL,
+ `not_null` bit(1) DEFAULT NULL,
+ `query_type` varchar(255) DEFAULT NULL,
+ `remark` varchar(255) DEFAULT NULL,
+ `date_annotation` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`column_id`) USING BTREE,
+ KEY `idx_table_name` (`table_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='代码生成字段信息存储';
+
+/*Data for the table `code_column_config` */
+
+/*Table structure for table `code_gen_config` */
+
+DROP TABLE IF EXISTS `code_gen_config`;
+
+CREATE TABLE `code_gen_config` (
+ `config_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `table_name` varchar(255) DEFAULT NULL COMMENT '表名',
+ `author` varchar(255) DEFAULT NULL COMMENT '作者',
+ `cover` bit(1) DEFAULT NULL COMMENT '是否覆盖',
+ `module_name` varchar(255) DEFAULT NULL COMMENT '模块名称',
+ `pack` varchar(255) DEFAULT NULL COMMENT '至于哪个包下',
+ `path` varchar(255) DEFAULT NULL COMMENT '前端代码生成的路径',
+ `api_path` varchar(255) DEFAULT NULL COMMENT '前端Api文件路径',
+ `prefix` varchar(255) DEFAULT NULL COMMENT '表前缀',
+ `api_alias` varchar(255) DEFAULT NULL COMMENT '接口名称',
+ PRIMARY KEY (`config_id`) USING BTREE,
+ KEY `idx_table_name` (`table_name`(100))
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='代码生成器配置';
+
+/*Data for the table `code_gen_config` */
+
+/*Table structure for table `component` */
+
+DROP TABLE IF EXISTS `component`;
+
+CREATE TABLE `component` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `component` varchar(128) DEFAULT NULL,
+ `vulnerability` varchar(128) DEFAULT NULL,
+ `timestamp` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+/*Data for the table `component` */
+
+/*Table structure for table `dns_type` */
+
+DROP TABLE IF EXISTS `dns_type`;
+
+CREATE TABLE `dns_type` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ip` varchar(128) DEFAULT NULL,
+ `type` tinyint(4) DEFAULT NULL,
+ `epoch` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
+
+/*Data for the table `dns_type` */
+
+insert into `dns_type`(`id`,`ip`,`type`,`epoch`) values
+(1,'1.1.1.1',1,2),
+(2,'2.2.2.2',2,2),
+(3,'3.3.3.3',3,2),
+(4,'4.4.4.4',4,2),
+(5,'5.5.5.5',5,2),
+(6,'6.6.6.6',1,2),
+(7,'7.7.7.7',1,2),
+(8,'1.1.1.1',3,1),
+(9,'2.2.2.2',5,1);
+
+/*Table structure for table `doh_attribute` */
+
+DROP TABLE IF EXISTS `doh_attribute`;
+
+CREATE TABLE `doh_attribute` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ip` varchar(128) DEFAULT NULL,
+ `port` int(11) DEFAULT NULL,
+ `host` varchar(128) DEFAULT NULL,
+ `path` varchar(128) DEFAULT NULL,
+ `method` varchar(4) DEFAULT NULL,
+ `connect_type` int(11) DEFAULT NULL,
+ `status_code` int(11) DEFAULT NULL,
+ `rep_header` varchar(2048) DEFAULT NULL,
+ `rep_body` varchar(1024) DEFAULT NULL,
+ `timestamp` datetime DEFAULT NULL,
+ `component` varchar(128) DEFAULT NULL,
+ `rounds` tinyint(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `idx_ip` (`ip`)
+) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
+
+/*Data for the table `doh_attribute` */
+
+insert into `doh_attribute`(`id`,`ip`,`port`,`host`,`path`,`method`,`connect_type`,`status_code`,`rep_header`,`rep_body`,`timestamp`,`component`,`rounds`) values
+(1,'1.1.1.1',8443,'192.168.32.46','/test1','post',1,200,'{head1}','{body1}','2022-05-12 14:59:11','nginx',2),
+(2,'2.2.2.2',8443,'192.168.77.88','/test2','get',2,400,'{head}','{erro}','2022-05-11 15:00:02','bind',2),
+(3,'3.3.3.3',8443,'192.168.74.32','/test3','post',1,404,'{head}','{not found}','2022-04-10 15:00:52','nginx',2),
+(4,'1.1.1.1',8443,'192.168.32.46','/test4','get',1,200,'{head2}','{body2}','2022-05-09 11:56:55','bind',2),
+(5,'1.1.1.1',443,'192.168.32.47','/test1','post',1,200,'{head1}','{body1}','2022-05-08 16:58:48','nginx',2),
+(6,'4.4.4.4',443,'192.168.1.1','/test4','get',1,200,'{head4}','{body4}','2022-05-07 14:37:43','bind',2),
+(7,'5.5.5.5',443,'192.168.5.5','/test5','del',3,500,'{head5}','{body5}','2022-05-06 14:38:40','nginx',2),
+(8,'6.6.6.6',443,'192.168.5.6','/test6','get',3,500,'{head6}','{body6}','2022-05-05 09:06:47','bind',2),
+(9,'2.2.2.2',443,'192.168.77.88','/test2','get',2,400,'{head}','{erro}','2022-04-01 14:21:42','bind',1),
+(10,'3.3.3.3',443,'192.168.74.31','/test3','post',1,404,'{head}','{not found}','2022-04-01 14:22:31','bind',1),
+(11,'7.7.7.7',443,'192.168.77.77','/test7','post',1,404,'{head}','{not found}','2022-05-06 16:53:13','bind',2),
+(12,'8.8.8.8',443,'192.168.88.88','/test8','post',1,404,'{head}','{not found}','2022-05-06 16:54:53','nginx',2),
+(13,'9.9.9.9',443,'192.168.99.99','/test9','post',1,404,'{head}','{not found}','2022-05-06 16:54:59','nginx',2),
+(14,'9.9.9.8',443,'192.168.99.98','/test98','post',1,404,'{head}','{not found}','2022-05-06 16:55:28','nginx',2),
+(15,'9.9.9.7',443,'192.168.99.97','/test97','post',1,404,'{head}','{not found}','2022-05-13 16:59:18',NULL,2);
+
+/*Table structure for table `forward_dns` */
+
+DROP TABLE IF EXISTS `forward_dns`;
+
+CREATE TABLE `forward_dns` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `forwarder` varchar(128) DEFAULT NULL,
+ `upstream` varchar(128) DEFAULT NULL,
+ `epoch` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
+
+/*Data for the table `forward_dns` */
+
+insert into `forward_dns`(`id`,`forwarder`,`upstream`,`epoch`) values
+(1,'1.1.1.1','2.2.2.2',2),
+(2,'2.2.2.2','1.1.1.1',2),
+(3,'2.2.2.2','2.2.2.2',2),
+(4,'3.3.3.3','4.4.4.4',2),
+(5,'1.1.1.1','5.5.5.5',1),
+(6,'2.2.2.2','6.6.6.6',1);
+
+/*Table structure for table `ip_cert` */
+
+DROP TABLE IF EXISTS `ip_cert`;
+
+CREATE TABLE `ip_cert` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ip` varchar(128) DEFAULT NULL,
+ `port` int(11) DEFAULT NULL,
+ `certificate` varchar(5120) DEFAULT NULL,
+ `ca` varchar(128) DEFAULT NULL,
+ `timestamp` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `idx_ip` (`ip`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
+
+/*Data for the table `ip_cert` */
+
+insert into `ip_cert`(`id`,`ip`,`port`,`certificate`,`ca`,`timestamp`) values
+(1,'1.1.1.1',8443,'t1证书','t1证书颁发者','2022-04-27 15:01:33'),
+(2,'2.2.2.2',8443,'t2证书','t2证书颁发者','2022-04-27 15:01:49'),
+(3,'3.3.3.3',8443,'t3证书','t3证书颁发者','2022-04-27 15:02:01'),
+(4,'1.1.1.1',8443,'t1证书2','t1证书颁发者2','2022-05-06 09:03:22'),
+(5,'2.2.2.2',443,'t2证书443','t2证书颁发者443','2022-05-18 13:51:00'),
+(6,'3.3.3.3',443,'t3证书443','t3证书颁发者443','2022-05-18 13:51:01');
+
+/*Table structure for table `ip_information` */
+
+DROP TABLE IF EXISTS `ip_information`;
+
+CREATE TABLE `ip_information` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ip` varchar(128) DEFAULT NULL,
+ `country` varchar(50) DEFAULT NULL,
+ `province` varchar(50) DEFAULT NULL,
+ `city` varchar(50) DEFAULT NULL,
+ `district` varchar(50) DEFAULT NULL,
+ `provider` varchar(50) DEFAULT NULL,
+ `isp` varchar(50) DEFAULT NULL,
+ `asnumber` int(11) DEFAULT NULL,
+ `timestamp` datetime DEFAULT NULL,
+ `zipcode` varchar(50) DEFAULT NULL,
+ `timezone` varchar(50) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `idx_ip` (`ip`)
+) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
+
+/*Data for the table `ip_information` */
+
+insert into `ip_information`(`id`,`ip`,`country`,`province`,`city`,`district`,`provider`,`isp`,`asnumber`,`timestamp`,`zipcode`,`timezone`) values
+(1,'1.1.1.1','中国','河北','邢台','1','华为','华为',123456789,'2022-04-27 14:55:00','100000','UTC'),
+(2,'2.2.2.2','哥伦比亚','德克萨斯州','纽约','2','特斯拉','特斯拉',987654321,'2022-04-27 14:56:27','500000','USA'),
+(3,'3.3.3.3','刚果','伦敦省','伦敦市','3','长安','长安',741852963,'2022-04-27 14:57:31','800000','UK'),
+(4,'4.4.4.4','日本','北京','怀柔','4','烤鸭','烤鸭',8888888,'2022-04-28 11:16:40','100010','UTC'),
+(5,'5.5.5.5','韩国','河南','郑州','5','三星','三星',55555555,'2022-05-06 14:39:53','100010','UTC'),
+(6,'6.6.6.6','英国','河北','石家庄','5','苹果','苹果',666666,'2022-05-13 14:25:55','100010','UTC'),
+(7,'7.7.7.7','法国','江苏','南京','5','移动','移动',77777777,'2022-05-13 14:30:16','100010','UTC'),
+(8,'8.8.8.8','德国','柏林','柏林',NULL,'运营商1','运营商1',8888888,'2022-05-17 16:58:06','100010',NULL),
+(9,'9.9.9.9','瑞典','斯德哥尔摩','斯德哥尔摩',NULL,'运营商2','运营商2',999999,'2022-05-17 16:58:10','100010',NULL),
+(10,'9.9.9.8','丹麦','哥本哈根','哥本哈根',NULL,'运营商3','运营商3',9999998,'2022-05-17 16:58:12','100010',NULL),
+(11,'9.9.9.7','意大利','罗马','罗马',NULL,'运营商4','运营商4',333333,'2022-05-17 16:59:55',NULL,NULL);
+
+/*Table structure for table `mnt_app` */
+
+DROP TABLE IF EXISTS `mnt_app`;
+
+CREATE TABLE `mnt_app` (
+ `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) DEFAULT NULL COMMENT '应用名称',
+ `upload_path` varchar(255) DEFAULT NULL COMMENT '上传目录',
+ `deploy_path` varchar(255) DEFAULT NULL COMMENT '部署路径',
+ `backup_path` varchar(255) DEFAULT NULL COMMENT '备份路径',
+ `port` int(255) DEFAULT NULL COMMENT '应用端口',
+ `start_script` varchar(4000) DEFAULT NULL COMMENT '启动脚本',
+ `deploy_script` varchar(4000) DEFAULT NULL COMMENT '部署脚本',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`app_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='应用管理';
+
+/*Data for the table `mnt_app` */
+
+/*Table structure for table `mnt_database` */
+
+DROP TABLE IF EXISTS `mnt_database`;
+
+CREATE TABLE `mnt_database` (
+ `db_id` varchar(50) NOT NULL COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '名称',
+ `jdbc_url` varchar(255) NOT NULL COMMENT 'jdbc连接',
+ `user_name` varchar(255) NOT NULL COMMENT '账号',
+ `pwd` varchar(255) NOT NULL COMMENT '密码',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`db_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='数据库管理';
+
+/*Data for the table `mnt_database` */
+
+/*Table structure for table `mnt_deploy` */
+
+DROP TABLE IF EXISTS `mnt_deploy`;
+
+CREATE TABLE `mnt_deploy` (
+ `deploy_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `app_id` bigint(20) DEFAULT NULL COMMENT '应用编号',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`deploy_id`) USING BTREE,
+ KEY `FK6sy157pseoxx4fmcqr1vnvvhy` (`app_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='部署管理';
+
+/*Data for the table `mnt_deploy` */
+
+/*Table structure for table `mnt_deploy_history` */
+
+DROP TABLE IF EXISTS `mnt_deploy_history`;
+
+CREATE TABLE `mnt_deploy_history` (
+ `history_id` varchar(50) NOT NULL COMMENT 'ID',
+ `app_name` varchar(255) NOT NULL COMMENT '应用名称',
+ `deploy_date` datetime NOT NULL COMMENT '部署日期',
+ `deploy_user` varchar(50) NOT NULL COMMENT '部署用户',
+ `ip` varchar(20) NOT NULL COMMENT '服务器IP',
+ `deploy_id` bigint(20) DEFAULT NULL COMMENT '部署编号',
+ PRIMARY KEY (`history_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='部署历史管理';
+
+/*Data for the table `mnt_deploy_history` */
+
+/*Table structure for table `mnt_deploy_server` */
+
+DROP TABLE IF EXISTS `mnt_deploy_server`;
+
+CREATE TABLE `mnt_deploy_server` (
+ `deploy_id` bigint(20) NOT NULL COMMENT '部署ID',
+ `server_id` bigint(20) NOT NULL COMMENT '服务ID',
+ PRIMARY KEY (`deploy_id`,`server_id`) USING BTREE,
+ KEY `FKeaaha7jew9a02b3bk9ghols53` (`server_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='应用与服务器关联';
+
+/*Data for the table `mnt_deploy_server` */
+
+/*Table structure for table `mnt_server` */
+
+DROP TABLE IF EXISTS `mnt_server`;
+
+CREATE TABLE `mnt_server` (
+ `server_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `account` varchar(50) DEFAULT NULL COMMENT '账号',
+ `ip` varchar(20) DEFAULT NULL COMMENT 'IP地址',
+ `name` varchar(100) DEFAULT NULL COMMENT '名称',
+ `password` varchar(100) DEFAULT NULL COMMENT '密码',
+ `port` int(11) DEFAULT NULL COMMENT '端口',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`server_id`) USING BTREE,
+ KEY `idx_ip` (`ip`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='服务器管理';
+
+/*Data for the table `mnt_server` */
+
+/*Table structure for table `nonstandard_dns` */
+
+DROP TABLE IF EXISTS `nonstandard_dns`;
+
+CREATE TABLE `nonstandard_dns` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ip` varchar(128) DEFAULT NULL,
+ `record` varchar(128) DEFAULT NULL,
+ `epoch` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
+
+/*Data for the table `nonstandard_dns` */
+
+insert into `nonstandard_dns`(`id`,`ip`,`record`,`epoch`) values
+(1,'1.1.1.1','aaaaa',2),
+(2,'1.1.1.1','vvvvv',2),
+(3,'2.2.2.2','22aaaa',2),
+(4,'3.3.3.3','33aaaaa',2),
+(5,'4.4.4.4','444aaaa',2),
+(6,'5.5.5.5','555aaaa',2);
+
+/*Table structure for table `scan_result` */
+
+DROP TABLE IF EXISTS `scan_result`;
+
+CREATE TABLE `scan_result` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ip` varchar(128) DEFAULT NULL,
+ `flags` int(11) DEFAULT NULL,
+ `opcode` tinyint(4) DEFAULT NULL,
+ `qr` tinyint(4) DEFAULT NULL,
+ `aa` tinyint(4) DEFAULT NULL,
+ `ra` tinyint(4) DEFAULT NULL,
+ `rcode` int(4) DEFAULT NULL,
+ `query_name` varchar(256) DEFAULT NULL,
+ `query_response` varchar(512) DEFAULT NULL,
+ `component` varchar(128) DEFAULT NULL,
+ `epoch` int(11) DEFAULT NULL,
+ `scan_type` tinyint(4) DEFAULT NULL,
+ `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
+
+/*Data for the table `scan_result` */
+
+insert into `scan_result`(`id`,`ip`,`flags`,`opcode`,`qr`,`aa`,`ra`,`rcode`,`query_name`,`query_response`,`component`,`epoch`,`scan_type`,`time`) values
+(1,'1.1.1.1',NULL,NULL,NULL,1,1,200,'1.1.1.1请求域名','1.1.1.1应答结果','bind',2,NULL,'2022-05-17 09:49:53'),
+(2,'2.2.2.2',NULL,NULL,NULL,2,2,400,'2.2.2.2请求域名','2.2.2.2应答结果','bind',2,NULL,'2022-05-16 16:26:15'),
+(3,'3.3.3.3',NULL,NULL,NULL,3,3,500,'3.3.3.3请求域名','3.3.3.3应答结果','bind',2,NULL,'2022-05-16 16:26:12'),
+(4,'4.4.4.4',NULL,NULL,NULL,4,4,404,'4.4.4.4请求域名','4.4.4.4应答结果','unbound',2,NULL,'2022-05-16 16:26:12'),
+(5,'5.5.5.5',NULL,NULL,NULL,5,5,500,'5.5.5.5请求域名','5.5.5.5应答结果','unbound',2,NULL,'2022-05-16 16:26:11'),
+(6,'1.1.1.1',NULL,NULL,NULL,3,4,404,'1.1.1.1请求域名2','1.1.1.1应答结果2','bind',2,NULL,'2022-05-16 16:26:11'),
+(7,'6.6.6.6',NULL,NULL,NULL,6,6,200,'6.6.6.6请求域名','6.6.6.6应答结果','bind',2,NULL,'2022-05-16 16:26:10'),
+(8,'7.7.7.7',NULL,NULL,NULL,7,7,400,'7.7.7.7请求域名','7.7.7.7请求域名','bind',2,NULL,'2022-05-16 16:26:09'),
+(9,'8.8.8.8',NULL,NULL,NULL,8,8,400,'8.8.8.8请求域名','8.8.8.8请求域名','bind',2,NULL,'2022-05-16 16:26:09'),
+(10,'9.9.9.9',NULL,NULL,NULL,9,9,400,'9.9.9.9请求域名','9.9.9.9请求域名','bind',2,NULL,'2022-05-16 16:26:08'),
+(11,'9.9.9.8',NULL,NULL,NULL,9,9,400,'9.9.9.9请求域名2','9.9.9.9请求域名2','bind',2,NULL,'2022-05-16 16:26:07'),
+(12,'9.9.9.7',NULL,NULL,NULL,9,9,400,'9.9.9.9请求域名3','9.9.9.9请求域名3','bind',2,NULL,'2022-05-16 16:26:07'),
+(13,'9.9.9.6',NULL,NULL,NULL,9,9,400,'9.9.9.9请求域名4','9.9.9.9请求域名4','bind',2,NULL,'2022-05-16 16:26:06'),
+(14,'1.1.1.1',NULL,NULL,NULL,1,1,200,'1.1.1.1请求域名2','9.9.9.9请求域名4','bind',1,NULL,'2022-05-16 16:26:04'),
+(15,'2.2.2.2',NULL,NULL,NULL,2,2,200,'2.2.2.2请求域名2','2.2.2.2请求域名2','bind',1,NULL,'2022-05-16 16:26:02');
+
+/*Table structure for table `sys_dept` */
+
+DROP TABLE IF EXISTS `sys_dept`;
+
+CREATE TABLE `sys_dept` (
+ `dept_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `pid` bigint(20) DEFAULT NULL COMMENT '上级部门',
+ `sub_count` int(5) DEFAULT '0' COMMENT '子部门数目',
+ `name` varchar(255) NOT NULL COMMENT '名称',
+ `dept_sort` int(5) DEFAULT '999' COMMENT '排序',
+ `enabled` bit(1) NOT NULL COMMENT '状态',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`dept_id`) USING BTREE,
+ KEY `inx_pid` (`pid`),
+ KEY `inx_enabled` (`enabled`)
+) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='部门';
+
+/*Data for the table `sys_dept` */
+
+insert into `sys_dept`(`dept_id`,`pid`,`sub_count`,`name`,`dept_sort`,`enabled`,`create_by`,`update_by`,`create_time`,`update_time`) values
+(2,7,1,'研发部',3,'','admin','admin','2019-03-25 09:15:32','2020-08-02 14:48:47'),
+(5,7,0,'运维部',4,'','admin','admin','2019-03-25 09:20:44','2020-05-17 14:27:27'),
+(6,8,0,'测试部',6,'','admin','admin','2019-03-25 09:52:18','2020-06-08 11:59:21'),
+(7,NULL,2,'华南分部',0,'','admin','admin','2019-03-25 11:04:50','2020-06-08 12:08:56'),
+(8,NULL,2,'华北分部',1,'','admin','admin','2019-03-25 11:04:53','2020-05-14 12:54:00'),
+(15,8,0,'UI部门',7,'','admin','admin','2020-05-13 22:56:53','2020-05-14 12:54:13'),
+(17,2,0,'研发一组',999,'','admin','admin','2020-08-02 14:49:07','2020-08-02 14:49:07');
+
+/*Table structure for table `sys_dict` */
+
+DROP TABLE IF EXISTS `sys_dict`;
+
+CREATE TABLE `sys_dict` (
+ `dict_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '字典名称',
+ `description` varchar(255) DEFAULT NULL COMMENT '描述',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`dict_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='数据字典';
+
+/*Data for the table `sys_dict` */
+
+insert into `sys_dict`(`dict_id`,`name`,`description`,`create_by`,`update_by`,`create_time`,`update_time`) values
+(1,'user_status','用户状态',NULL,NULL,'2019-10-27 20:31:36',NULL),
+(4,'dept_status','部门状态',NULL,NULL,'2019-10-27 20:31:36',NULL),
+(5,'job_status','岗位状态',NULL,NULL,'2019-10-27 20:31:36',NULL);
+
+/*Table structure for table `sys_dict_detail` */
+
+DROP TABLE IF EXISTS `sys_dict_detail`;
+
+CREATE TABLE `sys_dict_detail` (
+ `detail_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `dict_id` bigint(11) DEFAULT NULL COMMENT '字典id',
+ `label` varchar(255) NOT NULL COMMENT '字典标签',
+ `value` varchar(255) NOT NULL COMMENT '字典值',
+ `dict_sort` int(5) DEFAULT NULL COMMENT '排序',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`detail_id`) USING BTREE,
+ KEY `FK5tpkputc6d9nboxojdbgnpmyb` (`dict_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='数据字典详情';
+
+/*Data for the table `sys_dict_detail` */
+
+insert into `sys_dict_detail`(`detail_id`,`dict_id`,`label`,`value`,`dict_sort`,`create_by`,`update_by`,`create_time`,`update_time`) values
+(1,1,'激活','true',1,NULL,NULL,'2019-10-27 20:31:36',NULL),
+(2,1,'禁用','false',2,NULL,NULL,NULL,NULL),
+(3,4,'启用','true',1,NULL,NULL,NULL,NULL),
+(4,4,'停用','false',2,NULL,NULL,'2019-10-27 20:31:36',NULL),
+(5,5,'启用','true',1,NULL,NULL,NULL,NULL),
+(6,5,'停用','false',2,NULL,NULL,'2019-10-27 20:31:36',NULL);
+
+/*Table structure for table `sys_job` */
+
+DROP TABLE IF EXISTS `sys_job`;
+
+CREATE TABLE `sys_job` (
+ `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '岗位名称',
+ `enabled` bit(1) NOT NULL COMMENT '岗位状态',
+ `job_sort` int(5) DEFAULT NULL COMMENT '排序',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`job_id`) USING BTREE,
+ UNIQUE KEY `uniq_name` (`name`),
+ KEY `inx_enabled` (`enabled`)
+) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='岗位';
+
+/*Data for the table `sys_job` */
+
+insert into `sys_job`(`job_id`,`name`,`enabled`,`job_sort`,`create_by`,`update_by`,`create_time`,`update_time`) values
+(8,'人事专员','',3,NULL,NULL,'2019-03-29 14:52:28',NULL),
+(10,'产品经理','',4,NULL,NULL,'2019-03-29 14:55:51',NULL),
+(11,'全栈开发','',2,NULL,'admin','2019-03-31 13:39:30','2020-05-05 11:33:43'),
+(12,'软件测试','',5,NULL,'admin','2019-03-31 13:39:43','2020-05-10 19:56:26');
+
+/*Table structure for table `sys_log` */
+
+DROP TABLE IF EXISTS `sys_log`;
+
+CREATE TABLE `sys_log` (
+ `log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `description` varchar(255) DEFAULT NULL,
+ `log_type` varchar(255) DEFAULT NULL,
+ `method` varchar(255) DEFAULT NULL,
+ `params` text,
+ `request_ip` varchar(255) DEFAULT NULL,
+ `time` bigint(20) DEFAULT NULL,
+ `username` varchar(255) DEFAULT NULL,
+ `address` varchar(255) DEFAULT NULL,
+ `browser` varchar(255) DEFAULT NULL,
+ `exception_detail` text,
+ `create_time` datetime DEFAULT NULL,
+ PRIMARY KEY (`log_id`) USING BTREE,
+ KEY `log_create_time_index` (`create_time`),
+ KEY `inx_log_type` (`log_type`)
+) ENGINE=InnoDB AUTO_INCREMENT=3549 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统日志';
+
+/*Data for the table `sys_log` */
+
+insert into `sys_log`(`log_id`,`description`,`log_type`,`method`,`params`,`request_ip`,`time`,`username`,`address`,`browser`,`exception_detail`,`create_time`) values
+(3537,'修改用户','INFO','com.example.modules.system.rest.UserController.updateUser()','{\"gender\":\"男\",\"nickName\":\"测试\",\"roles\":[],\"jobs\":[{\"updateTime\":1589111786000,\"enabled\":true,\"jobSort\":5,\"updateBy\":\"admin\",\"createTime\":1554010783000,\"name\":\"软件测试\",\"id\":12}],\"avatarPath\":\"/Users/jie/Documents/work/me/admin/eladmin/~/avatar/avatar-20200806032259161.png\",\"updateTime\":1599273818000,\"dept\":{\"subCount\":0,\"name\":\"研发部\",\"id\":2},\"isAdmin\":false,\"enabled\":true,\"avatarName\":\"avatar-20200806032259161.png\",\"createBy\":\"admin\",\"phone\":\"19999999999\",\"pwdResetTime\":1588495111000,\"updateBy\":\"admin\",\"createTime\":1588648549000,\"id\":2,\"email\":\"[email protected]\",\"username\":\"test\"}','192.168.32.87',144,'admin','内网IP','Chrome 98.0.4758.102',NULL,'2022-04-24 11:18:20'),
+(3538,'新增用户','INFO','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"aaa\",\"roles\":[{\"level\":3,\"dataScope\":\"本级\",\"id\":2}],\"jobs\":[{\"id\":8}],\"updateTime\":1650790301429,\"dept\":{\"subCount\":0,\"id\":8},\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$39eu19DlibPMfC9EEPPErO86uBAZhCzySlhvSn/Evg0gdInNeNB3W\",\"createBy\":\"admin\",\"phone\":\"15014236547\",\"updateBy\":\"admin\",\"createTime\":1650790301429,\"id\":3,\"email\":\"[email protected]\",\"username\":\"test2\"}','192.168.32.87',171,'admin','内网IP','Chrome 98.0.4758.102',NULL,'2022-04-24 16:51:41'),
+(3539,'新增用户','ERROR','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"test3\",\"roles\":[{\"level\":3,\"dataScope\":\"本级\",\"id\":2}],\"jobs\":[{\"id\":8}],\"dept\":{\"subCount\":0,\"id\":7},\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$w8i0HM4aRHvCeVBg/KCx/O0kwDxrFDBpxvDX5ojBJ7xywJWEoDB6S\",\"phone\":\"15033669955\",\"email\":\"[email protected]\",\"username\":\"test3\"}','192.168.32.87',34422,'admin','内网IP','Chrome 98.0.4758.102','com.example.exception.EntityExistException: User with email [email protected] existed\r\n at com.example.modules.system.service.impl.UserServiceImpl.create(UserServiceImpl.java:90)\r\n at com.example.modules.system.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$5003e55c.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)\r\n at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$ea52fc62.create(<generated>)\r\n at com.example.modules.system.controller.UserController.createUser(UserController.java:109)\r\n at com.example.modules.system.controller.UserController$$FastClassBySpringCGLIB$$3a3729d2.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\r\n at com.example.aspect.LogAspect.logAround(LogAspect.java:68)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\r\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.controller.UserController$$EnhancerBySpringCGLIB$$9d3d2338.createUser(<generated>)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at com.example.modules.security.security.TokenFilter.doFilter(TokenFilter.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\r\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n at java.lang.Thread.run(Thread.java:748)\r\n','2022-04-24 16:59:29'),
+(3540,'修改用户','INFO','com.example.modules.system.controller.UserController.updateUser()','{\"gender\":\"男\",\"nickName\":\"管理员\",\"roles\":[],\"jobs\":[{\"updateTime\":1588649623000,\"enabled\":true,\"jobSort\":2,\"updateBy\":\"admin\",\"createTime\":1554010770000,\"name\":\"全栈开发\",\"id\":11}],\"avatarPath\":\"/Users/jie/Documents/work/me/admin/eladmin/~/avatar/avatar-20200806032259161.png\",\"updateTime\":1599273811000,\"dept\":{\"subCount\":0,\"name\":\"研发部\",\"id\":2},\"isAdmin\":false,\"enabled\":true,\"avatarName\":\"avatar-20200806032259161.png\",\"phone\":\"18888888888\",\"pwdResetTime\":1588495111000,\"updateBy\":\"admin\",\"createTime\":1534986716000,\"id\":1,\"email\":\"[email protected]\",\"username\":\"admin\"}','192.168.32.87',52,'admin','内网IP','Chrome 98.0.4758.102',NULL,'2022-04-24 17:03:00'),
+(3541,'新增用户','INFO','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"xx\",\"roles\":[{\"level\":3,\"dataScope\":\"本级\",\"id\":2}],\"jobs\":[{\"id\":8}],\"updateTime\":1650793621130,\"dept\":{\"subCount\":0,\"id\":7},\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$NGkgAoFjWGUueMJ81409I.mAJXa2KHf9b9GwgWZOCN8TdL35lLigy\",\"createBy\":\"admin\",\"phone\":\"15044878963\",\"updateBy\":\"admin\",\"createTime\":1650793621130,\"id\":4,\"email\":\"[email protected]\",\"username\":\"xx\"}','192.168.32.87',166,'admin','内网IP','Chrome 98.0.4758.102',NULL,'2022-04-24 17:47:01'),
+(3542,'新增用户','ERROR','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"xxx\",\"isAdmin\":false,\"enabled\":true,\"phone\":\"15044878963\",\"email\":\"[email protected]\",\"username\":\"xxx\"}','192.168.32.87',5,'admin','内网IP','PostmanRuntime 7.28.4','java.lang.NullPointerException\r\n at com.example.modules.system.service.impl.RoleServiceImpl.findByRoles(RoleServiceImpl.java:158)\r\n at com.example.modules.system.service.impl.RoleServiceImpl$$FastClassBySpringCGLIB$$dc8a47d1.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687)\r\n at com.example.modules.system.service.impl.RoleServiceImpl$$EnhancerBySpringCGLIB$$9cac769b.findByRoles(<generated>)\r\n at com.example.modules.system.controller.UserController.checkLevel(UserController.java:191)\r\n at com.example.modules.system.controller.UserController.createUser(UserController.java:106)\r\n at com.example.modules.system.controller.UserController$$FastClassBySpringCGLIB$$3a3729d2.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\r\n at com.example.aspect.LogAspect.logAround(LogAspect.java:68)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\r\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.controller.UserController$$EnhancerBySpringCGLIB$$c18ababd.createUser(<generated>)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at com.example.modules.security.security.TokenFilter.doFilter(TokenFilter.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\r\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n at java.lang.Thread.run(Thread.java:748)\r\n','2022-04-24 17:49:17'),
+(3543,'新增用户','ERROR','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"xxx\",\"isAdmin\":false,\"enabled\":true,\"phone\":\"15044878963\",\"email\":\"[email protected]\",\"username\":\"xxx\"}','192.168.32.87',6,'admin','内网IP','PostmanRuntime 7.28.4','java.lang.NullPointerException\r\n at com.example.modules.system.service.impl.RoleServiceImpl.findByRoles(RoleServiceImpl.java:158)\r\n at com.example.modules.system.service.impl.RoleServiceImpl$$FastClassBySpringCGLIB$$dc8a47d1.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687)\r\n at com.example.modules.system.service.impl.RoleServiceImpl$$EnhancerBySpringCGLIB$$9cac769b.findByRoles(<generated>)\r\n at com.example.modules.system.controller.UserController.checkLevel(UserController.java:191)\r\n at com.example.modules.system.controller.UserController.createUser(UserController.java:106)\r\n at com.example.modules.system.controller.UserController$$FastClassBySpringCGLIB$$3a3729d2.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\r\n at com.example.aspect.LogAspect.logAround(LogAspect.java:68)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\r\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.controller.UserController$$EnhancerBySpringCGLIB$$c18ababd.createUser(<generated>)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at com.example.modules.security.security.TokenFilter.doFilter(TokenFilter.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\r\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n at java.lang.Thread.run(Thread.java:748)\r\n','2022-04-24 17:49:31'),
+(3544,'新增用户','ERROR','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"xxx\",\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$yT504iKWln9Oi9ETxlXYe.1emlR9hqIL.utpSTXWrx2iFW51oIyXq\",\"phone\":\"15044878963\",\"email\":\"[email protected]\",\"username\":\"xxx\"}','192.168.32.87',102,'admin','内网IP','PostmanRuntime 7.28.4','com.example.exception.EntityExistException: User with phone 15044878963 existed\r\n at com.example.modules.system.service.impl.UserServiceImpl.create(UserServiceImpl.java:93)\r\n at com.example.modules.system.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$5003e55c.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)\r\n at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$9777835f.create(<generated>)\r\n at com.example.modules.system.controller.UserController.createUser(UserController.java:109)\r\n at com.example.modules.system.controller.UserController$$FastClassBySpringCGLIB$$3a3729d2.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\r\n at com.example.aspect.LogAspect.logAround(LogAspect.java:68)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\r\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.controller.UserController$$EnhancerBySpringCGLIB$$1e21cf61.createUser(<generated>)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at com.example.modules.security.security.TokenFilter.doFilter(TokenFilter.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\r\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n at java.lang.Thread.run(Thread.java:748)\r\n','2022-04-24 17:52:01'),
+(3545,'新增用户','INFO','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"xxx\",\"updateTime\":1650793939421,\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$y6hqVUiy6YSLngBuK4v/weonLYkyuIltwG0HTUCMTuCNtnGkFsDpW\",\"createBy\":\"admin\",\"phone\":\"15044878962\",\"updateBy\":\"admin\",\"createTime\":1650793939421,\"id\":5,\"email\":\"[email protected]\",\"username\":\"xxx\"}','192.168.32.87',121,'admin','内网IP','PostmanRuntime 7.28.4',NULL,'2022-04-24 17:52:19'),
+(3546,'新增用户','INFO','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"ssss\",\"roles\":[{\"level\":3,\"dataScope\":\"本级\",\"id\":1}],\"jobs\":[{\"id\":8}],\"updateTime\":1650873057518,\"dept\":{\"subCount\":0,\"id\":7},\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$P.hvDg2NaJs/kYeLn15u4upYvYxbl4HB4ExNERrU1SM5EqTQF2Hae\",\"createBy\":\"admin\",\"phone\":\"15033698785\",\"updateBy\":\"admin\",\"createTime\":1650873057518,\"id\":6,\"email\":\"[email protected]\",\"username\":\"bbbb\"}','192.168.32.87',14796,'admin','内网IP','Chrome 98.0.4758.102',NULL,'2022-04-25 15:50:59'),
+(3547,'修改用户','ERROR','com.example.modules.system.controller.UserController.updateUser()','{\"gender\":\"男\",\"nickName\":\"ssss\",\"roles\":[{\"level\":3,\"dataScope\":\"本级\",\"id\":2}],\"jobs\":[{\"id\":8}],\"updateTime\":1650873058000,\"dept\":{\"subCount\":0,\"name\":\"华南分部\",\"id\":7},\"isAdmin\":false,\"enabled\":true,\"createBy\":\"admin\",\"phone\":\"15033698785\",\"updateBy\":\"admin\",\"createTime\":1650873058000,\"id\":6,\"email\":\"[email protected]\",\"username\":\"bbbb\"}','192.168.32.87',3,'admin','内网IP','Chrome 98.0.4758.102','org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet\r\n at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:281)\r\n at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)\r\n at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)\r\n at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\r\n at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)\r\n at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)\r\n at com.sun.proxy.$Proxy171.findByUserId(Unknown Source)\r\n at com.example.modules.system.service.impl.RoleServiceImpl.findByUsersId(RoleServiceImpl.java:153)\r\n at com.example.modules.system.service.impl.RoleServiceImpl$$FastClassBySpringCGLIB$$dc8a47d1.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687)\r\n at com.example.modules.system.service.impl.RoleServiceImpl$$EnhancerBySpringCGLIB$$d77f5b25.findByUsersId(<generated>)\r\n at com.example.modules.system.controller.UserController.checkLevel(UserController.java:190)\r\n at com.example.modules.system.controller.UserController.updateUser(UserController.java:118)\r\n at com.example.modules.system.controller.UserController$$FastClassBySpringCGLIB$$3a3729d2.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\r\n at com.example.aspect.LogAspect.logAround(LogAspect.java:68)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\r\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.controller.UserController$$EnhancerBySpringCGLIB$$111a6b16.updateUser(<generated>)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at com.example.modules.security.security.TokenFilter.doFilter(TokenFilter.java:89)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\r\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n at java.lang.Thread.run(Thread.java:748)\r\nCaused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet\r\n at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)\r\n at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)\r\n at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)\r\n at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)\r\n at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:67)\r\n at org.hibernate.loader.Loader.getResultSet(Loader.java:2341)\r\n at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2094)\r\n at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2056)\r\n at org.hibernate.loader.Loader.doQuery(Loader.java:953)\r\n at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:350)\r\n at org.hibernate.loader.Loader.doList(Loader.java:2887)\r\n at org.hibernate.loader.Loader.doList(Loader.java:2869)\r\n at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2701)\r\n at org.hibernate.loader.Loader.list(Loader.java:2696)\r\n at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338)\r\n at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2142)\r\n at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1163)\r\n at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:173)\r\n at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533)\r\n at org.hibernate.query.Query.getResultList(Query.java:165)\r\n at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:126)\r\n at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)\r\n at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)\r\n at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)\r\n at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:618)\r\n at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)\r\n at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)\r\n ... 122 more\r\nCaused by: java.sql.SQLSyntaxErrorException: Table \'eladmin.sys_users_roles\' doesn\'t exist\r\n at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)\r\n at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)\r\n at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1003)\r\n at net.sf.log4jdbc.sql.jdbcapi.PreparedStatementSpy.executeQuery(PreparedStatementSpy.java:780)\r\n at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:3240)\r\n at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeQuery(FilterEventAdapter.java:465)\r\n at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:3237)\r\n at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.executeQuery(PreparedStatementProxyImpl.java:181)\r\n at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:227)\r\n at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57)\r\n ... 150 more\r\n','2022-04-25 15:56:34'),
+(3548,'新增用户','ERROR','com.example.modules.system.controller.UserController.createUser()','{\"gender\":\"男\",\"nickName\":\"xxxcds\",\"roles\":[{\"level\":3,\"dataScope\":\"本级\",\"id\":1}],\"jobs\":[{\"id\":8}],\"updateTime\":1650873529243,\"dept\":{\"subCount\":0,\"id\":7},\"isAdmin\":false,\"enabled\":true,\"password\":\"$2a$10$960h5w5vd1RMOIdiBp24HO2squJKm0D0EsZN5yMbZ7SF6VJlkaihW\",\"createBy\":\"admin\",\"phone\":\"15032145698\",\"updateBy\":\"admin\",\"createTime\":1650873529243,\"id\":7,\"email\":\"[email protected]\",\"username\":\"ghjg\"}','192.168.32.87',97,'admin','内网IP','Chrome 98.0.4758.102','org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement\r\n at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:281)\r\n at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)\r\n at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:538)\r\n at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)\r\n at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)\r\n at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:633)\r\n at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:386)\r\n at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$adc982a6.create(<generated>)\r\n at com.example.modules.system.controller.UserController.createUser(UserController.java:109)\r\n at com.example.modules.system.controller.UserController$$FastClassBySpringCGLIB$$3a3729d2.invoke(<generated>)\r\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\r\n at com.example.aspect.LogAspect.logAround(LogAspect.java:68)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\r\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\r\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)\r\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)\r\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\r\n at com.example.modules.system.controller.UserController$$EnhancerBySpringCGLIB$$111a6b16.createUser(<generated>)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n at java.lang.reflect.Method.invoke(Method.java:498)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\r\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)\r\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at com.example.modules.security.security.TokenFilter.doFilter(TokenFilter.java:89)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)\r\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)\r\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)\r\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)\r\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\r\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n at java.lang.Thread.run(Thread.java:748)\r\nCaused by: org.hibernate.exception.SQLGrammarException: could not execute statement\r\n at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)\r\n at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)\r\n at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)\r\n at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)\r\n at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)\r\n at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)\r\n at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1357)\r\n at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:52)\r\n at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)\r\n at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)\r\n at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)\r\n at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)\r\n at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)\r\n at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)\r\n at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)\r\n at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1363)\r\n at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:454)\r\n at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3213)\r\n at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2381)\r\n at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)\r\n at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)\r\n at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)\r\n at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)\r\n at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)\r\n at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:534)\r\n ... 118 more\r\nCaused by: java.sql.SQLSyntaxErrorException: Table \'eladmin.sys_users_roles\' doesn\'t exist\r\n at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)\r\n at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)\r\n at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)\r\n at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)\r\n at net.sf.log4jdbc.sql.jdbcapi.PreparedStatementSpy.executeUpdate(PreparedStatementSpy.java:1080)\r\n at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:3253)\r\n at com.alibaba.druid.filter.FilterAdapter.preparedStatement_executeUpdate(FilterAdapter.java:1092)\r\n at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeUpdate(FilterEventAdapter.java:491)\r\n at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:3251)\r\n at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.executeUpdate(PreparedStatementProxyImpl.java:194)\r\n at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeUpdate(DruidPooledPreparedStatement.java:255)\r\n at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)\r\n ... 138 more\r\n','2022-04-25 15:58:49');
+
+/*Table structure for table `sys_menu` */
+
+DROP TABLE IF EXISTS `sys_menu`;
+
+CREATE TABLE `sys_menu` (
+ `menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `pid` bigint(20) DEFAULT NULL COMMENT '上级菜单ID',
+ `sub_count` int(5) DEFAULT '0' COMMENT '子菜单数目',
+ `type` int(11) DEFAULT NULL COMMENT '菜单类型',
+ `title` varchar(255) DEFAULT NULL COMMENT '菜单标题',
+ `name` varchar(255) DEFAULT NULL COMMENT '组件名称',
+ `component` varchar(255) DEFAULT NULL COMMENT '组件',
+ `menu_sort` int(5) DEFAULT NULL COMMENT '排序',
+ `icon` varchar(255) DEFAULT NULL COMMENT '图标',
+ `path` varchar(255) DEFAULT NULL COMMENT '链接地址',
+ `i_frame` bit(1) DEFAULT NULL COMMENT '是否外链',
+ `cache` bit(1) DEFAULT b'0' COMMENT '缓存',
+ `hidden` bit(1) DEFAULT b'0' COMMENT '隐藏',
+ `permission` varchar(255) DEFAULT NULL COMMENT '权限',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`menu_id`) USING BTREE,
+ UNIQUE KEY `uniq_title` (`title`),
+ UNIQUE KEY `uniq_name` (`name`),
+ KEY `inx_pid` (`pid`)
+) ENGINE=InnoDB AUTO_INCREMENT=117 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统菜单';
+
+/*Data for the table `sys_menu` */
+
+INSERT INTO `sys_menu` VALUES (1, NULL, 7, 0, '系统管理', NULL, NULL, 1, 'system', 'system', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-18 15:11:29', NULL);
+INSERT INTO `sys_menu` VALUES (2, 1, 3, 1, '用户管理', 'User', 'system/user/index', 2, 'peoples', 'user', b'0', b'0', b'0', 'user:list', NULL, NULL, '2018-12-18 15:14:44', NULL);
+INSERT INTO `sys_menu` VALUES (3, 1, 3, 1, '角色管理', 'Role', 'system/role/index', 3, 'role', 'role', b'0', b'0', b'0', 'roles:list', NULL, NULL, '2018-12-18 15:16:07', NULL);
+INSERT INTO `sys_menu` VALUES (5, 1, 3, 1, '菜单管理', 'Menu', 'system/menu/index', 5, 'menu', 'menu', b'0', b'0', b'0', 'menu:list', NULL, NULL, '2018-12-18 15:17:28', NULL);
+INSERT INTO `sys_menu` VALUES (6, NULL, 5, 0, '系统监控', NULL, NULL, 10, 'monitor', 'monitor', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-18 15:17:48', NULL);
+INSERT INTO `sys_menu` VALUES (7, 6, 0, 1, '操作日志', 'Log', 'monitor/log/index', 11, 'log', 'logs', b'0', b'1', b'0', NULL, NULL, 'admin', '2018-12-18 15:18:26', '2020-06-06 13:11:57');
+INSERT INTO `sys_menu` VALUES (9, 6, 0, 1, 'SQL监控', 'Sql', 'monitor/sql/index', 18, 'sqlMonitor', 'druid', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-18 15:19:34', NULL);
+INSERT INTO `sys_menu` VALUES (10, NULL, 5, 0, 'DNS研究', NULL, NULL, 50, 'zujian', 'components', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-19 13:38:16', NULL);
+INSERT INTO `sys_menu` VALUES (11, 10, 0, 1, '清华大学-NISL', 'Icons', 'components/icons/index', 51, 'icon', 'http://netsec.ccert.edu.cn/chs/', b'1', b'0', b'0', NULL, NULL, NULL, '2018-12-19 13:38:49', NULL);
+INSERT INTO `sys_menu` VALUES (14, 36, 0, 1, 'DNS审查', 'Email', 'tools/email/index', 32, 'email', 'email', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-27 10:13:09', NULL);
+INSERT INTO `sys_menu` VALUES (15, 10, 0, 1, 'APNIC', 'Editor', 'components/Editor', 52, 'fwb', 'https://blog.apnic.net/', b'1', b'0', b'0', NULL, NULL, NULL, '2018-12-27 11:58:25', NULL);
+INSERT INTO `sys_menu` VALUES (18, 36, 0, 1, 'DNS威胁', 'Storage', 'tools/storage/index', 34, 'qiniu', 'storage', b'0', b'0', b'0', 'storage:list', NULL, NULL, '2018-12-31 11:12:15', NULL);
+INSERT INTO `sys_menu` VALUES (19, 36, 0, 1, 'DNS集中性', 'AliPay', 'tools/aliPay/index', 35, 'alipay', 'aliPay', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-31 14:52:38', NULL);
+INSERT INTO `sys_menu` VALUES (21, NULL, 1, 0, '关于', NULL, '', 900, 'menu', 'nested', b'0', b'0', b'0', NULL, NULL, 'admin', '2019-01-04 16:22:03', '2020-06-21 17:27:35');
+INSERT INTO `sys_menu` VALUES (22, 21, 0, 1, '二级菜单1', '', 'nested/menu2/index', 999, 'menu', 'menu2-1', b'0', b'0', b'1', NULL, NULL, 'admin', '2019-01-04 16:23:29', '2020-06-21 17:27:20');
+INSERT INTO `sys_menu` VALUES (23, 21, 0, 1, 'MESA', NULL, 'nested/menu2/index', 999, 'menu', 'https://www.mesalab.cn/', b'1', b'0', b'0', NULL, NULL, NULL, '2019-01-04 16:23:57', NULL);
+INSERT INTO `sys_menu` VALUES (24, 22, 0, 1, '三级菜单1', 'Test', 'nested/menu1/menu1-1', 999, 'menu', 'menu1-1', b'0', b'0', b'1', NULL, NULL, NULL, '2019-01-04 16:24:48', NULL);
+INSERT INTO `sys_menu` VALUES (27, 22, 0, 1, '三级菜单2', NULL, 'nested/menu1/menu1-2', 999, 'menu', 'menu1-2', b'0', b'0', b'1', NULL, NULL, NULL, '2019-01-07 17:27:32', NULL);
+INSERT INTO `sys_menu` VALUES (28, 1, 3, 1, '任务调度', 'Timing', 'system/timing/index', 999, 'timing', 'timing', b'0', b'0', b'0', 'timing:list', NULL, NULL, '2019-01-07 20:34:40', NULL);
+INSERT INTO `sys_menu` VALUES (30, 36, 0, 1, '新型DNS协议', 'GeneratorIndex', 'generator/index', 37, 'dev', 'generator', b'0', b'1', b'0', NULL, NULL, NULL, '2019-01-11 15:45:55', NULL);
+INSERT INTO `sys_menu` VALUES (32, 6, 0, 1, '异常日志', 'ErrorLog', 'monitor/log/errorLog', 12, 'error', 'errorLog', b'0', b'0', b'0', NULL, NULL, NULL, '2019-01-13 13:49:03', NULL);
+INSERT INTO `sys_menu` VALUES (33, 10, 0, 1, '南加州大学-ANT Lab', 'Markdown', 'components/MarkDown', 53, 'markdown', 'https://ant.isi.edu/', b'1', b'0', b'0', NULL, NULL, NULL, '2019-03-08 13:46:44', NULL);
+INSERT INTO `sys_menu` VALUES (34, 10, 0, 1, '普林斯顿大学-Noise Lab', 'YamlEdit', 'components/YamlEdit', 54, 'dev', 'https://noise.cs.uchicago.edu/security.html', b'1', b'0', b'0', NULL, NULL, NULL, '2019-03-08 15:49:40', NULL);
+INSERT INTO `sys_menu` VALUES (35, 1, 3, 1, '部门管理', 'Dept', 'system/dept/index', 6, 'dept', 'dept', b'0', b'0', b'0', 'dept:list', NULL, NULL, '2019-03-25 09:46:00', NULL);
+INSERT INTO `sys_menu` VALUES (36, NULL, 7, 0, '专题报告', NULL, '', 30, 'sys-tools', 'sys-tools', b'0', b'0', b'0', NULL, NULL, NULL, '2019-03-29 10:57:35', NULL);
+INSERT INTO `sys_menu` VALUES (37, 1, 3, 1, '岗位管理', 'Job', 'system/job/index', 7, 'Steve-Jobs', 'job', b'0', b'0', b'0', 'job:list', NULL, NULL, '2019-03-29 13:51:18', NULL);
+INSERT INTO `sys_menu` VALUES (38, 36, 0, 1, '接口文档', 'Swagger', 'tools/swagger/index', 36, 'swagger', 'swagger2', b'0', b'0', b'1', NULL, NULL, NULL, '2019-03-29 19:57:53', NULL);
+INSERT INTO `sys_menu` VALUES (39, 1, 3, 1, '字典管理', 'Dict', 'system/dict/index', 8, 'dictionary', 'dict', b'0', b'0', b'0', 'dict:list', NULL, NULL, '2019-04-10 11:49:04', NULL);
+INSERT INTO `sys_menu` VALUES (41, 6, 0, 1, '在线用户', 'OnlineUser', 'monitor/online/index', 10, 'Steve-Jobs', 'online', b'0', b'0', b'0', NULL, NULL, NULL, '2019-10-26 22:08:43', NULL);
+INSERT INTO `sys_menu` VALUES (44, 2, 0, 2, '用户新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'user:add', NULL, NULL, '2019-10-29 10:59:46', NULL);
+INSERT INTO `sys_menu` VALUES (45, 2, 0, 2, '用户编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'user:edit', NULL, NULL, '2019-10-29 11:00:08', NULL);
+INSERT INTO `sys_menu` VALUES (46, 2, 0, 2, '用户删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'user:del', NULL, NULL, '2019-10-29 11:00:23', NULL);
+INSERT INTO `sys_menu` VALUES (48, 3, 0, 2, '角色创建', NULL, '', 2, '', '', b'0', b'0', b'0', 'roles:add', NULL, NULL, '2019-10-29 12:45:34', NULL);
+INSERT INTO `sys_menu` VALUES (49, 3, 0, 2, '角色修改', NULL, '', 3, '', '', b'0', b'0', b'0', 'roles:edit', NULL, NULL, '2019-10-29 12:46:16', NULL);
+INSERT INTO `sys_menu` VALUES (50, 3, 0, 2, '角色删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'roles:del', NULL, NULL, '2019-10-29 12:46:51', NULL);
+INSERT INTO `sys_menu` VALUES (52, 5, 0, 2, '菜单新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'menu:add', NULL, NULL, '2019-10-29 12:55:07', NULL);
+INSERT INTO `sys_menu` VALUES (53, 5, 0, 2, '菜单编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'menu:edit', NULL, NULL, '2019-10-29 12:55:40', NULL);
+INSERT INTO `sys_menu` VALUES (54, 5, 0, 2, '菜单删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'menu:del', NULL, NULL, '2019-10-29 12:56:00', NULL);
+INSERT INTO `sys_menu` VALUES (56, 35, 0, 2, '部门新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'dept:add', NULL, NULL, '2019-10-29 12:57:09', NULL);
+INSERT INTO `sys_menu` VALUES (57, 35, 0, 2, '部门编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'dept:edit', NULL, NULL, '2019-10-29 12:57:27', NULL);
+INSERT INTO `sys_menu` VALUES (58, 35, 0, 2, '部门删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'dept:del', NULL, NULL, '2019-10-29 12:57:41', NULL);
+INSERT INTO `sys_menu` VALUES (60, 37, 0, 2, '岗位新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'job:add', NULL, NULL, '2019-10-29 12:58:27', NULL);
+INSERT INTO `sys_menu` VALUES (61, 37, 0, 2, '岗位编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'job:edit', NULL, NULL, '2019-10-29 12:58:45', NULL);
+INSERT INTO `sys_menu` VALUES (62, 37, 0, 2, '岗位删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'job:del', NULL, NULL, '2019-10-29 12:59:04', NULL);
+INSERT INTO `sys_menu` VALUES (64, 39, 0, 2, '字典新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'dict:add', NULL, NULL, '2019-10-29 13:00:17', NULL);
+INSERT INTO `sys_menu` VALUES (65, 39, 0, 2, '字典编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'dict:edit', NULL, NULL, '2019-10-29 13:00:42', NULL);
+INSERT INTO `sys_menu` VALUES (66, 39, 0, 2, '字典删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'dict:del', NULL, NULL, '2019-10-29 13:00:59', NULL);
+INSERT INTO `sys_menu` VALUES (73, 28, 0, 2, '任务新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'timing:add', NULL, NULL, '2019-10-29 13:07:28', NULL);
+INSERT INTO `sys_menu` VALUES (74, 28, 0, 2, '任务编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'timing:edit', NULL, NULL, '2019-10-29 13:07:41', NULL);
+INSERT INTO `sys_menu` VALUES (75, 28, 0, 2, '任务删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'timing:del', NULL, NULL, '2019-10-29 13:07:54', NULL);
+INSERT INTO `sys_menu` VALUES (77, 18, 0, 2, '上传文件', NULL, '', 2, '', '', b'0', b'0', b'0', 'storage:add', NULL, NULL, '2019-10-29 13:09:09', NULL);
+INSERT INTO `sys_menu` VALUES (78, 18, 0, 2, '文件编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'storage:edit', NULL, NULL, '2019-10-29 13:09:22', NULL);
+INSERT INTO `sys_menu` VALUES (79, 18, 0, 2, '文件删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'storage:del', NULL, NULL, '2019-10-29 13:09:34', NULL);
+INSERT INTO `sys_menu` VALUES (80, 6, 0, 1, '服务监控', 'ServerMonitor', 'monitor/server/index', 14, 'codeConsole', 'server', b'0', b'0', b'0', 'monitor:list', NULL, 'admin', '2019-11-07 13:06:39', '2020-05-04 18:20:50');
+INSERT INTO `sys_menu` VALUES (82, 36, 0, 1, '生成配置', 'GeneratorConfig', 'generator/config', 33, 'dev', 'generator/config/:tableName', b'0', b'1', b'1', '', NULL, NULL, '2019-11-17 20:08:56', NULL);
+INSERT INTO `sys_menu` VALUES (83, 10, 0, 1, '图表库', 'Echarts', 'components/Echarts', 50, 'chart', 'echarts', b'0', b'1', b'1', '', NULL, NULL, '2019-11-21 09:04:32', NULL);
+INSERT INTO `sys_menu` VALUES (102, 97, 0, 2, '删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'deployHistory:del', NULL, NULL, '2019-11-17 09:32:48', NULL);
+INSERT INTO `sys_menu` VALUES (103, 92, 0, 2, '服务器新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'serverDeploy:add', NULL, NULL, '2019-11-17 11:08:33', NULL);
+INSERT INTO `sys_menu` VALUES (104, 92, 0, 2, '服务器编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'serverDeploy:edit', NULL, NULL, '2019-11-17 11:08:57', NULL);
+INSERT INTO `sys_menu` VALUES (105, 92, 0, 2, '服务器删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'serverDeploy:del', NULL, NULL, '2019-11-17 11:09:15', NULL);
+INSERT INTO `sys_menu` VALUES (106, 93, 0, 2, '应用新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'app:add', NULL, NULL, '2019-11-17 11:10:03', NULL);
+INSERT INTO `sys_menu` VALUES (107, 93, 0, 2, '应用编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'app:edit', NULL, NULL, '2019-11-17 11:10:28', NULL);
+INSERT INTO `sys_menu` VALUES (108, 93, 0, 2, '应用删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'app:del', NULL, NULL, '2019-11-17 11:10:55', NULL);
+INSERT INTO `sys_menu` VALUES (109, 94, 0, 2, '部署新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'deploy:add', NULL, NULL, '2019-11-17 11:11:22', NULL);
+INSERT INTO `sys_menu` VALUES (110, 94, 0, 2, '部署编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'deploy:edit', NULL, NULL, '2019-11-17 11:11:41', NULL);
+INSERT INTO `sys_menu` VALUES (111, 94, 0, 2, '部署删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'deploy:del', NULL, NULL, '2019-11-17 11:12:01', NULL);
+INSERT INTO `sys_menu` VALUES (112, 98, 0, 2, '数据库新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'database:add', NULL, NULL, '2019-11-17 11:12:43', NULL);
+INSERT INTO `sys_menu` VALUES (113, 98, 0, 2, '数据库编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'database:edit', NULL, NULL, '2019-11-17 11:12:58', NULL);
+INSERT INTO `sys_menu` VALUES (114, 98, 0, 2, '数据库删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'database:del', NULL, NULL, '2019-11-17 11:13:14', NULL);
+INSERT INTO `sys_menu` VALUES (116, 36, 0, 1, '生成预览', 'Preview', 'generator/preview', 999, 'java', 'generator/preview/:tableName', b'0', b'1', b'1', NULL, NULL, NULL, '2019-11-26 14:54:36', NULL);
+
+/*Table structure for table `sys_quartz_job` */
+
+DROP TABLE IF EXISTS `sys_quartz_job`;
+
+CREATE TABLE `sys_quartz_job` (
+ `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `bean_name` varchar(255) DEFAULT NULL COMMENT 'Spring Bean名称',
+ `cron_expression` varchar(255) DEFAULT NULL COMMENT 'cron 表达式',
+ `is_pause` bit(1) DEFAULT NULL COMMENT '状态:1暂停、0启用',
+ `job_name` varchar(255) DEFAULT NULL COMMENT '任务名称',
+ `method_name` varchar(255) DEFAULT NULL COMMENT '方法名称',
+ `params` varchar(255) DEFAULT NULL COMMENT '参数',
+ `description` varchar(255) DEFAULT NULL COMMENT '备注',
+ `person_in_charge` varchar(100) DEFAULT NULL COMMENT '负责人',
+ `email` varchar(100) DEFAULT NULL COMMENT '报警邮箱',
+ `sub_task` varchar(100) DEFAULT NULL COMMENT '子任务ID',
+ `pause_after_failure` bit(1) DEFAULT NULL COMMENT '任务失败后是否暂停',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`job_id`) USING BTREE,
+ KEY `inx_is_pause` (`is_pause`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='定时任务';
+
+/*Data for the table `sys_quartz_job` */
+
+insert into `sys_quartz_job`(`job_id`,`bean_name`,`cron_expression`,`is_pause`,`job_name`,`method_name`,`params`,`description`,`person_in_charge`,`email`,`sub_task`,`pause_after_failure`,`create_by`,`update_by`,`create_time`,`update_time`) values
+(2,'testTask','0/5 * * * * ?','','测试1','run1','test','带参测试,多参使用json','测试',NULL,NULL,NULL,NULL,'admin','2019-08-22 14:08:29','2020-05-24 13:58:33'),
+(3,'testTask','0/5 * * * * ?','','测试','run','','不带参测试','Zheng Jie','','5,6','',NULL,'admin','2019-09-26 16:44:39','2020-05-24 14:48:12'),
+(5,'Test','0/5 * * * * ?','','任务告警测试','run',NULL,'测试','test','',NULL,'','admin','admin','2020-05-05 20:32:41','2020-05-05 20:36:13'),
+(6,'testTask','0/5 * * * * ?','','测试3','run2',NULL,'测试3','Zheng Jie','',NULL,'','admin','admin','2020-05-05 20:35:41','2020-05-05 20:36:07');
+
+/*Table structure for table `sys_quartz_log` */
+
+DROP TABLE IF EXISTS `sys_quartz_log`;
+
+CREATE TABLE `sys_quartz_log` (
+ `log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `bean_name` varchar(255) DEFAULT NULL,
+ `create_time` datetime DEFAULT NULL,
+ `cron_expression` varchar(255) DEFAULT NULL,
+ `exception_detail` text,
+ `is_success` bit(1) DEFAULT NULL,
+ `job_name` varchar(255) DEFAULT NULL,
+ `method_name` varchar(255) DEFAULT NULL,
+ `params` varchar(255) DEFAULT NULL,
+ `time` bigint(20) DEFAULT NULL,
+ PRIMARY KEY (`log_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='定时任务日志';
+
+/*Data for the table `sys_quartz_log` */
+
+/*Table structure for table `sys_role` */
+
+DROP TABLE IF EXISTS `sys_role`;
+
+CREATE TABLE `sys_role` (
+ `role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '名称',
+ `level` int(255) DEFAULT NULL COMMENT '角色级别',
+ `description` varchar(255) DEFAULT NULL COMMENT '描述',
+ `data_scope` varchar(255) DEFAULT NULL COMMENT '数据权限',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`role_id`) USING BTREE,
+ UNIQUE KEY `uniq_name` (`name`),
+ KEY `role_name_index` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色表';
+
+/*Data for the table `sys_role` */
+
+INSERT INTO `sys_role` VALUES (1, '超级管理员', 1, '-', '全部', NULL, 'admin', '2018-11-23 11:04:37', '2022-06-13 11:18:51');
+INSERT INTO `sys_role` VALUES (2, '普通用户', 2, '-', '本级', NULL, 'admin', '2018-11-23 13:09:06', '2020-09-05 10:45:12');
+INSERT INTO `sys_role` VALUES (3, '系统管理员', 1, '系统菜单,监控,用户,部门等系统信息管理员', '全部', 'admin', 'sysadmin', '2022-06-13 11:17:59', '2022-06-13 11:36:44');
+
+/*Table structure for table `sys_roles_depts` */
+
+DROP TABLE IF EXISTS `sys_roles_depts`;
+
+CREATE TABLE `sys_roles_depts` (
+ `role_id` bigint(20) NOT NULL,
+ `dept_id` bigint(20) NOT NULL,
+ PRIMARY KEY (`role_id`,`dept_id`) USING BTREE,
+ KEY `FK7qg6itn5ajdoa9h9o78v9ksur` (`dept_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色部门关联';
+
+/*Data for the table `sys_roles_depts` */
+
+/*Table structure for table `sys_roles_menus` */
+
+DROP TABLE IF EXISTS `sys_roles_menus`;
+
+CREATE TABLE `sys_roles_menus` (
+ `menu_id` bigint(20) NOT NULL COMMENT '菜单ID',
+ `role_id` bigint(20) NOT NULL COMMENT '角色ID',
+ PRIMARY KEY (`menu_id`,`role_id`) USING BTREE,
+ KEY `FKcngg2qadojhi3a651a5adkvbq` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色菜单关联';
+
+/*Data for the table `sys_roles_menus` */
+
+INSERT INTO `sys_roles_menus` VALUES (1, 2);
+INSERT INTO `sys_roles_menus` VALUES (1, 3);
+INSERT INTO `sys_roles_menus` VALUES (2, 2);
+INSERT INTO `sys_roles_menus` VALUES (2, 3);
+INSERT INTO `sys_roles_menus` VALUES (3, 3);
+INSERT INTO `sys_roles_menus` VALUES (5, 3);
+INSERT INTO `sys_roles_menus` VALUES (6, 1);
+INSERT INTO `sys_roles_menus` VALUES (6, 2);
+INSERT INTO `sys_roles_menus` VALUES (6, 3);
+INSERT INTO `sys_roles_menus` VALUES (7, 1);
+INSERT INTO `sys_roles_menus` VALUES (7, 2);
+INSERT INTO `sys_roles_menus` VALUES (7, 3);
+INSERT INTO `sys_roles_menus` VALUES (9, 1);
+INSERT INTO `sys_roles_menus` VALUES (9, 2);
+INSERT INTO `sys_roles_menus` VALUES (9, 3);
+INSERT INTO `sys_roles_menus` VALUES (10, 1);
+INSERT INTO `sys_roles_menus` VALUES (10, 2);
+INSERT INTO `sys_roles_menus` VALUES (11, 1);
+INSERT INTO `sys_roles_menus` VALUES (11, 2);
+INSERT INTO `sys_roles_menus` VALUES (14, 1);
+INSERT INTO `sys_roles_menus` VALUES (14, 2);
+INSERT INTO `sys_roles_menus` VALUES (15, 1);
+INSERT INTO `sys_roles_menus` VALUES (15, 2);
+INSERT INTO `sys_roles_menus` VALUES (18, 1);
+INSERT INTO `sys_roles_menus` VALUES (19, 1);
+INSERT INTO `sys_roles_menus` VALUES (19, 2);
+INSERT INTO `sys_roles_menus` VALUES (21, 1);
+INSERT INTO `sys_roles_menus` VALUES (21, 2);
+INSERT INTO `sys_roles_menus` VALUES (22, 1);
+INSERT INTO `sys_roles_menus` VALUES (22, 2);
+INSERT INTO `sys_roles_menus` VALUES (23, 1);
+INSERT INTO `sys_roles_menus` VALUES (23, 2);
+INSERT INTO `sys_roles_menus` VALUES (24, 1);
+INSERT INTO `sys_roles_menus` VALUES (24, 2);
+INSERT INTO `sys_roles_menus` VALUES (27, 1);
+INSERT INTO `sys_roles_menus` VALUES (27, 2);
+INSERT INTO `sys_roles_menus` VALUES (28, 3);
+INSERT INTO `sys_roles_menus` VALUES (30, 1);
+INSERT INTO `sys_roles_menus` VALUES (30, 2);
+INSERT INTO `sys_roles_menus` VALUES (32, 1);
+INSERT INTO `sys_roles_menus` VALUES (32, 2);
+INSERT INTO `sys_roles_menus` VALUES (32, 3);
+INSERT INTO `sys_roles_menus` VALUES (33, 1);
+INSERT INTO `sys_roles_menus` VALUES (33, 2);
+INSERT INTO `sys_roles_menus` VALUES (34, 1);
+INSERT INTO `sys_roles_menus` VALUES (34, 2);
+INSERT INTO `sys_roles_menus` VALUES (35, 3);
+INSERT INTO `sys_roles_menus` VALUES (36, 1);
+INSERT INTO `sys_roles_menus` VALUES (36, 2);
+INSERT INTO `sys_roles_menus` VALUES (37, 3);
+INSERT INTO `sys_roles_menus` VALUES (38, 1);
+INSERT INTO `sys_roles_menus` VALUES (39, 3);
+INSERT INTO `sys_roles_menus` VALUES (41, 1);
+INSERT INTO `sys_roles_menus` VALUES (41, 3);
+INSERT INTO `sys_roles_menus` VALUES (44, 3);
+INSERT INTO `sys_roles_menus` VALUES (45, 3);
+INSERT INTO `sys_roles_menus` VALUES (46, 3);
+INSERT INTO `sys_roles_menus` VALUES (48, 3);
+INSERT INTO `sys_roles_menus` VALUES (49, 3);
+INSERT INTO `sys_roles_menus` VALUES (50, 3);
+INSERT INTO `sys_roles_menus` VALUES (52, 3);
+INSERT INTO `sys_roles_menus` VALUES (53, 3);
+INSERT INTO `sys_roles_menus` VALUES (54, 3);
+INSERT INTO `sys_roles_menus` VALUES (56, 3);
+INSERT INTO `sys_roles_menus` VALUES (57, 3);
+INSERT INTO `sys_roles_menus` VALUES (58, 3);
+INSERT INTO `sys_roles_menus` VALUES (60, 3);
+INSERT INTO `sys_roles_menus` VALUES (61, 3);
+INSERT INTO `sys_roles_menus` VALUES (62, 3);
+INSERT INTO `sys_roles_menus` VALUES (64, 3);
+INSERT INTO `sys_roles_menus` VALUES (65, 3);
+INSERT INTO `sys_roles_menus` VALUES (66, 3);
+INSERT INTO `sys_roles_menus` VALUES (73, 3);
+INSERT INTO `sys_roles_menus` VALUES (74, 3);
+INSERT INTO `sys_roles_menus` VALUES (75, 3);
+INSERT INTO `sys_roles_menus` VALUES (77, 1);
+INSERT INTO `sys_roles_menus` VALUES (78, 1);
+INSERT INTO `sys_roles_menus` VALUES (79, 1);
+INSERT INTO `sys_roles_menus` VALUES (80, 1);
+INSERT INTO `sys_roles_menus` VALUES (80, 2);
+INSERT INTO `sys_roles_menus` VALUES (80, 3);
+INSERT INTO `sys_roles_menus` VALUES (82, 1);
+INSERT INTO `sys_roles_menus` VALUES (82, 2);
+INSERT INTO `sys_roles_menus` VALUES (83, 1);
+INSERT INTO `sys_roles_menus` VALUES (83, 2);
+INSERT INTO `sys_roles_menus` VALUES (90, 1);
+INSERT INTO `sys_roles_menus` VALUES (92, 1);
+INSERT INTO `sys_roles_menus` VALUES (93, 1);
+INSERT INTO `sys_roles_menus` VALUES (94, 1);
+INSERT INTO `sys_roles_menus` VALUES (97, 1);
+INSERT INTO `sys_roles_menus` VALUES (98, 1);
+INSERT INTO `sys_roles_menus` VALUES (102, 1);
+INSERT INTO `sys_roles_menus` VALUES (103, 1);
+INSERT INTO `sys_roles_menus` VALUES (104, 1);
+INSERT INTO `sys_roles_menus` VALUES (105, 1);
+INSERT INTO `sys_roles_menus` VALUES (106, 1);
+INSERT INTO `sys_roles_menus` VALUES (107, 1);
+INSERT INTO `sys_roles_menus` VALUES (108, 1);
+INSERT INTO `sys_roles_menus` VALUES (109, 1);
+INSERT INTO `sys_roles_menus` VALUES (110, 1);
+INSERT INTO `sys_roles_menus` VALUES (111, 1);
+INSERT INTO `sys_roles_menus` VALUES (112, 1);
+INSERT INTO `sys_roles_menus` VALUES (113, 1);
+INSERT INTO `sys_roles_menus` VALUES (114, 1);
+INSERT INTO `sys_roles_menus` VALUES (116, 1);
+INSERT INTO `sys_roles_menus` VALUES (116, 2);
+INSERT INTO `sys_roles_menus` VALUES (120, 1);
+
+/*Table structure for table `sys_user` */
+
+DROP TABLE IF EXISTS `sys_user`;
+
+CREATE TABLE `sys_user` (
+ `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `dept_id` bigint(20) DEFAULT NULL COMMENT '部门名称',
+ `username` varchar(255) DEFAULT NULL COMMENT '用户名',
+ `nick_name` varchar(255) DEFAULT NULL COMMENT '昵称',
+ `gender` varchar(2) DEFAULT NULL COMMENT '性别',
+ `phone` varchar(255) DEFAULT NULL COMMENT '手机号码',
+ `email` varchar(255) DEFAULT NULL COMMENT '邮箱',
+ `avatar_name` varchar(255) DEFAULT NULL COMMENT '头像地址',
+ `avatar_path` varchar(255) DEFAULT NULL COMMENT '头像真实路径',
+ `password` varchar(255) DEFAULT NULL COMMENT '密码',
+ `is_admin` bit(1) DEFAULT b'0' COMMENT '是否为admin账号',
+ `enabled` bigint(20) DEFAULT NULL COMMENT '状态:1启用、0禁用',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `pwd_reset_time` datetime DEFAULT NULL COMMENT '修改密码的时间',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`user_id`) USING BTREE,
+ UNIQUE KEY `UK_kpubos9gc2cvtkb0thktkbkes` (`email`) USING BTREE,
+ UNIQUE KEY `username` (`username`) USING BTREE,
+ UNIQUE KEY `uniq_username` (`username`),
+ UNIQUE KEY `uniq_email` (`email`),
+ KEY `FK5rwmryny6jthaaxkogownknqp` (`dept_id`) USING BTREE,
+ KEY `FKpq2dhypk2qgt68nauh2by22jb` (`avatar_name`) USING BTREE,
+ KEY `inx_enabled` (`enabled`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统用户';
+
+/*Data for the table `sys_user` */
+
+INSERT INTO `sys_user` VALUES (1, 2, 'admin', '管理员', '男', '18888888888', '[email protected]', 'avatar-20200806032259161.png', '/Users/jie/Documents/work/me/admin/eladmin/~/avatar/avatar-20200806032259161.png', '$2a$10$Egp1/gvFlt7zhlXVfEFw4OfWQCGPw0ClmMcc6FjTnvXNRVf9zdMRa', b'1', 1, NULL, 'admin', '2020-05-03 16:38:31', '2018-08-23 09:11:56', '2022-04-24 17:03:00');
+INSERT INTO `sys_user` VALUES (2, 2, 'test', '测试', '男', '19999999999', '[email protected]', NULL, NULL, '$2a$10$4XcyudOYTSz6fue6KFNMHeUQnCX5jbBQypLEnGk1PmekXt5c95JcK', b'0', 1, 'admin', 'admin', NULL, '2020-05-05 11:15:49', '2022-04-24 11:18:18');
+INSERT INTO `sys_user` VALUES (3, 8, 'test2', 'aaa', '男', '15014236547', '[email protected]', NULL, NULL, '$2a$10$39eu19DlibPMfC9EEPPErO86uBAZhCzySlhvSn/Evg0gdInNeNB3W', b'0', 1, 'admin', 'admin', NULL, '2022-04-24 16:51:41', '2022-04-24 16:51:41');
+INSERT INTO `sys_user` VALUES (4, 7, 'xx', 'xx', '男', '15044878963', '[email protected]', NULL, NULL, '$2a$10$NGkgAoFjWGUueMJ81409I.mAJXa2KHf9b9GwgWZOCN8TdL35lLigy', b'0', 1, 'admin', 'admin', NULL, '2022-04-24 17:47:01', '2022-04-24 17:47:01');
+INSERT INTO `sys_user` VALUES (5, NULL, 'xxx', 'xxx', '男', '15044878962', '[email protected]', NULL, NULL, '$2a$10$y6hqVUiy6YSLngBuK4v/weonLYkyuIltwG0HTUCMTuCNtnGkFsDpW', b'0', 1, 'admin', 'admin', NULL, '2022-04-24 17:52:19', '2022-04-24 17:52:19');
+INSERT INTO `sys_user` VALUES (6, 7, 'bbbb', 'ssss', '男', '15033698785', '[email protected]', NULL, NULL, '$2a$10$P.hvDg2NaJs/kYeLn15u4upYvYxbl4HB4ExNERrU1SM5EqTQF2Hae', b'0', 1, 'admin', 'admin', NULL, '2022-04-25 15:50:58', '2022-04-25 15:50:58');
+INSERT INTO `sys_user` VALUES (7, 5, 'sysadmin', 'sysadmin', '男', '18765432100', '[email protected]', NULL, NULL, '$2a$10$Wp0dKiYZpAgNap.0NhK40.LEd2AgDTFC.i/unDcRPmICf9JMEcYzC', b'0', 1, 'admin', 'admin', NULL, '2022-06-13 11:20:03', '2022-06-13 11:20:03');
+
+/*Table structure for table `sys_users_jobs` */
+
+DROP TABLE IF EXISTS `sys_users_jobs`;
+
+CREATE TABLE `sys_users_jobs` (
+ `user_id` bigint(20) NOT NULL COMMENT '用户ID',
+ `job_id` bigint(20) NOT NULL COMMENT '岗位ID',
+ PRIMARY KEY (`user_id`,`job_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+/*Data for the table `sys_users_jobs` */
+
+insert into `sys_users_jobs`(`user_id`,`job_id`) values
+(1,11),
+(2,12),
+(3,8),
+(4,8),
+(6,8);
+
+/*Table structure for table `sys_users_roles` */
+
+DROP TABLE IF EXISTS `sys_users_roles`;
+
+CREATE TABLE `sys_users_roles` (
+ `user_id` bigint(20) NOT NULL COMMENT '用户ID',
+ `role_id` bigint(20) NOT NULL COMMENT '角色ID',
+ PRIMARY KEY (`user_id`,`role_id`) USING BTREE,
+ KEY `FKq4eq273l04bpu4efj0jd0jb98` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='用户角色关联';
+
+/*Data for the table `sys_users_roles` */
+
+insert into `sys_users_roles`(`user_id`,`role_id`) values
+(1,1),
+(6,1),
+(2,2),
+(3,2),
+(4,2);
+
+/*Table structure for table `tool_alipay_config` */
+
+DROP TABLE IF EXISTS `tool_alipay_config`;
+
+CREATE TABLE `tool_alipay_config` (
+ `config_id` bigint(20) NOT NULL COMMENT 'ID',
+ `app_id` varchar(255) DEFAULT NULL COMMENT '应用ID',
+ `charset` varchar(255) DEFAULT NULL COMMENT '编码',
+ `format` varchar(255) DEFAULT NULL COMMENT '类型 固定格式json',
+ `gateway_url` varchar(255) DEFAULT NULL COMMENT '网关地址',
+ `notify_url` varchar(255) DEFAULT NULL COMMENT '异步回调',
+ `private_key` text COMMENT '私钥',
+ `public_key` text COMMENT '公钥',
+ `return_url` varchar(255) DEFAULT NULL COMMENT '回调地址',
+ `sign_type` varchar(255) DEFAULT NULL COMMENT '签名方式',
+ `sys_service_provider_id` varchar(255) DEFAULT NULL COMMENT '商户号',
+ PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='支付宝配置类';
+
+/*Data for the table `tool_alipay_config` */
+
+insert into `tool_alipay_config`(`config_id`,`app_id`,`charset`,`format`,`gateway_url`,`notify_url`,`private_key`,`public_key`,`return_url`,`sign_type`,`sys_service_provider_id`) values
+(1,'2016091700532697','utf-8','JSON','https://openapi.alipaydev.com/gateway.do','http://api.auauz.net/api/aliPay/notify','MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5js8sInU10AJ0cAQ8UMMyXrQ+oHZEkVt5lBwsStmTJ7YikVYgbskx1YYEXTojRsWCb+SH/kDmDU4pK/u91SJ4KFCRMF2411piYuXU/jF96zKrADznYh/zAraqT6hvAIVtQAlMHN53nx16rLzZ/8jDEkaSwT7+HvHiS+7sxSojnu/3oV7BtgISoUNstmSe8WpWHOaWv19xyS+Mce9MY4BfseFhzTICUymUQdd/8hXA28/H6osUfAgsnxAKv7Wil3aJSgaJczWuflYOve0dJ3InZkhw5Cvr0atwpk8YKBQjy5CdkoHqvkOcIB+cYHXJKzOE5tqU7inSwVbHzOLQ3XbnAgMBAAECggEAVJp5eT0Ixg1eYSqFs9568WdetUNCSUchNxDBu6wxAbhUgfRUGZuJnnAll63OCTGGck+EGkFh48JjRcBpGoeoHLL88QXlZZbC/iLrea6gcDIhuvfzzOffe1RcZtDFEj9hlotg8dQj1tS0gy9pN9g4+EBH7zeu+fyv+qb2e/v1l6FkISXUjpkD7RLQr3ykjiiEw9BpeKb7j5s7Kdx1NNIzhkcQKNqlk8JrTGDNInbDM6inZfwwIO2R1DHinwdfKWkvOTODTYa2MoAvVMFT9Bec9FbLpoWp7ogv1JMV9svgrcF9XLzANZ/OQvkbe9TV9GWYvIbxN6qwQioKCWO4GPnCAQKBgQDgW5MgfhX8yjXqoaUy/d1VjI8dHeIyw8d+OBAYwaxRSlCfyQ+tieWcR2HdTzPca0T0GkWcKZm0ei5xRURgxt4DUDLXNh26HG0qObbtLJdu/AuBUuCqgOiLqJ2f1uIbrz6OZUHns+bT/jGW2Ws8+C13zTCZkZt9CaQsrp3QOGDx5wKBgQDTul39hp3ZPwGNFeZdkGoUoViOSd5Lhowd5wYMGAEXWRLlU8z+smT5v0POz9JnIbCRchIY2FAPKRdVTICzmPk2EPJFxYTcwaNbVqL6lN7J2IlXXMiit5QbiLauo55w7plwV6LQmKm9KV7JsZs5XwqF7CEovI7GevFzyD3w+uizAQKBgC3LY1eRhOlpWOIAhpjG6qOoohmeXOphvdmMlfSHq6WYFqbWwmV4rS5d/6LNpNdL6fItXqIGd8I34jzql49taCmi+A2nlR/E559j0mvM20gjGDIYeZUz5MOE8k+K6/IcrhcgofgqZ2ZED1ksHdB/E8DNWCswZl16V1FrfvjeWSNnAoGAMrBplCrIW5xz+J0Hm9rZKrs+AkK5D4fUv8vxbK/KgxZ2KaUYbNm0xv39c+PZUYuFRCz1HDGdaSPDTE6WeWjkMQd5mS6ikl9hhpqFRkyh0d0fdGToO9yLftQKOGE/q3XUEktI1XvXF0xyPwNgUCnq0QkpHyGVZPtGFxwXiDvpvgECgYA5PoB+nY8iDiRaJNko9w0hL4AeKogwf+4TbCw+KWVEn6jhuJa4LFTdSqp89PktQaoVpwv92el/AhYjWOl/jVCm122f9b7GyoelbjMNolToDwe5pF5RnSpEuDdLy9MfE8LnE3PlbE7E5BipQ3UjSebkgNboLHH/lNZA5qvEtvbfvQ==','MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAut9evKRuHJ/2QNfDlLwvN/S8l9hRAgPbb0u61bm4AtzaTGsLeMtScetxTWJnVvAVpMS9luhEJjt+Sbk5TNLArsgzzwARgaTKOLMT1TvWAK5EbHyI+eSrc3s7Awe1VYGwcubRFWDm16eQLv0k7iqiw+4mweHSz/wWyvBJVgwLoQ02btVtAQErCfSJCOmt0Q/oJQjj08YNRV4EKzB19+f5A+HQVAKy72dSybTzAK+3FPtTtNen/+b5wGeat7c32dhYHnGorPkPeXLtsqqUTp1su5fMfd4lElNdZaoCI7osZxWWUo17vBCZnyeXc9fk0qwD9mK6yRAxNbrY72Xx5VqIqwIDAQAB','http://api.auauz.net/api/aliPay/return','RSA2','2088102176044281');
+
+/*Table structure for table `tool_email_config` */
+
+DROP TABLE IF EXISTS `tool_email_config`;
+
+CREATE TABLE `tool_email_config` (
+ `config_id` bigint(20) NOT NULL COMMENT 'ID',
+ `from_user` varchar(255) DEFAULT NULL COMMENT '收件人',
+ `host` varchar(255) DEFAULT NULL COMMENT '邮件服务器SMTP地址',
+ `pass` varchar(255) DEFAULT NULL COMMENT '密码',
+ `port` varchar(255) DEFAULT NULL COMMENT '端口',
+ `user` varchar(255) DEFAULT NULL COMMENT '发件者用户名',
+ PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='邮箱配置';
+
+/*Data for the table `tool_email_config` */
+
+/*Table structure for table `tool_local_storage` */
+
+DROP TABLE IF EXISTS `tool_local_storage`;
+
+CREATE TABLE `tool_local_storage` (
+ `storage_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `real_name` varchar(255) DEFAULT NULL COMMENT '文件真实的名称',
+ `name` varchar(255) DEFAULT NULL COMMENT '文件名',
+ `suffix` varchar(255) DEFAULT NULL COMMENT '后缀',
+ `path` varchar(255) DEFAULT NULL COMMENT '路径',
+ `type` varchar(255) DEFAULT NULL COMMENT '类型',
+ `size` varchar(100) DEFAULT NULL COMMENT '大小',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`storage_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='本地存储';
+
+/*Data for the table `tool_local_storage` */
+
+/*Table structure for table `tool_qiniu_config` */
+
+DROP TABLE IF EXISTS `tool_qiniu_config`;
+
+CREATE TABLE `tool_qiniu_config` (
+ `config_id` bigint(20) NOT NULL COMMENT 'ID',
+ `access_key` text COMMENT 'accessKey',
+ `bucket` varchar(255) DEFAULT NULL COMMENT 'Bucket 识别符',
+ `host` varchar(255) NOT NULL COMMENT '外链域名',
+ `secret_key` text COMMENT 'secretKey',
+ `type` varchar(255) DEFAULT NULL COMMENT '空间类型',
+ `zone` varchar(255) DEFAULT NULL COMMENT '机房',
+ PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='七牛云配置';
+
+/*Data for the table `tool_qiniu_config` */
+
+/*Table structure for table `tool_qiniu_content` */
+
+DROP TABLE IF EXISTS `tool_qiniu_content`;
+
+CREATE TABLE `tool_qiniu_content` (
+ `content_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `bucket` varchar(255) DEFAULT NULL COMMENT 'Bucket 识别符',
+ `name` varchar(255) DEFAULT NULL COMMENT '文件名称',
+ `size` varchar(255) DEFAULT NULL COMMENT '文件大小',
+ `type` varchar(255) DEFAULT NULL COMMENT '文件类型:私有或公开',
+ `url` varchar(255) DEFAULT NULL COMMENT '文件url',
+ `suffix` varchar(255) DEFAULT NULL COMMENT '文件后缀',
+ `update_time` datetime DEFAULT NULL COMMENT '上传或同步的时间',
+ PRIMARY KEY (`content_id`) USING BTREE,
+ UNIQUE KEY `uniq_name` (`name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='七牛云文件存储';
+
+/*Data for the table `tool_qiniu_content` */
+
+/*Table structure for table `vulnerability` */
+
+DROP TABLE IF EXISTS `vulnerability`;
+
+CREATE TABLE `vulnerability` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `component` varchar(128) DEFAULT NULL,
+ `vulnerability` varchar(128) DEFAULT NULL,
+ `timestamp` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
+
+/*Data for the table `vulnerability` */
+
+insert into `vulnerability`(`id`,`component`,`vulnerability`,`timestamp`) values
+(1,'nginx','nginx漏洞','2022-05-05 14:09:00'),
+(2,'bind','bind漏洞','2022-05-05 14:09:13'),
+(3,'unbound','unbound漏洞','2022-05-11 14:49:14');
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
diff --git a/UI source code/dns-dev-2.0/sql/eladmin.sql b/UI source code/dns-dev-2.0/sql/eladmin.sql
new file mode 100644
index 0000000..da53710
--- /dev/null
+++ b/UI source code/dns-dev-2.0/sql/eladmin.sql
@@ -0,0 +1,825 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server : localhost
+ Source Server Type : MySQL
+ Source Server Version : 100505
+ Source Host : localhost:3306
+ Source Schema : dns
+
+ Target Server Type : MySQL
+ Target Server Version : 100505
+ File Encoding : 65001
+
+ Date: 05/09/2020 10:49:19
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for code_column_config
+-- ----------------------------
+DROP TABLE IF EXISTS `code_column_config`;
+CREATE TABLE `code_column_config` (
+ `column_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `table_name` varchar(255) DEFAULT NULL,
+ `column_name` varchar(255) DEFAULT NULL,
+ `column_type` varchar(255) DEFAULT NULL,
+ `dict_name` varchar(255) DEFAULT NULL,
+ `extra` varchar(255) DEFAULT NULL,
+ `form_show` bit(1) DEFAULT NULL,
+ `form_type` varchar(255) DEFAULT NULL,
+ `key_type` varchar(255) DEFAULT NULL,
+ `list_show` bit(1) DEFAULT NULL,
+ `not_null` bit(1) DEFAULT NULL,
+ `query_type` varchar(255) DEFAULT NULL,
+ `remark` varchar(255) DEFAULT NULL,
+ `date_annotation` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`column_id`) USING BTREE,
+ KEY `idx_table_name` (`table_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=191 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='代码生成字段信息存储';
+
+-- ----------------------------
+-- Table structure for code_gen_config
+-- ----------------------------
+DROP TABLE IF EXISTS `code_gen_config`;
+CREATE TABLE `code_gen_config` (
+ `config_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `table_name` varchar(255) DEFAULT NULL COMMENT '表名',
+ `author` varchar(255) DEFAULT NULL COMMENT '作者',
+ `cover` bit(1) DEFAULT NULL COMMENT '是否覆盖',
+ `module_name` varchar(255) DEFAULT NULL COMMENT '模块名称',
+ `pack` varchar(255) DEFAULT NULL COMMENT '至于哪个包下',
+ `path` varchar(255) DEFAULT NULL COMMENT '前端代码生成的路径',
+ `api_path` varchar(255) DEFAULT NULL COMMENT '前端Api文件路径',
+ `prefix` varchar(255) DEFAULT NULL COMMENT '表前缀',
+ `api_alias` varchar(255) DEFAULT NULL COMMENT '接口名称',
+ PRIMARY KEY (`config_id`) USING BTREE,
+ KEY `idx_table_name` (`table_name`(100))
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='代码生成器配置';
+
+-- ----------------------------
+-- Table structure for mnt_app
+-- ----------------------------
+DROP TABLE IF EXISTS `mnt_app`;
+CREATE TABLE `mnt_app` (
+ `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) DEFAULT NULL COMMENT '应用名称',
+ `upload_path` varchar(255) DEFAULT NULL COMMENT '上传目录',
+ `deploy_path` varchar(255) DEFAULT NULL COMMENT '部署路径',
+ `backup_path` varchar(255) DEFAULT NULL COMMENT '备份路径',
+ `port` int(255) DEFAULT NULL COMMENT '应用端口',
+ `start_script` varchar(4000) DEFAULT NULL COMMENT '启动脚本',
+ `deploy_script` varchar(4000) DEFAULT NULL COMMENT '部署脚本',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`app_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='应用管理';
+
+-- ----------------------------
+-- Records of mnt_app
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for mnt_database
+-- ----------------------------
+DROP TABLE IF EXISTS `mnt_database`;
+CREATE TABLE `mnt_database` (
+ `db_id` varchar(50) NOT NULL COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '名称',
+ `jdbc_url` varchar(255) NOT NULL COMMENT 'jdbc连接',
+ `user_name` varchar(255) NOT NULL COMMENT '账号',
+ `pwd` varchar(255) NOT NULL COMMENT '密码',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`db_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='数据库管理';
+
+-- ----------------------------
+-- Records of mnt_database
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for mnt_deploy
+-- ----------------------------
+DROP TABLE IF EXISTS `mnt_deploy`;
+CREATE TABLE `mnt_deploy` (
+ `deploy_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `app_id` bigint(20) DEFAULT NULL COMMENT '应用编号',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`deploy_id`) USING BTREE,
+ KEY `FK6sy157pseoxx4fmcqr1vnvvhy` (`app_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='部署管理';
+
+-- ----------------------------
+-- Records of mnt_deploy
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for mnt_deploy_history
+-- ----------------------------
+DROP TABLE IF EXISTS `mnt_deploy_history`;
+CREATE TABLE `mnt_deploy_history` (
+ `history_id` varchar(50) NOT NULL COMMENT 'ID',
+ `app_name` varchar(255) NOT NULL COMMENT '应用名称',
+ `deploy_date` datetime NOT NULL COMMENT '部署日期',
+ `deploy_user` varchar(50) NOT NULL COMMENT '部署用户',
+ `ip` varchar(20) NOT NULL COMMENT '服务器IP',
+ `deploy_id` bigint(20) DEFAULT NULL COMMENT '部署编号',
+ PRIMARY KEY (`history_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='部署历史管理';
+
+-- ----------------------------
+-- Records of mnt_deploy_history
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for mnt_deploy_server
+-- ----------------------------
+DROP TABLE IF EXISTS `mnt_deploy_server`;
+CREATE TABLE `mnt_deploy_server` (
+ `deploy_id` bigint(20) NOT NULL COMMENT '部署ID',
+ `server_id` bigint(20) NOT NULL COMMENT '服务ID',
+ PRIMARY KEY (`deploy_id`,`server_id`) USING BTREE,
+ KEY `FKeaaha7jew9a02b3bk9ghols53` (`server_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='应用与服务器关联';
+
+-- ----------------------------
+-- Records of mnt_deploy_server
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for mnt_server
+-- ----------------------------
+DROP TABLE IF EXISTS `mnt_server`;
+CREATE TABLE `mnt_server` (
+ `server_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `account` varchar(50) DEFAULT NULL COMMENT '账号',
+ `ip` varchar(20) DEFAULT NULL COMMENT 'IP地址',
+ `name` varchar(100) DEFAULT NULL COMMENT '名称',
+ `password` varchar(100) DEFAULT NULL COMMENT '密码',
+ `port` int(11) DEFAULT NULL COMMENT '端口',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`server_id`) USING BTREE,
+ KEY `idx_ip` (`ip`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='服务器管理';
+
+-- ----------------------------
+-- Table structure for sys_dept
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dept`;
+CREATE TABLE `sys_dept` (
+ `dept_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `pid` bigint(20) DEFAULT NULL COMMENT '上级部门',
+ `sub_count` int(5) DEFAULT 0 COMMENT '子部门数目',
+ `name` varchar(255) NOT NULL COMMENT '名称',
+ `dept_sort` int(5) DEFAULT 999 COMMENT '排序',
+ `enabled` bit(1) NOT NULL COMMENT '状态',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`dept_id`) USING BTREE,
+ KEY `inx_pid` (`pid`),
+ KEY `inx_enabled` (`enabled`)
+) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='部门';
+
+-- ----------------------------
+-- Records of sys_dept
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_dept` VALUES (2, 7, 1, '研发部', 3, b'1', 'admin', 'admin', '2019-03-25 09:15:32', '2020-08-02 14:48:47');
+INSERT INTO `sys_dept` VALUES (5, 7, 0, '运维部', 4, b'1', 'admin', 'admin', '2019-03-25 09:20:44', '2020-05-17 14:27:27');
+INSERT INTO `sys_dept` VALUES (6, 8, 0, '测试部', 6, b'1', 'admin', 'admin', '2019-03-25 09:52:18', '2020-06-08 11:59:21');
+INSERT INTO `sys_dept` VALUES (7, NULL, 2, '华南分部', 0, b'1', 'admin', 'admin', '2019-03-25 11:04:50', '2020-06-08 12:08:56');
+INSERT INTO `sys_dept` VALUES (8, NULL, 2, '华北分部', 1, b'1', 'admin', 'admin', '2019-03-25 11:04:53', '2020-05-14 12:54:00');
+INSERT INTO `sys_dept` VALUES (15, 8, 0, 'UI部门', 7, b'1', 'admin', 'admin', '2020-05-13 22:56:53', '2020-05-14 12:54:13');
+INSERT INTO `sys_dept` VALUES (17, 2, 0, '研发一组', 999, b'1', 'admin', 'admin', '2020-08-02 14:49:07', '2020-08-02 14:49:07');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_dict
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict`;
+CREATE TABLE `sys_dict` (
+ `dict_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '字典名称',
+ `description` varchar(255) DEFAULT NULL COMMENT '描述',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`dict_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='数据字典';
+
+-- ----------------------------
+-- Records of sys_dict
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_dict` VALUES (1, 'user_status', '用户状态', NULL, NULL, '2019-10-27 20:31:36', NULL);
+INSERT INTO `sys_dict` VALUES (4, 'dept_status', '部门状态', NULL, NULL, '2019-10-27 20:31:36', NULL);
+INSERT INTO `sys_dict` VALUES (5, 'job_status', '岗位状态', NULL, NULL, '2019-10-27 20:31:36', NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_dict_detail
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_detail`;
+CREATE TABLE `sys_dict_detail` (
+ `detail_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `dict_id` bigint(11) DEFAULT NULL COMMENT '字典id',
+ `label` varchar(255) NOT NULL COMMENT '字典标签',
+ `value` varchar(255) NOT NULL COMMENT '字典值',
+ `dict_sort` int(5) DEFAULT NULL COMMENT '排序',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`detail_id`) USING BTREE,
+ KEY `FK5tpkputc6d9nboxojdbgnpmyb` (`dict_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='数据字典详情';
+
+-- ----------------------------
+-- Records of sys_dict_detail
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_dict_detail` VALUES (1, 1, '激活', 'true', 1, NULL, NULL, '2019-10-27 20:31:36', NULL);
+INSERT INTO `sys_dict_detail` VALUES (2, 1, '禁用', 'false', 2, NULL, NULL, NULL, NULL);
+INSERT INTO `sys_dict_detail` VALUES (3, 4, '启用', 'true', 1, NULL, NULL, NULL, NULL);
+INSERT INTO `sys_dict_detail` VALUES (4, 4, '停用', 'false', 2, NULL, NULL, '2019-10-27 20:31:36', NULL);
+INSERT INTO `sys_dict_detail` VALUES (5, 5, '启用', 'true', 1, NULL, NULL, NULL, NULL);
+INSERT INTO `sys_dict_detail` VALUES (6, 5, '停用', 'false', 2, NULL, NULL, '2019-10-27 20:31:36', NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_job
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_job`;
+CREATE TABLE `sys_job` (
+ `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '岗位名称',
+ `enabled` bit(1) NOT NULL COMMENT '岗位状态',
+ `job_sort` int(5) DEFAULT NULL COMMENT '排序',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`job_id`) USING BTREE,
+ UNIQUE KEY `uniq_name` (`name`),
+ KEY `inx_enabled` (`enabled`)
+) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='岗位';
+
+-- ----------------------------
+-- Records of sys_job
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_job` VALUES (8, '人事专员', b'1', 3, NULL, NULL, '2019-03-29 14:52:28', NULL);
+INSERT INTO `sys_job` VALUES (10, '产品经理', b'1', 4, NULL, NULL, '2019-03-29 14:55:51', NULL);
+INSERT INTO `sys_job` VALUES (11, '全栈开发', b'1', 2, NULL, 'admin', '2019-03-31 13:39:30', '2020-05-05 11:33:43');
+INSERT INTO `sys_job` VALUES (12, '软件测试', b'1', 5, NULL, 'admin', '2019-03-31 13:39:43', '2020-05-10 19:56:26');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_log`;
+CREATE TABLE `sys_log` (
+ `log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `description` varchar(255) DEFAULT NULL,
+ `log_type` varchar(255) DEFAULT NULL,
+ `method` varchar(255) DEFAULT NULL,
+ `params` text DEFAULT NULL,
+ `request_ip` varchar(255) DEFAULT NULL,
+ `time` bigint(20) DEFAULT NULL,
+ `username` varchar(255) DEFAULT NULL,
+ `address` varchar(255) DEFAULT NULL,
+ `browser` varchar(255) DEFAULT NULL,
+ `exception_detail` text DEFAULT NULL,
+ `create_time` datetime DEFAULT NULL,
+ PRIMARY KEY (`log_id`) USING BTREE,
+ KEY `log_create_time_index` (`create_time`),
+ KEY `inx_log_type` (`log_type`)
+) ENGINE=InnoDB AUTO_INCREMENT=3537 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统日志';
+
+-- ----------------------------
+-- Table structure for sys_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_menu`;
+CREATE TABLE `sys_menu` (
+ `menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `pid` bigint(20) DEFAULT NULL COMMENT '上级菜单ID',
+ `sub_count` int(5) DEFAULT 0 COMMENT '子菜单数目',
+ `type` int(11) DEFAULT NULL COMMENT '菜单类型',
+ `title` varchar(255) DEFAULT NULL COMMENT '菜单标题',
+ `name` varchar(255) DEFAULT NULL COMMENT '组件名称',
+ `component` varchar(255) DEFAULT NULL COMMENT '组件',
+ `menu_sort` int(5) DEFAULT NULL COMMENT '排序',
+ `icon` varchar(255) DEFAULT NULL COMMENT '图标',
+ `path` varchar(255) DEFAULT NULL COMMENT '链接地址',
+ `i_frame` bit(1) DEFAULT NULL COMMENT '是否外链',
+ `cache` bit(1) DEFAULT b'0' COMMENT '缓存',
+ `hidden` bit(1) DEFAULT b'0' COMMENT '隐藏',
+ `permission` varchar(255) DEFAULT NULL COMMENT '权限',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`menu_id`) USING BTREE,
+ UNIQUE KEY `uniq_title` (`title`),
+ UNIQUE KEY `uniq_name` (`name`),
+ KEY `inx_pid` (`pid`)
+) ENGINE=InnoDB AUTO_INCREMENT=118 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统菜单';
+
+-- ----------------------------
+-- Records of sys_menu
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_menu` VALUES (1, NULL, 7, 0, '系统管理', NULL, NULL, 1, 'system', 'system', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-18 15:11:29', NULL);
+INSERT INTO `sys_menu` VALUES (2, 1, 3, 1, '用户管理', 'User', 'system/user/index', 2, 'peoples', 'user', b'0', b'0', b'0', 'user:list', NULL, NULL, '2018-12-18 15:14:44', NULL);
+INSERT INTO `sys_menu` VALUES (3, 1, 3, 1, '角色管理', 'Role', 'system/role/index', 3, 'role', 'role', b'0', b'0', b'0', 'roles:list', NULL, NULL, '2018-12-18 15:16:07', NULL);
+INSERT INTO `sys_menu` VALUES (5, 1, 3, 1, '菜单管理', 'Menu', 'system/menu/index', 5, 'menu', 'menu', b'0', b'0', b'0', 'menu:list', NULL, NULL, '2018-12-18 15:17:28', NULL);
+INSERT INTO `sys_menu` VALUES (6, NULL, 5, 0, '系统监控', NULL, NULL, 10, 'monitor', 'monitor', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-18 15:17:48', NULL);
+INSERT INTO `sys_menu` VALUES (7, 6, 0, 1, '操作日志', 'Log', 'monitor/log/index', 11, 'log', 'logs', b'0', b'1', b'0', NULL, NULL, 'admin', '2018-12-18 15:18:26', '2020-06-06 13:11:57');
+INSERT INTO `sys_menu` VALUES (9, 6, 0, 1, 'SQL监控', 'Sql', 'monitor/sql/index', 18, 'sqlMonitor', 'druid', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-18 15:19:34', NULL);
+INSERT INTO `sys_menu` VALUES (10, NULL, 5, 0, '组件管理', NULL, NULL, 50, 'zujian', 'components', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-19 13:38:16', NULL);
+INSERT INTO `sys_menu` VALUES (11, 10, 0, 1, '图标库', 'Icons', 'components/icons/index', 51, 'icon', 'icon', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-19 13:38:49', NULL);
+INSERT INTO `sys_menu` VALUES (14, 36, 0, 1, '邮件工具', 'Email', 'tools/email/index', 35, 'email', 'email', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-27 10:13:09', NULL);
+INSERT INTO `sys_menu` VALUES (15, 10, 0, 1, '富文本', 'Editor', 'components/Editor', 52, 'fwb', 'tinymce', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-27 11:58:25', NULL);
+INSERT INTO `sys_menu` VALUES (18, 36, 3, 1, '存储管理', 'Storage', 'tools/storage/index', 34, 'qiniu', 'storage', b'0', b'0', b'0', 'storage:list', NULL, NULL, '2018-12-31 11:12:15', NULL);
+INSERT INTO `sys_menu` VALUES (19, 36, 0, 1, '支付宝工具', 'AliPay', 'tools/aliPay/index', 37, 'alipay', 'aliPay', b'0', b'0', b'0', NULL, NULL, NULL, '2018-12-31 14:52:38', NULL);
+INSERT INTO `sys_menu` VALUES (21, NULL, 2, 0, '多级菜单', NULL, '', 900, 'menu', 'nested', b'0', b'0', b'0', NULL, NULL, 'admin', '2019-01-04 16:22:03', '2020-06-21 17:27:35');
+INSERT INTO `sys_menu` VALUES (22, 21, 2, 0, '二级菜单1', NULL, '', 999, 'menu', 'menu1', b'0', b'0', b'0', NULL, NULL, 'admin', '2019-01-04 16:23:29', '2020-06-21 17:27:20');
+INSERT INTO `sys_menu` VALUES (23, 21, 0, 1, '二级菜单2', NULL, 'nested/menu2/index', 999, 'menu', 'menu2', b'0', b'0', b'0', NULL, NULL, NULL, '2019-01-04 16:23:57', NULL);
+INSERT INTO `sys_menu` VALUES (24, 22, 0, 1, '三级菜单1', 'Test', 'nested/menu1/menu1-1', 999, 'menu', 'menu1-1', b'0', b'0', b'0', NULL, NULL, NULL, '2019-01-04 16:24:48', NULL);
+INSERT INTO `sys_menu` VALUES (27, 22, 0, 1, '三级菜单2', NULL, 'nested/menu1/menu1-2', 999, 'menu', 'menu1-2', b'0', b'0', b'0', NULL, NULL, NULL, '2019-01-07 17:27:32', NULL);
+INSERT INTO `sys_menu` VALUES (28, 1, 3, 1, '任务调度', 'Timing', 'system/timing/index', 999, 'timing', 'timing', b'0', b'0', b'0', 'timing:list', NULL, NULL, '2019-01-07 20:34:40', NULL);
+INSERT INTO `sys_menu` VALUES (30, 36, 0, 1, '代码生成', 'GeneratorIndex', 'generator/index', 32, 'dev', 'generator', b'0', b'1', b'0', NULL, NULL, NULL, '2019-01-11 15:45:55', NULL);
+INSERT INTO `sys_menu` VALUES (32, 6, 0, 1, '异常日志', 'ErrorLog', 'monitor/log/errorLog', 12, 'error', 'errorLog', b'0', b'0', b'0', NULL, NULL, NULL, '2019-01-13 13:49:03', NULL);
+INSERT INTO `sys_menu` VALUES (33, 10, 0, 1, 'Markdown', 'Markdown', 'components/MarkDown', 53, 'markdown', 'markdown', b'0', b'0', b'0', NULL, NULL, NULL, '2019-03-08 13:46:44', NULL);
+INSERT INTO `sys_menu` VALUES (34, 10, 0, 1, 'Yaml编辑器', 'YamlEdit', 'components/YamlEdit', 54, 'dev', 'yaml', b'0', b'0', b'0', NULL, NULL, NULL, '2019-03-08 15:49:40', NULL);
+INSERT INTO `sys_menu` VALUES (35, 1, 3, 1, '部门管理', 'Dept', 'system/dept/index', 6, 'dept', 'dept', b'0', b'0', b'0', 'dept:list', NULL, NULL, '2019-03-25 09:46:00', NULL);
+INSERT INTO `sys_menu` VALUES (36, NULL, 7, 0, '系统工具', NULL, '', 30, 'sys-tools', 'sys-tools', b'0', b'0', b'0', NULL, NULL, NULL, '2019-03-29 10:57:35', NULL);
+INSERT INTO `sys_menu` VALUES (37, 1, 3, 1, '岗位管理', 'Job', 'system/job/index', 7, 'Steve-Jobs', 'job', b'0', b'0', b'0', 'job:list', NULL, NULL, '2019-03-29 13:51:18', NULL);
+INSERT INTO `sys_menu` VALUES (38, 36, 0, 1, '接口文档', 'Swagger', 'tools/swagger/index', 36, 'swagger', 'swagger2', b'0', b'0', b'0', NULL, NULL, NULL, '2019-03-29 19:57:53', NULL);
+INSERT INTO `sys_menu` VALUES (39, 1, 3, 1, '字典管理', 'Dict', 'system/dict/index', 8, 'dictionary', 'dict', b'0', b'0', b'0', 'dict:list', NULL, NULL, '2019-04-10 11:49:04', NULL);
+INSERT INTO `sys_menu` VALUES (41, 6, 0, 1, '在线用户', 'OnlineUser', 'monitor/online/index', 10, 'Steve-Jobs', 'online', b'0', b'0', b'0', NULL, NULL, NULL, '2019-10-26 22:08:43', NULL);
+INSERT INTO `sys_menu` VALUES (44, 2, 0, 2, '用户新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'user:add', NULL, NULL, '2019-10-29 10:59:46', NULL);
+INSERT INTO `sys_menu` VALUES (45, 2, 0, 2, '用户编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'user:edit', NULL, NULL, '2019-10-29 11:00:08', NULL);
+INSERT INTO `sys_menu` VALUES (46, 2, 0, 2, '用户删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'user:del', NULL, NULL, '2019-10-29 11:00:23', NULL);
+INSERT INTO `sys_menu` VALUES (48, 3, 0, 2, '角色创建', NULL, '', 2, '', '', b'0', b'0', b'0', 'roles:add', NULL, NULL, '2019-10-29 12:45:34', NULL);
+INSERT INTO `sys_menu` VALUES (49, 3, 0, 2, '角色修改', NULL, '', 3, '', '', b'0', b'0', b'0', 'roles:edit', NULL, NULL, '2019-10-29 12:46:16', NULL);
+INSERT INTO `sys_menu` VALUES (50, 3, 0, 2, '角色删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'roles:del', NULL, NULL, '2019-10-29 12:46:51', NULL);
+INSERT INTO `sys_menu` VALUES (52, 5, 0, 2, '菜单新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'menu:add', NULL, NULL, '2019-10-29 12:55:07', NULL);
+INSERT INTO `sys_menu` VALUES (53, 5, 0, 2, '菜单编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'menu:edit', NULL, NULL, '2019-10-29 12:55:40', NULL);
+INSERT INTO `sys_menu` VALUES (54, 5, 0, 2, '菜单删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'menu:del', NULL, NULL, '2019-10-29 12:56:00', NULL);
+INSERT INTO `sys_menu` VALUES (56, 35, 0, 2, '部门新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'dept:add', NULL, NULL, '2019-10-29 12:57:09', NULL);
+INSERT INTO `sys_menu` VALUES (57, 35, 0, 2, '部门编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'dept:edit', NULL, NULL, '2019-10-29 12:57:27', NULL);
+INSERT INTO `sys_menu` VALUES (58, 35, 0, 2, '部门删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'dept:del', NULL, NULL, '2019-10-29 12:57:41', NULL);
+INSERT INTO `sys_menu` VALUES (60, 37, 0, 2, '岗位新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'job:add', NULL, NULL, '2019-10-29 12:58:27', NULL);
+INSERT INTO `sys_menu` VALUES (61, 37, 0, 2, '岗位编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'job:edit', NULL, NULL, '2019-10-29 12:58:45', NULL);
+INSERT INTO `sys_menu` VALUES (62, 37, 0, 2, '岗位删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'job:del', NULL, NULL, '2019-10-29 12:59:04', NULL);
+INSERT INTO `sys_menu` VALUES (64, 39, 0, 2, '字典新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'dict:add', NULL, NULL, '2019-10-29 13:00:17', NULL);
+INSERT INTO `sys_menu` VALUES (65, 39, 0, 2, '字典编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'dict:edit', NULL, NULL, '2019-10-29 13:00:42', NULL);
+INSERT INTO `sys_menu` VALUES (66, 39, 0, 2, '字典删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'dict:del', NULL, NULL, '2019-10-29 13:00:59', NULL);
+INSERT INTO `sys_menu` VALUES (73, 28, 0, 2, '任务新增', NULL, '', 2, '', '', b'0', b'0', b'0', 'timing:add', NULL, NULL, '2019-10-29 13:07:28', NULL);
+INSERT INTO `sys_menu` VALUES (74, 28, 0, 2, '任务编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'timing:edit', NULL, NULL, '2019-10-29 13:07:41', NULL);
+INSERT INTO `sys_menu` VALUES (75, 28, 0, 2, '任务删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'timing:del', NULL, NULL, '2019-10-29 13:07:54', NULL);
+INSERT INTO `sys_menu` VALUES (77, 18, 0, 2, '上传文件', NULL, '', 2, '', '', b'0', b'0', b'0', 'storage:add', NULL, NULL, '2019-10-29 13:09:09', NULL);
+INSERT INTO `sys_menu` VALUES (78, 18, 0, 2, '文件编辑', NULL, '', 3, '', '', b'0', b'0', b'0', 'storage:edit', NULL, NULL, '2019-10-29 13:09:22', NULL);
+INSERT INTO `sys_menu` VALUES (79, 18, 0, 2, '文件删除', NULL, '', 4, '', '', b'0', b'0', b'0', 'storage:del', NULL, NULL, '2019-10-29 13:09:34', NULL);
+INSERT INTO `sys_menu` VALUES (80, 6, 0, 1, '服务监控', 'ServerMonitor', 'monitor/server/index', 14, 'codeConsole', 'server', b'0', b'0', b'0', 'monitor:list', NULL, 'admin', '2019-11-07 13:06:39', '2020-05-04 18:20:50');
+INSERT INTO `sys_menu` VALUES (82, 36, 0, 1, '生成配置', 'GeneratorConfig', 'generator/config', 33, 'dev', 'generator/config/:tableName', b'0', b'1', b'1', '', NULL, NULL, '2019-11-17 20:08:56', NULL);
+INSERT INTO `sys_menu` VALUES (83, 10, 0, 1, '图表库', 'Echarts', 'components/Echarts', 50, 'chart', 'echarts', b'0', b'1', b'0', '', NULL, NULL, '2019-11-21 09:04:32', NULL);
+INSERT INTO `sys_menu` VALUES (90, NULL, 5, 1, '运维管理', 'Mnt', '', 20, 'mnt', 'mnt', b'0', b'0', b'0', NULL, NULL, NULL, '2019-11-09 10:31:08', NULL);
+INSERT INTO `sys_menu` VALUES (92, 90, 3, 1, '服务器', 'ServerDeploy', 'mnt/server/index', 22, 'server', 'mnt/serverDeploy', b'0', b'0', b'0', 'serverDeploy:list', NULL, NULL, '2019-11-10 10:29:25', NULL);
+INSERT INTO `sys_menu` VALUES (93, 90, 3, 1, '应用管理', 'App', 'mnt/app/index', 23, 'app', 'mnt/app', b'0', b'0', b'0', 'app:list', NULL, NULL, '2019-11-10 11:05:16', NULL);
+INSERT INTO `sys_menu` VALUES (94, 90, 3, 1, '部署管理', 'Deploy', 'mnt/deploy/index', 24, 'deploy', 'mnt/deploy', b'0', b'0', b'0', 'deploy:list', NULL, NULL, '2019-11-10 15:56:55', NULL);
+INSERT INTO `sys_menu` VALUES (97, 90, 1, 1, '部署备份', 'DeployHistory', 'mnt/deployHistory/index', 25, 'backup', 'mnt/deployHistory', b'0', b'0', b'0', 'deployHistory:list', NULL, NULL, '2019-11-10 16:49:44', NULL);
+INSERT INTO `sys_menu` VALUES (98, 90, 3, 1, '数据库管理', 'Database', 'mnt/database/index', 26, 'database', 'mnt/database', b'0', b'0', b'0', 'database:list', NULL, NULL, '2019-11-10 20:40:04', NULL);
+INSERT INTO `sys_menu` VALUES (102, 97, 0, 2, '删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'deployHistory:del', NULL, NULL, '2019-11-17 09:32:48', NULL);
+INSERT INTO `sys_menu` VALUES (103, 92, 0, 2, '服务器新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'serverDeploy:add', NULL, NULL, '2019-11-17 11:08:33', NULL);
+INSERT INTO `sys_menu` VALUES (104, 92, 0, 2, '服务器编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'serverDeploy:edit', NULL, NULL, '2019-11-17 11:08:57', NULL);
+INSERT INTO `sys_menu` VALUES (105, 92, 0, 2, '服务器删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'serverDeploy:del', NULL, NULL, '2019-11-17 11:09:15', NULL);
+INSERT INTO `sys_menu` VALUES (106, 93, 0, 2, '应用新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'app:add', NULL, NULL, '2019-11-17 11:10:03', NULL);
+INSERT INTO `sys_menu` VALUES (107, 93, 0, 2, '应用编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'app:edit', NULL, NULL, '2019-11-17 11:10:28', NULL);
+INSERT INTO `sys_menu` VALUES (108, 93, 0, 2, '应用删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'app:del', NULL, NULL, '2019-11-17 11:10:55', NULL);
+INSERT INTO `sys_menu` VALUES (109, 94, 0, 2, '部署新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'deploy:add', NULL, NULL, '2019-11-17 11:11:22', NULL);
+INSERT INTO `sys_menu` VALUES (110, 94, 0, 2, '部署编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'deploy:edit', NULL, NULL, '2019-11-17 11:11:41', NULL);
+INSERT INTO `sys_menu` VALUES (111, 94, 0, 2, '部署删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'deploy:del', NULL, NULL, '2019-11-17 11:12:01', NULL);
+INSERT INTO `sys_menu` VALUES (112, 98, 0, 2, '数据库新增', NULL, '', 999, '', '', b'0', b'0', b'0', 'database:add', NULL, NULL, '2019-11-17 11:12:43', NULL);
+INSERT INTO `sys_menu` VALUES (113, 98, 0, 2, '数据库编辑', NULL, '', 999, '', '', b'0', b'0', b'0', 'database:edit', NULL, NULL, '2019-11-17 11:12:58', NULL);
+INSERT INTO `sys_menu` VALUES (114, 98, 0, 2, '数据库删除', NULL, '', 999, '', '', b'0', b'0', b'0', 'database:del', NULL, NULL, '2019-11-17 11:13:14', NULL);
+INSERT INTO `sys_menu` VALUES (116, 36, 0, 1, '生成预览', 'Preview', 'generator/preview', 999, 'java', 'generator/preview/:tableName', b'0', b'1', b'1', NULL, NULL, NULL, '2019-11-26 14:54:36', NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_quartz_job
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_quartz_job`;
+CREATE TABLE `sys_quartz_job` (
+ `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `bean_name` varchar(255) DEFAULT NULL COMMENT 'Spring Bean名称',
+ `cron_expression` varchar(255) DEFAULT NULL COMMENT 'cron 表达式',
+ `is_pause` bit(1) DEFAULT NULL COMMENT '状态:1暂停、0启用',
+ `job_name` varchar(255) DEFAULT NULL COMMENT '任务名称',
+ `method_name` varchar(255) DEFAULT NULL COMMENT '方法名称',
+ `params` varchar(255) DEFAULT NULL COMMENT '参数',
+ `description` varchar(255) DEFAULT NULL COMMENT '备注',
+ `person_in_charge` varchar(100) DEFAULT NULL COMMENT '负责人',
+ `email` varchar(100) DEFAULT NULL COMMENT '报警邮箱',
+ `sub_task` varchar(100) DEFAULT NULL COMMENT '子任务ID',
+ `pause_after_failure` bit(1) DEFAULT NULL COMMENT '任务失败后是否暂停',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`job_id`) USING BTREE,
+ KEY `inx_is_pause` (`is_pause`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='定时任务';
+
+-- ----------------------------
+-- Records of sys_quartz_job
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_quartz_job` VALUES (2, 'testTask', '0/5 * * * * ?', b'1', '测试1', 'run1', 'test', '带参测试,多参使用json', '测试', NULL, NULL, NULL, NULL, 'admin', '2019-08-22 14:08:29', '2020-05-24 13:58:33');
+INSERT INTO `sys_quartz_job` VALUES (3, 'testTask', '0/5 * * * * ?', b'1', '测试', 'run', '', '不带参测试', 'Zheng Jie', '', '5,6', b'1', NULL, 'admin', '2019-09-26 16:44:39', '2020-05-24 14:48:12');
+INSERT INTO `sys_quartz_job` VALUES (5, 'Test', '0/5 * * * * ?', b'1', '任务告警测试', 'run', NULL, '测试', 'test', '', NULL, b'1', 'admin', 'admin', '2020-05-05 20:32:41', '2020-05-05 20:36:13');
+INSERT INTO `sys_quartz_job` VALUES (6, 'testTask', '0/5 * * * * ?', b'1', '测试3', 'run2', NULL, '测试3', 'Zheng Jie', '', NULL, b'1', 'admin', 'admin', '2020-05-05 20:35:41', '2020-05-05 20:36:07');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_quartz_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_quartz_log`;
+CREATE TABLE `sys_quartz_log` (
+ `log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `bean_name` varchar(255) DEFAULT NULL,
+ `create_time` datetime DEFAULT NULL,
+ `cron_expression` varchar(255) DEFAULT NULL,
+ `exception_detail` text DEFAULT NULL,
+ `is_success` bit(1) DEFAULT NULL,
+ `job_name` varchar(255) DEFAULT NULL,
+ `method_name` varchar(255) DEFAULT NULL,
+ `params` varchar(255) DEFAULT NULL,
+ `time` bigint(20) DEFAULT NULL,
+ PRIMARY KEY (`log_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=151 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='定时任务日志';
+
+-- ----------------------------
+-- Table structure for sys_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role`;
+CREATE TABLE `sys_role` (
+ `role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `name` varchar(255) NOT NULL COMMENT '名称',
+ `level` int(255) DEFAULT NULL COMMENT '角色级别',
+ `description` varchar(255) DEFAULT NULL COMMENT '描述',
+ `data_scope` varchar(255) DEFAULT NULL COMMENT '数据权限',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`role_id`) USING BTREE,
+ UNIQUE KEY `uniq_name` (`name`),
+ KEY `role_name_index` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色表';
+
+-- ----------------------------
+-- Records of sys_role
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_role` VALUES (1, '超级管理员', 1, '-', '全部', NULL, 'admin', '2018-11-23 11:04:37', '2020-08-06 16:10:24');
+INSERT INTO `sys_role` VALUES (2, '普通用户', 2, '-', '本级', NULL, 'admin', '2018-11-23 13:09:06', '2020-09-05 10:45:12');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_roles_depts
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_roles_depts`;
+CREATE TABLE `sys_roles_depts` (
+ `role_id` bigint(20) NOT NULL,
+ `dept_id` bigint(20) NOT NULL,
+ PRIMARY KEY (`role_id`,`dept_id`) USING BTREE,
+ KEY `FK7qg6itn5ajdoa9h9o78v9ksur` (`dept_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色部门关联';
+
+-- ----------------------------
+-- Table structure for sys_roles_menus
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_roles_menus`;
+CREATE TABLE `sys_roles_menus` (
+ `menu_id` bigint(20) NOT NULL COMMENT '菜单ID',
+ `role_id` bigint(20) NOT NULL COMMENT '角色ID',
+ PRIMARY KEY (`menu_id`,`role_id`) USING BTREE,
+ KEY `FKcngg2qadojhi3a651a5adkvbq` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色菜单关联';
+
+-- ----------------------------
+-- Records of sys_roles_menus
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_roles_menus` VALUES (1, 1);
+INSERT INTO `sys_roles_menus` VALUES (2, 1);
+INSERT INTO `sys_roles_menus` VALUES (3, 1);
+INSERT INTO `sys_roles_menus` VALUES (5, 1);
+INSERT INTO `sys_roles_menus` VALUES (6, 1);
+INSERT INTO `sys_roles_menus` VALUES (7, 1);
+INSERT INTO `sys_roles_menus` VALUES (9, 1);
+INSERT INTO `sys_roles_menus` VALUES (10, 1);
+INSERT INTO `sys_roles_menus` VALUES (11, 1);
+INSERT INTO `sys_roles_menus` VALUES (14, 1);
+INSERT INTO `sys_roles_menus` VALUES (15, 1);
+INSERT INTO `sys_roles_menus` VALUES (18, 1);
+INSERT INTO `sys_roles_menus` VALUES (19, 1);
+INSERT INTO `sys_roles_menus` VALUES (21, 1);
+INSERT INTO `sys_roles_menus` VALUES (22, 1);
+INSERT INTO `sys_roles_menus` VALUES (23, 1);
+INSERT INTO `sys_roles_menus` VALUES (24, 1);
+INSERT INTO `sys_roles_menus` VALUES (27, 1);
+INSERT INTO `sys_roles_menus` VALUES (28, 1);
+INSERT INTO `sys_roles_menus` VALUES (30, 1);
+INSERT INTO `sys_roles_menus` VALUES (32, 1);
+INSERT INTO `sys_roles_menus` VALUES (33, 1);
+INSERT INTO `sys_roles_menus` VALUES (34, 1);
+INSERT INTO `sys_roles_menus` VALUES (35, 1);
+INSERT INTO `sys_roles_menus` VALUES (36, 1);
+INSERT INTO `sys_roles_menus` VALUES (37, 1);
+INSERT INTO `sys_roles_menus` VALUES (38, 1);
+INSERT INTO `sys_roles_menus` VALUES (39, 1);
+INSERT INTO `sys_roles_menus` VALUES (41, 1);
+INSERT INTO `sys_roles_menus` VALUES (44, 1);
+INSERT INTO `sys_roles_menus` VALUES (45, 1);
+INSERT INTO `sys_roles_menus` VALUES (46, 1);
+INSERT INTO `sys_roles_menus` VALUES (48, 1);
+INSERT INTO `sys_roles_menus` VALUES (49, 1);
+INSERT INTO `sys_roles_menus` VALUES (50, 1);
+INSERT INTO `sys_roles_menus` VALUES (52, 1);
+INSERT INTO `sys_roles_menus` VALUES (53, 1);
+INSERT INTO `sys_roles_menus` VALUES (54, 1);
+INSERT INTO `sys_roles_menus` VALUES (56, 1);
+INSERT INTO `sys_roles_menus` VALUES (57, 1);
+INSERT INTO `sys_roles_menus` VALUES (58, 1);
+INSERT INTO `sys_roles_menus` VALUES (60, 1);
+INSERT INTO `sys_roles_menus` VALUES (61, 1);
+INSERT INTO `sys_roles_menus` VALUES (62, 1);
+INSERT INTO `sys_roles_menus` VALUES (64, 1);
+INSERT INTO `sys_roles_menus` VALUES (65, 1);
+INSERT INTO `sys_roles_menus` VALUES (66, 1);
+INSERT INTO `sys_roles_menus` VALUES (73, 1);
+INSERT INTO `sys_roles_menus` VALUES (74, 1);
+INSERT INTO `sys_roles_menus` VALUES (75, 1);
+INSERT INTO `sys_roles_menus` VALUES (77, 1);
+INSERT INTO `sys_roles_menus` VALUES (78, 1);
+INSERT INTO `sys_roles_menus` VALUES (79, 1);
+INSERT INTO `sys_roles_menus` VALUES (80, 1);
+INSERT INTO `sys_roles_menus` VALUES (82, 1);
+INSERT INTO `sys_roles_menus` VALUES (83, 1);
+INSERT INTO `sys_roles_menus` VALUES (90, 1);
+INSERT INTO `sys_roles_menus` VALUES (92, 1);
+INSERT INTO `sys_roles_menus` VALUES (93, 1);
+INSERT INTO `sys_roles_menus` VALUES (94, 1);
+INSERT INTO `sys_roles_menus` VALUES (97, 1);
+INSERT INTO `sys_roles_menus` VALUES (98, 1);
+INSERT INTO `sys_roles_menus` VALUES (102, 1);
+INSERT INTO `sys_roles_menus` VALUES (103, 1);
+INSERT INTO `sys_roles_menus` VALUES (104, 1);
+INSERT INTO `sys_roles_menus` VALUES (105, 1);
+INSERT INTO `sys_roles_menus` VALUES (106, 1);
+INSERT INTO `sys_roles_menus` VALUES (107, 1);
+INSERT INTO `sys_roles_menus` VALUES (108, 1);
+INSERT INTO `sys_roles_menus` VALUES (109, 1);
+INSERT INTO `sys_roles_menus` VALUES (110, 1);
+INSERT INTO `sys_roles_menus` VALUES (111, 1);
+INSERT INTO `sys_roles_menus` VALUES (112, 1);
+INSERT INTO `sys_roles_menus` VALUES (113, 1);
+INSERT INTO `sys_roles_menus` VALUES (114, 1);
+INSERT INTO `sys_roles_menus` VALUES (116, 1);
+INSERT INTO `sys_roles_menus` VALUES (120, 1);
+INSERT INTO `sys_roles_menus` VALUES (1, 2);
+INSERT INTO `sys_roles_menus` VALUES (2, 2);
+INSERT INTO `sys_roles_menus` VALUES (6, 2);
+INSERT INTO `sys_roles_menus` VALUES (7, 2);
+INSERT INTO `sys_roles_menus` VALUES (9, 2);
+INSERT INTO `sys_roles_menus` VALUES (10, 2);
+INSERT INTO `sys_roles_menus` VALUES (11, 2);
+INSERT INTO `sys_roles_menus` VALUES (14, 2);
+INSERT INTO `sys_roles_menus` VALUES (15, 2);
+INSERT INTO `sys_roles_menus` VALUES (19, 2);
+INSERT INTO `sys_roles_menus` VALUES (21, 2);
+INSERT INTO `sys_roles_menus` VALUES (22, 2);
+INSERT INTO `sys_roles_menus` VALUES (23, 2);
+INSERT INTO `sys_roles_menus` VALUES (24, 2);
+INSERT INTO `sys_roles_menus` VALUES (27, 2);
+INSERT INTO `sys_roles_menus` VALUES (30, 2);
+INSERT INTO `sys_roles_menus` VALUES (32, 2);
+INSERT INTO `sys_roles_menus` VALUES (33, 2);
+INSERT INTO `sys_roles_menus` VALUES (34, 2);
+INSERT INTO `sys_roles_menus` VALUES (36, 2);
+INSERT INTO `sys_roles_menus` VALUES (80, 2);
+INSERT INTO `sys_roles_menus` VALUES (82, 2);
+INSERT INTO `sys_roles_menus` VALUES (83, 2);
+INSERT INTO `sys_roles_menus` VALUES (116, 2);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_user
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user`;
+CREATE TABLE `sys_user` (
+ `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `dept_id` bigint(20) DEFAULT NULL COMMENT '部门名称',
+ `username` varchar(255) DEFAULT NULL COMMENT '用户名',
+ `nick_name` varchar(255) DEFAULT NULL COMMENT '昵称',
+ `gender` varchar(2) DEFAULT NULL COMMENT '性别',
+ `phone` varchar(255) DEFAULT NULL COMMENT '手机号码',
+ `email` varchar(255) DEFAULT NULL COMMENT '邮箱',
+ `avatar_name` varchar(255) DEFAULT NULL COMMENT '头像地址',
+ `avatar_path` varchar(255) DEFAULT NULL COMMENT '头像真实路径',
+ `password` varchar(255) DEFAULT NULL COMMENT '密码',
+ `is_admin` bit(1) DEFAULT b'0' COMMENT '是否为admin账号',
+ `enabled` bigint(20) DEFAULT NULL COMMENT '状态:1启用、0禁用',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `pwd_reset_time` datetime DEFAULT NULL COMMENT '修改密码的时间',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`user_id`) USING BTREE,
+ UNIQUE KEY `UK_kpubos9gc2cvtkb0thktkbkes` (`email`) USING BTREE,
+ UNIQUE KEY `username` (`username`) USING BTREE,
+ UNIQUE KEY `uniq_username` (`username`),
+ UNIQUE KEY `uniq_email` (`email`),
+ KEY `FK5rwmryny6jthaaxkogownknqp` (`dept_id`) USING BTREE,
+ KEY `FKpq2dhypk2qgt68nauh2by22jb` (`avatar_name`) USING BTREE,
+ KEY `inx_enabled` (`enabled`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统用户';
+
+-- ----------------------------
+-- Records of sys_user
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_user` VALUES (1, 2, 'admin', '管理员', '男', '18888888888', '[email protected]', 'avatar-20200806032259161.png', '/Users/jie/Documents/work/me/admin/dns/~/avatar/avatar-20200806032259161.png', '$2a$10$Egp1/gvFlt7zhlXVfEFw4OfWQCGPw0ClmMcc6FjTnvXNRVf9zdMRa', b'1', 1, NULL, 'admin', '2020-05-03 16:38:31', '2018-08-23 09:11:56', '2020-09-05 10:43:31');
+INSERT INTO `sys_user` VALUES (2, 2, 'test', '测试', '男', '19999999999', '[email protected]', NULL, NULL, '$2a$10$4XcyudOYTSz6fue6KFNMHeUQnCX5jbBQypLEnGk1PmekXt5c95JcK', b'0', 1, 'admin', 'admin', NULL, '2020-05-05 11:15:49', '2020-09-05 10:43:38');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_users_jobs
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_users_jobs`;
+CREATE TABLE `sys_users_jobs` (
+ `user_id` bigint(20) NOT NULL COMMENT '用户ID',
+ `job_id` bigint(20) NOT NULL COMMENT '岗位ID',
+ PRIMARY KEY (`user_id`,`job_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Records of sys_users_jobs
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_users_jobs` VALUES (1, 11);
+INSERT INTO `sys_users_jobs` VALUES (2, 12);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for sys_users_roles
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_users_roles`;
+CREATE TABLE `sys_users_roles` (
+ `user_id` bigint(20) NOT NULL COMMENT '用户ID',
+ `role_id` bigint(20) NOT NULL COMMENT '角色ID',
+ PRIMARY KEY (`user_id`,`role_id`) USING BTREE,
+ KEY `FKq4eq273l04bpu4efj0jd0jb98` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='用户角色关联';
+
+-- ----------------------------
+-- Records of sys_users_roles
+-- ----------------------------
+BEGIN;
+INSERT INTO `sys_users_roles` VALUES (1, 1);
+INSERT INTO `sys_users_roles` VALUES (2, 2);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for tool_alipay_config
+-- ----------------------------
+DROP TABLE IF EXISTS `tool_alipay_config`;
+CREATE TABLE `tool_alipay_config` (
+ `config_id` bigint(20) NOT NULL COMMENT 'ID',
+ `app_id` varchar(255) DEFAULT NULL COMMENT '应用ID',
+ `charset` varchar(255) DEFAULT NULL COMMENT '编码',
+ `format` varchar(255) DEFAULT NULL COMMENT '类型 固定格式json',
+ `gateway_url` varchar(255) DEFAULT NULL COMMENT '网关地址',
+ `notify_url` varchar(255) DEFAULT NULL COMMENT '异步回调',
+ `private_key` text DEFAULT NULL COMMENT '私钥',
+ `public_key` text DEFAULT NULL COMMENT '公钥',
+ `return_url` varchar(255) DEFAULT NULL COMMENT '回调地址',
+ `sign_type` varchar(255) DEFAULT NULL COMMENT '签名方式',
+ `sys_service_provider_id` varchar(255) DEFAULT NULL COMMENT '商户号',
+ PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='支付宝配置类';
+
+-- ----------------------------
+-- Records of tool_alipay_config
+-- ----------------------------
+BEGIN;
+INSERT INTO `tool_alipay_config` VALUES (1, '2016091700532697', 'utf-8', 'JSON', 'https://openapi.alipaydev.com/gateway.do', 'http://api.auauz.net/api/aliPay/notify', 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5js8sInU10AJ0cAQ8UMMyXrQ+oHZEkVt5lBwsStmTJ7YikVYgbskx1YYEXTojRsWCb+SH/kDmDU4pK/u91SJ4KFCRMF2411piYuXU/jF96zKrADznYh/zAraqT6hvAIVtQAlMHN53nx16rLzZ/8jDEkaSwT7+HvHiS+7sxSojnu/3oV7BtgISoUNstmSe8WpWHOaWv19xyS+Mce9MY4BfseFhzTICUymUQdd/8hXA28/H6osUfAgsnxAKv7Wil3aJSgaJczWuflYOve0dJ3InZkhw5Cvr0atwpk8YKBQjy5CdkoHqvkOcIB+cYHXJKzOE5tqU7inSwVbHzOLQ3XbnAgMBAAECggEAVJp5eT0Ixg1eYSqFs9568WdetUNCSUchNxDBu6wxAbhUgfRUGZuJnnAll63OCTGGck+EGkFh48JjRcBpGoeoHLL88QXlZZbC/iLrea6gcDIhuvfzzOffe1RcZtDFEj9hlotg8dQj1tS0gy9pN9g4+EBH7zeu+fyv+qb2e/v1l6FkISXUjpkD7RLQr3ykjiiEw9BpeKb7j5s7Kdx1NNIzhkcQKNqlk8JrTGDNInbDM6inZfwwIO2R1DHinwdfKWkvOTODTYa2MoAvVMFT9Bec9FbLpoWp7ogv1JMV9svgrcF9XLzANZ/OQvkbe9TV9GWYvIbxN6qwQioKCWO4GPnCAQKBgQDgW5MgfhX8yjXqoaUy/d1VjI8dHeIyw8d+OBAYwaxRSlCfyQ+tieWcR2HdTzPca0T0GkWcKZm0ei5xRURgxt4DUDLXNh26HG0qObbtLJdu/AuBUuCqgOiLqJ2f1uIbrz6OZUHns+bT/jGW2Ws8+C13zTCZkZt9CaQsrp3QOGDx5wKBgQDTul39hp3ZPwGNFeZdkGoUoViOSd5Lhowd5wYMGAEXWRLlU8z+smT5v0POz9JnIbCRchIY2FAPKRdVTICzmPk2EPJFxYTcwaNbVqL6lN7J2IlXXMiit5QbiLauo55w7plwV6LQmKm9KV7JsZs5XwqF7CEovI7GevFzyD3w+uizAQKBgC3LY1eRhOlpWOIAhpjG6qOoohmeXOphvdmMlfSHq6WYFqbWwmV4rS5d/6LNpNdL6fItXqIGd8I34jzql49taCmi+A2nlR/E559j0mvM20gjGDIYeZUz5MOE8k+K6/IcrhcgofgqZ2ZED1ksHdB/E8DNWCswZl16V1FrfvjeWSNnAoGAMrBplCrIW5xz+J0Hm9rZKrs+AkK5D4fUv8vxbK/KgxZ2KaUYbNm0xv39c+PZUYuFRCz1HDGdaSPDTE6WeWjkMQd5mS6ikl9hhpqFRkyh0d0fdGToO9yLftQKOGE/q3XUEktI1XvXF0xyPwNgUCnq0QkpHyGVZPtGFxwXiDvpvgECgYA5PoB+nY8iDiRaJNko9w0hL4AeKogwf+4TbCw+KWVEn6jhuJa4LFTdSqp89PktQaoVpwv92el/AhYjWOl/jVCm122f9b7GyoelbjMNolToDwe5pF5RnSpEuDdLy9MfE8LnE3PlbE7E5BipQ3UjSebkgNboLHH/lNZA5qvEtvbfvQ==', 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAut9evKRuHJ/2QNfDlLwvN/S8l9hRAgPbb0u61bm4AtzaTGsLeMtScetxTWJnVvAVpMS9luhEJjt+Sbk5TNLArsgzzwARgaTKOLMT1TvWAK5EbHyI+eSrc3s7Awe1VYGwcubRFWDm16eQLv0k7iqiw+4mweHSz/wWyvBJVgwLoQ02btVtAQErCfSJCOmt0Q/oJQjj08YNRV4EKzB19+f5A+HQVAKy72dSybTzAK+3FPtTtNen/+b5wGeat7c32dhYHnGorPkPeXLtsqqUTp1su5fMfd4lElNdZaoCI7osZxWWUo17vBCZnyeXc9fk0qwD9mK6yRAxNbrY72Xx5VqIqwIDAQAB', 'http://api.auauz.net/api/aliPay/return', 'RSA2', '2088102176044281');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for tool_email_config
+-- ----------------------------
+DROP TABLE IF EXISTS `tool_email_config`;
+CREATE TABLE `tool_email_config` (
+ `config_id` bigint(20) NOT NULL COMMENT 'ID',
+ `from_user` varchar(255) DEFAULT NULL COMMENT '收件人',
+ `host` varchar(255) DEFAULT NULL COMMENT '邮件服务器SMTP地址',
+ `pass` varchar(255) DEFAULT NULL COMMENT '密码',
+ `port` varchar(255) DEFAULT NULL COMMENT '端口',
+ `user` varchar(255) DEFAULT NULL COMMENT '发件者用户名',
+ PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='邮箱配置';
+
+-- ----------------------------
+-- Table structure for tool_local_storage
+-- ----------------------------
+DROP TABLE IF EXISTS `tool_local_storage`;
+CREATE TABLE `tool_local_storage` (
+ `storage_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `real_name` varchar(255) DEFAULT NULL COMMENT '文件真实的名称',
+ `name` varchar(255) DEFAULT NULL COMMENT '文件名',
+ `suffix` varchar(255) DEFAULT NULL COMMENT '后缀',
+ `path` varchar(255) DEFAULT NULL COMMENT '路径',
+ `type` varchar(255) DEFAULT NULL COMMENT '类型',
+ `size` varchar(100) DEFAULT NULL COMMENT '大小',
+ `create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
+ `update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建日期',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`storage_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='本地存储';
+
+-- ----------------------------
+-- Records of tool_local_storage
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for tool_qiniu_config
+-- ----------------------------
+DROP TABLE IF EXISTS `tool_qiniu_config`;
+CREATE TABLE `tool_qiniu_config` (
+ `config_id` bigint(20) NOT NULL COMMENT 'ID',
+ `access_key` text DEFAULT NULL COMMENT 'accessKey',
+ `bucket` varchar(255) DEFAULT NULL COMMENT 'Bucket 识别符',
+ `host` varchar(255) NOT NULL COMMENT '外链域名',
+ `secret_key` text DEFAULT NULL COMMENT 'secretKey',
+ `type` varchar(255) DEFAULT NULL COMMENT '空间类型',
+ `zone` varchar(255) DEFAULT NULL COMMENT '机房',
+ PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='七牛云配置';
+
+-- ----------------------------
+-- Table structure for tool_qiniu_content
+-- ----------------------------
+DROP TABLE IF EXISTS `tool_qiniu_content`;
+CREATE TABLE `tool_qiniu_content` (
+ `content_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `bucket` varchar(255) DEFAULT NULL COMMENT 'Bucket 识别符',
+ `name` varchar(255) DEFAULT NULL COMMENT '文件名称',
+ `size` varchar(255) DEFAULT NULL COMMENT '文件大小',
+ `type` varchar(255) DEFAULT NULL COMMENT '文件类型:私有或公开',
+ `url` varchar(255) DEFAULT NULL COMMENT '文件url',
+ `suffix` varchar(255) DEFAULT NULL COMMENT '文件后缀',
+ `update_time` datetime DEFAULT NULL COMMENT '上传或同步的时间',
+ PRIMARY KEY (`content_id`) USING BTREE,
+ UNIQUE KEY `uniq_name` (`name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='七牛云文件存储';
+
+-- ----------------------------
+-- Records of tool_qiniu_content
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/UI source code/dns-dev-2.0/sql/tool_picture.sql b/UI source code/dns-dev-2.0/sql/tool_picture.sql
new file mode 100644
index 0000000..6b36d0d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/sql/tool_picture.sql
@@ -0,0 +1,2 @@
+-- 删除免费图床表
+DROP TABLE tool_picture; \ No newline at end of file
diff --git a/UI source code/dns-dev-2.0/sql/脚本如何选择.md b/UI source code/dns-dev-2.0/sql/脚本如何选择.md
new file mode 100644
index 0000000..9734971
--- /dev/null
+++ b/UI source code/dns-dev-2.0/sql/脚本如何选择.md
@@ -0,0 +1,11 @@
+## 脚本指南
+项目根目录的 sql 文件夹内提供了本次数据库变更的脚本,脚本如何选择,以及执行的顺序如下
+
+::: tip 注意
+操作数据库属于危险行为,请勿用于生产库,请事先做好备份!!!
+:::
+
+### 初次使用
+dns.sql 为 dns 项目完整的 sql 脚本,适合于初次使用的用户
+
+### 更新迭代