From dae82f62edd6337dd64e10eb7db008abff4d2388 Mon Sep 17 00:00:00 2001 From: macro Date: Sat, 15 Aug 2020 10:51:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7Spring=20Cloud=20Hoxton=20&?= =?UTF-8?q?=20Alibaba=EF=BC=8C=E8=AE=A4=E8=AF=81=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E6=94=B9=E7=94=A8Oauth2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 104 +++++---- .../admin/mall-admin-dev.yaml | 12 +- .../admin/mall-admin-prod.yaml | 13 +- .../demo/mall-demo-dev.yaml | 5 +- .../demo/mall-demo-prod.yaml | 8 +- config/gateway/mall-gateway-dev.yaml | 18 ++ config/gateway/mall-gateway-prod.yaml | 19 ++ .../portal/mall-portal-dev.yaml | 8 +- .../portal/mall-portal-prod.yaml | 8 + .../search/mall-search-dev.yaml | 10 +- .../search/mall-search-prod.yaml | 16 +- document/docker/docker-compose-app.yml | 57 ++++- document/docker/docker-compose-env.yml | 34 ++- document/docker/docker-deploy.md | 149 ------------ document/elk/logstash-springboot.conf | 14 -- document/elk/logstash.conf | 49 ++++ document/resource/mall_swarm_linux_02.png | Bin 64881 -> 0 bytes document/resource/mall_swarm_linux_04.png | Bin 32261 -> 0 bytes document/resource/mall_swarm_linux_07.png | Bin 37264 -> 0 bytes document/resource/mall_swarm_linux_08.png | Bin 28707 -> 0 bytes document/resource/mall_swarm_linux_09.png | Bin 17266 -> 0 bytes document/resource/mall_swarm_run_01.png | Bin 0 -> 22507 bytes document/resource/mall_swarm_run_02.png | Bin 0 -> 25850 bytes document/resource/mall_swarm_run_03.png | Bin 0 -> 17262 bytes document/resource/mall_swarm_run_04.png | Bin 0 -> 30672 bytes document/resource/mall_swarm_run_05.png | Bin 0 -> 25328 bytes document/resource/mall_swarm_run_06.png | Bin 0 -> 73150 bytes document/resource/mall_swarm_run_07.png | Bin 0 -> 87573 bytes document/resource/mall_swarm_run_08.png | Bin 0 -> 37677 bytes document/resource/mall_swarm_run_09.png | Bin 0 -> 7070 bytes document/resource/mall_swarm_run_10.png | Bin 0 -> 20914 bytes document/resource/mall_swarm_run_11.png | Bin 0 -> 21463 bytes document/resource/rabbitmq_install_1.png | Bin 13222 -> 0 bytes document/resource/rabbitmq_install_2.png | Bin 40324 -> 0 bytes document/resource/rabbitmq_install_3.png | Bin 34441 -> 0 bytes document/resource/rabbitmq_install_4.png | Bin 35392 -> 0 bytes mall-admin/pom.xml | 28 ++- .../com/macro/mall/MallAdminApplication.java | 2 + .../com/macro/mall/bo/AdminUserDetails.java | 62 ----- .../main/java/com/macro/mall/bo/WebLog.java | 144 ------------ .../component/ResourceRoleRulesHolder.java | 23 ++ .../macro/mall/config/GlobalCorsConfig.java | 35 --- .../macro/mall/config/MallSecurityConfig.java | 56 ----- .../com/macro/mall/config/MyBatisConfig.java | 2 +- .../java/com/macro/mall/config/OssConfig.java | 1 + .../com/macro/mall/config/RedisConfig.java | 19 ++ .../com/macro/mall/config/Swagger2Config.java | 80 ------- .../com/macro/mall/config/SwaggerConfig.java | 41 ++++ .../mall/controller/MinioController.java | 50 +++- .../mall/controller/UmsAdminController.java | 56 ++--- .../controller/UmsResourceController.java | 15 +- .../CmsPrefrenceAreaProductRelationDao.java | 2 +- .../dao/CmsSubjectProductRelationDao.java | 2 +- .../dao/PmsProductAttributeCategoryDao.java | 2 +- .../macro/mall/dao/PmsProductCategoryDao.java | 2 +- .../com/macro/mall/dao/PmsProductDao.java | 2 +- .../macro/mall/dao/PmsProductLadderDao.java | 3 + .../mall/dao/PmsProductVertifyRecordDao.java | 5 +- .../com/macro/mall/dao/PmsSkuStockDao.java | 2 +- .../java/com/macro/mall/dao/SmsCouponDao.java | 5 +- .../SmsCouponProductCategoryRelationDao.java | 5 +- .../mall/dao/SmsCouponProductRelationDao.java | 5 +- .../SmsFlashPromotionProductRelationDao.java | 2 +- .../dao/UmsAdminPermissionRelationDao.java | 5 +- .../mall/dao/UmsAdminRoleRelationDao.java | 7 +- .../java/com/macro/mall/dao/UmsRoleDao.java | 13 +- .../dao/UmsRolePermissionRelationDao.java | 2 +- .../macro/mall/dto/BucketPolicyConfigDto.java | 31 +++ .../com/macro/mall/dto/MinioUploadDto.java | 3 + .../com/macro/mall/dto/OmsMoneyInfoParam.java | 5 + .../com/macro/mall/dto/OmsOrderDetail.java | 3 + .../mall/dto/OmsOrderReturnApplyResult.java | 2 + .../macro/mall/dto/OmsReceiverInfoParam.java | 10 + .../com/macro/mall/dto/OssCallbackParam.java | 28 +-- .../com/macro/mall/dto/OssCallbackResult.java | 44 +--- .../com/macro/mall/dto/OssPolicyResult.java | 52 +---- .../com/macro/mall/dto/PmsBrandParam.java | 68 +----- .../dto/PmsProductAttributeCategoryItem.java | 15 +- .../mall/dto/PmsProductAttributeParam.java | 92 +------- .../mall/dto/PmsProductCategoryParam.java | 84 +------ .../PmsProductCategoryWithChildrenItem.java | 14 +- .../com/macro/mall/dto/PmsProductParam.java | 60 +---- .../macro/mall/dto/PmsProductQueryParam.java | 52 +---- .../com/macro/mall/dto/PmsProductResult.java | 16 +- .../com/macro/mall/dto/ProductAttrInfo.java | 24 +- .../com/macro/mall/dto/SmsCouponParam.java | 27 +-- .../mall/dto/SmsFlashPromotionProduct.java | 2 + .../dto/SmsFlashPromotionSessionDetail.java | 2 + .../macro/mall/dto/UmsAdminLoginParam.java | 20 +- .../java/com/macro/mall/dto/UmsMenuNode.java | 2 + .../com/macro/mall/dto/UmsPermissionNode.java | 2 + .../com/macro/mall/service/AuthService.java | 20 ++ .../service/PmsProductAttributeService.java | 9 +- .../mall/service/UmsAdminCacheService.java | 27 +++ .../macro/mall/service/UmsAdminService.java | 25 +- .../mall/service/UmsResourceService.java | 6 + .../impl/UmsAdminCacheServiceImpl.java | 45 ++++ .../service/impl/UmsAdminServiceImpl.java | 113 +++++---- .../service/impl/UmsResourceServiceImpl.java | 50 +++- .../mall/service/impl/UmsRoleServiceImpl.java | 9 +- mall-admin/src/main/resources/application.yml | 46 ++-- .../src/main/resources/bootstrap-dev.yml | 15 +- .../src/main/resources/bootstrap-prod.yml | 17 +- .../resources/dao/UmsAdminRoleRelationDao.xml | 8 + .../src/main/resources/logback-spring.xml | 32 --- {mall-config => mall-auth}/pom.xml | 55 ++++- .../macro/mall/auth/MallAuthApplication.java | 12 +- .../mall/auth/component/JwtTokenEnhancer.java | 29 +++ .../mall/auth/config/Oauth2ServerConfig.java | 89 +++++++ .../macro/mall/auth/config/SwaggerConfig.java | 27 +++ .../mall/auth/config/WebSecurityConfig.java | 41 ++++ .../mall/auth/constant/MessageConstant.java | 23 ++ .../mall/auth/controller/AuthController.java | 55 +++++ .../auth/controller/KeyPairController.java | 30 +++ .../mall/auth/domain/Oauth2TokenDto.java | 24 ++ .../macro/mall/auth/domain/SecurityUser.java | 95 ++++++++ .../exception/Oauth2ExceptionHandler.java | 20 ++ .../mall/auth/service/UmsAdminService.java | 16 ++ .../mall/auth/service/UmsMemberService.java | 15 ++ .../auth/service/impl/UserServiceImpl.java | 61 +++++ mall-auth/src/main/resources/application.yml | 13 ++ .../src/main/resources/bootstrap-dev.yml | 11 + .../src/main/resources/bootstrap-prod.yml | 11 + mall-auth/src/main/resources/bootstrap.yml | 5 + mall-auth/src/main/resources/jwt.jks | Bin 0 -> 1398 bytes mall-common/pom.xml | 22 +- .../common/annotation/CacheException.java | 12 + .../mall/common/config/BaseRedisConfig.java | 69 ++++++ .../mall/common/config/BaseSwaggerConfig.java | 54 ++--- .../mall/common/constant/AuthConstant.java | 54 +++++ .../mall/common/domain/SwaggerProperties.java | 47 ++++ .../com/macro/mall/common/domain/UserDto.java | 24 ++ .../com/macro/mall/common/domain/WebLog.java | 68 ++++++ .../macro/mall/common/log}/WebLogAspect.java | 7 +- .../mall/common/service/RedisService.java | 182 +++++++++++++++ .../common/service/impl/RedisServiceImpl.java | 198 ++++++++++++++++ .../src/main/resources/logback-spring.xml | 221 ++++++++++++++++++ mall-config/.gitignore | 31 --- .../src/main/resources/application-dev.yml | 4 - .../src/main/resources/application-native.yml | 4 - .../src/main/resources/application-prod.yml | 6 - .../src/main/resources/application.yml | 18 -- .../mall/MallConfigApplicationTests.java | 16 -- mall-demo/pom.xml | 20 +- .../mall/demo/config/Swagger2Config.java | 79 ------- .../macro/mall/demo/config/SwaggerConfig.java | 42 ++++ .../mall/demo/dto/UmsAdminLoginParam.java | 1 - mall-demo/src/main/resources/application.yml | 3 + .../src/main/resources/bootstrap-dev.yml | 15 +- .../src/main/resources/bootstrap-prod.yml | 17 +- mall-gateway/pom.xml | 46 +++- .../authorization/AuthorizationManager.java | 104 +++++++++ .../RestAuthenticationEntryPoint.java | 35 +++ .../component/RestfulAccessDeniedHandler.java | 36 +++ .../macro/mall/config/GlobalCorsConfig.java | 2 +- .../macro/mall/config/IgnoreUrlsConfig.java | 20 ++ .../com/macro/mall/config/RedisConfig.java | 19 ++ .../mall/config/ResourceServerConfig.java | 66 ++++++ .../mall/config/SwaggerResourceConfig.java | 55 +++++ .../macro/mall/filter/AuthGlobalFilter.java | 51 ++++ .../filter/IgnoreUrlsRemoveJwtFilter.java | 43 ++++ .../macro/mall/handler/SwaggerHandler.java | 58 +++++ .../src/main/resources/application-dev.yml | 5 - .../src/main/resources/application-prod.yml | 7 - .../src/main/resources/application.yml | 72 +++++- .../src/main/resources/bootstrap-dev.yml | 8 + .../src/main/resources/bootstrap-prod.yml | 8 + mall-gateway/src/main/resources/bootstrap.yml | 5 + mall-mbg/pom.xml | 8 + mall-monitor/pom.xml | 4 +- .../src/main/resources/application-dev.yml | 9 +- .../src/main/resources/application-prod.yml | 11 +- .../src/main/resources/application.yml | 6 - mall-portal/pom.xml | 18 +- .../mall/portal/MallPortalApplication.java | 2 + .../portal/config/MallSecurityConfig.java | 35 --- .../macro/mall/portal/config/RedisConfig.java | 15 ++ .../mall/portal/config/SwaggerConfig.java | 41 ++++ .../portal/controller/HomeController.java | 18 ++ .../controller/MemberAttentionController.java | 32 ++- .../MemberCollectionController.java | 56 ----- .../MemberProductCollectionController.java | 75 ++++++ .../MemberReadHistoryController.java | 19 +- .../controller/OmsCartItemController.java | 4 +- .../controller/OmsPortalOrderController.java | 58 ++++- .../PmsPortalProductController.java | 60 +++++ .../controller/PortalBrandController.java | 54 +++++ .../controller/UmsMemberController.java | 45 ++-- .../controller/UmsMemberCouponController.java | 27 ++- .../UmsMemberReceiveAddressController.java | 2 +- .../mall/portal/dao/PortalProductDao.java | 2 + .../mall/portal/dao/SmsCouponHistoryDao.java | 3 + .../portal/domain/MemberBrandAttention.java | 9 - .../mall/portal/domain/MemberDetails.java | 122 +++++----- .../macro/mall/portal/domain/OrderParam.java | 50 ++-- .../portal/domain/PmsPortalProductDetail.java | 33 +++ .../portal/domain/PmsProductCategoryNode.java | 17 ++ .../MemberBrandAttentionRepository.java | 5 +- .../MemberProductCollectionRepository.java | 5 +- .../MemberReadHistoryRepository.java | 5 +- .../mall/portal/service/AuthService.java | 20 ++ .../mall/portal/service/HomeService.java | 10 + .../service/MemberAttentionService.java | 15 +- .../service/MemberCollectionService.java | 11 +- .../service/MemberReadHistoryService.java | 10 +- .../portal/service/OmsCartItemService.java | 2 +- .../portal/service/OmsPortalOrderService.java | 28 ++- .../service/PmsPortalProductService.java | 28 +++ .../portal/service/PortalBrandService.java | 28 +++ .../mall/portal/service/RedisService.java | 35 --- .../portal/service/UmsMemberCacheService.java | 34 +++ .../service/UmsMemberCouponService.java | 16 +- .../UmsMemberReceiveAddressService.java | 2 + .../mall/portal/service/UmsMemberService.java | 11 +- .../portal/service/impl/HomeServiceImpl.java | 14 +- .../impl/MemberAttentionServiceImpl.java | 36 ++- .../impl/MemberCollectionServiceImpl.java | 36 ++- .../impl/MemberReadHistoryServiceImpl.java | 23 +- .../service/impl/OmsCartItemServiceImpl.java | 7 +- .../impl/OmsPortalOrderServiceImpl.java | 124 +++++++++- .../service/impl/OmsPromotionServiceImpl.java | 2 + .../impl/PmsPortalProductServiceImpl.java | 142 +++++++++++ .../service/impl/PortalBrandServiceImpl.java | 50 ++++ .../portal/service/impl/RedisServiceImpl.java | 43 ---- .../impl/UmsMemberCacheServiceImpl.java | 62 +++++ .../impl/UmsMemberCouponServiceImpl.java | 55 ++++- .../UmsMemberReceiveAddressServiceImpl.java | 10 + .../service/impl/UmsMemberServiceImpl.java | 110 ++++----- .../src/main/resources/application.yml | 53 ++--- .../src/main/resources/bootstrap-dev.yml | 15 +- .../src/main/resources/bootstrap-prod.yml | 17 +- .../main/resources/dao/PortalProductDao.xml | 27 +++ .../resources/dao/SmsCouponHistoryDao.xml | 17 ++ mall-registry/.gitignore | 31 --- mall-registry/pom.xml | 60 ----- .../macro/mall/MallRegistryApplication.java | 15 -- .../src/main/resources/application.yml | 13 -- .../mall/MallRegistryApplicationTests.java | 16 -- mall-search/pom.xml | 14 +- ...Swagger2Config.java => SwaggerConfig.java} | 24 +- .../service/impl/EsProductServiceImpl.java | 54 +++-- .../src/main/resources/application.yml | 5 +- .../src/main/resources/bootstrap-dev.yml | 15 +- .../src/main/resources/bootstrap-prod.yml | 17 +- .../search/MallSearchApplicationTests.java | 14 +- mall-security/.gitignore | 31 --- mall-security/pom.xml | 38 --- .../DynamicAccessDecisionManager.java | 51 ---- .../component/DynamicSecurityFilter.java | 77 ------ .../DynamicSecurityMetadataSource.java | 64 ----- .../component/DynamicSecurityService.java | 16 -- .../JwtAuthenticationTokenFilter.java | 57 ----- .../RestAuthenticationEntryPoint.java | 28 --- .../component/RestfulAccessDeniedHandler.java | 30 --- .../security/config/IgnoreUrlsConfig.java | 21 -- .../mall/security/config/SecurityConfig.java | 127 ---------- .../mall/security/util/JwtTokenUtil.java | 170 -------------- pom.xml | 64 +++-- 258 files changed, 4671 insertions(+), 3092 deletions(-) rename mall-config/src/main/resources/config/admin/admin-dev.yml => config/admin/mall-admin-dev.yaml (69%) rename mall-config/src/main/resources/config/admin/admin-prod.yml => config/admin/mall-admin-prod.yaml (72%) rename mall-config/src/main/resources/config/demo/demo-dev.yml => config/demo/mall-demo-dev.yaml (66%) rename mall-config/src/main/resources/config/demo/demo-prod.yml => config/demo/mall-demo-prod.yaml (63%) create mode 100644 config/gateway/mall-gateway-dev.yaml create mode 100644 config/gateway/mall-gateway-prod.yaml rename mall-config/src/main/resources/config/portal/portal-dev.yml => config/portal/mall-portal-dev.yaml (75%) rename mall-config/src/main/resources/config/portal/portal-prod.yml => config/portal/mall-portal-prod.yaml (84%) rename mall-config/src/main/resources/config/search/search-dev.yml => config/search/mall-search-dev.yaml (59%) rename mall-config/src/main/resources/config/search/search-prod.yml => config/search/mall-search-prod.yaml (58%) delete mode 100644 document/docker/docker-deploy.md delete mode 100644 document/elk/logstash-springboot.conf create mode 100644 document/elk/logstash.conf delete mode 100644 document/resource/mall_swarm_linux_02.png delete mode 100644 document/resource/mall_swarm_linux_04.png delete mode 100644 document/resource/mall_swarm_linux_07.png delete mode 100644 document/resource/mall_swarm_linux_08.png delete mode 100644 document/resource/mall_swarm_linux_09.png create mode 100644 document/resource/mall_swarm_run_01.png create mode 100644 document/resource/mall_swarm_run_02.png create mode 100644 document/resource/mall_swarm_run_03.png create mode 100644 document/resource/mall_swarm_run_04.png create mode 100644 document/resource/mall_swarm_run_05.png create mode 100644 document/resource/mall_swarm_run_06.png create mode 100644 document/resource/mall_swarm_run_07.png create mode 100644 document/resource/mall_swarm_run_08.png create mode 100644 document/resource/mall_swarm_run_09.png create mode 100644 document/resource/mall_swarm_run_10.png create mode 100644 document/resource/mall_swarm_run_11.png delete mode 100644 document/resource/rabbitmq_install_1.png delete mode 100644 document/resource/rabbitmq_install_2.png delete mode 100644 document/resource/rabbitmq_install_3.png delete mode 100644 document/resource/rabbitmq_install_4.png delete mode 100644 mall-admin/src/main/java/com/macro/mall/bo/AdminUserDetails.java delete mode 100644 mall-admin/src/main/java/com/macro/mall/bo/WebLog.java create mode 100644 mall-admin/src/main/java/com/macro/mall/component/ResourceRoleRulesHolder.java delete mode 100644 mall-admin/src/main/java/com/macro/mall/config/GlobalCorsConfig.java delete mode 100644 mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java create mode 100644 mall-admin/src/main/java/com/macro/mall/config/RedisConfig.java delete mode 100644 mall-admin/src/main/java/com/macro/mall/config/Swagger2Config.java create mode 100644 mall-admin/src/main/java/com/macro/mall/config/SwaggerConfig.java create mode 100644 mall-admin/src/main/java/com/macro/mall/dto/BucketPolicyConfigDto.java create mode 100644 mall-admin/src/main/java/com/macro/mall/service/AuthService.java create mode 100644 mall-admin/src/main/java/com/macro/mall/service/UmsAdminCacheService.java create mode 100644 mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminCacheServiceImpl.java delete mode 100644 mall-admin/src/main/resources/logback-spring.xml rename {mall-config => mall-auth}/pom.xml (54%) rename mall-config/src/main/java/com/macro/mall/MallConfigApplication.java => mall-auth/src/main/java/com/macro/mall/auth/MallAuthApplication.java (50%) create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/component/JwtTokenEnhancer.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/config/Oauth2ServerConfig.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/config/SwaggerConfig.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/config/WebSecurityConfig.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/constant/MessageConstant.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/controller/AuthController.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/controller/KeyPairController.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/domain/Oauth2TokenDto.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/domain/SecurityUser.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/exception/Oauth2ExceptionHandler.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/service/UmsAdminService.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/service/UmsMemberService.java create mode 100644 mall-auth/src/main/java/com/macro/mall/auth/service/impl/UserServiceImpl.java create mode 100644 mall-auth/src/main/resources/application.yml create mode 100644 mall-auth/src/main/resources/bootstrap-dev.yml create mode 100644 mall-auth/src/main/resources/bootstrap-prod.yml create mode 100644 mall-auth/src/main/resources/bootstrap.yml create mode 100644 mall-auth/src/main/resources/jwt.jks create mode 100644 mall-common/src/main/java/com/macro/mall/common/annotation/CacheException.java create mode 100644 mall-common/src/main/java/com/macro/mall/common/config/BaseRedisConfig.java rename mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java => mall-common/src/main/java/com/macro/mall/common/config/BaseSwaggerConfig.java (59%) create mode 100644 mall-common/src/main/java/com/macro/mall/common/constant/AuthConstant.java create mode 100644 mall-common/src/main/java/com/macro/mall/common/domain/SwaggerProperties.java create mode 100644 mall-common/src/main/java/com/macro/mall/common/domain/UserDto.java create mode 100644 mall-common/src/main/java/com/macro/mall/common/domain/WebLog.java rename {mall-admin/src/main/java/com/macro/mall/component => mall-common/src/main/java/com/macro/mall/common/log}/WebLogAspect.java (97%) create mode 100644 mall-common/src/main/java/com/macro/mall/common/service/RedisService.java create mode 100644 mall-common/src/main/java/com/macro/mall/common/service/impl/RedisServiceImpl.java create mode 100644 mall-common/src/main/resources/logback-spring.xml delete mode 100644 mall-config/.gitignore delete mode 100644 mall-config/src/main/resources/application-dev.yml delete mode 100644 mall-config/src/main/resources/application-native.yml delete mode 100644 mall-config/src/main/resources/application-prod.yml delete mode 100644 mall-config/src/main/resources/application.yml delete mode 100644 mall-config/src/test/java/com/macro/mall/MallConfigApplicationTests.java delete mode 100644 mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java create mode 100644 mall-demo/src/main/java/com/macro/mall/demo/config/SwaggerConfig.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/authorization/AuthorizationManager.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/config/IgnoreUrlsConfig.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/config/RedisConfig.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/config/ResourceServerConfig.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/config/SwaggerResourceConfig.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/filter/AuthGlobalFilter.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/filter/IgnoreUrlsRemoveJwtFilter.java create mode 100644 mall-gateway/src/main/java/com/macro/mall/handler/SwaggerHandler.java delete mode 100644 mall-gateway/src/main/resources/application-dev.yml delete mode 100644 mall-gateway/src/main/resources/application-prod.yml create mode 100644 mall-gateway/src/main/resources/bootstrap-dev.yml create mode 100644 mall-gateway/src/main/resources/bootstrap-prod.yml create mode 100644 mall-gateway/src/main/resources/bootstrap.yml delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/config/RedisConfig.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/config/SwaggerConfig.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/controller/MemberCollectionController.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/controller/MemberProductCollectionController.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/controller/PmsPortalProductController.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/controller/PortalBrandController.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/domain/PmsPortalProductDetail.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/domain/PmsProductCategoryNode.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/AuthService.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/PmsPortalProductService.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/PortalBrandService.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/RedisService.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCacheService.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/impl/PmsPortalProductServiceImpl.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/impl/PortalBrandServiceImpl.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/impl/RedisServiceImpl.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCacheServiceImpl.java delete mode 100644 mall-registry/.gitignore delete mode 100644 mall-registry/pom.xml delete mode 100644 mall-registry/src/main/java/com/macro/mall/MallRegistryApplication.java delete mode 100644 mall-registry/src/main/resources/application.yml delete mode 100644 mall-registry/src/test/java/com/macro/mall/MallRegistryApplicationTests.java rename mall-search/src/main/java/com/macro/mall/search/config/{Swagger2Config.java => SwaggerConfig.java} (59%) delete mode 100644 mall-security/.gitignore delete mode 100644 mall-security/pom.xml delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/DynamicAccessDecisionManager.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityFilter.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityMetadataSource.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityService.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java delete mode 100644 mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java diff --git a/README.md b/README.md index 461d81c..3251531 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## 项目介绍 -`mall-swarm`是一套微服务商城系统,采用了 Spring Cloud Greenwich、Spring Boot 2、MyBatis、Docker、Elasticsearch等核心技术,同时提供了基于Vue的管理后台方便快速搭建系统。`mall-swarm`在电商业务的基础集成了注册中心、配置中心、监控中心、网关等系统功能。 文档齐全,附带全套Spring Cloud教程。 +`mall-swarm`是一套微服务商城系统,采用了 Spring Cloud Hoxton & Alibaba、Spring Boot 2.3、Oauth2、MyBatis、Docker、Elasticsearch等核心技术,同时提供了基于Vue的管理后台方便快速搭建系统。`mall-swarm`在电商业务的基础集成了注册中心、配置中心、监控中心、网关等系统功能。 文档齐全,附带全套Spring Cloud教程。 ## 系统架构图 @@ -22,15 +22,14 @@ mall ├── mall-common -- 工具类及通用代码模块 ├── mall-mbg -- MyBatisGenerator生成的数据库操作代码模块 -├── mall-security -- 封装SpringSecurity+JWT的安全认证的模块 -├── mall-registry -- 基于Eureka的微服务注册中心 -├── mall-config -- 基于Spring Cloud Config的微服务配置中心 +├── mall-auth -- 基于Spring Security Oauth2的统一的认证中心 ├── mall-gateway -- 基于Spring Cloud Gateway的微服务API网关服务 ├── mall-monitor -- 基于Spring Boot Admin的微服务监控中心 ├── mall-admin -- 后台管理系统服务 ├── mall-search -- 基于Elasticsearch的商品搜索系统服务 ├── mall-portal -- 移动端商城系统服务 -└── mall-demo -- 微服务远程调用测试服务 +├── mall-demo -- 微服务远程调用测试服务 +└── config -- 配置中心存储的配置 ``` ## 项目文档 @@ -47,29 +46,30 @@ mall ### 后端技术 -| 技术 | 说明 | 官网 | -| ---------------- | -------------------- | ---------------------------------------------------- | -| Spring Cloud | 微服务框架 | https://spring.io/projects/spring-cloud | -| Spring Boot | 容器+MVC框架 | https://spring.io/projects/spring-boot | -| Spring Security | 认证和授权框架 | https://spring.io/projects/spring-security | -| MyBatis | ORM框架 | http://www.mybatis.org/mybatis-3/zh/index.html | -| MyBatisGenerator | 数据层代码生成 | http://www.mybatis.org/generator/index.html | -| PageHelper | MyBatis物理分页插件 | http://git.oschina.net/free/Mybatis_PageHelper | -| Swagger-UI | 文档生产工具 | https://github.com/swagger-api/swagger-ui | -| Elasticsearch | 搜索引擎 | https://github.com/elastic/elasticsearch | -| RabbitMq | 消息队列 | https://www.rabbitmq.com/ | -| Redis | 分布式缓存 | https://redis.io/ | -| MongoDb | NoSql数据库 | https://www.mongodb.com/ | -| Docker | 应用容器引擎 | https://www.docker.com/ | -| Druid | 数据库连接池 | https://github.com/alibaba/druid | -| OSS | 对象存储 | https://github.com/aliyun/aliyun-oss-java-sdk | -| MinIO | 对象存储 | https://github.com/minio/minio | -| JWT | JWT登录支持 | https://github.com/jwtk/jjwt | -| LogStash | 日志收集 | https://github.com/logstash/logstash-logback-encoder | -| Lombok | 简化对象封装工具 | https://github.com/rzwitserloot/lombok | -| Seata | 全局事务管理框架 | https://github.com/seata/seata | -| Portainer | 可视化Docker容器管理 | https://github.com/portainer/portainer | -| Jenkins | 自动化部署工具 | https://github.com/jenkinsci/jenkins | +| 技术 | 说明 | 官网 | +| ---------------------- | -------------------- | ---------------------------------------------------- | +| Spring Cloud | 微服务框架 | https://spring.io/projects/spring-cloud | +| Spring Cloud Alibaba | 微服务框架 | https://github.com/alibaba/spring-cloud-alibaba | +| Spring Boot | 容器+MVC框架 | https://spring.io/projects/spring-boot | +| Spring Security Oauth2 | 认证和授权框架 | https://spring.io/projects/spring-security-oauth | +| MyBatis | ORM框架 | http://www.mybatis.org/mybatis-3/zh/index.html | +| MyBatisGenerator | 数据层代码生成 | http://www.mybatis.org/generator/index.html | +| PageHelper | MyBatis物理分页插件 | http://git.oschina.net/free/Mybatis_PageHelper | +| Knife4j | 文档生产工具 | https://github.com/xiaoymin/swagger-bootstrap-ui | +| Elasticsearch | 搜索引擎 | https://github.com/elastic/elasticsearch | +| RabbitMq | 消息队列 | https://www.rabbitmq.com/ | +| Redis | 分布式缓存 | https://redis.io/ | +| MongoDb | NoSql数据库 | https://www.mongodb.com/ | +| Docker | 应用容器引擎 | https://www.docker.com/ | +| Druid | 数据库连接池 | https://github.com/alibaba/druid | +| OSS | 对象存储 | https://github.com/aliyun/aliyun-oss-java-sdk | +| MinIO | 对象存储 | https://github.com/minio/minio | +| JWT | JWT登录支持 | https://github.com/jwtk/jjwt | +| LogStash | 日志收集 | https://github.com/logstash/logstash-logback-encoder | +| Lombok | 简化对象封装工具 | https://github.com/rzwitserloot/lombok | +| Seata | 全局事务管理框架 | https://github.com/seata/seata | +| Portainer | 可视化Docker容器管理 | https://github.com/portainer/portainer | +| Jenkins | 自动化部署工具 | https://github.com/jenkinsci/jenkins | ### 前端技术 @@ -87,15 +87,17 @@ mall ### 开发环境 -工具 | 版本号 | 下载 -----|----|---- -JDK | 1.8 | https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html -Mysql | 5.7 | https://www.mysql.com/ -Redis | 3.2 | https://redis.io/download -Elasticsearch | 6.2.2 | https://www.elastic.co/downloads -MongoDb | 3.2 | https://www.mongodb.com/download-center -RabbitMq | 3.7.14 | http://www.rabbitmq.com/download.html -nginx | 1.10 | http://nginx.org/en/download.html +| 工具 | 版本号 | 下载 | +| ------------- | ------ | ------------------------------------------------------------ | +| JDK | 1.8 | https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html | +| Mysql | 5.7 | https://www.mysql.com/ | +| Redis | 5.0 | https://redis.io/download | +| Elasticsearch | 7.6.2 | https://www.elastic.co/cn/downloads/elasticsearch | +| Kibana | 7.6.2 | https://www.elastic.co/cn/downloads/kibana | +| Logstash | 7.6.2 | https://www.elastic.co/cn/downloads/logstash | +| MongoDb | 4.2.5 | https://www.mongodb.com/download-center | +| RabbitMq | 3.7.14 | http://www.rabbitmq.com/download.html | +| nginx | 1.10 | http://nginx.org/en/download.html | ### 搭建步骤 @@ -106,8 +108,6 @@ nginx | 1.10 | http://nginx.org/en/download.html - `ELK`日志收集系统的搭建请参考:[SpringBoot应用整合ELK实现日志收集](http://www.macrozheng.com/#/technology/mall_tiny_elk); - 使用MinIO存储文件请参考:[前后端分离项目,如何优雅实现文件存储](http://www.macrozheng.com/#/technology/minio_use); - 读写分离解决方案请参考:[你还在代码里做读写分离么,试试这个中间件吧](http://www.macrozheng.com/#/reference/gaea); -- 如果想使用`Consul`作为注册及配置中心的话请参考:[Spring Cloud Consul:服务治理与配置中心](http://www.macrozheng.com/#/cloud/consul); -- 如果想使用`Nacos`作为注册及配置中心的话请参考:[Spring Cloud Alibaba:Nacos 作为注册中心和配置中心使用](http://www.macrozheng.com/#/cloud/nacos); - `分布式事务`解决方案请参考:[使用Seata彻底解决Spring Cloud中的分布式事务问题!](http://www.macrozheng.com/#/cloud/seata)。 > Docker环境部署 @@ -120,21 +120,31 @@ nginx | 1.10 | http://nginx.org/en/download.html ## 运行效果展示 -- 注册中心控制台信息: +- 查看注册中心注册服务信息,访问地址:http://192.168.3.101:8848/nacos/ -![](http://img.macrozheng.com/mall/project/mall_swarm_linux_07.png) +![](/document/resource/mall_swarm_run_01.png) -- 监控中心应用信息: +- 监控中心应用信息,访问地址:http://192.168.3.101:8101 -![](http://img.macrozheng.com/mall/project/mall_swarm_linux_08.png) +![](/document/resource/mall_swarm_run_02.png) -![](http://img.macrozheng.com/mall/project/mall_swarm_linux_09.png) +![](/document/resource/mall_swarm_run_03.png) -- 可视化容器管理: +![](/document/resource/mall_swarm_run_04.png) -![](http://img.macrozheng.com/mall/project/mall_swarm_linux_02.png) +- API文档信息,访问地址:http://192.168.3.101:8201 -![](http://img.macrozheng.com/mall/project/mall_swarm_linux_04.png) +![](/document/resource/mall_swarm_run_05.png) + +- 日志收集系统信息,访问地址:http://192.168.3.101:5601 + +![](/document/resource/mall_swarm_run_06.png) + +- 可视化容器管理,访问地址:http://192.168.3.101:9000 + +![](/document/resource/mall_swarm_run_07.png) + +![](/document/resource/mall_swarm_run_08.png) ## 公众号 diff --git a/mall-config/src/main/resources/config/admin/admin-dev.yml b/config/admin/mall-admin-dev.yaml similarity index 69% rename from mall-config/src/main/resources/config/admin/admin-dev.yml rename to config/admin/mall-admin-dev.yaml index 3395943..8762958 100644 --- a/mall-config/src/main/resources/config/admin/admin-dev.yml +++ b/config/admin/mall-admin-dev.yaml @@ -15,7 +15,15 @@ spring: url: jdbc:mysql://localhost:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root + redis: + host: localhost # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: # Redis服务器连接密码(默认为空) + timeout: 3000ms # 连接超时时间(毫秒) logging: level: - root: info #日志配置DEBUG,INFO,WARN,ERROR - com.macro.mall: debug \ No newline at end of file + root: info + com.macro.mall: debug +logstash: + host: localhost \ No newline at end of file diff --git a/mall-config/src/main/resources/config/admin/admin-prod.yml b/config/admin/mall-admin-prod.yaml similarity index 72% rename from mall-config/src/main/resources/config/admin/admin-prod.yml rename to config/admin/mall-admin-prod.yaml index a0002db..52e3f79 100644 --- a/mall-config/src/main/resources/config/admin/admin-prod.yml +++ b/config/admin/mall-admin-prod.yaml @@ -15,5 +15,16 @@ spring: url: jdbc:mysql://db:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: reader password: 123456 + redis: + host: redis # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: #不设置密码 logging: - path: /var/logs #配置日志生成路径 \ No newline at end of file + file: + path: /var/logs + level: + root: info + com.macro.mall: info +logstash: + host: logstash \ No newline at end of file diff --git a/mall-config/src/main/resources/config/demo/demo-dev.yml b/config/demo/mall-demo-dev.yaml similarity index 66% rename from mall-config/src/main/resources/config/demo/demo-dev.yml rename to config/demo/mall-demo-dev.yaml index 6f0240f..53e977f 100644 --- a/mall-config/src/main/resources/config/demo/demo-dev.yml +++ b/config/demo/mall-demo-dev.yaml @@ -5,6 +5,7 @@ spring: password: root logging: level: - root: info #日志配置DEBUG,INFO,WARN,ERROR + root: info com.macro.mall: debug - com.macro.mall.demo.service.FeignAdminService: debug \ No newline at end of file +logstash: + host: localhost \ No newline at end of file diff --git a/mall-config/src/main/resources/config/demo/demo-prod.yml b/config/demo/mall-demo-prod.yaml similarity index 63% rename from mall-config/src/main/resources/config/demo/demo-prod.yml rename to config/demo/mall-demo-prod.yaml index 4e49a5f..1f6e91d 100644 --- a/mall-config/src/main/resources/config/demo/demo-prod.yml +++ b/config/demo/mall-demo-prod.yaml @@ -4,4 +4,10 @@ spring: username: reader password: 123456 logging: - path: /var/logs #配置日志生成路径 \ No newline at end of file + file: + path: /var/logs + level: + root: info + com.macro.mall: info +logstash: + host: logstash \ No newline at end of file diff --git a/config/gateway/mall-gateway-dev.yaml b/config/gateway/mall-gateway-dev.yaml new file mode 100644 index 0000000..38661e4 --- /dev/null +++ b/config/gateway/mall-gateway-dev.yaml @@ -0,0 +1,18 @@ +spring: + redis: + host: localhost # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: # Redis服务器连接密码(默认为空) + timeout: 3000ms # 连接超时时间(毫秒) + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: 'http://localhost:8201/mall-auth/rsa/publicKey' +logging: + level: + root: info + com.macro.mall: debug +logstash: + host: localhost \ No newline at end of file diff --git a/config/gateway/mall-gateway-prod.yaml b/config/gateway/mall-gateway-prod.yaml new file mode 100644 index 0000000..0a5f108 --- /dev/null +++ b/config/gateway/mall-gateway-prod.yaml @@ -0,0 +1,19 @@ +spring: + redis: + host: redis # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: #不设置密码 + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: 'http://mall-gateway:8201/mall-auth/rsa/publicKey' +logging: + file: + path: /var/logs + level: + root: info + com.macro.mall: info +logstash: + host: logstash \ No newline at end of file diff --git a/mall-config/src/main/resources/config/portal/portal-dev.yml b/config/portal/mall-portal-dev.yaml similarity index 75% rename from mall-config/src/main/resources/config/portal/portal-dev.yml rename to config/portal/mall-portal-dev.yaml index 75c292b..6b8d6df 100644 --- a/mall-config/src/main/resources/config/portal/portal-dev.yml +++ b/config/portal/mall-portal-dev.yaml @@ -19,10 +19,10 @@ spring: virtual-host: /mall username: mall password: mall - publisher-confirms: true #如果对异步消息需要回调必须设置为true # 日志配置 logging: level: - org.springframework.data.mongodb.core: debug - com.macro.mall.mapper: debug - com.macro.mall.portal.dao: debug \ No newline at end of file + root: info + com.macro.mall: debug +logstash: + host: localhost \ No newline at end of file diff --git a/mall-config/src/main/resources/config/portal/portal-prod.yml b/config/portal/mall-portal-prod.yaml similarity index 84% rename from mall-config/src/main/resources/config/portal/portal-prod.yml rename to config/portal/mall-portal-prod.yaml index accb7f9..2a898d9 100644 --- a/mall-config/src/main/resources/config/portal/portal-prod.yml +++ b/config/portal/mall-portal-prod.yaml @@ -20,4 +20,12 @@ spring: username: mall password: mall publisher-confirms: true #如果对异步消息需要回调必须设置为true +logging: + file: + path: /var/logs + level: + root: info + com.macro.mall: info +logstash: + host: logstash diff --git a/mall-config/src/main/resources/config/search/search-dev.yml b/config/search/mall-search-dev.yaml similarity index 59% rename from mall-config/src/main/resources/config/search/search-dev.yml rename to config/search/mall-search-dev.yaml index 38ee08e..1507e16 100644 --- a/mall-config/src/main/resources/config/search/search-dev.yml +++ b/config/search/mall-search-dev.yaml @@ -3,14 +3,12 @@ spring: url: jdbc:mysql://localhost:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root - data: - elasticsearch: - cluster-nodes: 127.0.0.1:9300 - cluster-name: elasticsearch elasticsearch: rest: uris: http://localhost:9200 logging: level: - root: info #日志配置DEBUG,INFO,WARN,ERROR - com.macro.mall: debug \ No newline at end of file + root: info + com.macro.mall: debug +logstash: + host: localhost \ No newline at end of file diff --git a/mall-config/src/main/resources/config/search/search-prod.yml b/config/search/mall-search-prod.yaml similarity index 58% rename from mall-config/src/main/resources/config/search/search-prod.yml rename to config/search/mall-search-prod.yaml index 3496b41..b7c1d48 100644 --- a/mall-config/src/main/resources/config/search/search-prod.yml +++ b/config/search/mall-search-prod.yaml @@ -3,16 +3,18 @@ spring: url: jdbc:mysql://db:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: reader password: 123456 - data: - elasticsearch: - cluster-nodes: es:9300 - cluster-name: elasticsearch elasticsearch: rest: uris: http://es:9200 -logging: - path: /var/logs #配置日志生成路径 management: health: elasticsearch: - response-timeout: 1000ms #加大健康检查超时时间 \ No newline at end of file + response-timeout: 1000ms #加大健康检查超时时间 +logging: + file: + path: /var/logs + level: + root: info + com.macro.mall: info +logstash: + host: logstash \ No newline at end of file diff --git a/document/docker/docker-compose-app.yml b/document/docker/docker-compose-app.yml index 42c9381..6eaf166 100644 --- a/document/docker/docker-compose-app.yml +++ b/document/docker/docker-compose-app.yml @@ -5,23 +5,78 @@ services: container_name: mall-admin ports: - 8080:8080 + volumes: + - /mydata/app/mall-admin/logs:/var/logs + - /etc/localtime:/etc/localtime + environment: + - 'TZ="Asia/Shanghai"' external_links: - mysql:db #可以用db这个域名访问mysql服务 + - nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务 mall-search: image: mall/mall-search:1.0-SNAPSHOT container_name: mall-search ports: - 8081:8081 + volumes: + - /mydata/app/mall-search/logs:/var/logs + - /etc/localtime:/etc/localtime + environment: + - 'TZ="Asia/Shanghai"' external_links: - elasticsearch:es #可以用es这个域名访问elasticsearch服务 - mysql:db #可以用db这个域名访问mysql服务 + - nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务 mall-portal: image: mall/mall-portal:1.0-SNAPSHOT container_name: mall-portal ports: - 8085:8085 + volumes: + - /mydata/app/mall-portal/logs:/var/logs + - /etc/localtime:/etc/localtime + environment: + - 'TZ="Asia/Shanghai"' external_links: - redis:redis #可以用redis这个域名访问redis服务 - mongo:mongo #可以用mongo这个域名访问mongo服务 - mysql:db #可以用db这个域名访问mysql服务 - - rabbitmq:rabbit #可以用rabbit这个域名访问rabbitmq服务 \ No newline at end of file + - rabbitmq:rabbit #可以用rabbit这个域名访问rabbitmq服务 + - nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务 + mall-auth: + image: mall/mall-auth:1.0-SNAPSHOT + container_name: mall-auth + ports: + - 8401:8401 + volumes: + - /mydata/app/mall-auth/logs:/var/logs + - /etc/localtime:/etc/localtime + environment: + - 'TZ="Asia/Shanghai"' + external_links: + - nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务 + mall-gateway: + image: mall/mall-gateway:1.0-SNAPSHOT + container_name: mall-gateway + ports: + - 8201:8201 + volumes: + - /mydata/app/mall-gateway/logs:/var/logs + - /etc/localtime:/etc/localtime + environment: + - 'TZ="Asia/Shanghai"' + external_links: + - redis:redis #可以用redis这个域名访问redis服务 + - nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务 + mall-monitor: + image: mall/mall-monitor:1.0-SNAPSHOT + container_name: mall-monitor + ports: + - 8101:8101 + volumes: + - /mydata/app/mall-monitor/logs:/var/logs + - /etc/localtime:/etc/localtime + environment: + - 'TZ="Asia/Shanghai"' + external_links: + - nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务 \ No newline at end of file diff --git a/document/docker/docker-compose-env.yml b/document/docker/docker-compose-env.yml index b4e1f82..c292a83 100644 --- a/document/docker/docker-compose-env.yml +++ b/document/docker/docker-compose-env.yml @@ -14,7 +14,7 @@ services: - /mydata/mysql/data/conf:/etc/mysql/conf.d #配置文件挂载 - /mydata/mysql/log:/var/log/mysql #日志文件挂载 redis: - image: redis:3.2 + image: redis:5 container_name: redis command: redis-server --appendonly yes volumes: @@ -40,8 +40,9 @@ services: - 5672:5672 - 15672:15672 elasticsearch: - image: elasticsearch:6.4.0 + image: elasticsearch:7.6.2 container_name: elasticsearch + user: root environment: - "cluster.name=elasticsearch" #设置集群名称为elasticsearch - "discovery.type=single-node" #以单一节点模式启动 @@ -52,8 +53,24 @@ services: ports: - 9200:9200 - 9300:9300 + logstash: + image: logstash:7.6.2 + container_name: logstash + environment: + - TZ=Asia/Shanghai + volumes: + - /mydata/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #挂载logstash的配置文件 + depends_on: + - elasticsearch #kibana在elasticsearch启动之后再启动 + links: + - elasticsearch:es #可以用es这个域名访问elasticsearch服务 + ports: + - 4560:4560 + - 4561:4561 + - 4562:4562 + - 4563:4563 kibana: - image: kibana:6.4.0 + image: kibana:7.6.2 container_name: kibana links: - elasticsearch:es #可以用es这个域名访问elasticsearch服务 @@ -64,9 +81,16 @@ services: ports: - 5601:5601 mongo: - image: mongo:3.2 + image: mongo:4.2.5 container_name: mongo volumes: - /mydata/mongo/db:/data/db #数据文件挂载 ports: - - 27017:27017 \ No newline at end of file + - 27017:27017 + nacos-registry: + image: nacos/nacos-server:1.3.0 + container_name: nacos-registry + environment: + - "MODE=standalone" + ports: + - 8848:8848 diff --git a/document/docker/docker-deploy.md b/document/docker/docker-deploy.md deleted file mode 100644 index 8cd872f..0000000 --- a/document/docker/docker-deploy.md +++ /dev/null @@ -1,149 +0,0 @@ -# docker环境部署 - -## docker环境安装 -### docker安装 -1. 安装yum-utils: -yum install -y yum-utils \ -device-mapper-persistent-data \ -lvm2 -2. 为yum源添加docker仓库位置: -yum-config-manager \ ---add-repo \ -https://download.docker.com/linux/centos/docker-ce.repo -3. 安装docker: -yum install docker-ce -4. 启动docker: -systemctl start docker -注:常见命令见document/reference文件夹中的docker.md -5. 安装上传下载插件: -yum -y install lrzsz -### docker compose安装 -1. 下载地址:https://github.com/docker/compose/releases -2. 安装地址:/usr/local/bin/docker-compose -3. 设置为可执行:sudo chmod +x /usr/local/bin/docker-compose -4. 测试是否安装成功:docker-compose --version - -## mysql安装 -### 下载镜像文件 -docker pull mysql:5.7 -### 创建实例并启动 -docker run -p 3306:3306 --name mysql \ --v /mydata/mysql/log:/var/log/mysql \ --v /mydata/mysql/data:/var/lib/mysql \ --v /mydata/mysql/conf:/etc/mysql \ --e MYSQL_ROOT_PASSWORD=root \ --d mysql:5.7 -> 参数说明 -- -p 3306:3306:将容器的3306端口映射到主机的3306端口 -- -v /mydata/mysql/conf:/etc/mysql:将配置文件夹挂在到主机 -- -v /mydata/mysql/log:/var/log/mysql:将日志文件夹挂载到主机 -- -v /mydata/mysql/data:/var/lib/mysql/:将配置文件夹挂载到主机 -- -e MYSQL_ROOT_PASSWORD=root:初始化root用户的密码 -### 通过容器的mysql命令行工具连接 -docker exec -it mysql mysql -uroot -proot -### 设置远程访问 -grant all privileges on *.* to 'root' @'%' identified by 'root'; -flush privileges; -### 进入容器文件系统 -docker exec -it mysql /bin/bash - -## redis安装 -### 下载镜像文件 -docker pull redis:3.2 -### 创建实例并启动 -docker run -p 6379:6379 --name redis -v /mydata/redis/data:/data -d redis:3.2 redis-server --appendonly yes -### 使用redis镜像执行redis-cli命令连接 -docker exec -it redis redis-cli - -## nginx安装 -### 下载镜像文件 -docker pull nginx:1.10 -### 创建实例并启动 -docker run -p 80:80 --name nginx \ --v /mydata/nginx/html:/usr/share/nginx/html \ --v /mydata/nginx/logs:/var/log/nginx \ --d nginx:1.10 -### 修改nginx配置 -1. 将容器内的配置文件拷贝到当前目录:docker container cp nginx:/etc/nginx . -2. 修改文件名称:mv nginx conf -3. 终止容器:docker stop nginx -4. 执行命令删除原容器:docker rm $ContainerId -5. 执行以下命令: -docker run -p 80:80 --name nginx \ --v /mydata/nginx/html:/usr/share/nginx/html \ --v /mydata/nginx/logs:/var/log/nginx \ --v /mydata/nginx/conf:/etc/nginx \ --d nginx:1.10 - -## rabbitmq安装 -### 下载镜像文件 -docker pull rabbitmq:management -### 创建实例并启动 -docker run -d --name rabbitmq --publish 5671:5671 \ - --publish 5672:5672 --publish 4369:4369 --publish 25672:25672 --publish 15671:15671 --publish 15672:15672 \ -rabbitmq:management - -## elasticsearch安装 -### 下载镜像文件 -docker pull elasticsearch:6.4.0 -### 创建实例并运行 -docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \ --v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ --v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \ --d elasticsearch:6.4.0 -### 测试 -访问会返回版本信息:http://192.168.1.66:9200/ -### 安装目录位置 -/usr/share/elasticsearch -### 安装head插件(可以不安装,仅用于测试) -1. 进入docker内部bash:docker exec -it elasticsearch /bin/bash -2. 安装插件,具体参考:https://github.com/mobz/elasticsearch-head -3. 测试:http://192.168.1.66:9200/_plugin/head/ -### 安装中文分词器IKAnalyzer -1. 进入docker内部bash:docker exec -it elasticsearch /bin/bash -2. 安装中文分词插件,执行以下命令:elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip -3. 测试: - - 访问header插件:打开地址http://192.168.1.66:9200/_plugin/head/ - - 选择复合查询,输入地址:POST:http://192.168.1.66:9200/_analyze - - 输入参数:JSON:{"analyzer":"ik","text":"我们是大数据开发人员"} - -## mongodb安装 -### 下载镜像文件 -docker pull mongo:3.2 -### 创建实例并运行 -docker run -p 27017:27017 --name mongo -v /mydata/mongo/db:/data/db -d mongo:3.2 -### 使用mongo命令进入容器 -docker exec -it mongo mongo - -## SpringBoot应用命令部署 -**docker容器间进行连接才能互相访问** -### 部署mall-admin -docker run -p 8080:8080 --name mall-admin \ ---link mysql:db \ --v /etc/timezone:/etc/timezone \ --v /etc/localtime:/etc/localtime \ --v /mydata/app/admin/logs:/var/logs \ --d mall/mall-admin:1.0-SNAPSHOT -### 部署mall-search -docker run -p 8081:8081 --name mall-search \ ---link elasticsearch:es \ ---link mysql:db \ --v /etc/timezone:/etc/timezone \ --v /etc/localtime:/etc/localtime \ --v /mydata/app/search/logs:/var/logs \ --d mall/mall-search:1.0-SNAPSHOT -### 部署mall-port -docker run -p 8085:8085 --name mall-portal \ ---link mysql:db \ ---link redis:redis \ ---link mongo:mongo \ --v /etc/timezone:/etc/timezone \ --v /etc/localtime:/etc/localtime \ --v /mydata/app/portal/logs:/var/logs \ --d mall/mall-portal:1.0-SNAPSHOT - -## SpringBoot应用自动化部署 -### 部署文件 -document/docker/docker-compose.yml -### 部署命令 -docker-compose up -d \ No newline at end of file diff --git a/document/elk/logstash-springboot.conf b/document/elk/logstash-springboot.conf deleted file mode 100644 index a71e919..0000000 --- a/document/elk/logstash-springboot.conf +++ /dev/null @@ -1,14 +0,0 @@ -input { - tcp { - mode => "server" - host => "0.0.0.0" - port => 4560 - codec => json_lines - } -} -output { - elasticsearch { - hosts => "es:9200" - index => "springboot-logstash-%{+YYYY.MM.dd}" - } -} \ No newline at end of file diff --git a/document/elk/logstash.conf b/document/elk/logstash.conf new file mode 100644 index 0000000..953d054 --- /dev/null +++ b/document/elk/logstash.conf @@ -0,0 +1,49 @@ +input { + tcp { + mode => "server" + host => "0.0.0.0" + port => 4560 + codec => json_lines + type => "debug" + } + tcp { + mode => "server" + host => "0.0.0.0" + port => 4561 + codec => json_lines + type => "error" + } + tcp { + mode => "server" + host => "0.0.0.0" + port => 4562 + codec => json_lines + type => "business" + } + tcp { + mode => "server" + host => "0.0.0.0" + port => 4563 + codec => json_lines + type => "record" + } +} +filter{ + if [type] == "record" { + mutate { + remove_field => "port" + remove_field => "host" + remove_field => "@version" + } + json { + source => "message" + remove_field => ["message"] + } + } +} +output { + elasticsearch { + hosts => "es:9200" + index => "mall-%{type}-%{+YYYY.MM.dd}" + } +} \ No newline at end of file diff --git a/document/resource/mall_swarm_linux_02.png b/document/resource/mall_swarm_linux_02.png deleted file mode 100644 index 970955ccc92294af1cce639554656b7afc7d95b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64881 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 AlmGw# diff --git a/document/resource/mall_swarm_linux_04.png b/document/resource/mall_swarm_linux_04.png deleted file mode 100644 index 471974ac9d7409e1309dbdc3b56343957491b225..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32261 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

UO6(^2gIum>B&3QADyi?3;9;CvSFj^ivz) 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

U79sV)=`VG2)97tMMbEtGJy&oyiRN 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 diff --git a/document/resource/mall_swarm_linux_08.png b/document/resource/mall_swarm_linux_08.png deleted file mode 100644 index 6b7c8b1d21f8527e9d2e7ce283a1493d086bcfcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28707 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 diff --git a/document/resource/mall_swarm_linux_09.png b/document/resource/mall_swarm_linux_09.png deleted file mode 100644 index 14961fc982ca35094453fc831c00dcc77677a110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17266 zcmcJ$cU+U*vo9J%5s)f9bVLx4YADi4Koq3+j?zMxj`SK(x*$mBp$bw2LT@5cl=jej zlNLZgB!Gaxjqh)td(J)k?0r9HpL_GiN}icnGpo#6Yo2drz0y=yCMAXvLm&{+Cyy1i zA&?sY1cFaXh>xQzT{WjdAlJ?`pXw@IU0rc$LBgXx2nmafwQxL*`l+d z#H8V~@V;N1+9=#_Uzf6v0B}!N?vtD{M3+vp<(TFo+OnQUE7x+ zcFQ#dyjV|C9I?DQ*?U+J%E@UeXsu{5pStp5EWQ#Kf&*UVg$f)Ph{z z9pQxy$5ZvmZgtX4N!+78oSg1r4_%*(x;zL)ic1-1dMVAH?wfyHshauhz1+S&((=%? z?rIWHNlt#DlH~d#%4x(B9r(0j5Hp-&Jzign`!wbISXjvB=t+!CB`i<-v`>4q#VCF` zSWTPu-(K)d;xu+KQy+fE+3C%hwsp0BcHTa`JUKbZnKfFoHe_t}B6G|VJjQ6K=OsZP z@(-RUD(L#o{+Q`dfj^_~J=kQALeZ%&Gy9URfE4SR6cU9~Ad@Je`v&dJuMxBwqXLgr z=`t4djCm%j=N@kPr7@5JM#Z?-MUE zDMVij3HkUMjvu0Tqv{Ec_U=hurW%f3|64w|09QffHs)^~)!)?DLi9Fn$wbemAoC!J z_+AM& zu_a9?tHd=quj?6VskfM$UokSI%FVL^>i(^771s^vUd}k9Q~A+T=hpku@M3~|3E6P- z>*OkAVSXc-%2U@;k4$9lK@AM(lqilYJHy}S=JS=`6eQ-2CZ+j7>fenr{1`^6_2b4D zvV2PgO2PJ%%NfqSaw{WM(@pYBSFZG@Tek;x(psKQkUJGEyjx5INBI&s@tEfbsQ^-8(p~^F-=|hDG215LbeKh zjffZ7HTU9_>;2=~lfA;DiN7Zsc!tG)VN_J(@QLZF^YmDyPUNY3*ENAFZA_b4QjY-} zdhDt&r`F@zTJ;$6p^eLxg&Oh&z4%ftJ1oy6(8@Gh*DC_G9-#Y8`I*{IhHe-Uv(4EmLDl6@@dgY8cb1>YJ;hu&>vnOKP1q}Au1rES_7y&FTyr}Ur|=v2 zWfa)1j`?=NxBRDpXra4=@41ZJc@v#X5~>v{mQVE*gKR!g_l7TJ5hY;N6tJ&FAYsWJ ziD2Ho2E|#bc4q4P;(aFI%7gOljPJ2d$lyMkr&#vjRdU3h4CZ&9sc3|(aVV(#L50zT z=26F+x4fyQ@Thceyezu1$T#D_ajgZ3j z#Y6K_FY%wjp5C|8@Yd;p5yzXtkqH5LVmebYO!4fT7{zrID#Gsg?G?mek~&tAF{yoek%&i=B&n#85QOyf28vJHf?{SnQTKZ zQO)%0$W{TuBFRIB#!G$|B-@y zdomeSMfeaY9DnCz=j)hoVH(5_28Hob`t36O`1tfJtC>$7!%eShEHx1pEfNtkPyL-d znD}BPg^Xyo=)FASm%CDtFGkOsii!6X3*Wr4%?dCp@W+N#Wa+&uBgG&Rivv3|Pn0 z4E>PkI8dug@id9LhMdtI3U}ORMWi{M%a_|f^3@DO%lIu2_xOJ((FlJM z4v)GK(PK-i9~IF+4Rf_5D0N}XppUSv2)uWEI{q+^AK!~Qb9B1kRH%!5@FqD6 z{l4RmmKfJgEq1`it^Oto-9cLYkOTeH)M)0ZTHps<@4i?O7^hJeT+^6zgO@>e5{kMVIEu>h;Ysw7qyju=8;9a*Hs4~$kKD}aX3L;p1w z5Vz9z?5W^Qifl!B?sV{7br>PLr$@;y^9Uh5%kMA{QN|8?^SeD4e2gNSSivo&tBNqW z%64kfaAsz1bQ%IpEL_tRqT7iNP>R+n5i96~JnTQwN!`YOQ1duVnV6EX(79EBg(vI2 z<8oBcv%4@1ts=3Kf97!sx8MGzyiRy=Rl4c)GcQF&eAQ18$r(wR(a0e6{@`cu{g1$nksKe2 zZWUr%5|wvCnZq?{=`;OCPq*&PRi@aAXQXa+CqAlY7W>J}L@C+D&!6*3lKE~okSNl| zBtgUo;Q30k(Hr1x%B0m4*{FT9RUAIQJ>5+lK^E0z;hl5yd4YE6{`34Ai8mTZqVh*I ztq-@Z)kwe@jpN8g7Di{)F(%KqIX3fa(!xK*B3bKJ>gTp7qN!EjW{OA>wjUc=BsO8t zpW2gBaH$Jf8$3rYZ1CZ2f!8zwys3T7eQgi7_A%}@@)lwiuurb*5*@}`v6_T3UaRvr z6GWIWwN!ri47a=P3Rl4kUx@2-SjEr2h#UM~>ho|ezA+BD7NSNjhN>M#n3JarBzR=u zWA^7Nn1JkWYlLRm(cdmdI1W$W?=Q-p`CMOWE4{%5(7+%~OjN`7A_vH%fUcQ)r!}VW zhCaB+W|a4tc08ze2Rg$Pq}IVAxe~Dv zE2YE7+lG(66Z&zbrd_&(Vb31EuWlG;vh@-fs)aS!5j4w7H ze;J}EuS1ncrVdCOBhB(c-+Pgp6@p(A@1W0V%7b%2xkJ?&`9*RfE&1KGHLT#*i#IW1k%}a6R8M20j&VLSxPA6x z!LDyM?}rUHH+P9O&p||enIGJaW*l4X?e6Zb^6t_HzTc@4;p*A3ewLmsnTH1nc}Bms zbaZ20zBYs~B&QR=dqfY-`vyYvPz3KqVDfJPyfP9}O&eqgF9Khe;a{v^Bn0~Ji2sTF zf0Y%VEm{AHp77c|N#+6O8c#_|3PZzdVkI}OLD};8%ksIroru0ueZ9V~H0hT;(3e|D z4b9_=B*3Tuc+J|#kpHvCGw;n!{^FM2frgUkq;y9`(}c09m(=9@>8ei)Tuf`7geTvb z*DOw)m@NExeewB%r%_8SAi#9nzO>HTrS7eL?irJPcBSaf{@9ZKqrFwxy+c>4+>^c< zmX6+i=<(9ZpO+8SQlDtiza^d z{_v>H7u|f42KX~Vs$CNh^jToc2YTA2Fi!Yz6}3ls47til=t_j`yI7Jcu|c^ARFCYA zPY1WBHm`U#7#L3hm2I41GV%N9)?m+uR_^|B3}1TH+rO~IV&fl6I2g_e&qc)S+HB>r z!BWd=tY@Ax+cHo7$o)VFw1`Vys&S*&U+}!)XkpM~!X&0q%ocnOAEbK_pK7p^1v(`N z0|qI|_F3FYtkvzeM{5@qw>`KcZ&5Uu?-%_u<~k)$XEiuq$l?@|Hh+ z<0F=zPe1`jT~v>P*1^^Fd_0P5(91uThkXkyhdWwfC!F6Lb4@k_;gg9H{swdf zni#o6)Td9uv5Ig;2peorVc>TL9QN;e>Pr+?5J7s z$^6)qsTV^F3=;jSjM=r5Mgtn#^eCwubIbw&$fVF(evT0Uuk3nx&wZb84 z3Bxo)*2O5XO#Jgm2hU!L41LGaAg>2EX}bts9KRPzy4Bj8=btYEn~){koeLNGNo%(n zAZntBeDbEyj+4^(4d+(yTSERP!84^+csMvKMB#FBY+8$=6Sp-~l90Z@Z4G<~d{YMK zGH%x}KoK;Gz&`yOi^l)tm{*7T=8Hckbmg(8?qAnSq6_=**~43XHE+Mv?JN2cejM&@ zz*+PzVbCq zb-|A0kpv;-xL5x~J!&YV2KT1_o36zNTB}yh+~dT;o(C>)_}Ho`9f5DVuCc1P%9d_V z^;=x;z|q6u+;;j#JHLtHtnO8Hdk6PA1@C#DSc<@{xS>Ch%qGTh%INe`KudR$GM{qBy`AbI9ZA6<<9zS@F3 zUgR-{f#zCatG z_%xBM^O0p!#^O$8Y-Yo}WjD{!E_AF()n|rni4EjMLg?J9c5w2{isQi&Dk!VR%oeSqDOvp|+$4H& zY~;T3VXgu&wn-f5)fyp2OTY6tlh0FQHJ{yz`9Sil9mzzz0F4}KH(lA>KGbJ)6o@W# z^fB^sTJ3t{@y_sVJHrQ`vF&x-#Hvy^-7$Fm z#rrJ_jUL0ViC4|HOh(@25!KgR$*S*t@-@+2sE;(KCUqHDxT*!?8U#tL276qIcfV5T zF?&A^)3KSzeCl7sZ}472YAB$h%t|8iRl=>EXGzP>b4FyF1#Xnyq4C7dqysIag7@7u zk-=i>AZk`cVfK;w2&yeWzQ;bQ`m@?n=4`pUBHy6?MDZWbLuqtiTVP9F`V~p!vF)mA zg@1r~V*5yK-QI?9=oiWU6{g0KV->)o5SiuGVamg_`FRj}GxGSy$V|=lTEEljvDHYa zC{2Y-2VeBmNJIU{iSSdgTBf9?l|U8oiVNq|0%~<#jh0W}sUisy*(<>xOSttW5)Icu zLX4CE9@yXYM-7$7L2bmOY&i4{C#6T70muJz6$Z!uONR9Qh2n6scz@XtYnuOI%`VNf zSTVg)V0#_bM=~7?JL%Z7MKb%|rhl*8Y+wtk-tp$TY+b-`W14UWfdnuJRu`Y`Cyu{Yt;>*cj45{VhETJ z6K-C;65+Y+LpU0Oy7|O~lr)yR0StD#40e(T(ORc%mRN0a9#b<|LL zy%zu;LCJsQ4`tJEIXvkBL4Uj0RTu?I3nuXX)6KkM;2Kd3zk9f1<;-gif%jRqjGTON zH1t&=rd3RA)1{a3}$tI{23Aog}`t8Q%UoGSqU45QokIz6dO{? zCj|}|VtoEv{i{t$biWvRj%2mmaCVZjgAD)NRIc3pdDqTXwU}ey*}U2!7SCzf6q%u2 z@-!(sCqW-H%<6y?ag~b_%dI@j^>!w0vrrvGAjpkmj14M)-IbD8{oJfS%6}{{N>)fB z@Z~)%F*b~|YAk7hMSTx{NBbb-X8VNzw}u!xiFqkK)CQwJt!IT%8sUp;RwA1paHw!O4QiD^w~|IkJFXsETc0bY$xa*o@Jmm=s1QPM%f!Y;616n)(p zl_QT5t;jHo*>v@gd0S)$HU2iCnhosg436~t8qVD%KzYyLT7>ugI^ta1(+3_VD>Wd7 z-A>xVHYNl8Wp5ArK-*oIS`1h6-Ay-yT-~sEE;DrYZJHD`qxxPH(8hT7!n>$f9Zc>k znfvy(ZsKEmIQ#2#)R36px%57%v-;#nV6|ToIcY_(QXznskF$d7Mq}`m0~=-w@oQ_l z`@~L)p;@?WT+$xd_I}EN;cRoxPxSm}yE_8WziAPVn|(?$gufV?#QAl5d!7wa=SQ=* z2zL1v)C$3^?XwVLtlVI~AS>Embyy9UrH_IT;V__Wzu!&5k$Qp1?<|po|KU!9)17MG zH~nY;S>^xE*Jkg~G-0qQ(BbhX5%ik02$~^#2aN5OAlY32EAr1(nHD+8AR#F8jTRALBtk+W}DV7~gQtyu;x9Xmi2!xo3d+1<^Vw#ht&b zxUTL<;@K8JY9)SYN(VPmCSoMJb6^46u{zS3X>e*LH-aFVmSp$BEMCBmP8BJ0nGPOO z4r&-byFdC26A5kZx44R!%&=HpJ%n=Q|D7Abagh0vi2qG`hX+KiBC#6tcj)~*L%ZaF zI{S`f5Yj+QvU_Mow(zRby>eVFQBs=9nDaqU3Bb^z)&;VVR$O&Em&?kwU6KucMF!7- zim*?+*Af1vQ7(H$a*0Q+kFT16%^Mw-iernhk+LMaW8h4+xM!(u|QaGCgd z=i@`l_>w75%Cul;3t0Jiq`v=WJq7gA}W12V`5~YTzQhi zE@G(Z*Pq?&>ahS>=&)@ri-qV(iYmd4b?E$2z6{#tqDlm4@Wou5|Jld9e@XC+w}VUi zF!)E9Q6xwj*m(ZtgZ=&8ixBgUq9bgd_TBY`t`M@)T>rH#6(sMzfA9m6)zX()Ur(h; zX4$q@3(V@eMl{}mCd2O1c8Z7h%GQI!ihIo_WU#NIqDY<~p&{fC0qf6O&bChJKle0L za^K;{-f}d;z{C#W0|JA8+F@j^qav?*?@RsSje`gE*PJC0wXI8|UF7A0!$EsTC_DFY2&U*7Dx_gkPpEkY!7!>nCXKiyVDM``e$pr7GB-3bW}DPlRx zeThsoy@MuZ3+nhPb=%4GkDulK^NbUGmlHzPle~AN#K;dMlkD_NKS@0iyl4$fw-g;b zxje#_pX=wkrIEfeZiKR;E(85WcP?)xC_UTQQ*Hr-9E(g2?Q<_^uK0+c=cb(Wh%?E4BwB{L!=HpXzWsAVdwmo^T*)3Rc3%5UFpp{cERmIJ&d0P0 z$H{vW?s@3~L`h)Q`eV^YOz^b0gI6B{oYw?znjrhPRk^TlWnkjOw(1_UF5lHVV>M2* zHHqTHhde;sxHrKux*xNvRglNhYe*KyUmNqzzMme=A*7fBBZ&e@$<62r75&E5>E@pl zIarXemdnHm-t_;MRvKv-z=0r&+v;ZITd#woUnR2TTJhL06L0lraMIPb)kb+sG!s*u zL0OvB-3XaaE2iqSMbg^2h>G~`B?LZ6?D)hoTO*lFbdk>@S@Y1+cnZ;M9O3+jO^=*e zwlFNaSO(oSqVo>qhg-M+JCDiO`%;JiW;@gqZCLAX0nU4|X*p_WnaX!ZtlU$o_bbol`jnR4zkcmrWzQ=|ZU*{T`n>rDs0V~F|2d(X1DI_A3_ z+E71N1el9xpNAI+%?gbO>ztOprj;zLFhX*en$-lLx>hi-rx;p5unzPx6j$@STPLf- zETolL~=dgS6e5D2!*`!Gl(L(7HzNez|M!5CuVh-9`bSVmsL zZ$5)t{E-1XvNeE{OTpenR8Al3M-Sai9@dk?*Z4SDP0Z@8pKlNV0+53UYGJT%SMh(| zws=Sl#o=r;|64@{tN&*5tS-gPWhOS=JEg)I#)#)=E`5V-JYxz^BMPk-e2u$LOq;0Z zU*aD?{BDRZev*QIrpe zqN7t@qb5O)|Czxkg1sDbq>~Z~mVJNiL0K1X(3Wkk!}B0^3ahR%`B&_1QY%V_tKmZd z+HqucATLJ+93gIlIoAk#mt=2)Ii(tJ{RVzriZP0gI@Zj#M53N!ENz!%zAT^bOLC0z z!aS`|K{9~QpCDNDBiXa)WCI4tszDu(A7^*QFJV}YA4N)qkx0xg^lWV;+zWO2XCs94 zrwK`0qqm!cku!$cdYVn?^XAy#3@eJvYmAX&R}tYl0dh-8mF$qnyc-reEGfWCjRPi7 z#Wd3_C2&l$uk3rqjF*aqaY#%B15_c`2BYM8&>Fmjl&2Z1e1NU_OyASd2@3BV>=eGZ zO{zv^7YP_C&PJdXa{x;0+5KKNU-4OLMDmLKP&(k|(b`xYM9zFRIJpZ%L5&M-kQfif zv(AF#!LUaKF;DCycCI6OnFX;sD1z1&4sx}r?!yyNL==D%efy87r`@J?LEZ;+&xZtZ zav{%Y%Gzf+<-(qi#WyR9(<|rqejj84uN;v{V);OWC6c;L9Xz%5{cSzj3I2XN-tB-vht1BMK_$TYj-ye5;^XKd(;Ev+` zo*i|~WVS*xqNgGX0w$bb_+Wt{kxAVN-dxuof8 z1~jl(jIP?+tC8OOydIPC4i7UrxAXa}W`gKhCk*A2X7(Y}z}2T^_+8MzyLCT%SxO#q z(l#Z;$?3z+2c*n;3`f4VGAA3o=yMC`rlbn2JTnNe?U8#rJ#4FM7F-W89++KR-u@v_B`_X@YjfB(M2(iF3`(x@Uc4_~sGT-9GEd(x|dd&zBMCv z^$huqMAa>oI_cU7sKy{k&p>78kFh^V9LINiL-lp+YYw(NO~|v-^_nzM4-AH~eX@wR zXqEc?D|F(`WkBlVBqXMogjq3GGZ_%(G9FCsbP7q9Ddq0f`9>ONvV%g6xXs#lg!M^9 z=+kH1RV>6!4`S)8=am;C`EorymudrL%k(t-yCZ6&Z4|U;V!xDR+v4*=_^aR37J)WX zBkT-zMG#}J?N>vZfi2x(M9Gn_aIF5~ku=(1S5f5=;>s1FGdxW608yeZFgihEHmtRo z`RrQjHp&)WH~`I|dYuxBa+w9E>&nzy0148f7g;AeWo9Ct(A1{1aZ!&o?(miX_*=4q zsx^S8SAyXO`P2t-<*0#gQ1dz}9tP5dkHD$A1s2w@`};HN<$9o!U}r5 z<-+SV-HEdcK)0;8+5?_$jk8>eQEd$FHCq#hE|`-=9%sYZ`2Hdr|K&nf6Vqz|8D7%@ z$f=w0e7T5s`EMq^ZD1lMwf+lZ{C`_;^I|7@`wzKD$QN2azM4B~4RTwMed(tc(D*9O zZziot@7%T4^>uZnE7Y=y`b;;ny=^DsVYdem)$;f-9=_!5^?^V_Y$LRtXlHh3%2lPK z-!`2fRRz${$7o#4Ps!;R#7JK>x}4B9)3Y{Lz&rS3giqT9twcf5arKdpro@4`<as~iCXC6ilb z-%aa-CcAvTNN#XNqPn#)9Y3;F%cvBn<^Ay#;(o{czN_{p&#lNIZ0d|xxvGsD9f?(72WZeEN)bB zWs;<{GL&rZt8d%!Q9e)T)+I57N_q%Fwn5*u#P z)gy`Sy9!0g&VsJ$S-xj?6jtXcezg2_q?c@a9nw&X+Aw#-y!c~Fw<0po#>8(`YNx}&!rOmj0I+X%|j)7gI<9>7a+&gO`MSKL+z2nu%4#A^r{aUpPP{n zUwG<~PL3s3^79?hs#Ei!5IzLA~U}rcB-ZNH+Aw*(c z(u%`g>w_F`{_SVb;Uk5ZJ|QF~H?KpS`&Bd&qkxF%>j?WBBaHI>6FgM?6Fju#0|_us zS(d(}(BZ(|tY{LbUyc&#;Ay2ail5^)PFt!dc0w?B6l}LtSCmH#*S-g)8Z0)OxU*cl ziNdsgM8E0v{vE&LQ$@nT0rh)`aIJSFVfI3P8#yhLB$GeAi?9fI$sgQPTf`i$|6-4t zUj$+{nP%`J^s%W@hnSB0)`&wLtHXmwNh!i~t{XCs+@sV5|HyHSQbNxN5u54y^v&h; z8|-@151-#8iKEv^5dUbeN^r7tKV34AHogLXGPmITos}lY*C`A73K|~64?NLB=FL&2bGQSdwIlY4 zquA&anHTKAmRSGe?a)WD@0*AM7}+>3aK0gg%})Nvk6OI=1iG@?c!hrMj_My5=m|7k zhn*0dwZ{uobJjaE&!b-a)Lo+Yo~>K7MwybD?FYCbFCRufRz_kh#9)@IN6JH*>EfQa zb3@z%<5riTe-Db#dH!jvB7WZ{6SxZ_}?1XF2ZVPfS z13-efXMnGz%_7MDTyYvI*3 z_4Gjmxl%J6A&4Cpx6OiPj9yzB^ZGmq#)b>i$ce%_JWxZi_piN)k{9*#R9NzyX;Hs7 zdI#D}hiEX_Ed!cN?3$<$Q|eLM;Pts{1S`f-@p50(xHettsJ3pCUX+jydbOxeOVlsg zNJ@)hPedK4=i<2@CrhJMt)x|nKaX3Oa#L^NLIzwEV%5Y{OD6q@PoH>4zvY#cYDZ67 z%H2M#;O!w>fvrzSmu2r`cg^*CAKqG%3Lo~S*R@Qj7plUrpHUm>?O0gL?lGFJE&Tp3lwI~0N&gF?=cxeu8|IK)r^p~` zKS)46C~#AA-TfX+^Y3w?`xkWA`wNM`h4cOIlDeL4#=DIZd=?@ZCi)q6--z}`H=(kS z!23Rykmq-`M>UJgUZp0l5pUJ2(Kw&Yv#r-RJ^B-TCr&=K;xXIx$#Yt~;XmG|eKlR9 zZ77gXP4NT@zXPLOa3l=81K3#0njT%r7gQccq!)FXw2RyNQFkKf*vW zz-M?z09YbFK>f~)s4USa+P`faQ)(-q>kRa&x`G{<-#SYk?k1$o!>LHwBHGKqmJ!VK zT~A8huYblOTnOum$N-IyiTH)v4H1)eG8b*-PO^hrw;Djja6+Jp3mvjY)huR&ke#8H zO!;62pHujF5~{xKAWp=*#J&yfoV)R3?yKqPj>cXz<^X}&A>z+#$#tjR*!%G@5iClO z$R*;>WDNAEoqN;T*?x1WIZAAW+rvzouf$_em{KN)Ft8fj*))>_iRNZoYTUW7);XoE zs}DVYZgE}+N-e16-l`DHC2MxAKY-C`aOdMifONM4nc}?Ld-dDIIlR|f z#ZTvb#qUE!=a)W`QJ^A%2oR)_q+|}|;(%jvT=>z^1V|2T!iA;5NZJvInj$Uy#K#es zIP<-ZJ_0X~vEv3r2yeONtATa&VY z$TZ&$bB!zt78T0(g7Jslk)a1}aW>*_rb)g=yIgL71DrA9q%AnepDq~7?Di;EJz|~@1tplsMcr5cm8Udvm zr`^zLQ1tugzQ~jWpdorZ9A!QLYV=Cq>HN|?%h?0gZhb)Pps z1F7!*6lGg~r${)DRY_Bp{JT;i2Mnu?lBKazC&?y%ETX^l(ORNDrR!h~-Ul4wj?Txk zAfCtQu7e9^G&5Q^0%g8d>dGl0j-{ZYUiJF?!s*M%eZC+EBm3jv z;X?;%#*xPoXGN@K{@+#!1%|xfNyH_^ ziJfhWioySr(*O3^S#8%L&7cL-IR1mnhh@Ej^GuZkdnf1iEZn2)9unKbWlEQwTK7eA zb!{ixsQoP9Oa2+3x@U|RPj#jj*syIdyA0w{9uG*sEnOox6dqP@h3E%AomiU)nBkkY7_)~N>N(eUk!HdD=TI*PvGe2vwVw|hAG=`|A3m^q z)WA(RxN%*giZJ_=8Zr6KiF+ZH;|UmZDHIW}L_J$xz=NHHF9rLa`Q!QBC1ftgKmV*zZp+%2o>XFcOxuI-@$R za{{zl$lCZ~P>KSYZxTZ0psZm>1HZ%DQ-7=NG6-qTyB1*ecUWwR+rrJ_pL$Ax?}&$_ z4+QKCbMA(DboupPt3V*1tNPuJF7e;!I?Qqv5ZN!eyo- zD+VWb>D|0w$R|Zb0#pBL2sAmVXi5F&BBIBhtM^+9@BE@P`aBK~rYSo>I zpKR&Kg6aPB@87it*^Y11)8YFX7`p&wGs1;o3qA3b%*{(>3}2OtZs}I{Qtv8@ndC4f zAB7HqvP|ytI{Mu}+Xp_y){J)gvQTyEj?8!#zz^#v$ zbD>?h`w><>KP6z!o~?h1tT(VPMZ^T?12o1;PN9#xji0mkq)JDBVED3NVU_k$ch!?u zX0(RxrO*fVj`X+5a92K96)g&MQoBk671rJAkH1f}5H4hWqrkU_PlV}PoxYg)4O3%CcWAC9!`R%=bCNrAiG!8ZIh(G8}Pd=>j84hKiMrpM01X;HXFfs zF}THJXmiDIw`*EYv{z`B8aiYW5&ywqz)d0|e)q?_ZU*NRsMUQ$~HPIckZ#BHv?2UKsxSlygU#S-;=*~3Yq5_p2qn$@W! zU9-7C!fnWZgN3#tDu|;&K9{?3f2nOfrBQy$95l>t+g?+ z@Ts)LGnZEK;8~)aYmr0uU?I5h|EK3Y^py_bzh%PwldkeVW#jxW5@!A5r-@y6jXuy@}@C2}Aq<%3|^ytF>cp_~K&sUw=uL>UA;`pqR`UJi-Uk8)Z#mqSm zbmxj~|GK&rlzmpc&}^nYcPDM`$Tbp$gMTz$kIPd>d4$;h3E!n>z9Lz$c4~I^*~X*3 z-hj_R>~f>QgE-B+Gm@>*{Vt1q)pAem@9mSHq#AwbX|?-ZC&JmfZMsF?OVm}oUky9K zaE7zD{q+|IFFNQ?S8g6U-H z;zGx&%4}D=3zWVP$?jPjl6e8FIov+DhQNV;TH{XTA>PvNk_gecub} zdt9J^bt}E`4@XcG0lhfApB*YSZ&(Cd*63?g{JHGgs0^y!yI%HvvT$;l&6Xh|_G$E4 zj)xHJQ{yMF6`hEul*hxJ#Enk&*`jQ#e5dU3o`uC(IEM!^WCeYB<=4UPZh(*t$WMXm}Oj^w;A-& zKDr$#W3VZCj1z>Cw1wYS*7785UIO3Ll4V?~^qYUcUiL=ekO$dc# z5FoDbj@lj)K_Cbmlm_X!hUx(!ntb$7Tt-fXC6a^`QWpj^z&z*P;=5j6hlB#+LRr8O zF6Z*>bIGA!Hvt5KVu=kx^s26>E^OV(`fHScV9>o0xOn^LgQM#YrAK^$)ayQE`}0T$ zj`s;QnO6GE-llgFTRt^>5eZbaH|nV$mZnvVDVoYwY0r0Nnl{Q(8kCzmI7}5bW|S2y z{5-a<5eO~#y0%q8FSvITauf>qz@jE^WnNI-+Y-&20Yz-IHk0OH9-QGU(j6mA(r=Us zx+3={11e=Jm+i5qMeB7z>R%>G|NIcpxyUGx634~}!#Jq|LZF?X38N&j2)6q?rb7gM z-@jYNxoE3%!Q^Wl3Qio*CMz@HGjC4nZfe)PE8t+$aEy#yL0prMw8V6hTWd z>^8g89UcK9WEo?|RHcTcH;qJFCK2(l%#v?A&J;wgW`!!uK^~7aZtt*G*Tu)~P&`v~+-9V@+YxNLna@QIeZ2e+e|JXO> z$oE-w&Cq4vGtMW5+}GbTkjNwg50a$4NA+7)EI%;IuUldyNh-F=H+m5H>_#{VS`xD; z0Oy)8TrS+zO_D($V!S;4f1ZpxL7dk++(1|%A@6BO;()<cLgY@^yK7NXWbQ(U{AY z<1NC#<4@Mn^w9SrXdK*xVEoU2V4X0It&m%>{a`Y1avlJomDpbZ$MW&?`>roA`$<7k zr+F2kq6mIV{r3wm|J4gD|KSaqe-yGxdELh))I)^&mi(Yn#2o)Vf&M?qt^fa>MO^N!E-oAQzxp*1kdq6?PZ>}{GeX&H)blHtApEtj m>Jj)~a5wS)z2b@Tqic~WPxNVkO)%?EeCFmEaWs diff --git a/document/resource/mall_swarm_run_01.png b/document/resource/mall_swarm_run_01.png new file mode 100644 index 0000000000000000000000000000000000000000..5254d49e3bc8aaccff9ee4e1609a1eae95d15e21 GIT binary patch literal 22507 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 E1}i4VLI3~& literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_02.png b/document/resource/mall_swarm_run_02.png new file mode 100644 index 0000000000000000000000000000000000000000..635d3e260a154f60dfef634ec777867bd307d2fb GIT binary patch literal 25850 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ⅈQv!7!jmXu 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 G*?$0h4zn%* literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_03.png b/document/resource/mall_swarm_run_03.png new file mode 100644 index 0000000000000000000000000000000000000000..74327bbffc351a682c219f2a306706b228a24b1a GIT binary patch literal 17262 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 BaCra# literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_04.png b/document/resource/mall_swarm_run_04.png new file mode 100644 index 0000000000000000000000000000000000000000..e3de4b9743b5ac8a7aaf75cd5ed51b230f650db2 GIT binary patch literal 30672 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 literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_05.png b/document/resource/mall_swarm_run_05.png new file mode 100644 index 0000000000000000000000000000000000000000..1bbfe3ea556d07638963fdba52a2ca00f21a53d3 GIT binary patch literal 25328 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 G`2PprVTC>b literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_06.png b/document/resource/mall_swarm_run_06.png new file mode 100644 index 0000000000000000000000000000000000000000..d5e4acc25f3b82d85c513f2793ee24ae8009869a GIT binary patch literal 73150 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 Z+L|dqw-#s@s&RvG=sz^pexvCe|34tNhOPhr literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_07.png b/document/resource/mall_swarm_run_07.png new file mode 100644 index 0000000000000000000000000000000000000000..07143a7f1199b37cffcf9b5b0acb38377ba3a76c GIT binary patch literal 87573 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ℜU6?qIQElLx{QncvX$|+>)a*94u(Kp#mOT=bCI zwmMp_Im+O)``%LRDC57ZDRxW&ezG;~9bwoFp>Cosi{a6 zU$}8xoPhQ`I`jyGPy6{Jgqpga7XBc`1981toH-LnRf3pOB0@tS=3>f)bFa%X-7q#k>}` za4}l;XGM2)x`6B9q}l$ZvKxzr4E$2(bF#3kHAJgoG;$+iB(Q76mpYSID!(Bm$Bl9G z>V(E4c#Oy{(7wD2Q=458pKpo%8oN z(hua_SeO6s9ZgSLx-=ZJh?qralw0Aw}AxaTbwQ|F@rlq^K!IrZ1r{>~Ldgj|i-edk{vX1#Nn zq`(+1vq}+P5-lDos1wAF7f^xA19JGtENf9QhYQ=AiTvVk{TRq*i6!rgcYohKD!;l< ze)4ZkK%{!6PR{oH15i}hb+j?3bLBzUhG76bnLq&ONj(U$ZcuKH-4w>lked$p%j zb(L2Hc=&4C-SvRMYyZBv9}iyg;ssGaD&PNYa8ZUbuxu{>{~KIA{xwlQ#N-sc81Ydi zOW4^R@a~NEzXsQgeSa;S(7iF%x5jit=Ul%$d*I*f7u&1OR16R*Mf`;t1**OkIh`-V z%6z}P#`w*8OesG65Zf{e17t~tBHSEqz6HSSE9G1ZA^KMva)PiO@($mKD+gT1nl|KB6v4ME-wIEe&!cT#$SGuQ(sGk80 z?YoZucD8g~f6-JuEIID`;LkOqQFu;7}|H0}^c z;}YB<1P>Y-2=4B|8i(op{&U~E-n-V^H8bD(Lsj*uQ*vtWXYc)Zir}k@hE4sLHLQ$6 z&o~HR752jk7?`OGBzOc34$yI(%f?@qSG~G!iS@+$zm0*H!O<3Ep1Nz~^uhyt@|oDr zFaO%k+9bhRyf)BUyp)nWd>X5zWc=mvTAsefFHiW_v%wA{Z)3!!YwvRKW{Q1Ow(=^f7#3JtFoqw+skY`gzU9H`##*vsC8!WD3qg!7DQiVtY<_T?4I5&jrSbz0Xn zyEw-GGg$oo_3)9b!!TYp2^3A)^1`54oEqq>#RcsLJqqysMIFhMDEE#R0iH^aU4Ik7 z;U7}}!dRF#0Dg|rkPeAefIuBq5=3dm2s<=z%#|fTO>3U)_y}#wS0N(lM_~bUFk`mh zZzY3g6AQm_VHDVqFPnf%O-YGFc%Ah?jP*$fIH&waYAgGL%;*PHko{EQ2`S*xRxors zqZP6GrRW<(zpO^(k^8fe%%!R&p%#Dfhw(%5Zv=irjD!4d|9S>aZx2NpaXW_KuHB9t zob{1A;ORPwV>w$j&(VUi6Yy=JiZ(`J8R0So){Ys4n}E^tG{u`Ztz;H781H8kz^nz8 zzxg)STch`d(z2v=UMF& zPIQ8&d`+}7R+8qo>&q30Jg1Hk& zZseSfxcsi);IR2Vd=d@T;0n&SSIbPM+yZjg?L~Hr(sNZOEe*^OmO18(kfuy-^=3uV zmj7-Pu(Z%@b`8YZ6GlUY$5!~61<`@3yI;CO{pvn$ol6(RQUGk;zul|WqPaJmfFu*P z)$sRRwq5vrWpDTu|2y(SIgxe&pbI;T^TUkJsqvf#>`Q3(8#LaZ?(PS>^eWg9*Qq-^ zyX%Y1wcJe*BddR0gKp17`l2M`dvppa9ILafA@(=Krb4vR@V_Pi3cA7>Sqb8iOfq?h zu$&dw>>VvQuhbouI%K)}u_^YW=vce+yVnr%@F458-(I0Xe@@RaR$b*nIJ44h=G3{z zo)^1<@`Qjwubwlham#blaVa!N|`sD6kTj$Km2U6Dv`s{s68faeICUtwN; z^fkA@wF1+?5?PSrPcfQ+{@*EE)o5IZD0hZ+`a!;e7Q}2q0RyVCnzFX0x`K`G-IFvO zxa568@w@kZBGH>w5mj!0D1eY1W9- zTdk(V5IkGcPy-a4wO`ELi8y{BeaE8wfWe_n4?$Bl`K>~hCcoVOLCajgzLE}<(qhS- z1(0kr9VKuW-y+^z0>q9Al8!fcPbSeP4H_J~GKb7hF1H*Wyq)?)P4W#< zA@GY4uq1Y*_T(yp4PJiSv`2Q%+5{X`n4p5H7uV!>N;>T4(K%EzcM=Hi>PhBLoK>{| zto3$32SXJfl}Mnie@;S6i)evgd|~eYFTt{}%`Cr>Agj^{3tKyQya>q4jt^@uA_uaa z1)L9Ps^w2gO{2kT%ohGQlUtGg)RTS2b3@4bavb}UghGfu%B2=KxO;?0a`{zxJft1 za6>i(_V+QKUf5Xgv1(0fYa|!N$xMox^(%gsZ^1LN*8^j2{Wc;dlK$%;!(Gycr+msC z4cG@T^yGj1!u(=i{9_!8I2t$MZ4_kV%f^=y63+dqLsl4#~LB)dpJjrDkk3^DW`4LuFSg89HYEVUY z!sp^JH2+~?LAjw0uTj3Osk(1_j4$hh#a0woMQ9e&d7$m~n6(K*C!WkhObsWIYhn(U zssLownM1|1t8>;g%s_*OB4vuDAov$D>$uAT1rBi?;$CIPlMls#7v-=6_pHJeO0%vK5D_YFrJjbNFO4)db5l zWZh1>k8Qd5tEm&9Bn9H*tNesr`uZf2ts(PNVV>IFta`4oDWC}l6n4xgd`?}`8prmf zh&k`fRR6Loz*pnHJ)V#R=vdK`s@?CQgn919VALag(TRK=tu{nAY1!SW>fyIHzREfz zDN8&$O1lIEJ|SihUImrY~yvlM1hUr7KuMPE}r3-a&xebgKVJ!aULSV)3mEm0zH zIIXWu3!B+Ki{zHjm!_r~1%(-G>zz^cz3!=7c$Xiez}pXHZXdeA7gi1m?yOh-?~GC5 z=`W<&)2-W0e{}tVK2&3PX0yXjv#teWuy>QRZVTDW%(zN0$`FIH?EFeU#qP-yxpQ2s z@cR`7`AM@X_>5k0TQJM>Ojbs0op7vT9E6(Fn9(ag^NVz#79xEs!gsso( zqk`h4#;G80U#dy}5~Y$c_hGXg3B~z5%jrcY_8$G^=23AXR%u68Z{Cb-6f`LYnm!}T z6jw2*JI)?!6DXVIxP+lG;uyclH>mzsXe6Wb#_4#`TzKwCDiuoV-MekqOmoN=E>HSQ zG1r)K_Q=Je*EZB{2k(_V?yS%2-f_E&EBBujk0+Mo8L-^N$AWhoq>9$#jwgZk<-oXk zOatLjy+aH_{<1C8Ki+?o?zN(7-td<|$HN6m&m3;=B4v;|*-`&JR!K)0^S^TkPWJtH&qN0vm{ntRH zxNxp-C!Yd!5&=hVa;|(0Hw#)BL1v8E;3i|s-?Xs8u*p-WU5O_g;96TfGzc3Oo!oPMmPA+J;8ERLYlRMI{y^lj;hR zwNc0tGi8q2v$&PcY87ry1XyR-k4M0zFlmvtTHveYw1;V>&`}MYPETyv{hi0^=CouQ z#fV4N00mA`jL@VEfz9I^D*}+Z*NHftjI>hj(`Hec>DbTY2 zzl()bfuw0~J74*~WnV)5YR*FuuD}f;65r2Cd5X<45{<0(@AzD;q7G$vSDl-b7zJ*B zZ-PbS2(^}}zU(AW`?Dk9&U%XAu-YR{!O*7rsi{1gUAD}LuZ6y57;Gl!|Hd6KTIRJ) zgy3@%F}7@kNAm+tl)`y^~VA*1+~g}eJxLit1eGVpd(>N!3>SYV0395nX@ z<{To)>ji3p#w;w#lQerMeAR;z%Z4({HoxQ${IzB-kv2D;SL?8JD725ey=Axc47zPc zAGj5<43NPa!a%i226%=1dW}~vB%$_C7H{|Sc$FjL`uRUuyjb{nNBw74SgwHasZNV8 zHwLn7?Piu?0Hr~et@qXhQrpmYIqrf%t}rHXcGs=A!{*HwUNGqj1)4&*rP&&#>rM7B z$9LpwV_;e{R&8AaKpx%0rU5jRH^BXdD|g(OmY)M-`Cug)IbQ%2(GO0BlR6O-)m)HT zVtJ@k=lWk9K2MD>MWGaDG*o`sk0Y} z&P%4YWH{va`QBpKXa!}A0UN2)@+0-@&<@L+N~ZN)E>u+dfo90|XTk?xSMKg3Z18id z1dN+;^HW=OWz7O)HT;&+6?yJ2dbNVfDXX@(HSNU1P`K)@P`ZK7lNUj=))DEL;h z2gF*D9ls{7AO+Y|B^`Ag@f`%Bzl}s&BK{Ukx88#9oe#KFoX(Yg_5pThuf(KJC_qG2 zh_UxJyP0}0xYvH>YX zq>WR1LjI?&P3Aic;h=nec+i7<&SPIxe25Jf0e%ziUYp(dPPgH@__CW67K+q$H5a;y z`L}b6Tl3DVi^wqWlgm*Q(wyb70w?!WhK$P;SjQ|LU+ANu(&)qmq<{-dpY`4GEqvIJ6<)dR*FlRlZ4`Y@{-hq{|env$;uLN z>MrA=dDeeu-C`huu*{mHPMKxztXpGT$T;6w?o8IL{yM-2ZiRsc^TLd?8dShFx1tsY zjygyae1_t{U$^=C+w=RsJKZgh`ptXA|8*)%igH$e-#US1l;Da?raizmgRx}q*JU7X z-o68hcO+U|dtFR!%YZSqLz3(N2HusV{(*N5`}Kg5x=wo+PArRq8EwE+%IKc@hrg=0Fw!WdaEflOgT35q~>SjAz+xUKeJWdy9g!dX#?Y32LK z^|~mC$vy!Usu(t+*QNa_b*X*&Z=)V1ssgRz`Um9P6#T4n9^n?RnEe2A9nW91iHh`I z15of46$lZH>_L|?Pl>U>kJjSE%bh<7aUmG^c4AB=ami8n%Q|X0yQ0YWI|$Z~clJZ> ztgAqhpAem9G)N6kWtslE3~<^@`_1x<{)F0T-i8M(fB!&wBY+gRmdRk*uw6@8 zC3(JYe!sjWGKG<<;QywYB;YrGB4Sn-NG(;jj0+QixwlyofK2GMUUQHnx=z2jm}eXv zc1-j?^4WB&yijwyfa#}egBlZB!L)mS?dF$mjE(y2S=g$&733qt0rY96TNb0pepgwV z|1ki72>m@Be|}PTktx6LLzV&MZD(`b)%9;HH2Sd)eyVvTdDQJf!#RfThu-*K6CNxr z55LS|V|VH*P#oqva4p*bf53g%7aZU)e~4;PhZ51(}hYO9P$a6X^cygDHct9TWX;R#{XQT6u;)YwPvoPX0Ei&hb+((U1;)S^ zq@j07GT51tqizWshjCrn;(hfFPrGnBKLJO!gtEZLbvj?V(knv`V2S#uKf2N?15mzt z6=2br4Pl{Yd`DM`24kT&prGFVsw<9dJ1UJ3hY#)Sh>NO%zIi7o;2Pe&0CtSKc(oIK z3@?)r7(D;|nQ&q6kqVGvy!$p%-S9V1Q6!m&e9Q38RU9r#L5N(#eLElCLB1{Sbf9~|+7(0HNDwYnm=%m|*fT>#o@!*M< z$2OkL*34&PT2gJ>*Le+jFEf#^1cra5{qN0Nc1MhR$e)71(~0MNnxWRqKeAa#I{Zj{ zPiinw1LNzcKZ$Tuj|Ga3Pc@R=3Ii@_fm;yIxda9$DR}49TZre$(09qz??+g{TR$5e zr51j?JYG;?X=%YD8)abPQVrSjn%mE^X*wM(~auw#+Pl3j-p22*rU%# zP<(O{usjvsDvVR*p8pYQn#mMJN4!ejsV@UHsD3npNxP(B0Y#;#sU{$(!+CGU~(TjdNe5}gJq zK?ts|5*(lo;KBl4`Pda90r~l9!cGHm5cimdxz5edjeY{l7OE5fJ7l8-N-PSwZPuNG zxn?&~p^9CmkKVj|F&!_OpK;QnixwajGppC>6Kr(!kJZq7 z4iNdJ1BI9#Ljt*n9tK-S^0? zDG7)v=hW-(v4@hQVt~Zdm?_mPTgpkFAjVW*70YPky7TMFSA?21-YX7#{U2B^1yWKM zqpo6RI%aG+phr*IA)eF2H-($LRl9Tehy44dS9C002U-tN`Bk4#c38?(Y<}?yXQ0f1g~GI#w29AT^uFRF>njYe={Fi0<(70@FXKwa z>DPFwlte1#fl0&#e7w-T-Y+vBU}k1!Pt`s}KlRA1s2HXuXzte%&6FHOvqp{9ndeyh z7o+k=`cjCWF-7vcB_)&~$57BC`5R3Rpem3jS8ibrHTM0=Tw;={sNf6ui1)l8dWMK^ zn0uJ}$MM{<_DPzpw_u|3E#}L~$pKrx47=rHiB1oE(8L^*`+fjAA*QvCoTg4{6d#u* z08{`(L>I3wJuY35{8M=3mH?66^%!;D<>umiYprbh0%W$H7}e(dX=~7S!cu^gFv#dN z0{V*d`K=N#@Pjt#Kb3>U22iCUKffWn5fN$Nl)+xO|5xA5 zFyZTU3&++!iAC#Tg10d9%#ECcWX))=J$V9$8Awovm_@p%bUBQ!)DIk!2qH@EU`hG% zi$t)Hs!#njk!4`_)<-u@8{cNq*X>f{31u_8TwIsR5x&!%EKDWyllp4U_4_p*)jSKN z%|&g>HNf0|Bm|bBE`3h7u3Ed>YA!AE`jRIXU9Y0&VO(B`nK>j&l; z=bGbw^NZx%1#~Ivmmi(&`kW+Z01w+?aucFioCN~~Mw14cddh9DsLjWAzUDn;yfmW5 zQid4qlM{S&at!R%Q?A*Je?P<&otu_s1tOxpJddSHsWnA)yL~=^SWzQEO6gC%PlB-F z{zDC7jPX=3EGYRv17*+#p6RP-N5<4w?$(R(1H4)(5l8P~ zg_<58^nK}}{vC(Gk$6?dPX1DWBalMZEH13KVLaV@DAvi5JL=w;{?@xDpZqzFrS9?Q z=3OMsM&(N8@%%H6lf+Q3(rWV7!MfV9S%04T*Ew3Lyrb5uJgDkBh&T6_jBWHCKki<% zH_54o0$9`o%9eW00t{gV?YLC}K~x4#sdjl%P$TkwPX?eG;hWZjx8VSb4%t)tH-En( zV-jhy4)DVO;ZOb4dJ{;EeUqbnCdu^I92uZYl3Dipr;CQ?ab^my4gYGiO!L}%p^Aje zJqHda#%ao-?onh)NRJ)ll4se8u6%Wa5`H&76w5jQl0Gm1`+P*3Ii%OG@O^(}NWp%m zG=dw9YNh+LU5{Q|g;SssW9lz7{_+1>tx5sv+t)^eCsvLW|B$<)(PFvr83z;7tS|8+ zx@co!Dz!hDmI)>umimKA>&7Jo4oJoAAeWTA)5tdQPaZ9Hfki8t(e&F@kjnR99rx1n zkj-%hfM2ILzV`;^G7 zKk>7RCcR%41@5&dDr~Cai`P$IsfA|GTuR6Y^<4k#HgXHAP0qrGnRzuw!fyA0TzdaE zElo$Wa6xQmUz>4w672#+N2B?}Tg zU-kxwARF=Irc96|kv~!%1)w3-_JM+Qr~RE=9ky+|Bm}vKk24MH+03rGC>ZQhdATV< zaV`f7mv)byX}`maP*GujeB?W(e~-$}F1LbK#L);_Pdk&#n<)^3P)lI1qDLo7 z9_Y+ws8GOu-qsH2m|PDEsQ{!Fwxq4Z9Ff8T9eSHdR`*wX7arl0s{c-c!>{X|u1i;u z8IN4LWP&=LqXCm46_V>P5^VBEOIPPc@zjWjd;#<&LQxC6R3C2}eEUt{i0u!X`gws> ze1{^XVb^l;RlIs8wo1~vgQ=v9ROW?2OOf)$DpF~s?V^);P>speDOn$^+&Y}mF^E<2 z%oYS>9*FLW;TAk~h~6kw6U%$fNgFx=RG=~5*Ni<|a)tSw@}=1PDkO)&5M^!Mn0v}5GNyZTv!b(?+y2`7EMg2EdOT+j${r(c z9WSQ@)T|=zxv5cnk7$oKAaOP@Sar-e@5m%q*hDJFc7_ zh~7{6o0J`>^&(>-*!%g8@IUo|UkU!F#Mr{F&QKN$;$8oIq($&phtW#ae~ohx2DyM_ zYUVR>0lCyNJjBS%x)Kls-Z30E{6RlcCKM?N#;dL>1iT9El2Tm|wZfZ;{3X-L^=8lV#i zqb;tIzj(1FgP{smQE!5gncCvD2?r|IRAlX1SiRFshyp(BSa1cO`GR-hqx5*4qqXbh z4710`3Ymo{vMI2|`g1~%&Pz6X$-K>Pef`>sWW|3bHtS9q*m`LL6Up=y`*XQ!{!m?n zkLM+-uYo_!TNib4ra;8ifH<+DN*WpB}C(cg}DfMsfE=P%usM%((W#3-$J8<>!T&6{>q!-w|{$Z zU%Dg@5ScM)oD}LsH|E>RLnFriQI6x9~OdPdQwf>i$%iI;3SnX5y ziDnuD^+?nbEB~mmp269Smhp%054v)b)>Wlbt?OoK$n2MGYf5>*c7sv4>@zlQKg&lU z5LA_n98NKQ>m*Nz4h~hQvgOUf!4tr=HLXp13}U&dwhj@Nd)4fncg^I|f+2@ow&-W1hcU`Wn|xV9Uy#StvEB%Jqq+arx5 zML&X#=ei#2c>J|HEh;wH^yM{uJ~kK?3*^rIx8~$4BX#~&2KDGGcPQMjuJr}`R6?Q! zNBQwKpDLejQu>CCE?wl|@5D4qC$wPU`16#!N|r+MO$6y%oYW*!wQ*v1z39Tlyl(Ox zC9N&62n?@}TLG#_lq3ljdBce{RR8i-gHGmt7~~=ZyqZw8hXTv~=1JLq>ycD!Nqk6} zz6><;F|PjnwrWbI)F!>H+jxwQOM^#kC`EAQ)VpQ-ll@QwQN#(*>kv3I*6ea)4$c0~ zn9=^!Ld!lLb&WXBTBeSe_+%iteb|_ zTdq~+L+W)F9eyS}NdsM-9X6|Ug1SUk^`_86OeHjc`PD)F6u{iKc?JX)VS6u zkY{0MeIzOIZ}fmAhX!=lISsN@o70acbW23JrisRsy?~xk>wgj?8Ue2$2x@ro;V|DW zJ(E%!7SW6SJP@Q>g|*o^T@~sVvLWj*k3l>DvA4rOv_LLcYqe} zA)Z}Db5$_fbIEj;>5=4R`3RxldbHh!+z|4LcPY=&KxXn7;8m$X3&VXKGaGDB!1QvC z>*n(h*CUJ%PUP z&?#;}u<&2{-{lB_JEtfFMMPNd9S~2pEbO#xxWKl*Y_^ykmF}5bkq|U<)O^)wa+;`4E zXq{R?1x8S`vap<82YwrMeUo!!2gaRxoi1hiGIK@Ep>R47RuyB-3)xSqONCiGee{7h z5p$=fmbhdk2}{rw5gpM6`i}^IlYsL>>}oVQMwhx&Y&C}KRdUOR^IXdldWl)DrP62e zG)R-Dx_NC0WK%tMZbeQKrD`FH&!@pyfB*H*Ur==|=SQ(xbgq7?^a<*_EJ#%gg&D<0mu-6(pVrZBY;=dM@yvNJyX zg^2qL%<=Rv@A3JtT%VZn`R{v&c1K%C(VRw>J}iQ7+;X3~U)%WSwz9_eazTk12@G(Q zn?kDPtM8*p!6q(xP|r~t+Od82LlRfWI7{%+?Rca^kQGk(V8PZ zW6r8wPT3t{CTh3sZuW=qmU`*%1+>lxWhTO(%)9|{Ch2)-bV?t%bbe(esD9~=^U$aH zy+%AfgqKT+)N6x4iM!dM z%V1Mv$Y)6ke|`ZdJ<64sXg53;`(iLWJ+`mbO|#hf8R*j54ha)EX`#5P&?Mk}SR>90 zio;T2+1y#-r_bg4Oqg3g^Zt(5H~GN0r=k-RTomWpdBOBlgC~1|mix_62 zhgHRANPSi$(%JypkHI}C>wuv9ytVxmg&6cGD5&K^`9;M*@|>dEq<@kC_n&lr2MdWfUhkj(VUI49Jc7`s+?#64@tGf|zS=jpDS)2@ zxicOUZ9-F^s!z^8iTr*D?n;8Sv-KKScSHlCDaaR8*cm7+{YWYHbH=aB@So^Dx5Rbj zkrizi>lKMJS~6%w_p3R+Oe>obJRR5eMqh7!2BxV+}*z|p?S-RvahuNHGxHEkf|YX-R9 z39HTgK;!?8Fjm7deI&s3OYMv*J|JJ?U}!~^`vF7H($?xfPXL-%2#X34e4#zoG_4?I zXG7|E4#deXmW_xM=FA4^h;ngpLhN;2@VGOv2^j9a;y2_6+?sjr2a=3fc91`pC0K>GbWllh~)bB)_=ae^-4L zlKie-&i_)H3@@4^?~bkp_?3>G6_LrTO(I7Urj*&?w@UW6Mo86b*K<5iY||X+j(<(o zdNX0p|2uh1N~W5$KotBc2WD$G3s7-=|NDKSi+O#+%U2VgTty?tnQL|X#RMb*+U8s(krR%3`z5q3qoUiOzDv&DRqfnT@T}YOR z8%2P@A7fIrc`iL=(`Q~S_WS~iT!4<^*Z$|H(FzVP5{K63{Y8!xQ%R9GMPXt#m9MZK z@7*JvCh-bRK3AWG z2sYv-%p~{NpLyw+QDN&HsntE!-AQUi?>~+0zJ>Z79T(F}F|mFca66JAI@&f@Dhq}? z(6Lqp_Ai2r-ka-7Z2s8)-SnBDuo`$B>h8k6A~r>(qu_A#^o%3k(XyI9h4-$8zK$nf zSsmGOe*OE??9uMSQWTQYxq^E@$0RG247QajKdaI^umK`W3OYlgE*p~6>$h)EKt|z` za3%DW=@qNDNlV$>zPRM3AieA32^Ms8zqCM%+gS!&ctTj(u_P4}(D=KKbS9;AiP6v0 z{%y$~PP!=u*#Cz1y>NjF54=#q@y^ka?|8!hC#08e9T@H``oj55_&3FN?cw~z;k4QD zP=PnVLe#Tu*h27v8g5I~Sam&ybrr65pUWg5;SojN3Ky;X^D1>9ovey}JGZ(3^bNPD z@k8a6yj2`GEOt5v1IA{ap%WBzERv~uc9J^@5bkZWxMyDhYC3s241?k_YP4&g3ddv* z+N(SCc%sWgJ+@7P6khYK2>9aI*e{ei<@MB9jjH&x@6QsC1;Xwb^H|tcUn>_e?_6Q) zBDlkm8I%W(cG5mQX~ZPH2rHz^w_Bc@BY#jwT7=uV2(N`Lf)#H-`d~@h9p?J_k=Ty6 z<+^_=zv<`5hB*3jG$2{gcO8+{9L-_yP6O2v^V;*4A?u1k>DCi$HsG!f@b2N z7>y6@MyumKefE|`1w<5fQb9hxTS3|Mz*g*bTQX-d2}lj z)QU$q_rDm33VA80;@Tgt{-)I#cR93!WVOk6NipNw5fVUDd}Ce77psb~qKP?Xv?$=t z6B|pCBi!3C6!Kn$c{^JcaB*ujX@~*)>}7g{kK)7s7x@SN{N+^Ea28fdmQnwYjEM*# z4**kmv~dJyz|iEI4D5keAh=_fo@F5Xod4zQuEtes=%JcQksSDqunbPkLt?5ffM6o5 z&G=BfLk3*MvS@d78o*h|qU(DeO$m!ndT~&o?kt7ON+J?(jvU9M1&}Wf>>-&j0_?#dTS^Tm-wHZm5AzBa0cTdN{ z?3h2eam?{=N#N#JGJ^(oJ7_H>oyT%uk1zF_o~am&7H^ipjObnKdei z#QrXbLOV*nA3$B>N6}GRtD`N5LHzFoQC;(%Y(idTs9Eu`aY5Oj!d`@DE+)uG{3SH? zNb*H=$dt@>mO^;04Q>36ueTOH(wP4qa^qhxj0Jm9qOpj~4Nxz_&=QkB{0flI2xr%> zM6LP0XltO;KEWX&$oBp)gVZrjLFf9OD}y|DyO_@w_X}w6Su)<0onIT7{-@7*U1cDR zOza#{*+10Csh!gJJDaY3{inE!!8?TL2y8_H(~U=m&YP@w!-1*>rFgRBD06A}*OmE! zKMu_*skedg1`c~z6v5;#sgt^U)dl}T5W`+G`hTZiznjw@C&q(GBMtf!Qq^|(NK)(b ziu1GU$>E^a>$u{NId?B3B0)vkdx0r+EKqkyXyjxD{Vsp`_j;ST$Ql5V_M6iF`JorD zI3IeJTLx71dffu#jXj7j0czl5Ke{wo=o@nljRi;FUO09{V>`D2=htX!;@`~7v9SfZ zalu1MZwff;jW9*nS7`&}K2qtSbu;3s$|siu*?)-? zrfT2I+}0jC3sI?YZMa1z2hC!DNikWnPCsyCY`Q{=y1i8GW+VI(m+q`W`0I#rXP*P} z754I90MFCDyt|;oJ!p4{p8N2PTh!8T(FPS>^LO$UGd=jE{h1nWgSGzFe|86pfjR9m zRDRo-pu8p zzY$xWF@zBBWESl&p4LCxvgigxkQUu-Lavlv{+9PplDH`Xo6ROvrQ_xzi~x`oijzKELys182D#btJ6 zr$F|gP&%ECGmMdD-25-ktIC;qiB3ej=_v^ zIsl}`ROza-?p3`uop|>@Ite*~qizLm=Awdsq`^s@(0Ud!MPSE{bt1!$;kppBhvn-F z+A{qb++agoiw+{3V|!N!Q}R~*0gz&IgK!#BtwCNVUKLYOJdKCUn7n!y`AU5q3;YX; zxlCglJ0%Eev^wibbKZ*i5LTaz;e$B^h?wJEKYkS*S0>}q@WjSfso>nOlGES7MErB2 z%J$ULupcNRtSafL@r}bn+bx-j%gxRQox2_to|$aD!cGY4S~4L;h3le`vs98GkN(rb z__!^F!>DNo6%jipVU1Q&T%Ur_e;zk381 z7EI?lqpTP|vT8Un!YT*2Cg#z&sQ#oa>X`lKhggg^U?t;Hkplt8X3QJsCwE^Xrhhv; zp^#J}cvF)}03VEx)E+(Akba1iFf3=i|{dsoj0{*e3$CKy^jqHdV%0g9Q z>ozn2^C=Rq+T`rS@m_b93f9kW5Zm0p{2Ll=R#0=$XDi}Nu&JiBmu7K^trJRUvyfnh z_l&ss1R@0yFs)# zcyKC_s@M>_^-uqa41723j%K{sc2ucgof$1nX^H7ucMF9I^Aj}nBBN7n35PVsjYANidu5k3Cg%D8n--^A_9l1QL6v0tI}0BkaKs#T0iM8k@ME z+PjmJ#MZ~INcoTEOwk#ygAfP~K0dyPF%BU0M`*{v*JoVFw{;}zds#OlEbrQvPEymf zXCg>(zT`J+x_iQjk{l9Ha@uUHaWp|dP_HMC)8|04JA#|rzA-bi96do%(KV*HBaP`R z{cd4Gw&>EPl+?Wcv$reR2Gs@!*xF{n~sy|49ms$nKk z_$O+|p~zxU(dqN4V2Yz5NjU|J@RqoKT~~V84wR|tNKO57gHgH)y5lPi!8TQl?g>+l zNsjLDUT=()cVF-SXCjdNb|?W_JDmpuPd7kR-vB&nu>&KCBTHw8#52Sq%uLM-h-4R$>vli?SB=Ej13*?Ck!xbD8Qs2*g%$2%RzCTK5hM64(DrtU1$66msY>{Tb9H-@hb&aRF-UtdVAVdMVK5HUSq*5ca& zZ|&Psy*$OGM8_5@daiszP>-{AGl^(^;w(#it!+7zkQH5?D73(G3QjoP{BqrE{e^u? zL-R%O&7w69Z2q6>`ZGE|i4itO6wH*ab72EG3YyH(%6r{Iw--EQ>OV4( z8P6Z_ltmLyGko=|2Q(RlnF*DE4VZf=p15QKYZ-YC>3z<4c3!QMXf2q)*7Z#%KW8r~QR%UUwit4e?{M~5*Ql_+%4!(rNc3ZknVGe}Azs}^8LUhxYuq!WPFiF@l9w z=Dz>0e0LmVFH-M8u0>QDDC7IrW(N@wuFN>I+_X(!BWg{ld;D<+g;L(}jcu^=+0_xfKH~XsE~DO(a2*#AUl!6=8Z1&R(^yJ`np*ha!mFGd##>{)?Rg z=c*w8wRwU6!VtWpHvZk_=kQ;WsB{U->%(hl2&5M`3#6mC@+I%wpj9hCLt@}lXa@dQ zNC@()0+Yv3?sJ!zIBMZYe1FsVH(#F-qYOy?d8^FdrMwgIww&7`2uli0miC3rvr2?* z5IlRRQ;kRvx-I`SI`ciB?*dy1fVmC#@;6&9hpnOf)I8))(Gcv!RpC{ber&AY)+Yc* zE!a1lzyS2dmxHu-$Y6u%qWYe`wa@!*CPIO1_i+T&pG1M@{_JZLzaL_-K+U!q?#^$u z?Nj_OKI5yJZiO%ek~+5|tge<Vp()*B6e1AX=>ps2f^2e#Su|l8GGwg;W0(X{V=BN5cw>SW~cs`te(LBSSf13zSspPd8*WQ{>dnQu6!{mij~Yw zc$OcjLzVbtjx7u+iY3Y!E1r21Fm66pTuBes92ce5ZHU*S^W%JXN&AnhY2zMCm%g#SUAL*81j7GXIK`r^`W1f$KK5Q(Xk8tcx{adPr$@%>w)p) z`&_~AZ${>Dpso6-6`cc#PDrgmY@-}DAfogX<@G6q$S&C28i1*T_}lj0M30M#4F!#o zTjwvv=N%ZCp)aEOtXLM})n{ed^H_El^W#I4`U=KWb;0J{aRhV6$+CkjuZs@NE&hwQ zyQ##89t}DC_c1v7z5H~rRgD2s;^L!KoSB~G?D}Pv;YcODdlZBIm%q?|52vTzWJWD% zQD*FPN#9+z+ehK=NOk3l>z$zpX=a=c%Xrs@<4^8kS1)s;Vsl9`yVftZZJ70Ue*twX zyc(B~6MahMRKtNiBvI4Tmwz_qH+bX~8xN(AbD>o8Py!8dw&s4cyJ^g`9Le6Pe|S$; z1fDST|I$4)ZVltiGlTfLJl*JrEN8BC^@4y;nN61O3YWP|jU$=Pi-l5Oz1HZ2aK z&W&O~;IauY(n4Qu?Y72sF6ukQ>s%SzyS2_dZSpM~8;j$i@N(!(r(Ye9E2)GA&Mr{F z`9;P!I)m0*&@QTRv4We&!eH7znE{6fgs~#>H9#KXCM2DNjM?@3osyC?W+$5OX;VpO+4GAYze@jO_`#AAF$yqr>zfLq& z?}J`>@$=oRg3Xs^S0mbj2VdphW7J~5{MZ^_;cchHcZqO4B1qfWOxEkV@+{!g0s1M; zCd+pxTc_^JM8934c+_)^V9kw0{bSM+?DPIA`{$JROELA5UQ!bpJF&5@XbbWGgRZv< zYqM#ih0$Wgog%>rTHM`&LvSx%thl>tLvV)z!QCBNti>IQ7btE;ibMar-#+`Vy*bGN zGm~fT%ri4&|3%4!{R7FTkNe)id?d5JjE@gqBDkpG^m$YA zgEdkPA7tYVY!%<+Xf-bBnRSd4={->a^GHb$Y!0X-dc1_Y&9A>kxs22z>g`j2=FH&K z`#D()=sp+u_d{W#CBH4a<~0Rfr@otxaU_`4c6qv-$lRtMKE#vYPkQD0e{z640Bh08 zHyuB{Occrq>u8*&WH$Po{J6Je_D0DtXsWIvVNOrhn13fEf(i5cb-I~zGsQ2wo^xwE$@`|B+lZmKu>Z8d*+mvU_Hg1W~1nV^)yH|AT^yq3?O~p927kPxiD- zw<|P07MRxcjp|hpDR-qBo_YvJ^V)}Tc(F&Qm0GG}C7yYzQvlBY1`-NL#XYpdQ{kmK(2y@KkniU!fh5IV z&6VC!q{rJL_VQXXV4d>2OJQ)r3tnrjwL$+fQF)T2!m8srOe$%gX!&qN>NT)KFyrY{ ztrGCo`MA)j?g#+QNcmM4N&$OsEWd7w(WupWPk!k%0kJhL8sw^s|F&K^1M8nTerAdzKqxCBxRd(jnaIgp^q+^}^b#!4A-`}A8-h3OKZ`75O>^`Aw5#&aY^(Ex^ z0@l#vsry`e`{9}DM6ayl4gZ0ZX0*59H5%>u)qMKsehviD{=`kWrA-Pm`Y+>Msvaaw z2`+;~PdqB8Jex$6a{V`>_I9JrJ^8e{Xz>-1&gjgL9Y`+~>B<%R08vURgRi&+rmb9I z{|rkIJTI)08-ag|xC%c`-rA^F6R*H#Q^NgqT38%*pOGv)21vIpeytI^wyZerWbtg7@eXbY zc7FXE(EsES-TZYg*MXQ`K9C2B)!2TVe^`Eu2tq0RGLh zzIuy@!Qm!GmBu=|AyFz;)$N&{&-d%0#oKT~1 zTpJyzMzob>`!A<{H6&=-(Wd@T#dwzKqG$wKCWxA%0bTlz#%eDO5Pvd;ENC)FZDG&y zaVoL`S@S7AQXQHcf^!-2{Vqo*pC0IxR5$M2Gxb5nmc17jba1$>PXf@Dhyju~6%k1q za_xOKEvIFQXU-Y&m(yKP=bC=T{XgmmGk&PR13lxQ1WQ6o^9c>nIE*RznlwD16|r4m z1(){{U~%p^5iat9$;*;)Y6MP3_J)i8sC690a*c{Avt2gInfY>ae{Wre7ljvWBBv)F zkQ;0Y&NAyz%G0r}bFUHeqmv-wAy`d5E`lcnh?KxX82Cq=Q^Nrys{HxTmtNbNKrAmc z=PKT1qAX5iAr_t=Z}GWzX${CDxa-l6G5+g10f*eA?-f|pc8;RC z4q%u;S8;hL{Ab1nV2nEgFGBA>-61QYA`K^ggrako~#lQ$V>f6lpn2*5qXttsbWaGHE+9l~=h409{HXIuzOAOp# zX*@_L#IvmLUrsY*e=$#zL(w71lcH8Zw*m6qup*wl_OK0w8Qo34pFZk04DL^E6~+MEQVk3=*o10er+X z^7f@=H~AdB^*io@D{_dh{pghdbQgM979eu8&O=+ZV2tX5aIR3S3O8pzS75wJ()M@= zKaq`-`L9yV{8HS`A##+%YOp#byp|~B0u)D)9M}L!^P5U;3VKOvuCSmE)bR6vUn!v& zFR|1(mcC-7Xk@IonrxnuuNDrV6j#WJQc}w7GWb3J@bbm_+oKQ7$_R%2`(3i5e9man z3;TRIuJIt;&1DRZJmfH!kbY0@xs5AkH&{3T;k!HB9(QqM1QbDhC-$j4PQYrdC6dpW z?OK#0C*`i}4MrqU2_A#3yE@m^Y!HLn`q>&=}PNMPpUC`DYzTJ*Ao?R>ot*@(i#|~30=_TEz?%##9 z%{e1pi{WRh#m3&=UViQVmu3C*7w{wL-)6`HlUBWCR`Y>LpqfjHrqYi&1`+VQgu2G2 zl~X~jKTUVjk4xtHp@4ti%zrF<2y7S`cLdD;+=0%8lrySu4->%B7;0UALXs)SZGl~< zTVBHmGHi-Q${iC3hDDzV!0cEZ2f1qD^sU*=O2DHxgfE6riOvVZ!{#4!j}-&Tq2?2G zIf0j#sz zZur9GrNU4dlO3}sn~KnvyDZV%oLF@>6S98i-kAI;bRyNg@%EFrY%o20nfEa!i#M~L zX4Ht>kq=C~_&ABK-iK3)O9XP`EX{_+?e&C`VL~0?*hPSBhAri6sv)w5ZAsNgmedPG zf469@ntg;TnV&M=(_w=Fo}x;26d+8DMd8Eni4VzK5&JmyD3l`1@!6BO@s$mLeS7}T zM|!nr?|FCGDco~!zshGIPO0^60H)qe25f|*57oXRTpJ~e`2o->S>Owl*x;+Nw-;Z> z7DP}!>tH=K-w!LU{*m_TQ1}^<;~=XfSl!BJe<~f?`=j*6epTVDxr0NqQE&evv*(eZ znw{fRqSXFWo$Ia@^#nTtQE(Oh*|K=xv-%}cMbjOh?3{Y`m%62ZNc}5HTOseS18?og z!f4-Jd4C_NR`Dn@?Zr@z*nB~(B80+yL3;ICO`BFqec9TzMD<1#Z_A_{bWX$BT?~!g zuax`}uoWG+RL7+4_CTM%v^{e^(_JS9?rg|qtf5sNJBv{##1jkDWEQB+HS=g7{K47C z3uAPA%^+wH^WFcIP1t-Vp0o9G{FBgbUvjJM;u3mbw@(u&FXeAopRsvImOv|LYaG_1 zyU}GwcwLRi%{(cy+wcbgt#U`c!9gXzO)37OSXLAdW{{BsK}hF(De%z0+fNkmPuYJS(k7Hd{WcQU&2qn8`$pb4nSFTys2<*7B1OxU>m(n^FRcy^ zT3Zd^Ce3QeQ-Jnzhw|ghIq@W_M)vebDdsAkYp#WfKWw1_5t-c=GA|^L)kAeuuAwqi znxCIZ`NPvp4o3pvf z-NX2!viBPOvErwm(`rwbN_}(jVr`BaD=3}($){uj+%nHJO|JmuilR?Aa{!}-=99*8 zY9%+Ec3f-kDVYczsRIxHY@{r|F6d zbUT94kqHgfxT|mc9$K|g*aEmobPk|gg50U;Nb+fSg&dv0we&fUtIqe~yA~Gdh|320 z?waoi)Ixg$@`YT>mbw}ll|IcTE7oty^`kw(5`R(WPBeX4@AQC29Su|)G#wM)Qw6SP zD2|dytdlkX5y8Dai+>XJP`_YdJ7clT#d}tv2ysS6rXOD9DGZeyN2kWNHyA}HX|mgu z$c}e9nin$Q*5#ieJAcN^O7PPB$R)_gyI#D3roJ~-Fg^x4h4YJluOC zLqE>#!+bYVr!%gFQcNF@1_OLP1wX6%hZQCuLBu=P=EXNY_?6c&0rn{6InY_Kf~Kx? zi*fk=y-}?49Qvaq+`iga#>Vm&{XSDoMHtK*HS&WjNlPEsp=%WrHt=W?n$|kxTET6V z?{}-=5obR7t{7wAOEyLgs$l$d)$gUb_%4ZA?G1QI^$iF=V;LPJ+7d|<))KWEv{e%N zxl}wMxz0g5q=Q>w)yiX|BPZK^VKupU4j)}XG2SDHA%~Nx`qCQkR}Y7o(*D81uf^#z zuW$y*7K^m3F|2eKG7O5Fe2bhl4C2+;yQJkYq$y<;06c%$p7ZA9%{A-<_2qT+hYZO=1yZY4o^!_jLhHI zVA9L^4thYlAlxbG!DDBuk7N27x#VpHYi!X)B$;OGC{ZDxnj6CiTBxLx*vhh znWEGKcSNn!*buj^o!>MDb3qWng`L=eHJ2qIW&W^axR&(^5cT0A-E$|?RO2?ab&`B; z5A(nNHA!_{aMP|PNySJ14Q(13`;Xh=lhHq#d5^_fg zG}6Z1GE9l1Xw)uJfbPsm1ea&}Uly6Ch3OcpeSdla@asGeo+wQ-9mcpVx7r+l!Z^;} zolik+q4W(m3!I{gIY>wPw^LjE@hq{sj;=Kvb5T&H^mH{$d=yc(1fuxQrBFSm+7?|< z>WB=j3@i5SE9!Q9^9&e7Th^SK#z{Ti5KOk;>6+W#c@ab3{d9h&QiYr9Cs{_DyA>kY z+1K3nw?hinvicQ#t0brF+kjzrL^|y&rI#5OCX>ub6@PR1``#`dNAChH@x;oEK)$>iKe*@4ac3h(S0HcmsiHJv{+O@35M5A*JP<)Iu6+6mo_Jf9GieMV+rS*yH%PR{_!xnjn(dln@{wd zDQhunSQ3s_oMiGa>QihJ73H^E!`V844NnE7mk)P5cSc>yeGbWOOdH*gyJs~4PRG9= zV%TWj(Q@(+3(r~i2bqocb^9XC_eYU%Y)QEAHMDb{3-tx~^Q(st$XF+uFZUf(60x}m z1jh;cX60e-174W!>`R9)7{Ih;AVax$9a{^~m?0gXl}W!x#h5GRxa){geU-;vse)%i zGoCgBq5T2fKwA%TU`90LGJA@;#$P3V(d=2hR3S18@Q>GV`UlT4iC`#C*r*lWj;p3IN?+wM50=Q@Hjzo~38|9XF=3(-O6E(5u>@n{z!XfYIY=Y9l5_^yE1N>VMFL+TTh;LinrCDM$IWYVaF z?S^PKdVEP$&R@beRJhAx;dReNz`>L%Iyq|f??!Hz`+xT@_uwxL*Sf>&VNE0(ZN+C8 zq)}ad^$hh%VEd(=_N>2&xVpj+NhYc|MkoWXh^ZnIV`4PTo8Lf^7LK}KZ($Wui(iSu zfo~ZOql=pTBJe9XlKCa<)oQw9vjX>=i(G=cb!zp5OdS4OTR`~C)uzjYrmShpeFes_ z$ITw3179tK?To_+uSofG`zW8+p7&Rb==C7_^=nmXlLS8{*I&K+4f$`E6XYpS62sQW zdSueRu^k=_$kNfSB1FlT;WQjAIf>*K{Gd{a>SXo&sKMO%?+s{m+Rxau4CB2q5yxOEJ9Y@*9k*e7;rN#S0^R_a* zYK71L_+G7cTx?y)$|R$EYti#g^{wr^?GEY&&kp*ob62QZrmcx*o4HNd?ShE4jQ_FO zoOueprZT1%hHB`rXIrxdUw&vNR&;PcC8h`eh_vh|K3J}{f>piyvpAp;N>IsWF3;yC zVpg~j{$cSJo+>`c|2ra+Jz`;2UcqcxA`DvXt8TO`!JfY7_s5}_WOdLoU}tA%Ygh>X zCC|z>Hz~y4DRkjyLY<06W({twqlN(a_yTS>oE0v^d`N=qHrp>+J|kG@wjgX%Fl|8F zk0)?KxM)$+S7#E4tHES9Aa4EfUj?dhUIzK%2LVeIWN}r$t%F)e-H2d zd2m=wmy0=8N}j5>-1hWIA9!wklAD;tHyPWfmNJ~MydwNKcg+M1TWaRvS-J}1Rw3fT zFLoR&3(8Wi70@$5A;KzP%XUbZJx4;ua7w)St^w^$W}qbS$d8mCQVj%^==&s-3$}gq z+W7W$3PosL*>-4|AjF~5G2ochD1sE{;jZpVTIphkE=iF4Q=1;CV9dm1&{yM`1s-4i ziO3(bM#r8Wb5_HKM2TvqD22o36e)ikHl%~C|8U4?fn8T*5y$&(vj$otTGzV16;1mEL(q-w|f30A|F8%Xp~G^+t+L;`)T(d4k+K*5k|eS@cZ~{=4*iQsc*J>M;x|*{OnYZK&UF}LSCA+*H`g5E!z zcAJ!e^25KGh_HtIHbjKudskF4);Hik)=5Ub{V5|88s+0#4k(UxeW=D# zTA`)_Bf)HD5=~l|8WC$RVh9FWEukY6RDXW&e_adhoX8bR%NcSMiZCRqYi{~GVIoL5 zUQ1h~Fdn&d)8tYig{FfSTfdwUku;N$i5s3)pd@TmN7ZMVhiW4_7KBpBXhvc7zBBs| zeS}MxT$cA=7tx#X>M(D+4sP%_sZwEUf(n^3Zn1Mqw#wkVG$I1xax0>QTA@Wc&^8<4 zYkg^9_u-o7qqu})dS6hxMcl7}{%z`efvxSZq@p{Dd{X#rf}-SL97K;mBv@8;{S@pRM)YC&{FMebpK>{e-n!{?1|^ zMS&OWnu-?8f^^bJU&}idK|eX+TvnTlAQ_1?%_!yIn%3*%mJ#B2#hw4Fc}OL~hNC~} z4}JY*yA++0VSjr{49RBa&eWW_^p`kAMidq5|u!OFL&VY$Wlv#dxW;SfkPui zAit87)@EzWB>Nkx;B7l5-a%-#F%Qi3uv(m(6ZESitj5Uu=UW)DqB`6T$N_sxAMCGp zlZW+~#7?F9sMA5b}s0-LE+5dlaYYuKPnz8xm?YaH2QaaHCQBt0FDWi8oQaJd$< zxgk(bpttu7kTBF3xBYWdaCBQH{rz^6WPq`iIn?w1Ry8iyYPF!o7fTX}6(snWcp;m3 z6ZS2{wLKv*NttwrV2N|)#CA(KYN3Q8I#u~MfSl2&qS!xa-2CNI>ww+`?o~9sPGGGY zW}s#%OPIOoI#sgvYE%qo+p)m(MFsj)jMY@wt0I~BYv}lRaoZYRzj;x8@^(iO|B0<;N5EUv6jjHPuGmK+KV)^kbch7uP3*O(o&a*_wFo}bBKV$XcP51@yZxvDlOMBy=H7k z9VG&!8sA+sorB^miYc%OfA`u>s!?x)WS7oLy5~-4T>^uhSRbs5Tw0fuC?vl^HEel$E58w-qIiN z!Gr|s`L2vjj*LtrY6T<1bz8qA1GZ*M%jj@}_Zf%3;-8h;Axr=Bysi_E738jtbCFwU z$^NWgDMfJz@=kbHR$Ol9EIUODO1D$)$5bmG&RnLv2L{(KBz9RE2?wl^u zi7H^uGahdFYWL3*!D8buePVHn$SMJJTQR+?$5Sc?U+j)A6Du^_w1JO}5)L$nKYxvf zFoLB0HRvbmv(Gm!5neE(rpI?ZT^T|SmcPaKPI|1})Ife}ZcCwkMk6N;K7>ai1Nw|; ziVX(o;a}*;uzQ|8RJ^z-Df#>;x&5BnQLxOld#F?5SH@}ulc1pI*xcI3s=>e^q-Wf0 zVL`yiTrZfR9&ESs3@k7BXH#kzfC=RRkXZw>j`krpK)~=l%Rl`QVYr+F>gXVbXiHi3X;`zmGE_WLYT`%e$P`YXs zf}gvUR)svuv!fN>P9Wk`ROmp~p1)1Wt(YNdlsN?f#>#Cz<2FTy- zroUKCN}G{&6;DezncNrc!u2aIC>d8l0Mx<9oI7$}#jzpjsyszZKP~VCJ@K$b|4~KI z!X#&kH(TPW3&3)rU^pcuY7x3dxGFnaaO0ahULzjkeTGbg^}4qqefG!UyQrg*t#;5M zjR5r^{L0qK$nGPxJ#f6h6<0KgsK!2=%+Qh%tG7GRub2l^#B6nq=6NP)8lKrv z2+_x91eHdHxDc*GzwPXOIm(=-FExE4_kqp#E7%^E6lW=p-2(}pYm#t&iwJB&>d1)sJ!p_fPE*=w5ZD}WChhX{8!n)z!C1n^4|-waJ?Efp8`0)9Q{wS-@>JWp z)$o=2D3HC5Ii75}7T3L#l@eR?@f76jz-{uG-MuO0?@*uN0tERDKHQL9ZZ2Kl{7`tf z+1k?K<(>8>Lz~k}z0E!dpUB1x?r`-h?jAU%1oj-?BV0`RSlt4<3RC)X!))B<^f_vx zT(Ytuwz#y3R#(j;#Wg`+Wh7lymXquSlkv}6q@%M0al$)4m;lImC0;J-2xP+?Up}*I zi5~K!na*OO*hq~5bLS4&J0xc+zYyHe%we3&a!m#tp)-qDf*9>s`VtUoT+{Rra+42> zT}I^2sv!;PN+eTN_AbQ2i&p%hs{HT;>QCw&F-99`LR_%sGMZdmTybT8%Uay#v_e6u z$m&#l`maH0DBr2=TSD+y`lT2vXQWHb_wzIr5r(rSef(CN@ujS3dfo3pEwi947CO3O z2G+1k;bMlG-KxFLH*NI)6(9@K@d{x1_bpf_jo>C#kS@Zi(j75T!%2QP$)AMH3^;tg zy4Galm`GKLBF-xtA6tg!f6GI`3jT$MA<0FY-Y*vX-U2PxX{Cucj0YKLW^3jh1t2QZ z>CmTK)Zy^`&PIZo&JF(kk=WG#S%wU@{Id!Eo#{W;lXn6VC*GV5_U}=t6@xpqFC(JN z4PEu9=v)8S82>&*ClR(=z{67+TgCzdhT+%|d4n%Ofm%2bRQ1_*-{C=T;vWIX`wp25 zAd4L<%41Y!_UUh_RuL4m)=TkEugn+1pNYSK8ytvC5KXnoN@55`Tpyf#>R!lu?;@!){(`RH!BO*s(`e`AE%d#z3c! zzhNRP;XBF$qB6Dq?R7?o-Wh)Y^Ew*@8x|-w<{Tbk=vCropDsSD0A}y?RaIxbj*e3P z7I~eGGFfFmS}eCt8yuo+SOPd7eGbwDXlTh5^R@RM5{a*{ESiH6`4Fb}n~h}sG*6-8 z1`l^L8CA5_Zs@RvoM&7|rT7TeFfO}7nfW*;b9RjC83ui~fQ9G_&cC81!OwIPWWa)n zNP8f%iabdQ6{DBS37!rs>X5d>H1aw-)Ztt?=!VWCLv#~vqLO-UGU%iBcn~{x`)KW=&Bqll|e?pr0 z(Isc6S6iF)8s)%{2l-vsXt7N`JeySTnEdHv^hnZiv`h~vTsF!HzGtoxbk>;ZhsBS;q2>d&t@Ij>++U4UNHoTXNAuk@tgw+6YK>YTI|L`};- z>+WZc*4v+sV;~}ThW?MK{zW#FAYE%W1!@5TU}vb8V*ECnqA5o>-{VN(F4enw!&HfD z#DTv21Jut!({JKJ6zg`oAO^)}2+f{P{b<0iS2JIW!tUB`@;6ppulnxZw3!_qiMC%2 zd|i?y1%f2`Q!obnv4+64qLuK?2e=l5(nSg=uW+CKK zm}~a$5WYZg^+SvPM-KkU4bDN+H@QefYV8m&!G(#g-r%qC+WhJI8!p;A%DXKM*AY7~ z?4QE6bvMPHMB+*?Pef%#&aA?RZ{{f;lDO01@Y!dI*xEkTgXlcb{8q>CV0Z zO3(3ya@Hw**S@dfQLJHOIQz8~WMfrMtW%7DmWYAO40$qbKk8ncV}kwoXUXm%!6HI;kLrQdUj#;aBWzk z$&~|yE3&Jl|2N(%V73ZjgE=Z0>9DOV6iP|2iaK)uO*Q*J8giKI?=%gbksp4%nf0bD z5=W+z-2}nOflyLPdzS)c6jdY$QOD}r$&LRTzWY*Yt>{1C{HyC<{)*hGRydK6$nW

Wg9q4%0uDOM&O!1v@10;Q}KS9^h{|Pq?j!lv~|5%g^IlztS8& z)vesgke`(W=N2%>tYtkXEz4Ha91H5=vxj2lf zeZLm9`I1{i2K0Q(^yeqstkVGLOlFpJyw3x(Qjz~HbNUZy9_1E1&qdSML3V+Fy!nuLF3b;lWt2d+Of^0XzQiI^oP&An#BGvsLOf~Ox zk$m%$hedTeyGkI4*o<%+@-os#EO~1t{?X+aKS+e z;#%_Glp^V|HK#|#D`+_T2|sOvT93s=df(@-{NE6k?He#XShM+~p)mbL{YqdG0gOkn z*}Dnqfsk|I-khCntU>>UzbuNWw`nyWPi3~i%-W+v_1*31mUzJwAj|wj&gVUSD=Gy~I=BVG!NujwC5&SI*Rub&Vo{3GSe6@b%t&wT_ z(1!Z*&gIxAnueYjNR*#;R}#Q?>0f;4v;c=2=tN0DDG>T1MbL|i;+PdI(EOVV|0*Pi zu1rt_z(MO3FD@@hpkiO}yTGWVTY_S{0tJ8pNky)YCsn zYCuTIq=32I&4MtB4%p*{pN)+HChal>=eJuKx~z&t=AO-gLKrlycM+43HDV52?gvpe zTdiL*r14$HsDN+m-BPGGJ~iBRxBm9*{#oJ<<67rZ$ba^dPalcJ#~xBfzWOC;$haTn z)ChEV^4?M_Ub}evJsDF1XL(~J-_u%F&3~=x;r6)v8fd20qo(t2=d|Aq7PwGwF;8;9 zq+c4ZwXcO}za^~PlKdZ~l>dU)7Lpbhp(C6`bX5$?Qe=%E44&6|s>n5EIMX9*-I5xr z5KmxaJfROuOIl@HCG5JTg(4ZTX(#&d&Lm6W&d)QIjpgb170igufiuLnslBOz2J#S((7yz za|OwM%hYIl!tEi`z!T;>m(oJ`dH)&~sW42X1llp_MCv36{Mo{E0wKbpuMS?=Prl6$ zJYoJB_;2X|8oI^xmwZk8S|d1Ei{anu^Y@Gg-9C9zj?jh2e6=uSVO8_$NB8|}#e__Y zf0mmC-guuDP|TxEysKXYF$EP^(P3t$I6j5)MgrycPJD@x@7Y;3AIx>|t6t(MD?5?e zk5+3sgsp<=#sA;HgE&l|?abb>g>N^VLH7G;rr5>7x&T;k`#gB z?yD2DMpTDlw^yFbN|P#rQSf?$8({bDojm@?6 zf`0ahSRadwT3Ybs`2YgHj8V7b~+O=qKyX zx<5U2K8Tha^u83Te|)Yzh5vmLJ$t#8oSrysFsMmoBZP}s!(CJUD2Rd(aW9!dZLh1}j(acgsepBQIDi`=QC)`JY#KM5|2&On|pQ zvGeYVJ0nh(FIk6ria6ld!YlwH2-$lAkKLB-jb z#M|{Hvp<)AWcP-#ld$zdh;mMU0AXZTi@;bk+P98ZFarV;=HOJ;qMwtHv|-CqVpuHC z5D)_$eeVyW8mmp3y5gU@W6xcKkY|C3>evGKgBq06<3eR(Ac`dvR6r>4pXx1yxJ2Kf zd2HDiY%>9m@5xODHQOvMP+RinZQvF-K9*lj1+fZnY9b?>FzJ^FVzIF~pI{dG>18&GhBR>p(1fqb7WHBoo;KDOOUX&!eR#13DH{U_T*t!B)a(U+%N}ezlr}}qS z2>TyWESU7(Ot;!K8VqWg0ft}w^hb`eeQ^|2+%TEFS+{fVbjdwov6^b{ITED*i;4h5 z$0PGAy;x$<na!N+9QWkNZN32BbGP^k`%|&^M7ZM|SGZL6ByZlh zekHWs=0I5gp!`tE2#?+*U{M(5jaF%BNCz2}=Hy!P05R?Ody6qKy9FiN!_dIs&(!c< z?V*D6EM3rjt5AC4sMW)?-Tw5fQ@qr8w}s6@F}OGXeS3G6{~xAtwY)78ohGUImtSC{ zRxN;`7vCcAdn-A|v=B#%Ax{Jug;L=c;&(5FlT9+kTnF>_RQ!yN0;TU@TS2ePzx`_H z{6GHYO}p)n|Hu@$ujhrXSEcjd34qcN)TDjfNm%O&90oN${fJZ?R+H5s76UTAttb7K z4Nn7^(b+5wqArqlg+>#$T!@$rFay_~(h)dQ=Dy(z)~H^~c69m~ zdSA6cN+`nAx)^^YH))nB)#yPg{@vQBbJ?jhYe8R`L4`+L&m!lxi(+cR8;+vLVHl|? z((ym&c1WJr0KLH$axk;Zj{c~RM_nD)CEf|ETF!J)4jn#y{1;IMo?~^IlW7>qSGCiz zBg|I=*L8WelL78sQ1`pBiyv?U?wE8HUbo+F+ zzG6IR&x~FL8(t6R9QzM;-O><|NYD^ekD!pO09yTXWLDl`$qjex>77K1tyPg!m|!gJ za?HLqHYQ|x4ml{UpmR9Kzum{oDA`X6|2FwkgC8J(``V8~5| zhzV66_WNE01pL5)X;)X>VyArSaaKQO3$WLQqRjpIh~(($1#wB4 zGoO9OMF_IbZ4F1DxIbj#(IJ5SPNohr=lfZBes)u&e^oQB`#Y@*##SJCljAd$(&yl& zYLXIiQkM{aRJVIw&TO-14{+u!c-EvOchoo8|gj;FS9Re^F#Atg*u^Xl;CFe7X<8CMcpiKcT8 zdP86M;w$TWZq4j>s;Sx*tbq+K{`-tXtL5gXBL_h_fmi=L&j3Vzji`;>^P-8%WWiO zSw(!ROv-IXyyTy9>2&-WS5-VJ9I#T{QB|t0mOr^o^J9H7nrYj>g8dRlw46yB>C9z@ zGkWx;m>$)BwR3iGBAF=mYAA|q1)0n{Rpi9X(2~DP|l3L-kFY|snq!ZLf4fUQ=+C>WM-dSR=>UoCdj=L}5y$vR=F4~ea zk01qIdik=3d5F2eU6lc29i9^EB*Ssqc*UsOhVd7#QaSXJQ@l=GijnM^8vbLoRQ!L# zZ3IeSPc7o*D2rMmaZ_o2O&}zgd>gL`C@BE05$DAsE`&Ze7GtaIuMQJ)Y*#+d+U(hT z9;C&Ew#_C9yvix&7`uhjpRr&IIb0oq;_?a5ZKTWl(_Vw`?_ zTTjt^vJd5hNjPi@tK0%+r`ZZ^h z`jb4;=v&L+R#4Kn6v@dO0&#!3YE=XdsNBs0O0;{o#O4^K{o$umjkewa9f>kbqzW~D zi>Z0g&_?@uw-#7Cy`Fa0`y~+zb>F~)!1AZYACsl~X^YLDau$u&;YJf2$^y5-_{Go5 zgq`7xx}AKWOESk7HT^o8aQeRn&Dy)nx2twVr8?&C&veEWu$(A|F-@Xe*>Orm#GwT4 zl;#U*rwNe_OP?s;DN6yD-C!^V#T*tMbg;wPKZQ)bP(HD{P;B^mG+ZeqGMXdm%CcW? z&t(NWDO+4G`wkL)tR|>JgWzl=r;MSachQ&PzFOLMrS+UN+j^CsrL8_M^mt^n6b?KP zYsL+$U`A$?QdTbf^}NcCOICJ;@B1CrCOYuS$m|~q1awOmK%`6G8s%oTJWQ~Z!H_f| zG4J=Hm41@RWACJl=2R%XB9w^J%9MW^8!-%uK$d+xt|KSX>_&TMA85<3)=j<8yV1afsfbjBlz>clyvnm0g;HV{ z=jiXG3DY%R>VZj41Du99sBEN7Oxu#h5XyJ#qHi%!SF>DMBGkxK%>rXVccMR&UexPt*g4} zQ>>jy0R;V#7kE^bhE*OdXBYosIGDL4Jt|ovg0>!HG#CE9{kyvSY#E{5(R-`al--ih zdpos>Z?m#I@yWxgU@n;slun=Cc*V85l+1ip^OR|L%_Nry@tkjxL!z=rf_>sV%l`!; z)SykEs$>$DbH0vVlfRuqr3Ub4OSZ-cEC6xe4<}#yX1p?%7A;5_W}QcF8w4(H9SNK% zqUvoLF)02D`qu}#p;ENx_3G3Fl$r$yGjNGGPF(iVGlKHz^iHxaPL6n*K5uZSBhG~l zrhF_%0Fo~)4^I0FgB9g)C>1e>b(HuaY4Ily`({u0nK5!J=?jkiG8JY4qhZYaLd_rEu2RZ@^cdh%4Bs9)2t%3foG`IfPQS8}zPGx*I&vcMZ>-2+DW=Z}pf z4|NepT8(|!v2qII$+}yS2xy}$$g{V`xZ6HtnudrzpPuzdLf6d#sj{FVDE(Dzx9PUe zydYMhyYs3NJTIw^6K@cZZz>O0P3WwVHrxWA=|>e`M<0URatIo*gsZQ%7gYgCy4PO` zBaoxTA{f;MLj$EoMrpPeTwD;2zP`2x!zO)Pg48h{?@AHv0zT}&PA66VF2sGkotYR- zc1(IesQj0$##pbX6hutAnSy|-*3)>_!de%PwhEIuwg5Sh*6u8Wj-k|@|`XFjch3}Q1&5aUk}!#}>nOXR;3T`r)jU~oJ~tna*qPXmu8 zPuO-2b>iWC{wfbte|Pv=j?}*?e|9hjdfrGRnIe^*@%zv8#UN^Z6?vN|V@z#LR)m=l zB}GUb@XQ?*sQ%p~puI5?Q=2d(MGE@JaKv#yz2W|KgE+hLX;UmgaiZaM_v#Gfb}lw` zKJF?3E2qcof?CdxV`uZ^m-Ga|FJuh*?mgH&Pit%r>W7rzhiDgN4V%7OR-;)G} z0-);%0jK$6hoo?UMngD)lI*=bM8P(_YOqXovk-yN7vljx4eZ1P;PSR@G_Z$n zY}oSE5!4t>&M>lLp|V@mO`)@^kh=jN@(Yk(B|eFx(Ad@lQ>=i)!XT=2W3RK(+2+p} zn3VljE~q|ZD`j3%VI05)j-fOqD1icb+}H!YReecJB)y!Fa-VtI%!IAMhS>iD=QN-W zBU2x-iqOn>v-bha(Yncf=muiZZu*pxUx;`1vJBam`VT;j!|eT1UpZZq@7-;GSB|(6 zvSLRr1E>E3mSJQ>B7VTQ)|Q z^hm`&YYj*+hnCM;Q$W$s_%pHek#iG=Vm>-s7XA;%^4+ZtW~s@V5XD7XXk7DrS(WCX zjQ=yDCsFV@l0Fy5?%v;5*m5)JyWi$?n@yMDwk$8LqMb>v{mj%{Ek`M%WJXXnxij~Iup@wU|H(h4UVs?y5G);potcDmY9eoSFKxAYzEelvZ%7vQ(VDBMI9^FrL2Q*(2Z)qD z2w0Fhkg?f?78AMtf0VsdSR3E_#S6uuxH}Y=LZLXtB>{>Brxc32ySr;}r$BHm?z9wl zg1fuB6*&3+{uk$Y&fU46%*@_1nb~XJcYPLKTrk4T!?{IQym~h*@tF;6_YC+8ANxM6 z;Nnhk0jP?75Jmo5i9*2L6~Y3zgatnHdg*fU1wZ1@ zr3m*}-oyv~U!L>L#^4DcjdG$PPH?q3(9G6I7atPqr>x9p$f?gQm&)c4!Rg?J`a&Nf z{ylU8C?Wn1`Hab7ym$!tFpc^Z-jky~f-1W$61rxNJ3GJf_O%Eh47_Qsi(imA;O64( z3}IbA&}J!M-BVqe%KGq`mgvRn4;7wxOf4eU3XH)l-G#0%B^4pF)vYQ#GBP36^JLVgzPsk%$9?tM& zV~SXVB#ta5W~Q^`5q%UjEn z9tF)T8{0Ns-G3%1&l_ocZdn%CtmSx*v}QHcZJsh7BVJQS4Zj5R<+0nl3pBZEUdROn z;~y49WMuQ;4n5mb!})pCK7eWkWj`vezaI4mg<0&*Zb=D@C})xVh(*%U-PLU(Tfcg2 z67$$nta)tm_I^%UN*KoKexjv!#ZgBeHpKffIxwb3$?~x?FuD5poEu>??K$QfCtl9B zpz?0fqFkn*x)+PWx*)-Ui==eH^~;Kac3Iwx11dT;#LGoqTV;{)Pp0AKMxF z8*bs)hhn`dE>zOtlc(55x{^JUx+Wf7iI{*~k5&oBw9J*0H=lA=#sOMp)P=!Wbu@;& zPl03cgtY6MyZ$?((&bc*J{7z++^*0X|JuBK{RRhuZ;rar;4k6o(RZfsuR2t6x+{Ku z4K1A?Ivud3j~WfNYL) znmc;&VNpfNxN$ZmiOnMmzv)pp!Lzs?IpwC(#1fzerKTHlwJ!xJ&^ipeuHAH)rRj^D z7yIdh$1!o)Mt_9*cnWapYBO$-eyJ7I22w5`d#5wlOjwdO#1mma+(JJX&&#KdmbcT; z#C*u-r15huZvpUPGNtJi?hq_W#wvb$0T;XLU$0&U$&7CV)*CmlS*Mgg_$Uzf`VXgG zY*;vqT9dnid^&gho#`#nN1KS3n_gMp4MDL42f8?^t_+hUbb4Q zvH;Lh{Ll@S-fq2*<~66H@6r7AEPGkNQ*@h8nR*L3suvm1Jw84L->BZ4YKg0IU^Jgu0&h?TuyqcA1K@#K9e zIhCMudF;$#q_k{_^ty62nu&-xiPH(0r(7)%wokn7Q5fBO`8RF{5B)35VRUaWiOa6X zNoJ+m$NriA=gAUA-0&?jcly?`J^SEpSUvl2h^^l94 zgtu-S!P4hO&dB!rciE$H;KZ>QuHq;#(Ya-kqI`}Ek*JC+;tRuA-A{U$)ctGf<|cXH z6?ViXp6QR^n2bkhHlG{!&BzVdHvF&0A=7HeRC_$Upz?~oE8b{JhX3oN``3K-yor(e zJ8?!I>SU9wl%fFk9jO?CQ+r7!Vy&ex@t!WDgDonkxgdN*GCRh+1hXdl3-gP-Xs zi=FB`t-=O-s6`nRsyx=a8v&+>%!9F81VOY|ppJNg@}bNtQIP8Qo%XmTWx9wO%TFQp(ZB99>Y{KCZCtp@hcX1 z>W}U#`}*D6T#z~{aaT7I-Cv^0;4Gf~>Y=jpCdbY>QgVhsKOQ?HK&zJrYsEMQ&KSE^ zjWf;#N-rVw?=^aTa%+TG41)Obc4_F`>c93(?Z=knzw&y$~{pyK|G`LunJNlvfbIA8O>8aHtW%_F%P1z_yo1p`~FTGL>%7Nxjg8dWW zCC-KN1(hGurVjp12$flt3vYw=k&1vY= zhgT1!J%R5G<*W*$T2Xb))p^P&%3!D#?&0kuMGrQXAMa&7#UC{BDS{J`Pyqs!FW3?s z4EO#71OKsM6IJz%An2^Dj887!bfN(y{crhXHkE!S=)Scn&^TB&>oLq+iq86BH{jb3 zT3Un_G+9Cq47C-OKj+eSQ$o?D{~gE5CXV1&v4k#9j3=w`- zA;V5(ZYO|XJ25%2Rh(02>jy1XT?KbQGpc57=EW22g4Y~N0lX4ZVVimEOo5?dH$HH( zEVrd1l|l}zf-wZCuDe|T^cc1ef->&^Mb0wLgNtdhK50jGT9{A}z^TI5v?xXy<=y#v z*qG!mE%BsCVnm6e(c0gxPM?($tPb*os)y6cydB_W@~1(6ZG+Bpqqc znx*iz6)POH)0a48D2*ro8!`sZW8vNKK4(sL@BZp9Dgm8YMU~&$mBBtG2_=n-@23Z8Yr zg?QAV;zq9DMH}E0CL4+vbamyJi4%J06$Dso+%hB7TG4MWI5g5n(6Ey~G$-63AN4#< zJ>N0?kJ)N6vp`uE^1+A@kYNI@N91#g{cVK!JJKZK7(sntlKg5+FiX_S!Q`%RB+guS zAp2}tyq@ouKLA%~R$r*eEM)269u5S-@lb#7%355mW`{^VT;(7uveBl2pV$3vZF!mg zJX_Jg?*V0}b@YRm!x3YDKW}vD+?)LWX^gk14@gGUOU6Ln_|tkV%p^ty%nAuxGS^bID!sj`cJ01NaNBR0}a zCPX2R)_wbx=%+Ptf6Y6L*}X#i7O6M}Dc{l?GG$-kUR`hpYZtD>X7s~~{`N=E2lk22 z#TW@o>pddA{ndn9h!CIG?M_CMoWzEBRrd^&^25Bkz3BD(hhm=>FdJ}|S$%~D9f<_7 zZ=q-~_;fN<2oO&&uJHm#BmhNwXF1f9D~E8{v3Truevb-OTy_$TUL>A{+r6>VvmlwR z$CJ<%;>9$Vns`zcUjpS+!?>r^>;(-8-$C~)R~I#o$V6hTk+U_*@tmWnJ2X}6s@B)dZ~ZvrOH-8jolH$P zC@&f?p|?IbrM#=`x?{cn%huF(zhL&9Q@&d63)b;1*4y61YNpqPK~;+wz6{9fz5 zt-`)_k(yS?oh`bXM#=L2cvp7z#9rMs5!o^tq^U^2e*WqrY;U?4S=;zeN-PrQ)XXSW zy`OmF2;{mx*8b6Fnfl9R@x0G+XD{$il+fbdYk}#>)Ce~K>#J}SeYhk~o>gMBe6G0s zJk&iS@LxpAJ?37PH)%qHoD-y;nf0l?yKYWg1~j&BqnU?f<8j(N>_x#?5iu^J2|0X@~|Z+ zdCMCR&hk^%Z?eUNy$py8k;pw_U~(#p^+6rqny%AIBW+uUV#%#gMFkD=dt5>Y!6{4H zF?vhIrfbYM<+e79@hIHW#l-oKv7bG85iPgeas3{Rg57BA>}*ZJn7;j54KH8IFVw^G zQe~XI(BQP}=;o#4PVz}KbSyf4>G=S46~`#d<6Ejf_|A^qfVEavMkUBB%L_W1w?`Y~ zKPb|XwLU!YwBpb(7%Z6$G-FqmQ2+jGYIKf9gGtrpUQGs}(C?kkX1J&H(L&0gE~V;@UG&WLhc z%v^s(tm4dwWi^Gx#XfcnJ|vpO)5Oli!Ncuf%>AVYfJOBlZTWI+>&L#$=f_itO$zz9 z|I=ICUWD293B#OxK&`NyJ{3tK*Y&^2yI@G)={_KOnQc(&Hfp5PL7ubSR+*@~BOIhz z*M=d)(E*8F(LzXavQ}>EJuKgLEyXO^tJ*P>X)0;4B2OI}`GhHP^p7KmoCDo0Cu6*R zkTUc`T4UJ0`NI$@SYc~*UVo`A)^xuLwTT4tA3jn&|23<$ir?hyc4vR^4rzFV8-XGQ z5Fo$mKwAOXd!pJ)u#~~4w0!uj+5P=UxI5+fyAx#RD+5sLyLbR7cxIgD z(ML52#zVK>ok$h1D4-kT7Hk{B-5Ktt9owt-q$#26`_7n0_wl7HZFQ#0WeD0tyPi(T zQh-xOf$E&_o*7v@^wrA<7edHL{B(6uMjzH0%=06UX<8uFOugir0vhNF^CKyjJfi%S zRhiAo|1TMr&+>mVjx~Z;q-L>5Yr=POpYZUu13@?4&`lb9Uj}0Y@k=lY9|}f=R3Dah zOJfNp^t0Ci_b8!R-&F4OF!5fW`{0m8@XW@PsH~G8@#R|UAl?H`b@bh!^#cpQC(33? zb;w2N_dmTQSsMxJ0OD9;h-)w38V8~(JSg>TI&u3ohFq~7@-VcXYw)CG-J`6QqL)rn z<=tMguyk_at#DRpx)bQ5_Rj1P%AhuWm3Q~IidM2555fmv0G2gUWscPGCvBe-iv60= z4T|LaL=MT2>90p$EA4s@hEH&?k^o$a(YZcMzQ;C8m9AeTLIP4dXX; znP>VG76~gybtq?D%r5qh6P*&pNj@Fk5c^NC0x^wgNm$SIA%A!q`p)RsS~tlH6F!Uk z?uNy`ZyRQ7|G?I`N}sdGq^`c-wEMX8cqr>HF}Hth^DdEp_9ZAmv)6GNPyOX`3N}*O zX3;WHtj!yO=>!m z0uqZ?`DtG9w~+r#xo68XvZb5sdkPj7ct`=GiR`D9&VT5)H_pdS&}5DvM-?K-6;sQ_-5FYsb3#UKQ@dpi8?s|ipyy*{>hSn zetTFH^HhmD{GAcx`yTql&~@vhbgU84G{vHD_n?;zQd>FK6mK3!7B zk27v&NRa?aRK?J2@i!~Iv`5V%cRRjcNYrk-qUs{o@&g!rUeBF=jc33AvNho-)>lh@qQs)BC!Pa z11p-?v1F(tFk-+_KQ2|?p^dnHu|y44JNkgl7|i4OWnGNX#3DtSuRKF>{y9FXvdIV0 za`&NVGx7vz*+cCaELp5@&~7_|A-${_#@f`MB*Ds+E1%lGUbg84{W_m@WwquE_QFa4&E*;e+eGGN zDUKj^l+AJS^3Cgil&48CmNqsXvD=(2aw>&j<<(;?DkVUrU;EtMD*A8<&)F}|GdZk# zIM45}TUqzeL5T%pHx{qfzkyzF zHX8#h07Vy zN*yChY8$^B9}O?JJixQFF7i)E1rT13ELUh8!7gniKs$ta1%ZqR@t`Fy)0;1YT$r4+ zsPK!)sjEd#rN~yIcS|p@brdOpJx}Evi2Ix|`ZBW`w`jv_WRe_q6ig@cR{CA0yoBKc zQCsVZ0m1KR1=Pu^g3 Sy|a&Y*0skXEPz-2kKb$bc^z? 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 literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_08.png b/document/resource/mall_swarm_run_08.png new file mode 100644 index 0000000000000000000000000000000000000000..53721a388fdc97ddb69e18f72d8657109f6958f1 GIT binary patch literal 37677 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 Inoa0`0IRt?uK)l5 literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_09.png b/document/resource/mall_swarm_run_09.png new file mode 100644 index 0000000000000000000000000000000000000000..819234ddabb316f5424eeb1749a2781ac9ad9b46 GIT binary patch literal 7070 zcmY*;2RNHy_cvA5LD502XsgvKf~rx3R*hM?#xu?88Nh^l_Vl?bFfS}D(9xOZFD&Gn(qTg-|IKugp;$>eI_&WyN#J4u8wyB- z0@wMb3kz64JQR2=X_{{;xq!{j$1a!xQov19V8DjvW3lH;#{d;4n1}r321Pk1b*WozPG^NlCzfB%okQXCWzdtPi*VlmICJ1#o?A77Lh@ z1SA)LBQ*5b7=RJ57wRue_mPf{J5odC;d4LyY9`Y(?g4X~iHc~>vj;yhJA?rE`cZPX zRFaZZ;ftDnhpg=8Ea$bf`8EFlNlo7Kk*&YoWdAempZkO)<+ipU;xnY?S8E1tXgkbx zR9YAccbDniUE&j$VXo}>Z6{&V^7!xO!1p`eTTjwJN|$xV#THf1zwYVJNe=#mrP}=BB;h*j7!b&VfWr7V60(*T!$sh%HYYAk$}~d$wtqht35`HwLV)l z^CaabaxWAZ%0Y6aJ8#4_#|pK7F)0rRzf3a~uEwI$G>O-{$+I@a9r-s+qR--g{rP&P z59>H)Saq9UvtWD1vdOZBwIJ)G1@q2@f8K=|{A3css6TQ(D%^cb6;wyInub&B3vw|8 z6^}SPbnlu+4<5c`OJMpP`-OU)=(c(? zg?gZ$4yk*^RP=;1b)>}i>3Pw`Me)n~a^!3BLP4UfnpuKRE(z5<@VwnpYM^SAub~5C z&3gD)ue$2-&u2p7r2|w{8lR3x&Ra_B%<4 zR?BMUIEGH9!q99dg`*rtn;&FQ?er&&ihhJkzM~erc8rfxZhnV`^c_gyqfZmw+h@o0 zcC^@DjGT*HYMaPHTJ9EszjGzpY3KUMVE)#;D4}NGtV9 z6ncdk_G(`!@5#}H(RW4rGR-dh7toJV0g$nSCzxdHr%k$a>pmxKzVY82_V#~&$z${F z<3OY3hM?!da>D(=87uoLW!?d18#DDfcq?{PJ5PfP|2u)CEm?(bqxCVyoFLKHgQ_di zDJR36IYX(mwr&e@947BjC!-yX^TLD2rQ>{X=rOQ3pw^>&cKeCmk#4E>bd4&|8Y9D9lhfkfkR>UqErzux^ zV7A&H62@+Y#8kcKM)}tms3Rh2a*L4#dFrLZmh5sXQ?+(2Y8mGm-hAbWAAR1LdLhMe zL9yBidw^>Y(9T1t$8DXM+i4bM)NJ3Awbh>eBDx;ifC{)-{{{TUY?y|Q?qq}iP$lF4k}Snz#{ zH4;AAawFwMbnRep-?bqBT4(Q}_~Cj!e7Gzp%5frIwnPW-sp;IMY{xA)ntvv+QE4j&UmpkDCHEj{pyg{75b*@OLfO_T9v8}&Ggx~wA^{9H?jOh zz-!Tk2gRfVwyQMsa(RTlah_K=%`jbC+;JoGD}PI1k``^ku419)rrTSGZ$&}Fln%G` z7I<(v6~hpDK04cqBUx&U5uXl_!j(CZ3*_&1<8J2OCuNC8Fnc*PxJ|IZAopBlSt4K} zhKlnyWi`PM1uhSocd(=2Mnh#Ny(Sjeg6b+kf2 zMsDzfZV_@_ChPliD`W8+8k^bN_iJBH?)qmEzUm>KSlihWPqhpB-;*}Z@hj(G8;@OL z=y({AcUt=OSsy3jnJo3BrkOOSB%WBQjd5k&`@u%8xtQT^I_S+!J?!_!^1)#8wf#t` zpYlTt>IgYXydHEGR}3BiSwG-P73AR2)D<&e7kR&`cH_!?4kYqpn$%563xR1Drvd{H zuF~*=%N)(AbDR+IL1qv$<&xQ`y#?&_(Qo%zzO&?ssz+1GNe$u|1hWF-&v%K2DCjGV zrws<@89f5OH&;*mog}p>GTJA<=^F5yiT?0e^3||&)`9YQyytwKKi*Terq6I^6WoRq z>}>3E_r{d*MgKgtpI5Z_OteLprk*1AHZS?4C}-gy3DaLOlFRYUgYPeIi^QtllkjgR z_6=bfevzVuLEzl)i@9&6>lORgimyqijdaj|%vY9~rVgsQhgHz$Fq`J&IXT@c`tmXN zLP;DN;?bW)Cm5?&0&V{Wr(vcP-P(_HSN(@7I*dUgUnE zMog*iL$LjkJiaB_g%aKh>)x2h_%&Xrir^(DHYMSBH`oq^AzDqX2EJRWn=>;4M53L` zLay_Ep; zeiPaI$+DL*GKi2P)TQ}=%yjVFsN6D^f+}y(elWcC(a>7xraiOY=_B_{zev2aR)MHO zh(&_m*r@;VSY!H!7~}i%ao}so9?m(COe2bbblUUh{a*oQ{pseZ)15>eKeXIu&M9Gk zQtq>D?1>=?I5SW;)~n^}8)Og{_jjCmkDNe5wq~fk;b&Bt^eKh6M;o%6=M6<|C$n}# z*zqM25*MtTGI{l7Y9gpl&A9AT8TG-=ZN-l`>JOfh#?cU=M*+?1KPL`tLl(VG5iv6%EMt)<@hjuf`i4ax z{l^tiYjy)6Q2E)Gv>ZsFx%W^mB>kDQ)4kc#u5HEP)DBf?qO?Z9YA93b#N5;`xEDSA z3}lNVthJIY*GNxeY3w=k53w`{8+tfPDX?zOY6*XzY==s5zVxqm2?^E`ilt}$t)$?h zbXfr17_Bp^$U@#-7k8XHTi^QI?li{a7WGiaJF>OP#MHd25^J;${K$xNU7a#18GLZ* zohAHPpNXm}o2tT0tW22iY{c$SNaBYa<-m)nJ zgZ-{3f}n9w5pom_?F*9YnXUbUg9H#@P&Tryfo8H(YvbvKj9q$CPAqaiYnz)My zkVpWBjCsSNr-}KS?O}&==0zb76n`QkdxTxT3V|_+#?+&DXoYA1`tdfd%zF|oXHi!B z(zh4V5m`scaflqhgfO2zF_;Q6h4H!`98NE|(){xrY!HN2b0zJ8`{`44t2KCCJvBw` znY-jp8Nh8+ajK>}>5r&*CdpFBv#CtVNw_ffnot!mhlbDNG%KDa`#-xr)gaP6ziKtXfnyIDa*)8V}(287#V|Hr4d5r|Pk=&bV9IvlrH}h+(PJ%J5J5&)Dms4gY zCf$1uHOK;kiwqe$FSfBrUtWF5bbugY3nmF0Gh4%5i1>D^FnX+$=PM{b88_fOAp&)}A~vYq`0oJ9Tz%@+vEOKZ27lFm!o%H4*oVfNr*JbCGzkk2+0#DW#5bP=#GdJf>RTTkavVT;o zo5DaY+zP(P+_fK#hTM@O68yp$sAHk3V2}yS*ANh!y%K28>#$;*+b8+PqA%FV;bJ32 zA-}`3J;*lu&-clZ7d26xwrg7}B>JC7Us(oLAq&Nyv$&GD?})ZsgTM|ne>%Pi3^@hK zl3$az8oZ@`a1VJ}P@brOJ;D3Hp#EmNqAg`VHnr z-sL-7PSnnSbBXr@)KwldrRgTffgt$B{K(M-2hjLz=6?Rq_Pd5ZNVJE3*{iKim+=(| zpkc&8#L-RJ5J17)cbN3ui%Pb3ZOIC;L4d+R+p&E-%-+BHh7HQA^`9!jON=dHPJoLm za4I8#Jc|L4p`(PPxVXogIoeo6H1J^k? zq#jI@5&NEvl!k|WjTqr}W^WGH@jHSRlHW*0?T<}it$v?2Ub&NE+ubs2OsV^@pccgq zK>7-h&bsw0%OZqg0Epq(C1ci~NJDsg1gl|+q1#^c3scyfMAy2FD-}Mt52H@7?$3iU zF8y=$bIqRNWmpq{eqvZwR(jxj=z51==|yEAXKcamkIToM6u~x&JNJK8bnR`+0*>J| z5NBWc^uiA{+Z(%ob~h%kv{o=lFz?OcaPEcHQO*xb$pUV@M@>Ru!1v5@yy;*d{Qjbk~Qp*4ycTNy7eb*vA!F96O6e$EY%8dPn*3WQ;u?5==i!C z8JO8=1|ymi94kU&wKVtsTw(B3 z^{5pV?8AJv9*eeQEl2GQ=`BuNK$t)B?h&u5qcoKCCcTm?NjdmfAz2UY6N_{5a_FkF zO7>$;2H;?uX5^*;q7?HRY(4>rQlhyi&98K?;p9aEq~)X*M)efp6oMhc2Xa35j^((E z9gh+0lueUMtp6jq!oM}XG=vI76FUa=0fQI+!}73H?s04*$$<>Z!u|h{5|-l~5tOkd zfI)2?Gmq+@`o43M@{WdEB|z#cnsRK9O%t#1Pq0)W1>g@Wy3uzVq3h%62b_K`^iv^y z&G)uego>eBdBwtu0W>-OSzI`fZ3xg#A#S$}b`e1ReD0`by#mZfH-0Jd0u%!a&u_f| z+v>ZjY;PYLPP(aL7p~5FT-==POl&@qH%c2hsSz|Bb2jP%y@Tc-3rOa8a!4QLLe%?z zpZ!EI2F7m&ODvQbx4DZ_c`E>y_XrDOm9g+xtGeVxT9}AyhA_M^Wc%dUKnec3>P?br zoWgv%cKt`Z`uHsxDB!mI&Wp1Rlr7#Mc@_TYrtoelGgt^__2?pk0FSg%#Clx2&g-8P zRJ|Ubv^r@ew1i`*R?E^T0b|a9Pz_A`JzvkoU=cnIk9b?tzz_p@f>8bX`!DymvQkXI z<2#R^c&(9tnIi}ZHAuiUJqRVS+qMJm1XSLQJ9CeCk!q^7*W>{(ktX1=9k*>&A_!{e zMWWYEfHcu|@%H5;+(g%>71y>DvDjc{AOzXUn2gWFxeuq+L4DZ(ewStdmAyKGa6zr- z?at_Nl!AW!YL0i{S4`yNkYx9#X0Sp%Sf3aH3iw%$Yr+J!y9^(Du4cA42T14PJ6xbQCH=-h&EFyvc! z+dx!Rqpl)S5ptU@iiT@ic?Y7ZaW%%xiB=%~{7Qv0_$>X3Q5-4%8K=U}x3QBgduKUhPO-@~>rdIe`Yrr4a9$X|*rozRaE0f&})=yRL5%(yDuCF5w zLS}JRHBEwXuA?Q{-6m-?!nfAZ>W>(IX4WNKbbxj5Ke^TFKESGd`>Yx-xz;{U#p%Lb zP?P`uvj+%JC8t)AU||ErfXKBI^)==1rJ#y{VZjEreNt*brh ztlSpAn~yF7d{R$H#$+tx9wr6l0#e5P$_M70GAtbu}0+)|)u@aoH=eQKNVOB17M?cxF3#f8Dw z^Pv?H-7zaqqspfbk#pyz&-|3B!D2PQO2l>GEJ_kV{iA4BSwqD z^C7nVUuDEX&`f5q0i@xcV0;6mw)g8VBH$R~BbcqH@l(Rs`-vESOYJ0l+3D^veDfm6E{uTE#lbKx^= zuTKHw@0E!GB-)!afJ1VM+}@ph@vAK|54zq|-HufMkm&wbeEcS0$=L~5czTiQKxm!% zk))XX8;EZx068DA#SMl*PNOG z6bYY){}b4C332tGo>w$@&LL_MFo-dehGJxeNVOd#OIWgBfP(BWr081=rmNdRLYfKhW$TJdXicI literal 0 HcmV?d00001 diff --git a/document/resource/mall_swarm_run_10.png b/document/resource/mall_swarm_run_10.png new file mode 100644 index 0000000000000000000000000000000000000000..64f5f985429818f61ea87c1027e012cae7eae536 GIT binary patch literal 20914 zcmd42Wn5I>7d|?GD1u0bNX?+Y&@IvobpSyaKoF$Mp$tm8yJkoQNe|#4A*s@cf`EiW zx6(r?jnv%n`@1jh|HZwp@0;`4XPsSVpY^QuthM)vGtk$frevdpKp@oGfI1QaAqOB3 zGI0trqU3rZ_6-C=dSY3RR zIGdXJ8D@=q{mjPG*I!@hj*N()0PpRJK$M*>Lapb$larH*ii)7Q;caEPw`JvWg~>7r z0rg?-idETSPwZi$!Ywh+XJ%%U8w$QA`Y81;sWcZC`#8$V%JzTnM|8f+&dD=3H*ek` ztTm_L2!zy(tTh4wSL{DHxjr%Uov_~Knb<}k40?hi+S=Oj&Fce069mEtpnIP%Qd}@X zI67X3LZJl0#=tA$L_$1$Q?i_#=10Cic75XHl%=YwI?z9sIY6jiCG77X#{2jW5C~0) z{wsAMA$2Q+wYq{A{w5DC4GavNg6l(^oGvadMt+{G5C{s`jPE1AqGJ>4gPo4%N9T`E zkJcs$16c&Zil?3RYx-Ej3WeC5DzO2Xlyn>?eh)7XyOyw#;`TgI~nmIq@?N4TzJjcdD3?e$rPvHkn<#m_>trH?vjEk zIn@w|zNfajs_~1d&5`P>pH&zkLlG&tHqO5;Wgc!j&{4=HzJ18ufUUqaVz|Q?Q3|BL zD1KA#;Fv=nA|YZ40Es#!S_6a>)4@XllA2h?0x1|dEnI~eLz=D$LSW?IV8~EhETakt zd8kflz=k1>W#lHd(&0hckRKk{7R`0T)G5mmL5Xqp90|vKIOl^{RUP={QqTH?A6s*l zjR6dA2Aj4{8~nc7_|Ag)0->S-zMC*<+ON+7fATd{8EK<#gMJmjiH+@z4kvRBS+i%R zRk*Rwh|SDRr!2wi%rov)4CQWBHPxR!M+3%LX^OR)1S>7s#^@e)}CRWfJ z&mJKrLw8KadBAOpHmdq(0#|6|%*RU)kcg>_{XUDU_{OQXAD}U+I4U`?A`uC3FS!$B_uTHNVs8dXp9En}VSKlM>u{ni_&|$m8hA#r&X)^hiNA4$3Xv<_>?Be5dEp6ZDwfO6o-MDT^uY`Bq2h&q1;bjlAKok5` zR%uLdLO18OXHQP?1e&*w28H<$1147Tf}@Fs(jk$IKO+}QV;EEN_o0eZ!Xx4bCBcdN zm)7@>*WQZa*<1=~?r3pd zOPc3Z@q$~E&H0&Ix_%S+Q&sy(7XpePzZ&qn?~t}AUoXpD+gG{z?KI6&2uU6I`$H2s z^G2MRjlt{sE$OaD_fFK=x^yQ?O6t`e`Wj3;r2LCK+U{Ev&Xxk3; zg!YHtNxPaTz7q0DAF8op6*K&|fTHwoX9rc5z%z8dO}YLH+Pf7oqkUeCLI#R$FrkGSndBkk&ORWI!ub%zZ2l&R%F0< z+18l3q1fI2A+zdxvR}4#c5d2L})0epWkI4S3R7#X2p-G92 z;?SfZ9WqoC%0c}8Z_w8}xk1R2PrmyIfMo93###oNR5k}Oa1PAjT~Ynq&GEw z$5%l*n;s`A@0*6xWWD?}aBOzz)(vsASR^_OSN>I_5$?%I{)9 za$A!{*Nq>k5o?d3q0}__zgzdch+RrZy8*+(rDdf?SK;VVTQxS$abG1(n&T>JcHEyA zKc-Lh5R^;b_?E~h;O&Ny`%HcP+HUjtg9*-QWsqY&=q%pL^AlUQ%Zz9-CDiY4)>Sk_BM@fk%kRlpQ9#lV=x0up`aXFP< z33;Db1-LNa+Q_gNVo!=ch6GjyBc2ZE_x-3H{YZ`16L=fP$RAnf`pge`Z+lQPNp5AB z0<~1v@Axodj~Dc=t-CLY_i3T|v!XVou<1oO@Iq>dj2}qdt{3>i?viI+o=nF}kNuR-25s?}I!2#4b?X4${e-`c30N+JL%T zids(0kHSXCi$y5)a&s)YWYWuXR{}ISB{kk-{|6HXjeolPlb@)?H~#~|8zKZe{sT!e z5iXzTkPs-jY&@ED=|3g^S21LwDPXp)Q0)5RwY=vfGZD@_jy7@W0{l7x8n@NxVT`M4 zfY+b)nO9+-=uL-mY`&2@BscnOaTssm2!2U!O6;8&gZSB1K60+_cN0?v!uUxJsiEXV zctWfw;E>Im#6lz^q?r~8nYcqN5M?i*AmsfMVu2|8LxiEtJh8wHHu>%aLLe4AAbB1c zWP%ea{FD{~f!+ooa|nQnSVM^dMS`GgzXBB|BL0{gEWU0{1YY~)$ht3!n+MB-ZY~;% zD4h?OyB>LWm;+sU|1Q^CHqfB>Yq&|;IkOJNTk%*o|Qj-b=VCt zJ^S2^mHb%~)AbZ{bLIReq8d6br#agVT7Uf!l*Y&wgn%G))GVtqN{V`Ibju&OiDbta zvTIiQ(|^$N1D1bn1}orEF|Y3Hs>%5uE8J6?qLE58d2~l`V5Rg)W@|>~(#BP|fp$F& zmScStTJPCv3h-p<`eI@-(8+__8ERB0nF{;6-Yty%-pbhyYO}e6SvwAEL?-0;ubrOv zb*%jGyVS|#eM36SY0T7!9&}4E&{mcPwV=8Ewv`zd%!x}*{^JLDcSrjH(voqwH^J#u ze4xth(YxRj+FT{27JYrcmJQibhG$EUGKM~y!kCNbA{w7*m64~}(z==;fUvT6?m!Ms z@5;RN(5UZ7f;4CW^PPH-e;PXX|Dv@alT8sBGU2kxi=GokTsHFs zF^Wvt;V}rf-eX!O(BFWkgH_`_;`$t^fOvR8p2AftUF*+kisQ93KU!6&whG(+{%%CA zX-Y8Oa%<&Ey;svTyqGmP`_c~gpUy*QBhjSoAQU7YYgHf%t)@c;*Ij~yxaKc7??V#f z(9A@SgrLQd5&=wsFel=hLiIl^Kq>Gqowh59o)Ho0C1i2u$hXa-vWBKwh=}hS2)U9c zca$y5*nabu)JF}Wd#6pcQ@^{P7-nyMnNHFlwEnGS*g}sl#>Q|l497|c=R9UOvvpUt zv^Z}bn{g66_l2aZ-&I>T1&{8S9?Ildj{I@5_48hKbhljzDyN>lxzl_~E9(Aar1f-k z{d)k1F(cCCecI-U;S`r}@cOU6+fRX7drywhJ1!qT7xRU#Kk+SR$G|=$vO~OIA?ud?fuZ|Rb&FDJCBR^VXAIS8~3y`*#q`?+pGp9(BexaXx z(4=eN)m#LT2H4 zW5>BDSf8gbp<3+ZIju2Mm-QawOK@$(UNUt-6~A;Puy>``pA)yW&xW@ftxPfp&LxR2 zCBwVx-!@nGHn~xgNPQmU{gp;q-yf~h&qv=^%g)`s5|}cAm_j*CZi3eA6@18QVKNSjx~a$p zAE$YqeoX`=F@9PW%^{l5Ro-PS-Lu||Q=okx3YG&Tv`8(Y58wvLiP}LMSw}%g;17jF z?!(J9AVkCYv*-U*ynixo3MhG~wi-Y}R4^4C_t(dBkCQ}RD97O9T5Z3gkn z=7tAu%}=ZC0CC}V{hQEk#1K$r99`hfb&X3S2lPJiz_bGnsg+WS%7{ zsV+3Cix!u}{C9MzGD4%3OXhX_(-L@;m(`)?4Vr{xHRaB8)|rRElbII+1hJXxJLGH# z;7(4(;Bfcz61lk?pi^lW_Gm9>N6Nu7$S#CwzO#Doc!&|vsETRWV8OnE7VXp-p%La* zySoPX(bI&wm6VO+W+}bd7C`s`@-a~%h)ml&lF?@TKlVLBbsAv*Si`8(2`dA_sZoKI+gMf)D`P+peOBG`pVSe^vQSa@+hqJcux!doQJ1B-xy%g_p<-(mj$y8fhT^1jz8 z27!pbSIaUGstx7uCOs~GzzFZ;py-Q3ix2||s3n5(7NRkd5s366GHnVxJ(8OaM~oz3 zpe_)m4rHN8|9@KXlp~)d6m9h^ID@!Kx^t@}f9^oZpMnr#)TQvh_zMOq`)t3YfY4qJ zx1ls%5Q6=Qy~L}w_q8%skmi3OT6^q&AsW%(uo45c|Ak>Z|Ak>($~Y@>ZjdYHEU58k zjc-@EJDDMSh%2A_oh89b+Gan^DR{yhZ(ftgtYBL}KEB+2K^gV4>gVm9IrvcWZC%Oq z^cSeY{K8qv$wr^`(|K)XY3N~KGuPTa*yM1w)8?uoc4m>v_E+JoKl zjZeMi=eNJ6%>MfNY07Xj!HW>4F<~|DW(FQ@b{`g7$Jfc+9ugJ5+KkqD(Q;F^U^SJS zg4wPZplWc~NeB2`y6Ghq9$!!J@(PgCfE^?~=$ROyjqED2FI{qs2q~zHTR`8!P=>cm zz>%$){Kmc$>pb~$aNgmjzpDC>;$GfaXzv5ACp5gc-`5#ZOPEp3f8NQu(4zuoAK&M} zNsZsJk8!2La+@XQ!lHQKQ5si1>4SUWj#p6w8HMeQs=;-DUP`)f+|L`?=W>`=Cm*Li z2E<9l#vX?QHyO3U>?yQqFHuz^!E5^IW(C;ZvI<2PaA+H?#mQS{=l9r^M%HOpOmAP4 zBVypy3noA90JfsatuoU>vQWX546AT!Zi?^>GdM1M#pRD}i3%KNJRaDTE9}=`^Xg*R zCETc#N1ZLFw&?gMO9$+r5$+n0b#DKWy_OeN*yi3``yNwrOb|dQ+I?7X%Nz| zuR`iS zyM#R%V2s;;t4v3oT4BK{(UHelc9Ll@s+F|AV+5aA0W7=|*j*@YV<G2YCBmZSc#E5wMU($q#$C3Xm`8{H0<3B@gLp16C zv*Qd<^0)uRg)b@KSuJ~h?y%T}WA^4q_LWRR(L2k>3^J*qKSJNeozp#zx4DjD*cWK2 zyP#5BzE6v4DPF?CiVF;cj1_?@astVY@}Hn1N1s}c&mSpyCtGQ5Ny=~L1a15pz9T;^ zK=HX83gZ~8XtCopnrV_wdiuo|u4J^yn_m#(pV#j+c>mO>>FDX@zxm}+IpMKhLRAv8 zQ!7ptIex^d$)+Ka9jE2L&Kb8Al_I!jD3EYm#e?LJ1QP4}Q+GQ%OId`@(opf6I`R#q4w1R}0?v{^@#hQA<3MvD#5Nssb81;hRC0YE6_FC6DRjnd*g0OiG$1zRd2r}X=%w<#DYY+uzR4dHWrXt4X)E8ZD0uh!Pp`-_sZfu6V`$a# zV&nDSc`G13a~+LZ*ac&`j9gLQQQ+(wyosn1*fS=pl2U)Aw7 z)_&a4(zwT7*h!WXz4VVumUM=eHtzy{u-04Y6H|%Tm!~Q4r zoOwa5-&#D#H6BNKC46SoQ>kV?bp84gcqnqcu@DgcMGJR(J2LpDy*-&z!8#P+>$WF- z@Iy5MTwc!&7ocWiQ1{Ox7agH$Q{-9+QpW&(S^FOO-~+(@Wn}O zNKQf3Fz*%WrpKup=_?=lgp{*l%u~5UargVWTkdOuV>c23#TS^shX%JT+r?7~#|{m6 zTvOyecJDqNB9#8+hcP+jr^ic;qgFXNWw=f&mv(FQ1dl0C8Ji4U->rFk3_}tOz)Nzs zUkDche+_L5L0hhGQI8B^)n*#KN=qAAvmFIwOgO!%38^fdv0vz-KK}f#_szc zeHOgU09T^r@gOmpDPcxbtv)mT*`5D_j#SPnmY{T%YV z0uXzuK1DBpLZ~qBZQu+zVt>4;Mm1WU_o*H0dH&V)Efs@Z_T(N68Q42 z%H#ldm0AAUI{!&b|5~z@qer0}8E?yVZ?`)~PZM;|Zy*2itIbVjCk5@0qxZPm1bmD( zPzM#hK}VP(AMzE$w)iW759Ya;cw_8a0JT{&)pL}$a09=@@?rt@b^W#LcLVV7>G=F+ z^5#^)+p+R0RK?#HI%DGg~NYk z|6FEt41mtxhz@uITc#YoK(zLm?tHvShh0(N<$J<}<)zHLQ3NyTsBH1W%9u^@2)Al+ zDin&sfha%jV%UKou9n$-kjvPUBp1-=U3$0w8G9B_+~{U9G-ZT?F<$Y;7ms^32|wuR zuxOY%7|u-rL#on7s>cH4st@gkw4}^LNKK2>L;DSz7TZ*qzdRNgX?SM zs4JmUCt(jEyShY`xaku!ORnm0lSYvdzK_#v;HRWND!?MH3nEUhnm_Ic;GTz;21dQ0 zo+~H6T0CS^I3#0`g7cj7thsvgTL-|s-OAM{DVIn1F3-@t%pmIP;e z{){&zUGzLY^!ximi4zx+m)`JBjZN>k*Jr0zqBgqy!w>x0Cj$PICR{vIWrGWsd(98` zSxdUT^g$WE)9GgArHbbqbr%j+p%*zHAQ6)t@zB|#KsiI;06{KYdI`f%w33ht?@Fc@xhb=S+?t?0Z+w6%b9U|uhWrV)dbRuOc`^R&=S~(?)N9*E5FcIX8Hd*6<$NWN9S1K6Z6GNn{9dqVutnv( zC|FVv`Rl7%ywLi)SDul}8qnn*dDUNZQ~*NoS2X9TRKstFN@;#jc3l(^@9N9dM#lD6 zyg)1TaxI>7_Fld)6Yfl=EcRO_kK?w%rv~+bQCOrJO(CeT`IPwT&6gsjh80j5$>KSW zO|M``b)aA0%S?Om6br%!4ivcuS)f6Re`zSxP9Oxg=g$>-t!sR{g|0^0Lb`v;ls1T{ z8J0eMnh+Zu{Wh93i@xqDnm&@Zumf9AQCQs5k}@=QXRBbNR#NXOcbDCgShEu(naW zM}y-1YX3J>14fG!6?+ad*%4~y+FJTBFOXN$#I1(kaK8J}aN2rTpWt)>)f3`<1UZaV z0dyS|F}=0=oeWqW|2sJ@%6ZY|d!i8!_jmMNPM*y)O@3ihgp5`GxOoqx@9R)!qr{d1 zz(G)nr^(2n&M+~>Tuy_{2KJtJUKA}*r*Gc|%L=5OAH$f)+eYy|=VNxBU0e5cMIamJ z1hoF@df|p|-T-?Hnv@%qB(|l%5)*HUv^X(h#*hL^eL9Nva9?`<5J4G=*5|^xjU_SJ z6H_Bl>8q$0{O*ZVD20iv{1L4p-}h`>u?h$mPTYi3&^=&r{8@{F=oY0nEs}ee0{aZu z_}cZ+6~sp_N#c1AvbNF!S2^F4LOE>hwD_WonNv$7&dF51&>=g~UBn&cMdhi!e5>5H zavB*qGK>~Lt=5=N<>nTJC@UTfKf6~J@<;xAC^ZF~W{Hd&ybdL|i9|;eX`ChniuHdt z=eg)qlXjiR{hVCMZ{BQ|KZ{vW-?Y%q(WyZ4GZ{vFBxCtWTJC@4%ViOW#ZQSx@w#Fm zeA{2V5u9&Tx9pYP&&HL;ndWzGz0(7uZC?WUF99wNFv4r`u3yPzwq@TjhfXn!1TRkO z3N;?{?9wepDZ2BQ+R~=;HZbXXV9>S}xRG_!S2bwjXaT2!Jq!H10x!JZ$9R&@nm*aevYB6TXAIa z0lAAMq__9p+QPOx$yPBXm}&N>-}g>lJgV?{{(aB3Rw?+ahAB_G^heLrgLb-7$$HP< zN`dP)lO7XuNoaoA8>t+}twK|oK)q=-fAii}YN^@V$c~V?y-@gf^5jga=9_BAV>WAl zzR_axe2>HO&9>hyJj8$OS#*G3q~jR%V_6*gUrz+07Ah1;)U){$M#C;^OeNH%s)I_S z4orei&#xveaj7`m4CqvsyW+7hlA1y@J=G>#`D3igH9b2}fKdRMEH)y&!Ek-HaJuI4 zhC53vF#6`gp@zHUOTnc>`qzw)yk$m;guhrY2@DFzdWa)-or5im+SBIbJ;af{j+1f5 zmnRr#VqqEGOi7#P(@{ppMU|f(2Tqut@oGwVAAD^M&1w4D+itL~(91-DbN{4cl>5$I z2P`opPKd$d#9koCs~70!~BhQ!Q0UZ3oA-P&boD>d?pIH zj-A&dDNBy7Da_!tbczpDZ`BpqvXbtt6$L9!GsXdhPtHRk>~|{1h52>u%Ky&m%wU=-kKQEzthRISmXkibaYY^chRfigtFUlm{}RFw zauNAL2L$dRrHc5?Pp9U@Fv*gHj)D37MmT1D&T1s?L6z0-yeCUj_#x*9YaaEVSvA(z z&-zN9-)961-Yw9ozL2pHZG#W2U*jjUH@=1>}+#X&oYgMJc5HVZJ>R5qf&!m;q{~yVBP>)m>oct}h~f=i0LJ;&SM)wyY^M z4A{64v1<%?1_t77NMxK;x4K;av2FKX@^}K1PP7}Zy<8YB%SYkuv+>GKPfhN#5Mn=O;Qh9?mImO1bl>i-@8LoGBo^SiPxbZ5Qie|Oy?hlOQQ{czuVQJ= z+np0qY)q*6mc+P`kDm8HvU}_sXFk_4E2|l?$^gGoN4Ty7FNOWQ>YA2@^YAI_Xc+#r73EGFeA(jh}Lw!^5k77`B9EyZZ9?F`6_s33LHdBUM)Y#V7%{ zKdUa2Ul4U=4z39!h*u>OL&x!TuOF^F=Y2EmVi;2NlWUFYO6-1n05~;~ztGA1JlFs{ zS3g<7=k#>I+(itY6iqM=t%A1OfX5k;$ zxoobY>^%^=aKFw|UJ&=K?cP>rtJiXO{hNoKszrJObA&&l#nk{XQC?s*mtjwl_y@443xSG?=Wk0VBA zS4_c=lMkP)zH?0CWMiL^dDdKMZ)Dn(Q&c~}DAl)&&?pNjPd);YY9?kWz6ypK*^WP` z38vHXwC!fCJD*nd-Z91u#mHkH(_ z3&;6!nwfFFV9%?JpfhbweUo|y?DzGm(%twnPp$+7wJJ4m^8MnMRiNKfW=swItO{Eu zuHK;m$afqTIK#l288}hBbw%EA8d6>*i<$Z;bK1(KYsvB^v*!~6lUD$U_wz-*reVbQ z#MON=%eOp~gf2$I6z^i_5d+lm>9E_82B0rL5&?+vBWX0`q@dmksYx-{d-k2~{M588 zT)ItstkpNIhdHP7Z-f#~hf2O#7tj=QUXWUp$sB6k zxG6@@kBr|>iGwv1_lkFjGL4$@Ijr8a;L5gIqq*LEOxqKQr11(P@oFLGwaF}5425mM zaY@4U%Fo~LxnQ*ew4dsv#obP-BfA&>$}yuva$5pczosZZA~#6*j?Ovr$C!_&HMJ)z zE3T1eC!SjrP;1CB^W(19Y^bGhZn~icy6LbQn~umVPon?^_#yHE^$JHyl4I*}&!Xs1 zC6q%)@h7=m?T?=btGo4FRE&5r7>Ck?Um=uFmOSJd^@GLv@*g&{!AZjhr3%64w)Am- z2gt2_XE(523Rw;M%0D0fj+bJcg(Y1X@}^R*U`XGz&-c;rC#X{F&XZKOzJ9zYGPn8a zYBA>uX@m#%LnsseMFBvtb0JuV=i1I(wwG>@-K*jr_PMukAG$)pK0maz_OtHs`&ZT^tW2#!c&79JjO_V z9a7yYQJfk5s{CfCmrZZ={@AP+{{foiaZU&oY3ZSTIIKT@WY13WZt#0aGznuKLKmz? z>m`f`$b64=cE>Q2OoSP)KhKY^+e_g^yrGsf=`}i@WyUuDoT}H>-x@9)iLkOc{kZiW z#&MGo6@r-y@;eH-Bp*>WHHa5v!19~3ZA^{K;r6I>yR}5{`_RTrQVzu&B*F@OkZ>FE zr^U{4-ZUwinlyLHp5dplduoU~Z@Pa0RieeZ@XzjiO)`xs0w?}MQ#XxISAv%Sh1rzT z_|HWDA~{W(ihv2myq5?@*7`s)+!1z>*+&N%Y@Dcjlz{}B9&O4#7Gp5 zs96^H$)6hv&GB%MGvcqtr*{lQzGnG{tp7?k|0~fx_b>n%;m}A}iy9GQ{;I^|@VH+) zn6FTIr@`G%c`=FCh^W(hv9E$@++(G^-*rX9UkEc*qwo9Y8ih(u<)$x3wpZd#j?6dK zLO}kTdZrC(SOqr9iW`02GE{%u{pE^$DY3WKi@IxrHq^=61whZs0w5rMfBS>)+@BBtU${w_}+Ikl%`(X>X}vHUa!+P>7BoTeyQ+N+-5%gPs& zaOfDQ-su>?wmS$)G&!O;T;WIwbADVfEa<{(Z>y*8&XumUt!6AN>F>bvg4A5i4`vt{ zlZfHS#=IvRF0+q>rGEU)1ge~~91XiR-yknhFerT##oU+NS=pCZuNGR~ymAy`n)jH# zV}K*9N2JEAQKZP|{^Jg;;tfGYlr=^vNNKWJHqfOiI-NR++r-)Z#y|jO!1_GW)iA#| z&P1{8q%dwEjadVZdIQ5vR)Xp0FLPq55x!K6B@4ZlK6AfqoTYOA&3@@;>vbvqvwX(dV7z>;&~5K`Nq$51F0JHi@k*GxQi8G| z+{^@g@#7kQ&QuN{9wAy;`VvDd)OVNIP~@=5$cUs!(Y<`lg!-7V)kAz;X-1SL*m_Ix zxbHXf#`&G7IUyEY5=~Baf}E4=n+k5^M`rPU>qFS6`l>!=Ve-ctEh9SaJpQi|brgq} zuBz>jq)S_Y#Mgvel);u)fgXxN;8RV{FP;SV`EoW3d*v=!dkG1mwN9r+VCD*etI(DL zfSA64f-H>K7})J4mH=n;v=nWWt&_By+t)ZctlNS*_gk1qdpP;DRe|6(Z8e+)QtfIe z`kC%k*6OdGd-oQ;kzboHoyc=G?cW~0*}Zr3au{Gl3x`}I#guR(A*`2Rda58qj6ywI zf*Mn4y6Y8O;D?ii9A~M3SB|~QJ%82>rAoy!Vo1-@xN#jE_&C=szSB%Phzdv}itB#j zs}`PX$>X|W0?Kq+dvuzgQe6#qK?L^54BYVSxi$g{f~J zujf^`!~i6`)G)>NooFxMy{DzCft42MJt|Yd@@o-dgX6}j!bY=_KK@W&FKfiIL+;&F zmoo~@tvI|d}`vnqIyuQsUqMqThPr^tv8{X^eSy-_w=nA;#k>@&! zH+6gKSiZnzUd*?WfYaE;kw9P^dSK>eV9RL|Ot|If6Tf>1zsy|D^opP1O3WjHiH>B; zV6!nLMBel`^Ptmp2rd32tfleUHj&=yZ;d)Vk387ZapC1zzVYXLX8vRB(QAlgjGg)77$+_-9aT+X<&7f62u+8T_u9+iVMmhS+KqJf@_&=F-r zx8BLx!5lkg_3SGd*?_Y5P0cDZ$NHXO_7fv5HiNs}!FRIM;)o|%hzk^Sq`8f;%H_fJ z!bkVY?t@A4_cEDoz8Vp2?Wt25TqvKWDwJqWYSuQ|sB{czg=q*Po1}^VY0%wLabdgpg^+{nt|yZUd>KUHiP82gL7HpZ;av?jyqEkIGHsbD8n4^eQP0Xr$~ zj)*y*Nca0|9_&V{0*366{qc!(l)%H`oWyzB?7C)Xd>|<6l+6 znCFU6AM_exoPN31>iyD*Lk~QJ5(n!Y>z)?jN+ z?vq=t`_jXA`*eLj@cY5IAedxP+-%Nl&(*&NTYaNjY32`xEQ&neB)#R8+b|E%^$PY6 zsUmzf@09uBH^;C%!&I8W9@sHkwVgjTUsk_2==;^uDpiX(Di^Qj6W<{3Y~VwGpH8M2 z$}W#ru1V(_n|=Ng&Yjh?u^5&VH}JKPe|0430Vfmo!{_e)G3n*y*;R?Ysmn~n6^ey< zr?j=U2K(D-nOiDYkC{BaQ#?PSzN+$8kO8kzzpd-_0OL~RiBZ3M6lW~UuRD(uL?--T zz+858o@^!l-xKR4yG>zwM@_x)tR`LlP4-$d-|J+UWt;WkZMk>AwEF5_4FBq_ZTOAi z`g1=R(p{Gh4uJ*nW2{>J?x=&$P3tIgc;%>6D-1zz`?!HCrHAfCo~bHR^B5mDd`jGi zOM(zS*6T2yUGaEe?#7ZFHJPnh`I$@ueYTEqMW~LUYOLVXFso3>_W^cfETO```O9Ug zV>&{DX(ARc-F+Kg^1UkS&Z{q+H<{;ee%Sfqz}@mkKF6v}sdFrx@p#6gO<`7B!@2bn z+{BCXyOn_4D))hi0HCpIj$Wy1HA->HeCJR3oC=5tnsku30aX1BJJbD!T^rmr?s+&9 z!K%U)QWFmHriJZ?kl?=-=kpsJsz^ylE+fhC1m3K|YEH1$okOa>Gp^`8I&6Q; zf&1KoJLrOuW+4G?-7Pfz8yhvqWy=8XZ<~(>8Ma?j%}n;9`t@624~RL?=KhXGycyGI zCEq&-qEqr7ZsE?RPm=@l>{-e1>yF&HLo<0LwytY8EOIg<(k(Vo%n|8<21Wv2cJCR= zp4har=_t(IG)eYI8Su;A9>31|0UvWXS9mo;fz`_y*y#$`3nB;Z9w0P?sI`r*;AGw( z>X_7T{1uqg`P#gAPxOp<@F4tssMOvy&^05hju~9td*6Mrd^fMPSqA<54m~xTp~iox zhYZ+>3grK+ee*~Rgyy>FIPZl5F6DfO=in^2U7^e%o$WLr%p)hueA3vb}2q(Rz z4g6O9Jb+hh;8~k`v+Bc_GLvT2q`Dj6c4PP1F3vzNf7hsL)RH0?_9-6G)s9$m5Sfys88I# z?7(e#8P`NSdHQ6&?YKJNxEm3)dyV-W8{{IAg7zu$qj{HLiAjNtliB4ho53U~?G zZlE_DA<*Hep%*v4zgfVo@r70Nn6@RxAbjMCtPP!NwnDoY^J|Z2^g6s*Ez6Kb53+m- zc}7)~wK5YH-F^9IqE2+R-I=~%L!v6%Dns)%7MYa4%1bc}abZt&Rm*IQO6ft`O?F@} zj2gTHBf}%ntpNccrsPNxXMxQ}LR+e)#?e#T$Ai9#?G_ofA*=E-ZnRIO@fvtsboB{+g~b$2VEX3)a^UDn-9+x8jj$?ZO>)+u zRmxJY#4FtZkuVe^np8FT`KxByy3N))T^|ZRH(Hz^peWbZo1+`B69^HzeM^z{?g8;& zE$~bk;?D74i4-RSetOmb@=@E{^7|xP>Y~HjB-lUGsC2Ow4Hd^qk5;a}bCAy)&KfZa z84VwCyn%fk>&$Igbq!?5_B(;Ev%}2^RsljY_nV9-{CwGTQ-hCF@uOLa%m?_s z60K9y`z5Nqe3-}R#~o0h)`5xoQ9H*K9eQy8qf)dkx}^69XWK0$)%a*b4hFdtUe;J{ zCeecYNKmVh=dzM8n&dIg;g@1FE&BPu$Jh?>*KA#>Re549F=CWAp6W*H8mWFOq4DJQ zzGce+>}5{XhAto9Flyn;RuQo;bH0I(cjUHQ94Lt`a1CK?V|+dkMYCvayf<1YSmvM;&n4W$48vxa;6ksA4LeP5p zfM?39Rsvl~M>NLxvi}UQ&F^F+TQmve+K2moNJe(qFAettUOG=*RS0w5O_iZ8cAG4q zi;)cGny!%<>dyBVx2 z_(XJ*JqCv+&0xUQXy|Hgs5Q=h?OtE)&%U02s`n^$Y3uwAxeE*&r^5S;-}eRa_G^u{ zYyQxv6AJtRV#>GE5I8ra%%Dd?$s_ANjiQtLq-ka^Zh^s5YC(~8PiiN+uhFC$ky5_zpcy8|e38Zg3DiAuzcg|< z;%TtR5?^v;U)Cf2$+ld73M{&k0`;K#sjW!j${;_d`lR$KcBkU)nIGb$4;nOgKVh?F zvq8`|hUWgBnBR*ax9QRsb-44{Ms(K~jo~AWY@MoG`IM_qlsfJ1u8yS>Q@p&y6feb_ z{ocum-uZtiUUl_Xm|vtqX786tYkRLwsJoH=%kd6$EW;bb|1WKesVsB;HxBF+|EHA&j+^C2|lFc zvZddN=j_dj$K*44_2JQsm&ssBdLg)y{TI;y%c-cTsm9IpsxaQB;-yyeIkF3Z7AZ2DhvgPGxPVB)dDjp_9knt_KJG0detV6)aZT% zqaOWggw2*rI$d}zM7qr}Vg0JNbeAPQ$w;5-4^J9b8va-x^T|7ze4i6^Lw_qmf)+K8 zFb;CJ(VK+($7%$yvc^i8gE7-@d4>Kl6e>ZWsuH&7_*hpLx zEO)TP3Pc4}=rXt?Trnk6aV~uFlWyG?4bdnW?cXfeg^gQoruBd7*y>?tqH`5KT<;FW z7->*xyxGMkJpGHhm9)8 z_Y?w&CC2+IqOtpzVi_TJDj=T<2%-H~JA@ynVIm88A;gXQX0!UHbv_axfnf4DHp|(q zlGq_cN?f3T{9rYDwg263wxP}4-}2afjT79bWt} gou^4rdTLTp00aRA1}rRRrV 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 literal 0 HcmV?d00001 diff --git a/document/resource/rabbitmq_install_1.png b/document/resource/rabbitmq_install_1.png deleted file mode 100644 index 73d45867502d6ab81cac3b16490b211d129154d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13222 zcmb`OWmFt%zva=;KyV9A6D(+gyEFusKycRp!QC27@qB z=bn-G&iybSSPP!jO;uA>&))yv-h_Tol)^wGL4$*X!;q1dP=SMkSA%^C0bamX8VgT| z;ozv?WF*8?-G3aWVkD|bCG8w=ckRBy@P9=lu?x@s4YdcG-nfGk(hew!qD@YNwTrJf!HY=DlEX6a)LNB8x_*?HA`+o7D+pk=Cg5Cge*@gre$W<4OKd1 z%>1Zzwb{dNiJ$Vyb*U8kbhKsdpj4QqGE;HX&u~czU z+VYM_fvvB}+%T3<#)JHAXJ*$&>^KK-r#QuA7f6ur1LPMkceB1FGnF<~WCUI)`QFCV zU(Q?E2;be_4r!UEnt6J89R`g8bjpnbBfiu@R1vzW3JV9Bb!v*nf=}9@fBsbUdI!|n zEYwh+bl%w5*yPX5*V?5Y`dW07fTegNc`%fTV~K@k>wz+ZD3L2pqeA27d%q7`#;-Rh zpI+&KPr8-8yc!>V5REgetfKXPH;1gfTBl+a##3RP&?p-XPkH$Ikoi9R4~2IZ%DkSw zZWab9_pH+fw+!Cip1ll_7kQ+6#87eV^5-l3sl<&4#-jB5O?sOwWQ)3%prE&8h#}!l zfHx>OiVx&Jh3XMVg9#M{uQ%4IbzdT~OwY=>Puv8I*ww$>(akVcCLfswnBu54x9?lw zR}r9%wbfeBso-K6Q8$GYlF|dGK+KBi*Je2HBLIb(jau`i+`I$8*flY^YT1)QR9l}M ztSVU&QsO1i*)EdqKKgv`P{T0yUlz&Y7%GbM4I?f2~WO&sHMJE@xR1c<$D{tS~%yTxb zG`iW%4Hi@Ytg4X+ko0n8<>I2g_h-w*{1Fx@Vk=km&U~{vdwX#p*Mailg}jwjVYOg4 zKQi{`X2t5PtStMNClkzSKpD-#H+fWfc@rwdtQJ3^w{y$~9~=}_I_bN5+rOX`cLNIX z@0iJi!L!gUWcZgW@48Sb%|~mfLyxPiW|C>;;_*icd-&DT%hYu~w9iI`h6c(i7h|Fm zv2s>^8fHWjxcgISvT=Ze2-bqcqDug#^Rb$c;0AF;o!@2mh9g*5@ow+?z1;Jb<`*S} zyREFTs6;rCAg(G?|M)?yJHEg!Pl>6z0lX_tSz#yNzll$B6wjg~OP7yLhldan9u(?? z`UVAn6SSM?j4(TBUIxB7%@l5RIZ(IK0#(`T&y&W_i)at?6jX)4&Q6S#Q5;zrCoXK; zegs3N{>CB}jP8DcUpkTL(8ew*?)o5aQRJ>b(8=oj5^!QJayQ4nl^Au4$fFf6v$S>` zVF&JPx?4J8T~V>Qyn0MY{pNeWv0c&#tuVgX=4qX~Z9b<|@_#yS^GCdVemq8irko#b z#HM0t3tBFswyaIBf5HwEcyZIi(=t91<@3jcvQkc?%=`EYWfdL*ZxC;Y&ftspeHP}E z4|^hGe+aoHa6518e9ls)Z?N3p?tjf56C1%^g|78kaUxgeurJK)00YC*MC8ck3O=tk7eY(3m z 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 diff --git a/document/resource/rabbitmq_install_2.png b/document/resource/rabbitmq_install_2.png deleted file mode 100644 index 89dee1b8a35ea8543b98c5c29f7fa663c02c7a15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40324 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

UT}qt1ztheo7pBQa+h7*%;3ATbp!HrHtj31 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 - com.macro.mall - mall-security + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config - org.springframework.cloud - spring-cloud-starter-config + org.springframework.boot + spring-boot-starter-data-redis com.aliyun.oss aliyun-sdk-oss - - net.logstash.logback - logstash-logback-encoder - io.minio minio + + jakarta.validation + jakarta.validation-api + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + io.github.openfeign + feign-okhttp + diff --git a/mall-admin/src/main/java/com/macro/mall/MallAdminApplication.java b/mall-admin/src/main/java/com/macro/mall/MallAdminApplication.java index 2f95822..8e1e27b 100644 --- a/mall-admin/src/main/java/com/macro/mall/MallAdminApplication.java +++ b/mall-admin/src/main/java/com/macro/mall/MallAdminApplication.java @@ -3,11 +3,13 @@ package com.macro.mall; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; /** * 应用启动入口 * Created by macro on 2018/4/26. */ +@EnableFeignClients @EnableDiscoveryClient @SpringBootApplication public class MallAdminApplication { diff --git a/mall-admin/src/main/java/com/macro/mall/bo/AdminUserDetails.java b/mall-admin/src/main/java/com/macro/mall/bo/AdminUserDetails.java deleted file mode 100644 index a46ab68..0000000 --- a/mall-admin/src/main/java/com/macro/mall/bo/AdminUserDetails.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.macro.mall.bo; - -import com.macro.mall.model.UmsAdmin; -import com.macro.mall.model.UmsResource; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -/** - * SpringSecurity需要的用户详情 - * Created by macro on 2018/4/26. - */ -public class AdminUserDetails implements UserDetails { - private UmsAdmin umsAdmin; - private List resourceList; - public AdminUserDetails(UmsAdmin umsAdmin,List resourceList) { - this.umsAdmin = umsAdmin; - this.resourceList = resourceList; - } - - @Override - public Collection getAuthorities() { - //返回当前用户的角色 - return resourceList.stream() - .map(role ->new SimpleGrantedAuthority(role.getId()+":"+role.getName())) - .collect(Collectors.toList()); - } - - @Override - public String getPassword() { - return umsAdmin.getPassword(); - } - - @Override - public String getUsername() { - return umsAdmin.getUsername(); - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return umsAdmin.getStatus().equals(1); - } -} diff --git a/mall-admin/src/main/java/com/macro/mall/bo/WebLog.java b/mall-admin/src/main/java/com/macro/mall/bo/WebLog.java deleted file mode 100644 index 98c51dd..0000000 --- a/mall-admin/src/main/java/com/macro/mall/bo/WebLog.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.macro.mall.bo; - -/** - * Controller层的日志封装类 - * Created by macro on 2018/4/26. - */ -public class WebLog { - /** - * 操作描述 - */ - private String description; - - /** - * 操作用户 - */ - private String username; - - /** - * 操作时间 - */ - private Long startTime; - - /** - * 消耗时间 - */ - private Integer spendTime; - - /** - * 根路径 - */ - private String basePath; - - /** - * URI - */ - private String uri; - - /** - * URL - */ - private String url; - - /** - * 请求类型 - */ - private String method; - - /** - * IP地址 - */ - private String ip; - - private Object parameter; - - private Object result; - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public Long getStartTime() { - return startTime; - } - - public void setStartTime(Long startTime) { - this.startTime = startTime; - } - - public Integer getSpendTime() { - return spendTime; - } - - public void setSpendTime(Integer spendTime) { - this.spendTime = spendTime; - } - - public String getBasePath() { - return basePath; - } - - public void setBasePath(String basePath) { - this.basePath = basePath; - } - - public String getUri() { - return uri; - } - - public void setUri(String uri) { - this.uri = uri; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getMethod() { - return method; - } - - public void setMethod(String method) { - this.method = method; - } - - public String getIp() { - return ip; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public Object getParameter() { - return parameter; - } - - public void setParameter(Object parameter) { - this.parameter = parameter; - } - - public Object getResult() { - return result; - } - - public void setResult(Object result) { - this.result = result; - } -} diff --git a/mall-admin/src/main/java/com/macro/mall/component/ResourceRoleRulesHolder.java b/mall-admin/src/main/java/com/macro/mall/component/ResourceRoleRulesHolder.java new file mode 100644 index 0000000..721094c --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/component/ResourceRoleRulesHolder.java @@ -0,0 +1,23 @@ +package com.macro.mall.component; + +import com.macro.mall.service.UmsResourceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * 资源与角色访问对应关系操作组件 + * Created by macro on 2020/7/17. + */ +@Component +public class ResourceRoleRulesHolder { + + @Autowired + private UmsResourceService resourceService; + + @PostConstruct + public void initResourceRolesMap(){ + resourceService.initResourceRolesMap(); + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/config/GlobalCorsConfig.java b/mall-admin/src/main/java/com/macro/mall/config/GlobalCorsConfig.java deleted file mode 100644 index f07d095..0000000 --- a/mall-admin/src/main/java/com/macro/mall/config/GlobalCorsConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.macro.mall.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; - -/** - * 全局跨域配置 - * 注意:前端从网关进行调用时不需要配置 - * Created by macro on 2019/7/27. - */ -//@Configuration -public class GlobalCorsConfig { - - /** - * 允许跨域调用的过滤器 - */ - @Bean - public CorsFilter corsFilter() { - CorsConfiguration config = new CorsConfiguration(); - //允许所有域名进行跨域调用 - config.addAllowedOrigin("*"); - //允许跨越发送cookie - config.setAllowCredentials(true); - //放行全部原始头信息 - config.addAllowedHeader("*"); - //允许所有请求方法跨域调用 - config.addAllowedMethod("*"); - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); - return new CorsFilter(source); - } -} diff --git a/mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java b/mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java deleted file mode 100644 index 23b6f15..0000000 --- a/mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.macro.mall.config; - -import com.macro.mall.model.UmsResource; -import com.macro.mall.security.component.DynamicSecurityService; -import com.macro.mall.security.config.SecurityConfig; -import com.macro.mall.service.UmsAdminService; -import com.macro.mall.service.UmsResourceService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.access.ConfigAttribute; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.userdetails.UserDetailsService; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * mall-security模块相关配置 - * Created by macro on 2019/11/9. - */ -@Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class MallSecurityConfig extends SecurityConfig { - - @Autowired - private UmsAdminService adminService; - @Autowired - private UmsResourceService resourceService; - - @Bean - public UserDetailsService userDetailsService() { - //获取登录用户信息 - return username -> adminService.loadUserByUsername(username); - } - - @Bean - public DynamicSecurityService dynamicSecurityService() { - return new DynamicSecurityService() { - @Override - public Map loadDataSource() { - Map map = new ConcurrentHashMap<>(); - List resourceList = resourceService.listAll(); - for (UmsResource resource : resourceList) { - map.put(resource.getUrl(), new org.springframework.security.access.SecurityConfig(resource.getId() + ":" + resource.getName())); - } - return map; - } - }; - } -} diff --git a/mall-admin/src/main/java/com/macro/mall/config/MyBatisConfig.java b/mall-admin/src/main/java/com/macro/mall/config/MyBatisConfig.java index 4f0677a..1164256 100644 --- a/mall-admin/src/main/java/com/macro/mall/config/MyBatisConfig.java +++ b/mall-admin/src/main/java/com/macro/mall/config/MyBatisConfig.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; /** - * MyBatis配置类 + * MyBatis相关配置 * Created by macro on 2019/4/8. */ @Configuration diff --git a/mall-admin/src/main/java/com/macro/mall/config/OssConfig.java b/mall-admin/src/main/java/com/macro/mall/config/OssConfig.java index d0112a9..9f7da2a 100644 --- a/mall-admin/src/main/java/com/macro/mall/config/OssConfig.java +++ b/mall-admin/src/main/java/com/macro/mall/config/OssConfig.java @@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** + * OSS对象存储相关配置 * Created by macro on 2018/5/17. */ @Configuration diff --git a/mall-admin/src/main/java/com/macro/mall/config/RedisConfig.java b/mall-admin/src/main/java/com/macro/mall/config/RedisConfig.java new file mode 100644 index 0000000..90bba12 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/config/RedisConfig.java @@ -0,0 +1,19 @@ +package com.macro.mall.config; + +import com.macro.mall.common.config.BaseRedisConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * Redis相关配置 + * Created by macro on 2020/6/19. + */ +@Configuration +public class RedisConfig extends BaseRedisConfig { + +} diff --git a/mall-admin/src/main/java/com/macro/mall/config/Swagger2Config.java b/mall-admin/src/main/java/com/macro/mall/config/Swagger2Config.java deleted file mode 100644 index a3da046..0000000 --- a/mall-admin/src/main/java/com/macro/mall/config/Swagger2Config.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.macro.mall.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.SecurityReference; -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; - -/** - * Swagger2API文档的配置 - * Created by macro on 2018/4/26. - */ -@Configuration -@EnableSwagger2 -public class Swagger2Config { - @Bean - public Docket createRestApi(){ - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .select() - .apis(RequestHandlerSelectors.basePackage("com.macro.mall.controller")) - .paths(PathSelectors.any()) - .build() - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); - } - - private ApiInfo apiInfo() { - return new ApiInfoBuilder() - .title("mall后台系统") - .description("mall后台模块") - .contact("macro") - .version("1.0") - .build(); - } - - private List securitySchemes() { - //设置请求头信息 - List result = new ArrayList<>(); - ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); - result.add(apiKey); - return result; - } - - private List securityContexts() { - //设置需要登录认证的路径 - List result = new ArrayList<>(); - result.add(getContextByPath("/brand/.*")); - result.add(getContextByPath("/product/.*")); - result.add(getContextByPath("/productCategory/.*")); - return result; - } - - private SecurityContext getContextByPath(String pathRegex){ - return SecurityContext.builder() - .securityReferences(defaultAuth()) - .forPaths(PathSelectors.regex(pathRegex)) - .build(); - } - - private List defaultAuth() { - List result = new ArrayList<>(); - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - result.add(new SecurityReference("Authorization", authorizationScopes)); - return result; - } -} diff --git a/mall-admin/src/main/java/com/macro/mall/config/SwaggerConfig.java b/mall-admin/src/main/java/com/macro/mall/config/SwaggerConfig.java new file mode 100644 index 0000000..37894e3 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/config/SwaggerConfig.java @@ -0,0 +1,41 @@ +package com.macro.mall.config; + +import com.macro.mall.common.config.BaseSwaggerConfig; +import com.macro.mall.common.domain.SwaggerProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; +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; + +/** + * Swagger API文档相关配置 + * Created by macro on 2018/4/26. + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig extends BaseSwaggerConfig { + + @Override + public SwaggerProperties swaggerProperties() { + return SwaggerProperties.builder() + .apiBasePackage("com.macro.mall.controller") + .title("mall后台系统") + .description("mall后台相关接口文档") + .contactName("macro") + .version("1.0") + .enableSecurity(true) + .build(); + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/controller/MinioController.java b/mall-admin/src/main/java/com/macro/mall/controller/MinioController.java index 1958965..71e015b 100644 --- a/mall-admin/src/main/java/com/macro/mall/controller/MinioController.java +++ b/mall-admin/src/main/java/com/macro/mall/controller/MinioController.java @@ -1,9 +1,11 @@ package com.macro.mall.controller; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.json.JSONUtil; import com.macro.mall.common.api.CommonResult; +import com.macro.mall.dto.BucketPolicyConfigDto; import com.macro.mall.dto.MinioUploadDto; -import io.minio.MinioClient; -import io.minio.policy.PolicyType; +import io.minio.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; @@ -20,6 +22,7 @@ import java.text.SimpleDateFormat; import java.util.Date; /** + * MinIO对象存储管理 * Created by macro on 2019/12/25. */ @Api(tags = "MinioController", description = "MinIO对象存储管理") @@ -43,39 +46,68 @@ public class MinioController { public CommonResult upload(@RequestParam("file") MultipartFile file) { try { //创建一个MinIO的Java客户端 - MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY); - boolean isExist = minioClient.bucketExists(BUCKET_NAME); + MinioClient minioClient =MinioClient.builder() + .endpoint(ENDPOINT) + .credentials(ACCESS_KEY,SECRET_KEY) + .build(); + boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(BUCKET_NAME).build()); if (isExist) { LOGGER.info("存储桶已经存在!"); } else { //创建存储桶并设置只读权限 - minioClient.makeBucket(BUCKET_NAME); - minioClient.setBucketPolicy(BUCKET_NAME, "*.*", PolicyType.READ_ONLY); + minioClient.makeBucket(MakeBucketArgs.builder().bucket(BUCKET_NAME).build()); + BucketPolicyConfigDto bucketPolicyConfigDto = createBucketPolicyConfigDto(BUCKET_NAME); + SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder() + .bucket(BUCKET_NAME) + .config(JSONUtil.toJsonStr(bucketPolicyConfigDto)) + .build(); + minioClient.setBucketPolicy(setBucketPolicyArgs); } String filename = file.getOriginalFilename(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); // 设置存储对象名称 String objectName = sdf.format(new Date()) + "/" + filename; // 使用putObject上传一个文件到存储桶中 - minioClient.putObject(BUCKET_NAME, objectName, file.getInputStream(), file.getContentType()); + PutObjectArgs putObjectArgs = PutObjectArgs.builder() + .bucket(BUCKET_NAME) + .object(objectName) + .contentType(file.getContentType()) + .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build(); + minioClient.putObject(putObjectArgs); LOGGER.info("文件上传成功!"); MinioUploadDto minioUploadDto = new MinioUploadDto(); minioUploadDto.setName(filename); minioUploadDto.setUrl(ENDPOINT + "/" + BUCKET_NAME + "/" + objectName); return CommonResult.success(minioUploadDto); } catch (Exception e) { + e.printStackTrace(); LOGGER.info("上传发生错误: {}!", e.getMessage()); } return CommonResult.failed(); } + private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) { + BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder() + .Effect("Allow") + .Principal("*") + .Action("s3:GetObject") + .Resource("arn:aws:s3:::"+bucketName+"/*.**").build(); + return BucketPolicyConfigDto.builder() + .Version("2012-10-17") + .Statement(CollUtil.toList(statement)) + .build(); + } + @ApiOperation("文件删除") @RequestMapping(value = "/delete", method = RequestMethod.POST) @ResponseBody public CommonResult delete(@RequestParam("objectName") String objectName) { try { - MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY); - minioClient.removeObject(BUCKET_NAME, objectName); + MinioClient minioClient = MinioClient.builder() + .endpoint(ENDPOINT) + .credentials(ACCESS_KEY,SECRET_KEY) + .build(); + minioClient.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build()); return CommonResult.success(null); } catch (Exception e) { e.printStackTrace(); diff --git a/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java b/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java index ee36dc7..5237008 100644 --- a/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java +++ b/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java @@ -1,7 +1,9 @@ package com.macro.mall.controller; +import cn.hutool.core.collection.CollUtil; import com.macro.mall.common.api.CommonPage; import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.domain.UserDto; import com.macro.mall.dto.UmsAdminLoginParam; import com.macro.mall.dto.UmsAdminParam; import com.macro.mall.dto.UpdateAdminPasswordParam; @@ -13,16 +15,14 @@ import com.macro.mall.service.UmsRoleService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; -import java.security.Principal; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 后台用户管理 @@ -32,10 +32,6 @@ import java.util.Map; @Api(tags = "UmsAdminController", description = "后台用户管理") @RequestMapping("/admin") public class UmsAdminController { - @Value("${jwt.tokenHeader}") - private String tokenHeader; - @Value("${jwt.tokenHead}") - private String tokenHead; @Autowired private UmsAdminService adminService; @Autowired @@ -56,45 +52,23 @@ public class UmsAdminController { @RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public CommonResult login(@RequestBody UmsAdminLoginParam umsAdminLoginParam, BindingResult result) { - String token = adminService.login(umsAdminLoginParam.getUsername(), umsAdminLoginParam.getPassword()); - if (token == null) { - return CommonResult.validateFailed("用户名或密码错误"); - } - Map tokenMap = new HashMap<>(); - tokenMap.put("token", token); - tokenMap.put("tokenHead", tokenHead); - return CommonResult.success(tokenMap); - } - - @ApiOperation(value = "刷新token") - @RequestMapping(value = "/refreshToken", method = RequestMethod.GET) - @ResponseBody - public CommonResult refreshToken(HttpServletRequest request) { - String token = request.getHeader(tokenHeader); - String refreshToken = adminService.refreshToken(token); - if (refreshToken == null) { - return CommonResult.failed("token已经过期!"); - } - Map tokenMap = new HashMap<>(); - tokenMap.put("token", refreshToken); - tokenMap.put("tokenHead", tokenHead); - return CommonResult.success(tokenMap); + return adminService.login(umsAdminLoginParam.getUsername(),umsAdminLoginParam.getPassword()); } @ApiOperation(value = "获取当前登录用户信息") @RequestMapping(value = "/info", method = RequestMethod.GET) @ResponseBody - public CommonResult getAdminInfo(Principal principal) { - if(principal==null){ - return CommonResult.unauthorized(null); - } - String username = principal.getName(); - UmsAdmin umsAdmin = adminService.getAdminByUsername(username); + public CommonResult getAdminInfo() { + UmsAdmin umsAdmin = adminService.getCurrentAdmin(); Map data = new HashMap<>(); data.put("username", umsAdmin.getUsername()); - data.put("roles", new String[]{"TEST"}); data.put("menus", roleService.getMenuList(umsAdmin.getId())); data.put("icon", umsAdmin.getIcon()); + List roleList = adminService.getRoleList(umsAdmin.getId()); + if(CollUtil.isNotEmpty(roleList)){ + List roles = roleList.stream().map(UmsRole::getName).collect(Collectors.toList()); + data.put("roles",roles); + } return CommonResult.success(data); } @@ -215,4 +189,12 @@ public class UmsAdminController { List permissionList = adminService.getPermissionList(adminId); return CommonResult.success(permissionList); } + + @ApiOperation("根据用户名获取通用用户信息") + @RequestMapping(value = "/loadByUsername", method = RequestMethod.GET) + @ResponseBody + public UserDto loadUserByUsername(@RequestParam String username) { + UserDto userDTO = adminService.loadUserByUsername(username); + return userDTO; + } } diff --git a/mall-admin/src/main/java/com/macro/mall/controller/UmsResourceController.java b/mall-admin/src/main/java/com/macro/mall/controller/UmsResourceController.java index 09685e9..5261007 100644 --- a/mall-admin/src/main/java/com/macro/mall/controller/UmsResourceController.java +++ b/mall-admin/src/main/java/com/macro/mall/controller/UmsResourceController.java @@ -3,7 +3,6 @@ package com.macro.mall.controller; import com.macro.mall.common.api.CommonPage; import com.macro.mall.common.api.CommonResult; import com.macro.mall.model.UmsResource; -import com.macro.mall.security.component.DynamicSecurityMetadataSource; import com.macro.mall.service.UmsResourceService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -12,6 +11,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; /** * 后台资源管理Controller @@ -24,15 +24,12 @@ public class UmsResourceController { @Autowired private UmsResourceService resourceService; - @Autowired - private DynamicSecurityMetadataSource dynamicSecurityMetadataSource; @ApiOperation("添加后台资源") @RequestMapping(value = "/create", method = RequestMethod.POST) @ResponseBody public CommonResult create(@RequestBody UmsResource umsResource) { int count = resourceService.create(umsResource); - dynamicSecurityMetadataSource.clearDataSource(); if (count > 0) { return CommonResult.success(count); } else { @@ -46,7 +43,6 @@ public class UmsResourceController { public CommonResult update(@PathVariable Long id, @RequestBody UmsResource umsResource) { int count = resourceService.update(id, umsResource); - dynamicSecurityMetadataSource.clearDataSource(); if (count > 0) { return CommonResult.success(count); } else { @@ -67,7 +63,6 @@ public class UmsResourceController { @ResponseBody public CommonResult delete(@PathVariable Long id) { int count = resourceService.delete(id); - dynamicSecurityMetadataSource.clearDataSource(); if (count > 0) { return CommonResult.success(count); } else { @@ -94,4 +89,12 @@ public class UmsResourceController { List resourceList = resourceService.listAll(); return CommonResult.success(resourceList); } + + @ApiOperation("初始化资源角色关联数据") + @RequestMapping(value = "/initResourceRolesMap", method = RequestMethod.GET) + @ResponseBody + public CommonResult initResourceRolesMap() { + Map> resourceRolesMap = resourceService.initResourceRolesMap(); + return CommonResult.success(resourceRolesMap); + } } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/CmsPrefrenceAreaProductRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/CmsPrefrenceAreaProductRelationDao.java index 6d2276f..9f8216f 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/CmsPrefrenceAreaProductRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/CmsPrefrenceAreaProductRelationDao.java @@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 自定义优选和商品关系操作 + * 自定义优选和商品关系操作Dao * Created by macro on 2018/4/26. */ public interface CmsPrefrenceAreaProductRelationDao { diff --git a/mall-admin/src/main/java/com/macro/mall/dao/CmsSubjectProductRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/CmsSubjectProductRelationDao.java index df2d05b..749aee6 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/CmsSubjectProductRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/CmsSubjectProductRelationDao.java @@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 自定义商品和专题关系操作 + * 自定义商品和专题关系操作Dao * Created by macro on 2018/4/26. */ public interface CmsSubjectProductRelationDao { diff --git a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductAttributeCategoryDao.java b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductAttributeCategoryDao.java index cf1e27e..b126010 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductAttributeCategoryDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductAttributeCategoryDao.java @@ -10,7 +10,7 @@ import java.util.List; */ public interface PmsProductAttributeCategoryDao { /** - * 获取商品属性分类,包括属性 + * 获取包含属性的商品属性分类 */ List getListWithAttr(); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductCategoryDao.java b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductCategoryDao.java index 3697f08..9ac86da 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductCategoryDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductCategoryDao.java @@ -10,7 +10,7 @@ import java.util.List; */ public interface PmsProductCategoryDao { /** - * 获取商品分类包括子分类 + * 获取商品分类及其子分类 */ List listWithChildren(); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductDao.java b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductDao.java index 443adbc..982b482 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductDao.java @@ -5,7 +5,7 @@ import org.apache.ibatis.annotations.Param; /** - * 商品自定义Dao + * 自定义商品管理Dao * Created by macro on 2018/4/26. */ public interface PmsProductDao { diff --git a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductLadderDao.java b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductLadderDao.java index 48b909f..ef95cb8 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductLadderDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductLadderDao.java @@ -10,5 +10,8 @@ import java.util.List; * Created by macro on 2018/4/26. */ public interface PmsProductLadderDao { + /** + * 批量创建 + */ int insertList(@Param("list") List productLadderList); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductVertifyRecordDao.java b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductVertifyRecordDao.java index c17c172..71c6ce7 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/PmsProductVertifyRecordDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/PmsProductVertifyRecordDao.java @@ -6,9 +6,12 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 商品审核日志自定义Dao + * 自定义商品审核日志管理Dao * Created by macro on 2018/4/27. */ public interface PmsProductVertifyRecordDao { + /** + * 批量创建 + */ int insertList(@Param("list") List list); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/PmsSkuStockDao.java b/mall-admin/src/main/java/com/macro/mall/dao/PmsSkuStockDao.java index 9ce1896..0568474 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/PmsSkuStockDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/PmsSkuStockDao.java @@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 自定义商品sku库存Dao + * 自定义商品SKU管理Dao * Created by macro on 2018/4/26. */ public interface PmsSkuStockDao { diff --git a/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponDao.java b/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponDao.java index 3c57ad0..603c03d 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponDao.java @@ -4,9 +4,12 @@ import com.macro.mall.dto.SmsCouponParam; import org.apache.ibatis.annotations.Param; /** - * 优惠券管理自定义查询Dao + * 自定义优惠券管理Dao * Created by macro on 2018/8/29. */ public interface SmsCouponDao { + /** + * 获取优惠券详情包括绑定关系 + */ SmsCouponParam getItem(@Param("id") Long id); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductCategoryRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductCategoryRelationDao.java index 78973ab..ae5054f 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductCategoryRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductCategoryRelationDao.java @@ -6,9 +6,12 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 优惠券和商品分类关系自定义Dao + * 自定义优惠券和商品分类关系管理Dao * Created by macro on 2018/8/28. */ public interface SmsCouponProductCategoryRelationDao { + /** + * 批量创建 + */ int insertList(@Param("list")List productCategoryRelationList); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductRelationDao.java index f78531e..10d7e01 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/SmsCouponProductRelationDao.java @@ -6,9 +6,12 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 优惠券和产品关系自定义Dao + * 自定义优惠券和商品关系关系Dao * Created by macro on 2018/8/28. */ public interface SmsCouponProductRelationDao { + /** + * 批量创建 + */ int insertList(@Param("list")List productRelationList); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/SmsFlashPromotionProductRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/SmsFlashPromotionProductRelationDao.java index d574bcc..2e4b02d 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/SmsFlashPromotionProductRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/SmsFlashPromotionProductRelationDao.java @@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 限时购商品关联自定义Dao + * 自定义限时购商品关系管理Dao * Created by macro on 2018/11/16. */ public interface SmsFlashPromotionProductRelationDao { diff --git a/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminPermissionRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminPermissionRelationDao.java index b75bfe6..6493161 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminPermissionRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminPermissionRelationDao.java @@ -6,9 +6,12 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 用户权限自定义Dao + * 自定义用户权限关系管理Dao * Created by macro on 2018/10/8. */ public interface UmsAdminPermissionRelationDao { + /** + * 批量创建 + */ int insertList(@Param("list") List list); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminRoleRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminRoleRelationDao.java index eba581d..fe55396 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminRoleRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/UmsAdminRoleRelationDao.java @@ -9,7 +9,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 后台用户与角色管理自定义Dao + * 自定义后台用户与角色管理Dao * Created by macro on 2018/10/8. */ public interface UmsAdminRoleRelationDao { @@ -37,4 +37,9 @@ public interface UmsAdminRoleRelationDao { * 获取用户所有可访问资源 */ List getResourceList(@Param("adminId") Long adminId); + + /** + * 获取资源相关用户ID列表 + */ + List getAdminIdList(@Param("resourceId") Long resourceId); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/UmsRoleDao.java b/mall-admin/src/main/java/com/macro/mall/dao/UmsRoleDao.java index d38ee0b..04873d8 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/UmsRoleDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/UmsRoleDao.java @@ -7,13 +7,20 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 后台用户角色自定义Dao + * 自定义后台角色管理Dao * Created by macro on 2020/2/2. */ public interface UmsRoleDao { + /** + * 根据后台用户ID获取菜单 + */ List getMenuList(@Param("adminId") Long adminId); - + /** + * 根据角色ID获取菜单 + */ List getMenuListByRoleId(@Param("roleId") Long roleId); - + /** + * 根据角色ID获取资源 + */ List getResourceListByRoleId(@Param("roleId") Long roleId); } diff --git a/mall-admin/src/main/java/com/macro/mall/dao/UmsRolePermissionRelationDao.java b/mall-admin/src/main/java/com/macro/mall/dao/UmsRolePermissionRelationDao.java index a09882d..795d573 100644 --- a/mall-admin/src/main/java/com/macro/mall/dao/UmsRolePermissionRelationDao.java +++ b/mall-admin/src/main/java/com/macro/mall/dao/UmsRolePermissionRelationDao.java @@ -7,7 +7,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; /** - * 后台用户角色管理自定义Dao + * 自定义角色权限关系管理Dao * Created by macro on 2018/9/30. */ public interface UmsRolePermissionRelationDao { diff --git a/mall-admin/src/main/java/com/macro/mall/dto/BucketPolicyConfigDto.java b/mall-admin/src/main/java/com/macro/mall/dto/BucketPolicyConfigDto.java new file mode 100644 index 0000000..c37f898 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/dto/BucketPolicyConfigDto.java @@ -0,0 +1,31 @@ +package com.macro.mall.dto; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * Minio Bucket访问策略配置 + * Created by macro on 2020/8/11. + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Builder +public class BucketPolicyConfigDto { + + private String Version; + private List Statement; + + @Data + @EqualsAndHashCode(callSuper = false) + @Builder + public static class Statement { + private String Effect; + private String Principal; + private String Action; + private String Resource; + + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/dto/MinioUploadDto.java b/mall-admin/src/main/java/com/macro/mall/dto/MinioUploadDto.java index 1ce3980..a2769c9 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/MinioUploadDto.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/MinioUploadDto.java @@ -1,5 +1,6 @@ package com.macro.mall.dto; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -10,6 +11,8 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = false) public class MinioUploadDto { + @ApiModelProperty("文件访问URL") private String url; + @ApiModelProperty("文件名称") private String name; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OmsMoneyInfoParam.java b/mall-admin/src/main/java/com/macro/mall/dto/OmsMoneyInfoParam.java index 8d4125f..71ba001 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OmsMoneyInfoParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OmsMoneyInfoParam.java @@ -1,5 +1,6 @@ package com.macro.mall.dto; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -12,8 +13,12 @@ import java.math.BigDecimal; @Getter @Setter public class OmsMoneyInfoParam { + @ApiModelProperty("订单ID") private Long orderId; + @ApiModelProperty("运费金额") private BigDecimal freightAmount; + @ApiModelProperty("管理员后台调整订单使用的折扣金额") private BigDecimal discountAmount; + @ApiModelProperty("订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单") private Integer status; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderDetail.java b/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderDetail.java index 494fb0c..129c0f2 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderDetail.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderDetail.java @@ -3,6 +3,7 @@ package com.macro.mall.dto; import com.macro.mall.model.OmsOrder; import com.macro.mall.model.OmsOrderItem; import com.macro.mall.model.OmsOrderOperateHistory; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -15,8 +16,10 @@ import java.util.List; public class OmsOrderDetail extends OmsOrder { @Getter @Setter + @ApiModelProperty("订单商品列表") private List orderItemList; @Getter @Setter + @ApiModelProperty("订单操作记录列表") private List historyList; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderReturnApplyResult.java b/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderReturnApplyResult.java index 4d77fdd..8e43953 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderReturnApplyResult.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OmsOrderReturnApplyResult.java @@ -2,6 +2,7 @@ package com.macro.mall.dto; import com.macro.mall.model.OmsCompanyAddress; import com.macro.mall.model.OmsOrderReturnApply; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -12,5 +13,6 @@ import lombok.Setter; public class OmsOrderReturnApplyResult extends OmsOrderReturnApply { @Getter @Setter + @ApiModelProperty(value = "公司收货地址") private OmsCompanyAddress companyAddress; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OmsReceiverInfoParam.java b/mall-admin/src/main/java/com/macro/mall/dto/OmsReceiverInfoParam.java index 773f314..5bd0351 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OmsReceiverInfoParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OmsReceiverInfoParam.java @@ -1,5 +1,6 @@ package com.macro.mall.dto; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -10,13 +11,22 @@ import lombok.Setter; @Getter @Setter public class OmsReceiverInfoParam { + @ApiModelProperty(value = "订单ID") private Long orderId; + @ApiModelProperty(value = "收货人姓名") private String receiverName; + @ApiModelProperty(value = "收货人电话") private String receiverPhone; + @ApiModelProperty(value = "收货人邮编") private String receiverPostCode; + @ApiModelProperty(value = "详细地址") private String receiverDetailAddress; + @ApiModelProperty(value = "省份/直辖市") private String receiverProvince; + @ApiModelProperty(value = "城市") private String receiverCity; + @ApiModelProperty(value = "区") private String receiverRegion; + @ApiModelProperty(value = "订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单") private Integer status; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackParam.java b/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackParam.java index 202fd85..26134b8 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackParam.java @@ -1,11 +1,15 @@ package com.macro.mall.dto; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; /** * oss上传成功后的回调参数 * Created by macro on 2018/5/17. */ +@Data +@EqualsAndHashCode(callSuper = false) public class OssCallbackParam { @ApiModelProperty("请求的回调地址") private String callbackUrl; @@ -13,28 +17,4 @@ public class OssCallbackParam { private String callbackBody; @ApiModelProperty("回调时传入参数的格式,比如表单提交形式") private String callbackBodyType; - - public String getCallbackUrl() { - return callbackUrl; - } - - public void setCallbackUrl(String callbackUrl) { - this.callbackUrl = callbackUrl; - } - - public String getCallbackBody() { - return callbackBody; - } - - public void setCallbackBody(String callbackBody) { - this.callbackBody = callbackBody; - } - - public String getCallbackBodyType() { - return callbackBodyType; - } - - public void setCallbackBodyType(String callbackBodyType) { - this.callbackBodyType = callbackBodyType; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackResult.java b/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackResult.java index 3213dd0..6cf67d4 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackResult.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OssCallbackResult.java @@ -1,11 +1,15 @@ package com.macro.mall.dto; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; /** * oss上传文件的回调结果 * Created by macro on 2018/5/17. */ +@Data +@EqualsAndHashCode(callSuper = false) public class OssCallbackResult { @ApiModelProperty("文件名称") private String filename; @@ -17,44 +21,4 @@ public class OssCallbackResult { private String width; @ApiModelProperty("图片文件的高") private String height; - - public String getFilename() { - return filename; - } - - public void setFilename(String filename) { - this.filename = filename; - } - - public String getSize() { - return size; - } - - public void setSize(String size) { - this.size = size; - } - - public String getMimeType() { - return mimeType; - } - - public void setMimeType(String mimeType) { - this.mimeType = mimeType; - } - - public String getWidth() { - return width; - } - - public void setWidth(String width) { - this.width = width; - } - - public String getHeight() { - return height; - } - - public void setHeight(String height) { - this.height = height; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/OssPolicyResult.java b/mall-admin/src/main/java/com/macro/mall/dto/OssPolicyResult.java index c42dc02..c24f780 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/OssPolicyResult.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/OssPolicyResult.java @@ -1,11 +1,15 @@ package com.macro.mall.dto; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; /** * 获取OSS上传文件授权返回结果 * Created by macro on 2018/5/17. */ +@Data +@EqualsAndHashCode(callSuper = false) public class OssPolicyResult { @ApiModelProperty("访问身份验证中用到用户标识") private String accessKeyId; @@ -19,52 +23,4 @@ public class OssPolicyResult { private String host; @ApiModelProperty("上传成功后的回调设置") private String callback; - - public String getAccessKeyId() { - return accessKeyId; - } - - public void setAccessKeyId(String accessKeyId) { - this.accessKeyId = accessKeyId; - } - - public String getPolicy() { - return policy; - } - - public void setPolicy(String policy) { - this.policy = policy; - } - - public String getSignature() { - return signature; - } - - public void setSignature(String signature) { - this.signature = signature; - } - - public String getDir() { - return dir; - } - - public void setDir(String dir) { - this.dir = dir; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public String getCallback() { - return callback; - } - - public void setCallback(String callback) { - this.callback = callback; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java index 7b3df4a..e903476 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java @@ -2,6 +2,8 @@ package com.macro.mall.dto; import com.macro.mall.validator.FlagValidator; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; @@ -10,6 +12,8 @@ import javax.validation.constraints.NotEmpty; * 品牌传递参数 * Created by macro on 2018/4/26. */ +@Data +@EqualsAndHashCode(callSuper = false) public class PmsBrandParam { @ApiModelProperty(value = "品牌名称",required = true) @NotEmpty(message = "名称不能为空") @@ -32,68 +36,4 @@ public class PmsBrandParam { private String bigPic; @ApiModelProperty(value = "品牌故事") private String brandStory; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getFirstLetter() { - return firstLetter; - } - - public void setFirstLetter(String firstLetter) { - this.firstLetter = firstLetter; - } - - public Integer getSort() { - return sort; - } - - public void setSort(Integer sort) { - this.sort = sort; - } - - public Integer getFactoryStatus() { - return factoryStatus; - } - - public void setFactoryStatus(Integer factoryStatus) { - this.factoryStatus = factoryStatus; - } - - public Integer getShowStatus() { - return showStatus; - } - - public void setShowStatus(Integer showStatus) { - this.showStatus = showStatus; - } - - public String getLogo() { - return logo; - } - - public void setLogo(String logo) { - this.logo = logo; - } - - public String getBigPic() { - return bigPic; - } - - public void setBigPic(String bigPic) { - this.bigPic = bigPic; - } - - public String getBrandStory() { - return brandStory; - } - - public void setBrandStory(String brandStory) { - this.brandStory = brandStory; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeCategoryItem.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeCategoryItem.java index 9109796..550596c 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeCategoryItem.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeCategoryItem.java @@ -2,6 +2,10 @@ package com.macro.mall.dto; import com.macro.mall.model.PmsProductAttribute; import com.macro.mall.model.PmsProductAttributeCategory; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; import java.util.List; @@ -10,13 +14,8 @@ import java.util.List; * Created by macro on 2018/5/24. */ public class PmsProductAttributeCategoryItem extends PmsProductAttributeCategory { + @Getter + @Setter + @ApiModelProperty(value = "商品属性列表") private List productAttributeList; - - public List getProductAttributeList() { - return productAttributeList; - } - - public void setProductAttributeList(List productAttributeList) { - this.productAttributeList = productAttributeList; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeParam.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeParam.java index 56279b2..28b6b8b 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductAttributeParam.java @@ -2,6 +2,8 @@ package com.macro.mall.dto; import com.macro.mall.validator.FlagValidator; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; import javax.validation.constraints.NotEmpty; @@ -9,6 +11,8 @@ import javax.validation.constraints.NotEmpty; * 商品属性参数 * Created by macro on 2018/4/26. */ +@Data +@EqualsAndHashCode(callSuper = false) public class PmsProductAttributeParam { @ApiModelProperty("属性分类ID") @NotEmpty(message = "属性分类不能为空") @@ -41,92 +45,4 @@ public class PmsProductAttributeParam { @ApiModelProperty("属性的类型;0->规格;1->参数") @FlagValidator({"0","1"}) private Integer type; - - public Long getProductAttributeCategoryId() { - return productAttributeCategoryId; - } - - public void setProductAttributeCategoryId(Long productAttributeCategoryId) { - this.productAttributeCategoryId = productAttributeCategoryId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getSelectType() { - return selectType; - } - - public void setSelectType(Integer selectType) { - this.selectType = selectType; - } - - public Integer getInputType() { - return inputType; - } - - public void setInputType(Integer inputType) { - this.inputType = inputType; - } - - public String getInputList() { - return inputList; - } - - public void setInputList(String inputList) { - this.inputList = inputList; - } - - public Integer getSort() { - return sort; - } - - public void setSort(Integer sort) { - this.sort = sort; - } - - public Integer getFilterType() { - return filterType; - } - - public void setFilterType(Integer filterType) { - this.filterType = filterType; - } - - public Integer getSearchType() { - return searchType; - } - - public void setSearchType(Integer searchType) { - this.searchType = searchType; - } - - public Integer getRelatedStatus() { - return relatedStatus; - } - - public void setRelatedStatus(Integer relatedStatus) { - this.relatedStatus = relatedStatus; - } - - public Integer getHandAddStatus() { - return handAddStatus; - } - - public void setHandAddStatus(Integer handAddStatus) { - this.handAddStatus = handAddStatus; - } - - public Integer getType() { - return type; - } - - public void setType(Integer type) { - this.type = type; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryParam.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryParam.java index 4b0ea74..b560b18 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryParam.java @@ -2,6 +2,8 @@ package com.macro.mall.dto; import com.macro.mall.validator.FlagValidator; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; @@ -11,6 +13,8 @@ import java.util.List; * 添加更新产品分类的参数 * Created by macro on 2018/4/26. */ +@Data +@EqualsAndHashCode(callSuper = false) public class PmsProductCategoryParam { @ApiModelProperty("父分类的编号") private Long parentId; @@ -36,84 +40,4 @@ public class PmsProductCategoryParam { private String description; @ApiModelProperty("产品相关筛选属性集合") private List productAttributeIdList; - - public Long getParentId() { - return parentId; - } - - public void setParentId(Long parentId) { - this.parentId = parentId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getProductUnit() { - return productUnit; - } - - public void setProductUnit(String productUnit) { - this.productUnit = productUnit; - } - - public Integer getNavStatus() { - return navStatus; - } - - public void setNavStatus(Integer navStatus) { - this.navStatus = navStatus; - } - - public Integer getShowStatus() { - return showStatus; - } - - public void setShowStatus(Integer showStatus) { - this.showStatus = showStatus; - } - - public Integer getSort() { - return sort; - } - - public void setSort(Integer sort) { - this.sort = sort; - } - - public String getIcon() { - return icon; - } - - public void setIcon(String icon) { - this.icon = icon; - } - - public String getKeywords() { - return keywords; - } - - public void setKeywords(String keywords) { - this.keywords = keywords; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getProductAttributeIdList() { - return productAttributeIdList; - } - - public void setProductAttributeIdList(List productAttributeIdList) { - this.productAttributeIdList = productAttributeIdList; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryWithChildrenItem.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryWithChildrenItem.java index 7d5a990..f69f4b4 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryWithChildrenItem.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductCategoryWithChildrenItem.java @@ -1,6 +1,9 @@ package com.macro.mall.dto; import com.macro.mall.model.PmsProductCategory; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; import java.util.List; @@ -8,13 +11,8 @@ import java.util.List; * Created by macro on 2018/5/25. */ public class PmsProductCategoryWithChildrenItem extends PmsProductCategory { + @Getter + @Setter + @ApiModelProperty("子级分类") private List children; - - public List getChildren() { - return children; - } - - public void setChildren(List children) { - this.children = children; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductParam.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductParam.java index 371cb7a..1f29d1e 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductParam.java @@ -2,6 +2,8 @@ package com.macro.mall.dto; import com.macro.mall.model.*; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; import java.util.List; @@ -9,6 +11,8 @@ import java.util.List; * 创建和修改商品时使用的参数 * Created by macro on 2018/4/26. */ +@Data +@EqualsAndHashCode(callSuper = false) public class PmsProductParam extends PmsProduct{ @ApiModelProperty("商品阶梯价格设置") private List productLadderList; @@ -24,60 +28,4 @@ public class PmsProductParam extends PmsProduct{ private List subjectProductRelationList; @ApiModelProperty("优选专区和商品的关系") private List prefrenceAreaProductRelationList; - - public List getProductLadderList() { - return productLadderList; - } - - public void setProductLadderList(List productLadderList) { - this.productLadderList = productLadderList; - } - - public List getProductFullReductionList() { - return productFullReductionList; - } - - public void setProductFullReductionList(List productFullReductionList) { - this.productFullReductionList = productFullReductionList; - } - - public List getMemberPriceList() { - return memberPriceList; - } - - public void setMemberPriceList(List memberPriceList) { - this.memberPriceList = memberPriceList; - } - - public List getSkuStockList() { - return skuStockList; - } - - public void setSkuStockList(List skuStockList) { - this.skuStockList = skuStockList; - } - - public List getProductAttributeValueList() { - return productAttributeValueList; - } - - public void setProductAttributeValueList(List productAttributeValueList) { - this.productAttributeValueList = productAttributeValueList; - } - - public List getSubjectProductRelationList() { - return subjectProductRelationList; - } - - public void setSubjectProductRelationList(List subjectProductRelationList) { - this.subjectProductRelationList = subjectProductRelationList; - } - - public List getPrefrenceAreaProductRelationList() { - return prefrenceAreaProductRelationList; - } - - public void setPrefrenceAreaProductRelationList(List prefrenceAreaProductRelationList) { - this.prefrenceAreaProductRelationList = prefrenceAreaProductRelationList; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductQueryParam.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductQueryParam.java index d24907c..ccba855 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductQueryParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductQueryParam.java @@ -1,11 +1,15 @@ package com.macro.mall.dto; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; /** * 产品查询参数 * Created by macro on 2018/4/27. */ +@Data +@EqualsAndHashCode(callSuper = false) public class PmsProductQueryParam { @ApiModelProperty("上架状态") private Integer publishStatus; @@ -19,52 +23,4 @@ public class PmsProductQueryParam { private Long productCategoryId; @ApiModelProperty("商品品牌编号") private Long brandId; - - public Integer getPublishStatus() { - return publishStatus; - } - - public void setPublishStatus(Integer publishStatus) { - this.publishStatus = publishStatus; - } - - public Integer getVerifyStatus() { - return verifyStatus; - } - - public void setVerifyStatus(Integer verifyStatus) { - this.verifyStatus = verifyStatus; - } - - public String getKeyword() { - return keyword; - } - - public void setKeyword(String keyword) { - this.keyword = keyword; - } - - public String getProductSn() { - return productSn; - } - - public void setProductSn(String productSn) { - this.productSn = productSn; - } - - public Long getProductCategoryId() { - return productCategoryId; - } - - public void setProductCategoryId(Long productCategoryId) { - this.productCategoryId = productCategoryId; - } - - public Long getBrandId() { - return brandId; - } - - public void setBrandId(Long brandId) { - this.brandId = brandId; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductResult.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductResult.java index 4db7f68..7ddeecc 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsProductResult.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsProductResult.java @@ -1,18 +1,16 @@ package com.macro.mall.dto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + /** * 查询单个产品进行修改时返回的结果 * Created by macro on 2018/4/26. */ public class PmsProductResult extends PmsProductParam { - //商品所选分类的父id + @Getter + @Setter + @ApiModelProperty("商品所选分类的父id") private Long cateParentId; - - public Long getCateParentId() { - return cateParentId; - } - - public void setCateParentId(Long cateParentId) { - this.cateParentId = cateParentId; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/ProductAttrInfo.java b/mall-admin/src/main/java/com/macro/mall/dto/ProductAttrInfo.java index 6bed624..3d6218a 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/ProductAttrInfo.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/ProductAttrInfo.java @@ -1,27 +1,19 @@ package com.macro.mall.dto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + /** * 商品分类对应属性信息 * Created by macro on 2018/5/23. */ +@Data +@EqualsAndHashCode(callSuper = false) public class ProductAttrInfo { + @ApiModelProperty("商品属性ID") private Long attributeId; + @ApiModelProperty("商品属性分类ID") private Long attributeCategoryId; - - public Long getAttributeId() { - return attributeId; - } - - public void setAttributeId(Long attributeId) { - this.attributeId = attributeId; - } - - public Long getAttributeCategoryId() { - return attributeCategoryId; - } - - public void setAttributeCategoryId(Long attributeCategoryId) { - this.attributeCategoryId = attributeCategoryId; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/SmsCouponParam.java b/mall-admin/src/main/java/com/macro/mall/dto/SmsCouponParam.java index 99643cb..bc974d9 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/SmsCouponParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/SmsCouponParam.java @@ -3,6 +3,9 @@ package com.macro.mall.dto; import com.macro.mall.model.SmsCoupon; import com.macro.mall.model.SmsCouponProductCategoryRelation; import com.macro.mall.model.SmsCouponProductRelation; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; import java.util.List; @@ -11,24 +14,12 @@ import java.util.List; * Created by macro on 2018/8/28. */ public class SmsCouponParam extends SmsCoupon { - //优惠券绑定的商品 + @Getter + @Setter + @ApiModelProperty("优惠券绑定的商品") private List productRelationList; - //优惠券绑定的商品分类 + @Getter + @Setter + @ApiModelProperty("优惠券绑定的商品分类") private List productCategoryRelationList; - - public List getProductRelationList() { - return productRelationList; - } - - public void setProductRelationList(List productRelationList) { - this.productRelationList = productRelationList; - } - - public List getProductCategoryRelationList() { - return productCategoryRelationList; - } - - public void setProductCategoryRelationList(List productCategoryRelationList) { - this.productCategoryRelationList = productCategoryRelationList; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionProduct.java b/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionProduct.java index a3e5877..d9b5e7f 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionProduct.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionProduct.java @@ -2,6 +2,7 @@ package com.macro.mall.dto; import com.macro.mall.model.PmsProduct; import com.macro.mall.model.SmsFlashPromotionProductRelation; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -12,5 +13,6 @@ import lombok.Setter; public class SmsFlashPromotionProduct extends SmsFlashPromotionProductRelation{ @Getter @Setter + @ApiModelProperty("关联商品") private PmsProduct product; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionSessionDetail.java b/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionSessionDetail.java index 4d35c6d..d441f6c 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionSessionDetail.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/SmsFlashPromotionSessionDetail.java @@ -1,6 +1,7 @@ package com.macro.mall.dto; import com.macro.mall.model.SmsFlashPromotionSession; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -11,5 +12,6 @@ import lombok.Setter; public class SmsFlashPromotionSessionDetail extends SmsFlashPromotionSession { @Setter @Getter + @ApiModelProperty("商品数量") private Long productCount; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java b/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java index dc0595b..988f8a6 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java @@ -1,6 +1,8 @@ package com.macro.mall.dto; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; import javax.validation.constraints.NotEmpty; @@ -8,6 +10,8 @@ import javax.validation.constraints.NotEmpty; * 用户登录参数 * Created by macro on 2018/4/26. */ +@Data +@EqualsAndHashCode(callSuper = false) public class UmsAdminLoginParam { @ApiModelProperty(value = "用户名", required = true) @NotEmpty(message = "用户名不能为空") @@ -15,20 +19,4 @@ public class UmsAdminLoginParam { @ApiModelProperty(value = "密码", required = true) @NotEmpty(message = "密码不能为空") private String password; - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/UmsMenuNode.java b/mall-admin/src/main/java/com/macro/mall/dto/UmsMenuNode.java index 8dcb13c..ec36ada 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/UmsMenuNode.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/UmsMenuNode.java @@ -1,6 +1,7 @@ package com.macro.mall.dto; import com.macro.mall.model.UmsMenu; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -13,5 +14,6 @@ import java.util.List; @Getter @Setter public class UmsMenuNode extends UmsMenu { + @ApiModelProperty(value = "子级菜单") private List children; } diff --git a/mall-admin/src/main/java/com/macro/mall/dto/UmsPermissionNode.java b/mall-admin/src/main/java/com/macro/mall/dto/UmsPermissionNode.java index adb570d..d38fc65 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/UmsPermissionNode.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/UmsPermissionNode.java @@ -1,6 +1,7 @@ package com.macro.mall.dto; import com.macro.mall.model.UmsPermission; +import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -13,5 +14,6 @@ import java.util.List; public class UmsPermissionNode extends UmsPermission { @Getter @Setter + @ApiModelProperty(value = "子级权限") private List children; } diff --git a/mall-admin/src/main/java/com/macro/mall/service/AuthService.java b/mall-admin/src/main/java/com/macro/mall/service/AuthService.java new file mode 100644 index 0000000..e25c505 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/service/AuthService.java @@ -0,0 +1,20 @@ +package com.macro.mall.service; + +import com.macro.mall.common.api.CommonResult; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.Map; + +/** + * 认证服务远程调用 + * Created by macro on 2020/7/19. + */ +@FeignClient("mall-auth") +public interface AuthService { + + @PostMapping(value = "/oauth/token") + CommonResult getAccessToken(@RequestParam Map parameters); + +} diff --git a/mall-admin/src/main/java/com/macro/mall/service/PmsProductAttributeService.java b/mall-admin/src/main/java/com/macro/mall/service/PmsProductAttributeService.java index 76b6851..2f1b6b8 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/PmsProductAttributeService.java +++ b/mall-admin/src/main/java/com/macro/mall/service/PmsProductAttributeService.java @@ -14,8 +14,7 @@ import java.util.List; public interface PmsProductAttributeService { /** * 根据分类分页获取商品属性 - * - * @param cid 分类id + * @param cid 分类id * @param type 0->属性;2->参数 */ List getList(Long cid, Integer type, Integer pageSize, Integer pageNum); @@ -36,14 +35,8 @@ public interface PmsProductAttributeService { */ PmsProductAttribute getItem(Long id); - /** - * 批量删除商品属性 - */ @Transactional int delete(List ids); - /** - * 获取和分类相关的商品属性 - */ List getProductAttrInfo(Long productCategoryId); } diff --git a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminCacheService.java b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminCacheService.java new file mode 100644 index 0000000..030fd8c --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminCacheService.java @@ -0,0 +1,27 @@ +package com.macro.mall.service; + +import com.macro.mall.model.UmsAdmin; +import com.macro.mall.model.UmsResource; + +import java.util.List; + +/** + * 后台用户缓存操作类 + * Created by macro on 2020/3/13. + */ +public interface UmsAdminCacheService { + /** + * 删除后台用户缓存 + */ + void delAdmin(Long adminId); + + /** + * 获取缓存后台用户信息 + */ + UmsAdmin getAdmin(Long adminId); + + /** + * 设置缓存后台用户信息 + */ + void setAdmin(UmsAdmin admin); +} diff --git a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java index fc241f6..cc42c38 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java +++ b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java @@ -1,12 +1,10 @@ package com.macro.mall.service; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.domain.UserDto; import com.macro.mall.dto.UmsAdminParam; import com.macro.mall.dto.UpdateAdminPasswordParam; -import com.macro.mall.model.UmsAdmin; -import com.macro.mall.model.UmsPermission; -import com.macro.mall.model.UmsResource; -import com.macro.mall.model.UmsRole; -import org.springframework.security.core.userdetails.UserDetails; +import com.macro.mall.model.*; import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -30,15 +28,9 @@ public interface UmsAdminService { * 登录功能 * @param username 用户名 * @param password 密码 - * @return 生成的JWT的token + * @return 调用认证中心返回结果 */ - String login(String username,String password); - - /** - * 刷新token的功能 - * @param oldToken 旧的token - */ - String refreshToken(String oldToken); + CommonResult login(String username, String password); /** * 根据用户id获取用户 @@ -95,5 +87,10 @@ public interface UmsAdminService { /** * 获取用户信息 */ - UserDetails loadUserByUsername(String username); + UserDto loadUserByUsername(String username); + + /** + * 获取当前登录后台用户 + */ + UmsAdmin getCurrentAdmin(); } diff --git a/mall-admin/src/main/java/com/macro/mall/service/UmsResourceService.java b/mall-admin/src/main/java/com/macro/mall/service/UmsResourceService.java index 131c555..33a1dc4 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/UmsResourceService.java +++ b/mall-admin/src/main/java/com/macro/mall/service/UmsResourceService.java @@ -3,6 +3,7 @@ package com.macro.mall.service; import com.macro.mall.model.UmsResource; import java.util.List; +import java.util.Map; /** * 后台资源管理Service @@ -38,4 +39,9 @@ public interface UmsResourceService { * 查询全部资源 */ List listAll(); + + /** + * 初始化资源角色规则 + */ + Map> initResourceRolesMap(); } diff --git a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminCacheServiceImpl.java b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminCacheServiceImpl.java new file mode 100644 index 0000000..16b45ad --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminCacheServiceImpl.java @@ -0,0 +1,45 @@ +package com.macro.mall.service.impl; + +import com.macro.mall.common.service.RedisService; +import com.macro.mall.model.UmsAdmin; +import com.macro.mall.service.UmsAdminCacheService; +import com.macro.mall.service.UmsAdminService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * UmsAdminCacheService实现类 + * Created by macro on 2020/3/13. + */ +@Service +public class UmsAdminCacheServiceImpl implements UmsAdminCacheService { + @Autowired + private UmsAdminService adminService; + @Autowired + private RedisService redisService; + @Value("${redis.database}") + private String REDIS_DATABASE; + @Value("${redis.expire.common}") + private Long REDIS_EXPIRE; + @Value("${redis.key.admin}") + private String REDIS_KEY_ADMIN; + + @Override + public void delAdmin(Long adminId) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + adminId; + redisService.del(key); + } + + @Override + public UmsAdmin getAdmin(Long adminId) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + adminId; + return (UmsAdmin) redisService.get(key); + } + + @Override + public void setAdmin(UmsAdmin admin) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + admin.getId(); + redisService.set(key, admin, REDIS_EXPIRE); + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java index 484a8f0..5f675f4 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java +++ b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java @@ -2,8 +2,14 @@ package com.macro.mall.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.BCrypt; +import cn.hutool.json.JSONUtil; import com.github.pagehelper.PageHelper; -import com.macro.mall.bo.AdminUserDetails; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.api.ResultCode; +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.common.domain.UserDto; +import com.macro.mall.common.exception.Asserts; import com.macro.mall.dao.UmsAdminPermissionRelationDao; import com.macro.mall.dao.UmsAdminRoleRelationDao; import com.macro.mall.dto.UmsAdminParam; @@ -13,19 +19,13 @@ import com.macro.mall.mapper.UmsAdminMapper; import com.macro.mall.mapper.UmsAdminPermissionRelationMapper; import com.macro.mall.mapper.UmsAdminRoleRelationMapper; import com.macro.mall.model.*; -import com.macro.mall.security.util.JwtTokenUtil; +import com.macro.mall.service.AuthService; +import com.macro.mall.service.UmsAdminCacheService; import com.macro.mall.service.UmsAdminService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -33,9 +33,7 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -46,10 +44,6 @@ import java.util.stream.Collectors; public class UmsAdminServiceImpl implements UmsAdminService { private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class); @Autowired - private JwtTokenUtil jwtTokenUtil; - @Autowired - private PasswordEncoder passwordEncoder; - @Autowired private UmsAdminMapper adminMapper; @Autowired private UmsAdminRoleRelationMapper adminRoleRelationMapper; @@ -61,6 +55,12 @@ public class UmsAdminServiceImpl implements UmsAdminService { private UmsAdminPermissionRelationDao adminPermissionRelationDao; @Autowired private UmsAdminLoginLogMapper loginLogMapper; + @Autowired + private AuthService authService; + @Autowired + private UmsAdminCacheService adminCacheService; + @Autowired + private HttpServletRequest request; @Override public UmsAdmin getAdminByUsername(String username) { @@ -87,30 +87,29 @@ public class UmsAdminServiceImpl implements UmsAdminService { return null; } //将密码进行加密操作 - String encodePassword = passwordEncoder.encode(umsAdmin.getPassword()); + String encodePassword = BCrypt.hashpw(umsAdmin.getPassword()); umsAdmin.setPassword(encodePassword); adminMapper.insert(umsAdmin); return umsAdmin; } @Override - public String login(String username, String password) { - String token = null; - //密码需要客户端加密后传递 - try { - UserDetails userDetails = loadUserByUsername(username); - if(!passwordEncoder.matches(password,userDetails.getPassword())){ - throw new BadCredentialsException("密码不正确"); - } - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - token = jwtTokenUtil.generateToken(userDetails); + public CommonResult login(String username, String password) { + if(StrUtil.isEmpty(username)||StrUtil.isEmpty(password)){ + Asserts.fail("用户名或密码不能为空!"); + } + Map params = new HashMap<>(); + params.put("client_id", AuthConstant.ADMIN_CLIENT_ID); + params.put("client_secret","123456"); + params.put("grant_type","password"); + params.put("username",username); + params.put("password",password); + CommonResult restResult = authService.getAccessToken(params); + if(ResultCode.SUCCESS.getCode()==restResult.getCode()&&restResult.getData()!=null){ // updateLoginTimeByUsername(username); insertLoginLog(username); - } catch (AuthenticationException e) { - LOGGER.warn("登录异常:{}", e.getMessage()); } - return token; + return restResult; } /** @@ -119,6 +118,7 @@ public class UmsAdminServiceImpl implements UmsAdminService { */ private void insertLoginLog(String username) { UmsAdmin admin = getAdminByUsername(username); + if(admin==null) return; UmsAdminLoginLog loginLog = new UmsAdminLoginLog(); loginLog.setAdminId(admin.getId()); loginLog.setCreateTime(new Date()); @@ -139,11 +139,6 @@ public class UmsAdminServiceImpl implements UmsAdminService { adminMapper.updateByExampleSelective(record, example); } - @Override - public String refreshToken(String oldToken) { - return jwtTokenUtil.refreshHeadToken(oldToken); - } - @Override public UmsAdmin getItem(Long id) { return adminMapper.selectByPrimaryKey(id); @@ -173,15 +168,19 @@ public class UmsAdminServiceImpl implements UmsAdminService { if(StrUtil.isEmpty(admin.getPassword())){ admin.setPassword(null); }else{ - admin.setPassword(passwordEncoder.encode(admin.getPassword())); + admin.setPassword(BCrypt.hashpw(admin.getPassword())); } } - return adminMapper.updateByPrimaryKeySelective(admin); + int count = adminMapper.updateByPrimaryKeySelective(admin); + adminCacheService.delAdmin(id); + return count; } @Override public int delete(Long id) { - return adminMapper.deleteByPrimaryKey(id); + int count = adminMapper.deleteByPrimaryKey(id); + adminCacheService.delAdmin(id); + return count; } @Override @@ -271,22 +270,46 @@ public class UmsAdminServiceImpl implements UmsAdminService { return -2; } UmsAdmin umsAdmin = adminList.get(0); - if(!passwordEncoder.matches(param.getOldPassword(),umsAdmin.getPassword())){ + if(!BCrypt.checkpw(param.getOldPassword(),umsAdmin.getPassword())){ return -3; } - umsAdmin.setPassword(passwordEncoder.encode(param.getNewPassword())); + umsAdmin.setPassword(BCrypt.hashpw(param.getNewPassword())); adminMapper.updateByPrimaryKey(umsAdmin); + adminCacheService.delAdmin(umsAdmin.getId()); return 1; } @Override - public UserDetails loadUserByUsername(String username){ + public UserDto loadUserByUsername(String username){ //获取用户信息 UmsAdmin admin = getAdminByUsername(username); if (admin != null) { - List resourceList = getResourceList(admin.getId()); - return new AdminUserDetails(admin,resourceList); + List roleList = getRoleList(admin.getId()); + UserDto userDTO = new UserDto(); + BeanUtils.copyProperties(admin,userDTO); + if(CollUtil.isNotEmpty(roleList)){ + List roleStrList = roleList.stream().map(item -> item.getId() + "_" + item.getName()).collect(Collectors.toList()); + userDTO.setRoles(roleStrList); + } + return userDTO; + } + return null; + } + + @Override + public UmsAdmin getCurrentAdmin() { + String userStr = request.getHeader(AuthConstant.USER_TOKEN_HEADER); + if(StrUtil.isEmpty(userStr)){ + Asserts.fail(ResultCode.UNAUTHORIZED); + } + UserDto userDto = JSONUtil.toBean(userStr, UserDto.class); + UmsAdmin admin = adminCacheService.getAdmin(userDto.getId()); + if(admin!=null){ + return admin; + }else{ + admin = adminMapper.selectByPrimaryKey(userDto.getId()); + adminCacheService.setAdmin(admin); + return admin; } - throw new UsernameNotFoundException("用户名或密码错误"); } } diff --git a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsResourceServiceImpl.java b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsResourceServiceImpl.java index 4d866c0..44f517f 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsResourceServiceImpl.java +++ b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsResourceServiceImpl.java @@ -2,15 +2,20 @@ package com.macro.mall.service.impl; import cn.hutool.core.util.StrUtil; import com.github.pagehelper.PageHelper; +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.common.service.RedisService; import com.macro.mall.mapper.UmsResourceMapper; -import com.macro.mall.model.UmsResource; -import com.macro.mall.model.UmsResourceExample; +import com.macro.mall.mapper.UmsRoleMapper; +import com.macro.mall.mapper.UmsRoleResourceRelationMapper; +import com.macro.mall.model.*; +import com.macro.mall.service.UmsAdminCacheService; import com.macro.mall.service.UmsResourceService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.Date; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; /** * 后台资源管理Service实现类 @@ -20,16 +25,28 @@ import java.util.List; public class UmsResourceServiceImpl implements UmsResourceService { @Autowired private UmsResourceMapper resourceMapper; + @Autowired + private UmsRoleMapper roleMapper; + @Autowired + private UmsRoleResourceRelationMapper roleResourceRelationMapper; + @Autowired + private RedisService redisService; + @Value("${spring.application.name}") + private String applicationName; @Override public int create(UmsResource umsResource) { umsResource.setCreateTime(new Date()); - return resourceMapper.insert(umsResource); + int count = resourceMapper.insert(umsResource); + initResourceRolesMap(); + return count; } @Override public int update(Long id, UmsResource umsResource) { umsResource.setId(id); - return resourceMapper.updateByPrimaryKeySelective(umsResource); + int count = resourceMapper.updateByPrimaryKeySelective(umsResource); + initResourceRolesMap(); + return count; } @Override @@ -39,7 +56,9 @@ public class UmsResourceServiceImpl implements UmsResourceService { @Override public int delete(Long id) { - return resourceMapper.deleteByPrimaryKey(id); + int count = resourceMapper.deleteByPrimaryKey(id); + initResourceRolesMap(); + return count; } @Override @@ -63,4 +82,21 @@ public class UmsResourceServiceImpl implements UmsResourceService { public List listAll() { return resourceMapper.selectByExample(new UmsResourceExample()); } + + @Override + public Map> initResourceRolesMap() { + Map> resourceRoleMap = new TreeMap<>(); + List resourceList = resourceMapper.selectByExample(new UmsResourceExample()); + List roleList = roleMapper.selectByExample(new UmsRoleExample()); + List relationList = roleResourceRelationMapper.selectByExample(new UmsRoleResourceRelationExample()); + for (UmsResource resource : resourceList) { + Set roleIds = relationList.stream().filter(item -> item.getResourceId().equals(resource.getId())).map(UmsRoleResourceRelation::getRoleId).collect(Collectors.toSet()); + List roleNames = roleList.stream().filter(item -> roleIds.contains(item.getId())).map(item -> item.getId() + "_" + item.getName()).collect(Collectors.toList()); + resourceRoleMap.put("/"+applicationName+resource.getUrl(),roleNames); + } + redisService.del(AuthConstant.RESOURCE_ROLES_MAP_KEY); + redisService.hSetAll(AuthConstant.RESOURCE_ROLES_MAP_KEY, resourceRoleMap); + return resourceRoleMap; + + } } diff --git a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsRoleServiceImpl.java b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsRoleServiceImpl.java index ddd9230..879099c 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsRoleServiceImpl.java +++ b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsRoleServiceImpl.java @@ -8,6 +8,8 @@ import com.macro.mall.mapper.UmsRoleMenuRelationMapper; import com.macro.mall.mapper.UmsRolePermissionRelationMapper; import com.macro.mall.mapper.UmsRoleResourceRelationMapper; import com.macro.mall.model.*; +import com.macro.mall.service.UmsAdminCacheService; +import com.macro.mall.service.UmsResourceService; import com.macro.mall.service.UmsRoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -35,6 +37,8 @@ public class UmsRoleServiceImpl implements UmsRoleService { private UmsRolePermissionRelationDao rolePermissionRelationDao; @Autowired private UmsRoleDao roleDao; + @Autowired + private UmsResourceService resourceService; @Override public int create(UmsRole role) { role.setCreateTime(new Date()); @@ -53,7 +57,9 @@ public class UmsRoleServiceImpl implements UmsRoleService { public int delete(List ids) { UmsRoleExample example = new UmsRoleExample(); example.createCriteria().andIdIn(ids); - return roleMapper.deleteByExample(example); + int count = roleMapper.deleteByExample(example); + resourceService.initResourceRolesMap(); + return count; } @Override @@ -137,6 +143,7 @@ public class UmsRoleServiceImpl implements UmsRoleService { relation.setResourceId(resourceId); roleResourceRelationMapper.insert(relation); } + resourceService.initResourceRolesMap(); return resourceIds.size(); } } diff --git a/mall-admin/src/main/resources/application.yml b/mall-admin/src/main/resources/application.yml index 09139a7..93213fb 100644 --- a/mall-admin/src/main/resources/application.yml +++ b/mall-admin/src/main/resources/application.yml @@ -1,5 +1,5 @@ server: - port: 8180 + port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai @@ -14,6 +14,12 @@ spring: stat-view-servlet: #访问监控网页的登录用户名和密码 login-username: druid login-password: druid + redis: + host: localhost # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: # Redis服务器连接密码(默认为空) + timeout: 3000ms # 连接超时时间(毫秒) rabbitmq: #rabbitmq相关配置 host: localhost port: 5672 @@ -35,30 +41,12 @@ management: #开启SpringBoot Admin的监控 endpoint: health: show-details: always -jwt: - tokenHeader: Authorization #JWT存储的请求头 - secret: mall-admin-secret #JWT加解密使用的密钥 - expiration: 604800 #JWT的超期限时间(60*60*24) - tokenHead: Bearer #JWT负载中拿到开头 -secure: - ignored: - urls: #安全路径白名单 - - /swagger-ui.html - - /swagger-resources/** - - /swagger/** - - /**/v2/api-docs - - /**/*.js - - /**/*.css - - /**/*.png - - /**/*.ico - - /webjars/springfox-swagger-ui/** - - /actuator/** - - /druid/** - - /admin/login - - /admin/register - - /admin/info - - /admin/logout - - /minio/upload +redis: + database: mall + key: + admin: 'ums:admin' + expire: + common: 86400 # 24小时 aliyun: oss: endpoint: oss-cn-shenzhen.aliyuncs.com # oss对外服务的访问域名 @@ -75,4 +63,10 @@ minio: endpoint: http://192.168.6.132:9090 #MinIO服务所在地址 bucketName: mall #存储桶名称 accessKey: minioadmin #访问的key - secretKey: minioadmin #访问的秘钥 \ No newline at end of file + secretKey: minioadmin #访问的秘钥 +feign: + okhttp: + enabled: true +ribbon: + ConnectTimeout: 3000 #服务请求连接超时时间(毫秒) + ReadTimeout: 3000 #服务请求处理超时时间(毫秒) \ No newline at end of file diff --git a/mall-admin/src/main/resources/bootstrap-dev.yml b/mall-admin/src/main/resources/bootstrap-dev.yml index d35a60c..365fbba 100644 --- a/mall-admin/src/main/resources/bootstrap-dev.yml +++ b/mall-admin/src/main/resources/bootstrap-dev.yml @@ -1,13 +1,8 @@ spring: cloud: - config: - profile: dev #启用环境名称 - label: master #分支名称 - name: admin #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ \ No newline at end of file + server-addr: http://localhost:8848 + config: + server-addr: http://localhost:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-admin/src/main/resources/bootstrap-prod.yml b/mall-admin/src/main/resources/bootstrap-prod.yml index 14e897e..fc71e7a 100644 --- a/mall-admin/src/main/resources/bootstrap-prod.yml +++ b/mall-admin/src/main/resources/bootstrap-prod.yml @@ -1,15 +1,8 @@ spring: cloud: - config: - profile: prod #启用环境名称 - label: master #分支名称 - name: admin #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - instance: - prefer-ip-address: true \ No newline at end of file + server-addr: http://nacos-registry:8848 + config: + server-addr: http://nacos-registry:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-admin/src/main/resources/dao/UmsAdminRoleRelationDao.xml b/mall-admin/src/main/resources/dao/UmsAdminRoleRelationDao.xml index 6b1ec7d..badc580 100644 --- a/mall-admin/src/main/resources/dao/UmsAdminRoleRelationDao.xml +++ b/mall-admin/src/main/resources/dao/UmsAdminRoleRelationDao.xml @@ -71,4 +71,12 @@ GROUP BY ur.id + \ No newline at end of file diff --git a/mall-admin/src/main/resources/logback-spring.xml b/mall-admin/src/main/resources/logback-spring.xml deleted file mode 100644 index a86c84c..0000000 --- a/mall-admin/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - ${APP_NAME} - - - - ${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log - 30 - - - ${FILE_LOG_PATTERN} - - - - - localhost:4560 - - - - - - - - - diff --git a/mall-config/pom.xml b/mall-auth/pom.xml similarity index 54% rename from mall-config/pom.xml rename to mall-auth/pom.xml index b8db18b..cacc678 100644 --- a/mall-config/pom.xml +++ b/mall-auth/pom.xml @@ -1,13 +1,16 @@ - + 4.0.0 com.macro.mall - mall-config + mall-auth 1.0-SNAPSHOT - mall-config - mall-config project for mall + jar + + mall-auth + mall-auth project for mall com.macro.mall @@ -17,12 +20,46 @@ - org.springframework.cloud - spring-cloud-config-server + com.macro.mall + mall-common + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.springframework.boot + spring-boot-starter-web + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + org.springframework.boot + spring-boot-starter-security org.springframework.cloud - spring-cloud-starter-netflix-eureka-client + spring-cloud-starter-oauth2 + + + com.nimbusds + nimbus-jose-jwt + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + io.github.openfeign + feign-okhttp @@ -62,4 +99,4 @@ - + \ No newline at end of file diff --git a/mall-config/src/main/java/com/macro/mall/MallConfigApplication.java b/mall-auth/src/main/java/com/macro/mall/auth/MallAuthApplication.java similarity index 50% rename from mall-config/src/main/java/com/macro/mall/MallConfigApplication.java rename to mall-auth/src/main/java/com/macro/mall/auth/MallAuthApplication.java index 2c6c13d..8c6cda8 100644 --- a/mall-config/src/main/java/com/macro/mall/MallConfigApplication.java +++ b/mall-auth/src/main/java/com/macro/mall/auth/MallAuthApplication.java @@ -1,17 +1,17 @@ -package com.macro.mall; +package com.macro.mall.auth; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.config.server.EnableConfigServer; +import org.springframework.cloud.openfeign.EnableFeignClients; -@EnableConfigServer +@EnableFeignClients @EnableDiscoveryClient -@SpringBootApplication -public class MallConfigApplication { +@SpringBootApplication(scanBasePackages = "com.macro.mall") +public class MallAuthApplication { public static void main(String[] args) { - SpringApplication.run(MallConfigApplication.class, args); + SpringApplication.run(MallAuthApplication.class, args); } } diff --git a/mall-auth/src/main/java/com/macro/mall/auth/component/JwtTokenEnhancer.java b/mall-auth/src/main/java/com/macro/mall/auth/component/JwtTokenEnhancer.java new file mode 100644 index 0000000..c6b9e80 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/component/JwtTokenEnhancer.java @@ -0,0 +1,29 @@ +package com.macro.mall.auth.component; + +import com.macro.mall.auth.domain.SecurityUser; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * JWT内容增强器 + * Created by macro on 2020/6/19. + */ +@Component +public class JwtTokenEnhancer implements TokenEnhancer { + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + SecurityUser securityUser = (SecurityUser) authentication.getPrincipal(); + Map info = new HashMap<>(); + //把用户ID设置到JWT中 + info.put("id", securityUser.getId()); + info.put("client_id",securityUser.getClientId()); + ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info); + return accessToken; + } +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/config/Oauth2ServerConfig.java b/mall-auth/src/main/java/com/macro/mall/auth/config/Oauth2ServerConfig.java new file mode 100644 index 0000000..ae90217 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/config/Oauth2ServerConfig.java @@ -0,0 +1,89 @@ +package com.macro.mall.auth.config; + +import com.macro.mall.auth.component.JwtTokenEnhancer; +import com.macro.mall.auth.service.impl.UserServiceImpl; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.rsa.crypto.KeyStoreKeyFactory; + +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.List; + +/** + * 认证服务器配置 + * Created by macro on 2020/6/19. + */ +@AllArgsConstructor +@Configuration +@EnableAuthorizationServer +public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter { + + private final PasswordEncoder passwordEncoder; + private final UserServiceImpl userDetailsService; + private final AuthenticationManager authenticationManager; + private final JwtTokenEnhancer jwtTokenEnhancer; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory() + .withClient("admin-app") + .secret(passwordEncoder.encode("123456")) + .scopes("all") + .authorizedGrantTypes("password", "refresh_token") + .accessTokenValiditySeconds(3600) + .refreshTokenValiditySeconds(86400) + .and() + .withClient("portal-app") + .secret(passwordEncoder.encode("123456")) + .scopes("all") + .authorizedGrantTypes("password", "refresh_token") + .accessTokenValiditySeconds(3600) + .refreshTokenValiditySeconds(86400); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); + List delegates = new ArrayList<>(); + delegates.add(jwtTokenEnhancer); + delegates.add(accessTokenConverter()); + enhancerChain.setTokenEnhancers(delegates); //配置JWT的内容增强器 + endpoints.authenticationManager(authenticationManager) + .userDetailsService(userDetailsService) //配置加载用户信息的服务 + .accessTokenConverter(accessTokenConverter()) + .tokenEnhancer(enhancerChain); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + security.allowFormAuthenticationForClients(); + } + + @Bean + public JwtAccessTokenConverter accessTokenConverter() { + JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); + jwtAccessTokenConverter.setKeyPair(keyPair()); + return jwtAccessTokenConverter; + } + + @Bean + public KeyPair keyPair() { + //从classpath下的证书中获取秘钥对 + KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray()); + return keyStoreKeyFactory.getKeyPair("jwt", "123456".toCharArray()); + } + +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/config/SwaggerConfig.java b/mall-auth/src/main/java/com/macro/mall/auth/config/SwaggerConfig.java new file mode 100644 index 0000000..4de6626 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/config/SwaggerConfig.java @@ -0,0 +1,27 @@ +package com.macro.mall.auth.config; + +import com.macro.mall.common.config.BaseSwaggerConfig; +import com.macro.mall.common.domain.SwaggerProperties; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * Swagger API文档相关配置 + * Created by macro on 2018/4/26. + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig extends BaseSwaggerConfig { + + @Override + public SwaggerProperties swaggerProperties() { + return SwaggerProperties.builder() + .apiBasePackage("com.macro.mall.auth.controller") + .title("mall认证中心") + .description("mall认证中心相关接口文档") + .contactName("macro") + .version("1.0") + .enableSecurity(true) + .build(); + } +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/config/WebSecurityConfig.java b/mall-auth/src/main/java/com/macro/mall/auth/config/WebSecurityConfig.java new file mode 100644 index 0000000..537f831 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/config/WebSecurityConfig.java @@ -0,0 +1,41 @@ +package com.macro.mall.auth.config; + +import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * SpringSecurity配置 + * Created by macro on 2020/6/19. + */ +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll() + .antMatchers("/rsa/publicKey").permitAll() + .antMatchers("/v2/api-docs").permitAll() + .anyRequest().authenticated(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/constant/MessageConstant.java b/mall-auth/src/main/java/com/macro/mall/auth/constant/MessageConstant.java new file mode 100644 index 0000000..a2f9738 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/constant/MessageConstant.java @@ -0,0 +1,23 @@ +package com.macro.mall.auth.constant; + +/** + * 消息常量 + * Created by macro on 2020/6/19. + */ +public class MessageConstant { + + public static final String LOGIN_SUCCESS = "登录成功!"; + + public static final String USERNAME_PASSWORD_ERROR = "用户名或密码错误!"; + + public static final String CREDENTIALS_EXPIRED = "该账户的登录凭证已过期,请重新登录!"; + + public static final String ACCOUNT_DISABLED = "该账户已被禁用,请联系管理员!"; + + public static final String ACCOUNT_LOCKED = "该账号已被锁定,请联系管理员!"; + + public static final String ACCOUNT_EXPIRED = "该账号已过期,请联系管理员!"; + + public static final String PERMISSION_DENIED = "没有访问权限,请联系管理员!"; + +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/controller/AuthController.java b/mall-auth/src/main/java/com/macro/mall/auth/controller/AuthController.java new file mode 100644 index 0000000..3aa8865 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/controller/AuthController.java @@ -0,0 +1,55 @@ +package com.macro.mall.auth.controller; + +import com.macro.mall.auth.domain.Oauth2TokenDto; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.constant.AuthConstant; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.annotations.ApiIgnore; + +import java.security.Principal; +import java.util.Map; + +/** + * 自定义Oauth2获取令牌接口 + * Created by macro on 2020/7/17. + */ +@RestController +@Api(tags = "AuthController", description = "认证中心登录认证") +@RequestMapping("/oauth") +public class AuthController { + + @Autowired + private TokenEndpoint tokenEndpoint; + + @ApiOperation("Oauth2获取token") + @ApiImplicitParams({ + @ApiImplicitParam(name = "grant_type", value = "授权模式", required = true), + @ApiImplicitParam(name = "client_id", value = "Oauth2客户端ID", required = true), + @ApiImplicitParam(name = "client_secret", value = "Oauth2客户端秘钥", required = true), + @ApiImplicitParam(name = "refresh_token", value = "刷新token"), + @ApiImplicitParam(name = "username", value = "登录用户名"), + @ApiImplicitParam(name = "password", value = "登录密码") + }) + @RequestMapping(value = "/token", method = RequestMethod.POST) + public CommonResult postAccessToken(@ApiIgnore Principal principal, @ApiIgnore @RequestParam Map parameters) throws HttpRequestMethodNotSupportedException { + OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody(); + Oauth2TokenDto oauth2TokenDto = Oauth2TokenDto.builder() + .token(oAuth2AccessToken.getValue()) + .refreshToken(oAuth2AccessToken.getRefreshToken().getValue()) + .expiresIn(oAuth2AccessToken.getExpiresIn()) + .tokenHead(AuthConstant.JWT_TOKEN_PREFIX).build(); + + return CommonResult.success(oauth2TokenDto); + } +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/controller/KeyPairController.java b/mall-auth/src/main/java/com/macro/mall/auth/controller/KeyPairController.java new file mode 100644 index 0000000..c21c1a2 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/controller/KeyPairController.java @@ -0,0 +1,30 @@ +package com.macro.mall.auth.controller; + +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.jwk.RSAKey; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.KeyPair; +import java.security.interfaces.RSAPublicKey; +import java.util.Map; + +/** + * 获取RSA公钥接口 + * Created by macro on 2020/6/19. + */ +@RestController +public class KeyPairController { + + @Autowired + private KeyPair keyPair; + + @GetMapping("/rsa/publicKey") + public Map getKey() { + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + RSAKey key = new RSAKey.Builder(publicKey).build(); + return new JWKSet(key).toJSONObject(); + } + +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/domain/Oauth2TokenDto.java b/mall-auth/src/main/java/com/macro/mall/auth/domain/Oauth2TokenDto.java new file mode 100644 index 0000000..8464b15 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/domain/Oauth2TokenDto.java @@ -0,0 +1,24 @@ +package com.macro.mall.auth.domain; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * Oauth2获取Token返回信息封装 + * Created by macro on 2020/7/17. + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Builder +public class Oauth2TokenDto { + @ApiModelProperty("访问令牌") + private String token; + @ApiModelProperty("刷令牌") + private String refreshToken; + @ApiModelProperty("访问令牌头前缀") + private String tokenHead; + @ApiModelProperty("有效时间(秒)") + private int expiresIn; +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/domain/SecurityUser.java b/mall-auth/src/main/java/com/macro/mall/auth/domain/SecurityUser.java new file mode 100644 index 0000000..c07017e --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/domain/SecurityUser.java @@ -0,0 +1,95 @@ +package com.macro.mall.auth.domain; + +import com.macro.mall.common.domain.UserDto; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * 登录用户信息 + * Created by macro on 2020/6/19. + */ +@Data +public class SecurityUser implements UserDetails { + + /** + * ID + */ + private Long id; + /** + * 用户名 + */ + private String username; + /** + * 用户密码 + */ + private String password; + /** + * 用户状态 + */ + private Boolean enabled; + /** + * 登录客户端ID + */ + private String clientId; + /** + * 权限数据 + */ + private Collection authorities; + + public SecurityUser() { + + } + + public SecurityUser(UserDto userDto) { + this.setId(userDto.getId()); + this.setUsername(userDto.getUsername()); + this.setPassword(userDto.getPassword()); + this.setEnabled(userDto.getStatus() == 1); + this.setClientId(userDto.getClientId()); + if (userDto.getRoles() != null) { + authorities = new ArrayList<>(); + userDto.getRoles().forEach(item -> authorities.add(new SimpleGrantedAuthority(item))); + } + } + + @Override + public Collection getAuthorities() { + return this.authorities; + } + + @Override + public String getPassword() { + return this.password; + } + + @Override + public String getUsername() { + return this.username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/exception/Oauth2ExceptionHandler.java b/mall-auth/src/main/java/com/macro/mall/auth/exception/Oauth2ExceptionHandler.java new file mode 100644 index 0000000..f237a4d --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/exception/Oauth2ExceptionHandler.java @@ -0,0 +1,20 @@ +package com.macro.mall.auth.exception; + +import com.macro.mall.common.api.CommonResult; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * 全局处理Oauth2抛出的异常 + * Created by macro on 2020/7/17. + */ +@ControllerAdvice +public class Oauth2ExceptionHandler { + @ResponseBody + @ExceptionHandler(value = OAuth2Exception.class) + public CommonResult handleOauth2(OAuth2Exception e) { + return CommonResult.failed(e.getMessage()); + } +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/service/UmsAdminService.java b/mall-auth/src/main/java/com/macro/mall/auth/service/UmsAdminService.java new file mode 100644 index 0000000..e386fb7 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/service/UmsAdminService.java @@ -0,0 +1,16 @@ +package com.macro.mall.auth.service; + +import com.macro.mall.common.domain.UserDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * Created by macro on 2019/10/18. + */ +@FeignClient("mall-admin") +public interface UmsAdminService { + + @GetMapping("/admin/loadByUsername") + UserDto loadUserByUsername(@RequestParam String username); +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/service/UmsMemberService.java b/mall-auth/src/main/java/com/macro/mall/auth/service/UmsMemberService.java new file mode 100644 index 0000000..25fb689 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/service/UmsMemberService.java @@ -0,0 +1,15 @@ +package com.macro.mall.auth.service; + +import com.macro.mall.common.domain.UserDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * Created by macro on 2020/7/16. + */ +@FeignClient("mall-portal") +public interface UmsMemberService { + @GetMapping("/sso/loadByUsername") + UserDto loadUserByUsername(@RequestParam String username); +} diff --git a/mall-auth/src/main/java/com/macro/mall/auth/service/impl/UserServiceImpl.java b/mall-auth/src/main/java/com/macro/mall/auth/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..4563988 --- /dev/null +++ b/mall-auth/src/main/java/com/macro/mall/auth/service/impl/UserServiceImpl.java @@ -0,0 +1,61 @@ +package com.macro.mall.auth.service.impl; + +import com.macro.mall.auth.domain.SecurityUser; +import com.macro.mall.auth.constant.MessageConstant; +import com.macro.mall.auth.service.UmsAdminService; +import com.macro.mall.auth.service.UmsMemberService; +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.common.domain.UserDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.authentication.CredentialsExpiredException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + * 用户管理业务类 + * Created by macro on 2020/6/19. + */ +@Service +public class UserServiceImpl implements UserDetailsService { + + @Autowired + private UmsAdminService adminService; + @Autowired + private UmsMemberService memberService; + @Autowired + private HttpServletRequest request; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + String clientId = request.getParameter("client_id"); + UserDto userDto; + if(AuthConstant.ADMIN_CLIENT_ID.equals(clientId)){ + userDto = adminService.loadUserByUsername(username); + }else{ + userDto = memberService.loadUserByUsername(username); + } + if (userDto==null) { + throw new UsernameNotFoundException(MessageConstant.USERNAME_PASSWORD_ERROR); + } + userDto.setClientId(clientId); + SecurityUser securityUser = new SecurityUser(userDto); + if (!securityUser.isEnabled()) { + throw new DisabledException(MessageConstant.ACCOUNT_DISABLED); + } else if (!securityUser.isAccountNonLocked()) { + throw new LockedException(MessageConstant.ACCOUNT_LOCKED); + } else if (!securityUser.isAccountNonExpired()) { + throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED); + } else if (!securityUser.isCredentialsNonExpired()) { + throw new CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED); + } + return securityUser; + } + +} diff --git a/mall-auth/src/main/resources/application.yml b/mall-auth/src/main/resources/application.yml new file mode 100644 index 0000000..b66c00d --- /dev/null +++ b/mall-auth/src/main/resources/application.yml @@ -0,0 +1,13 @@ +server: + port: 8401 +management: + endpoints: + web: + exposure: + include: "*" +feign: + okhttp: + enabled: true +ribbon: + ConnectTimeout: 3000 #服务请求连接超时时间(毫秒) + ReadTimeout: 3000 #服务请求处理超时时间(毫秒) diff --git a/mall-auth/src/main/resources/bootstrap-dev.yml b/mall-auth/src/main/resources/bootstrap-dev.yml new file mode 100644 index 0000000..d9d496a --- /dev/null +++ b/mall-auth/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,11 @@ +spring: + cloud: + nacos: + discovery: + server-addr: http://localhost:8848 + config: + server-addr: http://localhost:8848 + file-extension: yaml +logging: + level: + root: debug \ No newline at end of file diff --git a/mall-auth/src/main/resources/bootstrap-prod.yml b/mall-auth/src/main/resources/bootstrap-prod.yml new file mode 100644 index 0000000..15564b9 --- /dev/null +++ b/mall-auth/src/main/resources/bootstrap-prod.yml @@ -0,0 +1,11 @@ +spring: + cloud: + nacos: + discovery: + server-addr: http://nacos-registry:8848 + config: + server-addr: http://nacos-registry:8848 + file-extension: yaml +logging: + level: + root: info \ No newline at end of file diff --git a/mall-auth/src/main/resources/bootstrap.yml b/mall-auth/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..75e96d9 --- /dev/null +++ b/mall-auth/src/main/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + profiles: + active: dev + application: + name: mall-auth \ No newline at end of file diff --git a/mall-auth/src/main/resources/jwt.jks b/mall-auth/src/main/resources/jwt.jks new file mode 100644 index 0000000000000000000000000000000000000000..af359eae7aa8f056b49ef4ecb14e5fb09bf0ff8e GIT binary patch literal 1398 zcmezO_TO6u1_mY|W&~sAtnv~dyQoC1QwJ!%$DoO6hXEfOmo^(C3!@g3AR{9y14|Rr zlAqsLOXlWXYrONk{=gE~)g>p=1y(R|Xl*yn#+~#=t&Pcz_ z|E}PsT;By}cV3?C&gRCr-)lL`)Z#~Tgsv{xu232FaDrl%DYN9S3N80NsV-9Y3vS!2 zwU2ydDisox_&}w&^8AY>{9<+M)r_SM9^`#KnPr*Ic6-BShxAEF(tl0c{C&FZr5(1# z>Gf~X;g0aKxtyJ`lWU=E_*V8izfYar@}1$6RPg+b&A-&!&fnt__WtSWCw%{`(=YQ# z_cw3!E55zUJ=op2+_%Z)FVoR;s&Z)$b|fB3Xt{JIOIZDvxMIzwS^FPV zZKA(Uit{;pdA@vKXLIhlbn^2V>9ds9FZdQW$#aI;hD~kf?|v3C)RF z10U)m<9lkBGI*@H*LCauUYRL83oV}3-88G;z4_z!x2tAP-j&w-Z~NE zE1Q1#2!r^kMM`Sg=j%jMuY3A#ooYAXylbc6w^_ILczLdPJK5?(-mgph91Px=-_%b@ zsY-MZk9`|>r||fJ_T>pt*Z-W5Pm1}pb6wTi5SDVL6VKBZ9)e|XvU$E9S2_OI3-hqqdR6Etgto~eN)Fe#S- zlX8(k6XWd#%uI|-Oe~Uu&P)cpY@Awc9&O)w85y}*84Pj^1%Qd2Ih2J>m_0NvJ1@UH z4<^EaA;OL!!i6EijUmDe7cr0%=QT1gFf%YRurRVTF^B?k4UxEXc1`1az`rxUQ&C)iWJ9sD*EA5a?svns&Qh03EyQI zE`JM~vQptMR-qin9$P5Qu0F`PaE?a7xtr(a%#!`^x$4gH^i_Kljdz>tE6iAAaH21o z-MOUgQO++9zrT?VE=Ccq=)525n0l-&9&zJ&Fl|r9=v2?W@KPotY{!_APbBg zSw0pq7LgTe4Sl6;9(_oQeZ#XYrSM0}H2-7BJ^;oiGtlWv`ZBoB#Vz`=sLVp~{^w7x zHY%t;Jdlw5|AKYq?ZO34?0S56X3p#n?R=SERkk-)vzop38rw0I)7}#%?^=DPFlCv= z)n3nN^@;a_XXtOZy!vU;Q-0pX*Iv9~t<+c15c=`HV7}n&x)ZPC&-0$pdiX=V#N*Jj o!*yv-ZXBLEb+huL$X=Z~{kRF-&HK!yFFAeI`9HnjZ=>BK0CU?#vH$=8 literal 0 HcmV?d00001 diff --git a/mall-common/pom.xml b/mall-common/pom.xml index 4ffe1c4..ee34b46 100644 --- a/mall-common/pom.xml +++ b/mall-common/pom.xml @@ -20,35 +20,27 @@ com.github.pagehelper - pagehelper-spring-boot-starter + pagehelper org.springframework.boot spring-boot-starter-web - com.alibaba - druid-spring-boot-starter - - - io.springfox - springfox-swagger2 - - - io.springfox - springfox-swagger-ui + org.springframework.boot + spring-boot-starter-data-redis org.springframework.data spring-data-commons - cn.hutool - hutool-all + com.github.xiaoymin + knife4j-micro-spring-boot-starter - org.projectlombok - lombok + net.logstash.logback + logstash-logback-encoder diff --git a/mall-common/src/main/java/com/macro/mall/common/annotation/CacheException.java b/mall-common/src/main/java/com/macro/mall/common/annotation/CacheException.java new file mode 100644 index 0000000..fc37d5c --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/annotation/CacheException.java @@ -0,0 +1,12 @@ +package com.macro.mall.common.annotation; + +import java.lang.annotation.*; + +/** + * 自定义注解,有该注解的缓存方法会抛出异常 + */ +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface CacheException { +} diff --git a/mall-common/src/main/java/com/macro/mall/common/config/BaseRedisConfig.java b/mall-common/src/main/java/com/macro/mall/common/config/BaseRedisConfig.java new file mode 100644 index 0000000..27a137d --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/config/BaseRedisConfig.java @@ -0,0 +1,69 @@ +package com.macro.mall.common.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.macro.mall.common.service.RedisService; +import com.macro.mall.common.service.impl.RedisServiceImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +/** + * Redis基础配置 + * Created by macro on 2020/6/19. + */ +public class BaseRedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisSerializer serializer = redisSerializer(); + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(serializer); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + @Bean + public RedisSerializer redisSerializer() { + //创建JSON序列化器 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + //必须设置,否则无法将JSON转化为对象,会转化成Map类型 + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(objectMapper); + return serializer; + } + + @Bean + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); + //设置Redis缓存有效期为1天 + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1)); + return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + + + @Bean + public RedisService redisService(){ + return new RedisServiceImpl(); + } + +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java b/mall-common/src/main/java/com/macro/mall/common/config/BaseSwaggerConfig.java similarity index 59% rename from mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java rename to mall-common/src/main/java/com/macro/mall/common/config/BaseSwaggerConfig.java index 0a62e84..011af3e 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java +++ b/mall-common/src/main/java/com/macro/mall/common/config/BaseSwaggerConfig.java @@ -1,47 +1,45 @@ -package com.macro.mall.portal.config; +package com.macro.mall.common.config; +import com.macro.mall.common.domain.SwaggerProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.SecurityReference; +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; /** - * Swagger2API文档的配置 - * Created by macro on 2018/4/26. + * Swagger基础配置 + * Created by macro on 2020/7/16. */ -@Configuration -@EnableSwagger2 -public class Swagger2Config { +public abstract class BaseSwaggerConfig { + @Bean public Docket createRestApi() { - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) + SwaggerProperties swaggerProperties = swaggerProperties(); + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo(swaggerProperties)) .select() - .apis(RequestHandlerSelectors.basePackage("com.macro.mall.portal.controller")) + .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage())) .paths(PathSelectors.any()) - .build() - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); + .build(); + if (swaggerProperties.isEnableSecurity()) { + docket.securitySchemes(securitySchemes()).securityContexts(securityContexts()); + } + return docket; } - private ApiInfo apiInfo() { + private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { return new ApiInfoBuilder() - .title("mall前台系统") - .description("mall前台模块") - .contact("macro") - .version("1.0") + .title(swaggerProperties.getTitle()) + .description(swaggerProperties.getDescription()) + .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail())) + .version(swaggerProperties.getVersion()) .build(); } @@ -56,10 +54,7 @@ public class Swagger2Config { private List securityContexts() { //设置需要登录认证的路径 List result = new ArrayList<>(); - result.add(getContextByPath("/member/.*")); - result.add(getContextByPath("/cart/.*")); - result.add(getContextByPath("/order/.*")); - result.add(getContextByPath("/returnApply/.*")); + result.add(getContextByPath("/*/.*")); return result; } @@ -78,4 +73,9 @@ public class Swagger2Config { result.add(new SecurityReference("Authorization", authorizationScopes)); return result; } + + /** + * 自定义Swagger配置 + */ + public abstract SwaggerProperties swaggerProperties(); } diff --git a/mall-common/src/main/java/com/macro/mall/common/constant/AuthConstant.java b/mall-common/src/main/java/com/macro/mall/common/constant/AuthConstant.java new file mode 100644 index 0000000..34ed033 --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/constant/AuthConstant.java @@ -0,0 +1,54 @@ +package com.macro.mall.common.constant; + +/** + * 权限相关常量定义 + * Created by macro on 2020/6/19. + */ +public interface AuthConstant { + + /** + * JWT存储权限前缀 + */ + String AUTHORITY_PREFIX = "ROLE_"; + + /** + * JWT存储权限属性 + */ + String AUTHORITY_CLAIM_NAME = "authorities"; + + /** + * 后台管理client_id + */ + String ADMIN_CLIENT_ID = "admin-app"; + + /** + * 前台商城client_id + */ + String PORTAL_CLIENT_ID = "portal-app"; + + /** + * 后台管理接口路径匹配 + */ + String ADMIN_URL_PATTERN = "/mall-admin/**"; + + /** + * Redis缓存权限规则key + */ + String RESOURCE_ROLES_MAP_KEY = "auth:resourceRolesMap"; + + /** + * 认证信息Http请求头 + */ + String JWT_TOKEN_HEADER = "Authorization"; + + /** + * JWT令牌前缀 + */ + String JWT_TOKEN_PREFIX = "Bearer "; + + /** + * 用户信息Http请求头 + */ + String USER_TOKEN_HEADER = "user"; + +} diff --git a/mall-common/src/main/java/com/macro/mall/common/domain/SwaggerProperties.java b/mall-common/src/main/java/com/macro/mall/common/domain/SwaggerProperties.java new file mode 100644 index 0000000..4043805 --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/domain/SwaggerProperties.java @@ -0,0 +1,47 @@ +package com.macro.mall.common.domain; + +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * Swagger自定义配置 + * Created by macro on 2020/7/16. + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Builder +public class SwaggerProperties { + /** + * API文档生成基础路径 + */ + private String apiBasePackage; + /** + * 是否要启用登录认证 + */ + private boolean enableSecurity; + /** + * 文档标题 + */ + private String title; + /** + * 文档描述 + */ + private String description; + /** + * 文档版本 + */ + private String version; + /** + * 文档联系人姓名 + */ + private String contactName; + /** + * 文档联系人网址 + */ + private String contactUrl; + /** + * 文档联系人邮箱 + */ + private String contactEmail; +} diff --git a/mall-common/src/main/java/com/macro/mall/common/domain/UserDto.java b/mall-common/src/main/java/com/macro/mall/common/domain/UserDto.java new file mode 100644 index 0000000..ce2a718 --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/domain/UserDto.java @@ -0,0 +1,24 @@ +package com.macro.mall.common.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 登录用户信息 + * Created by macro on 2020/6/19. + */ +@Data +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +public class UserDto { + private Long id; + private String username; + private String password; + private Integer status; + private String clientId; + private List roles; + +} diff --git a/mall-common/src/main/java/com/macro/mall/common/domain/WebLog.java b/mall-common/src/main/java/com/macro/mall/common/domain/WebLog.java new file mode 100644 index 0000000..e4faf97 --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/domain/WebLog.java @@ -0,0 +1,68 @@ +package com.macro.mall.common.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * Controller层的日志封装类 + * Created by macro on 2018/4/26. + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class WebLog { + /** + * 操作描述 + */ + private String description; + + /** + * 操作用户 + */ + private String username; + + /** + * 操作时间 + */ + private Long startTime; + + /** + * 消耗时间 + */ + private Integer spendTime; + + /** + * 根路径 + */ + private String basePath; + + /** + * URI + */ + private String uri; + + /** + * URL + */ + private String url; + + /** + * 请求类型 + */ + private String method; + + /** + * IP地址 + */ + private String ip; + + /** + * 请求参数 + */ + private Object parameter; + + /** + * 返回结果 + */ + private Object result; + +} diff --git a/mall-admin/src/main/java/com/macro/mall/component/WebLogAspect.java b/mall-common/src/main/java/com/macro/mall/common/log/WebLogAspect.java similarity index 97% rename from mall-admin/src/main/java/com/macro/mall/component/WebLogAspect.java rename to mall-common/src/main/java/com/macro/mall/common/log/WebLogAspect.java index 6e5bdf8..fb99c70 100644 --- a/mall-admin/src/main/java/com/macro/mall/component/WebLogAspect.java +++ b/mall-common/src/main/java/com/macro/mall/common/log/WebLogAspect.java @@ -1,10 +1,9 @@ -package com.macro.mall.component; +package com.macro.mall.common.log; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; -import cn.hutool.json.JSON; import cn.hutool.json.JSONUtil; -import com.macro.mall.bo.WebLog; +import com.macro.mall.common.domain.WebLog; import io.swagger.annotations.ApiOperation; import net.logstash.logback.marker.Markers; import org.aspectj.lang.JoinPoint; @@ -40,7 +39,7 @@ import java.util.Map; public class WebLogAspect { private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class); - @Pointcut("execution(public * com.macro.mall.controller.*.*(..))") + @Pointcut("execution(public * com.macro.mall.controller.*.*(..))||execution(public * com.macro.mall.*.controller.*.*(..))") public void webLog() { } diff --git a/mall-common/src/main/java/com/macro/mall/common/service/RedisService.java b/mall-common/src/main/java/com/macro/mall/common/service/RedisService.java new file mode 100644 index 0000000..9f2de5e --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/service/RedisService.java @@ -0,0 +1,182 @@ +package com.macro.mall.common.service; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * redis操作Service + * Created by macro on 2020/3/3. + */ +public interface RedisService { + + /** + * 保存属性 + */ + void set(String key, Object value, long time); + + /** + * 保存属性 + */ + void set(String key, Object value); + + /** + * 获取属性 + */ + Object get(String key); + + /** + * 删除属性 + */ + Boolean del(String key); + + /** + * 批量删除属性 + */ + Long del(List keys); + + /** + * 设置过期时间 + */ + Boolean expire(String key, long time); + + /** + * 获取过期时间 + */ + Long getExpire(String key); + + /** + * 判断是否有该属性 + */ + Boolean hasKey(String key); + + /** + * 按delta递增 + */ + Long incr(String key, long delta); + + /** + * 按delta递减 + */ + Long decr(String key, long delta); + + /** + * 获取Hash结构中的属性 + */ + Object hGet(String key, String hashKey); + + /** + * 向Hash结构中放入一个属性 + */ + Boolean hSet(String key, String hashKey, Object value, long time); + + /** + * 向Hash结构中放入一个属性 + */ + void hSet(String key, String hashKey, Object value); + + /** + * 直接获取整个Hash结构 + */ + Map hGetAll(String key); + + /** + * 直接设置整个Hash结构 + */ + Boolean hSetAll(String key, Map map, long time); + + /** + * 直接设置整个Hash结构 + */ + void hSetAll(String key, Map map); + + /** + * 删除Hash结构中的属性 + */ + void hDel(String key, Object... hashKey); + + /** + * 判断Hash结构中是否有该属性 + */ + Boolean hHasKey(String key, String hashKey); + + /** + * Hash结构中属性递增 + */ + Long hIncr(String key, String hashKey, Long delta); + + /** + * Hash结构中属性递减 + */ + Long hDecr(String key, String hashKey, Long delta); + + /** + * 获取Set结构 + */ + Set sMembers(String key); + + /** + * 向Set结构中添加属性 + */ + Long sAdd(String key, Object... values); + + /** + * 向Set结构中添加属性 + */ + Long sAdd(String key, long time, Object... values); + + /** + * 是否为Set中的属性 + */ + Boolean sIsMember(String key, Object value); + + /** + * 获取Set结构的长度 + */ + Long sSize(String key); + + /** + * 删除Set结构中的属性 + */ + Long sRemove(String key, Object... values); + + /** + * 获取List结构中的属性 + */ + List lRange(String key, long start, long end); + + /** + * 获取List结构的长度 + */ + Long lSize(String key); + + /** + * 根据索引获取List中的属性 + */ + Object lIndex(String key, long index); + + /** + * 向List结构中添加属性 + */ + Long lPush(String key, Object value); + + /** + * 向List结构中添加属性 + */ + Long lPush(String key, Object value, long time); + + /** + * 向List结构中批量添加属性 + */ + Long lPushAll(String key, Object... values); + + /** + * 向List结构中批量添加属性 + */ + Long lPushAll(String key, Long time, Object... values); + + /** + * 从List结构中移除属性 + */ + Long lRemove(String key, long count, Object value); +} \ No newline at end of file diff --git a/mall-common/src/main/java/com/macro/mall/common/service/impl/RedisServiceImpl.java b/mall-common/src/main/java/com/macro/mall/common/service/impl/RedisServiceImpl.java new file mode 100644 index 0000000..8720014 --- /dev/null +++ b/mall-common/src/main/java/com/macro/mall/common/service/impl/RedisServiceImpl.java @@ -0,0 +1,198 @@ +package com.macro.mall.common.service.impl; + +import com.macro.mall.common.service.RedisService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * redis操作实现类 + * Created by macro on 2020/3/3. + */ +public class RedisServiceImpl implements RedisService { + @Autowired + private RedisTemplate redisTemplate; + + @Override + public void set(String key, Object value, long time) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } + + @Override + public void set(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + @Override + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + @Override + public Boolean del(String key) { + return redisTemplate.delete(key); + } + + @Override + public Long del(List keys) { + return redisTemplate.delete(keys); + } + + @Override + public Boolean expire(String key, long time) { + return redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + + @Override + public Long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + @Override + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + @Override + public Long incr(String key, long delta) { + return redisTemplate.opsForValue().increment(key, delta); + } + + @Override + public Long decr(String key, long delta) { + return redisTemplate.opsForValue().increment(key, -delta); + } + + @Override + public Object hGet(String key, String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + @Override + public Boolean hSet(String key, String hashKey, Object value, long time) { + redisTemplate.opsForHash().put(key, hashKey, value); + return expire(key, time); + } + + @Override + public void hSet(String key, String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + @Override + public Map hGetAll(String key) { + return redisTemplate.opsForHash().entries(key); + } + + @Override + public Boolean hSetAll(String key, Map map, long time) { + redisTemplate.opsForHash().putAll(key, map); + return expire(key, time); + } + + @Override + public void hSetAll(String key, Map map) { + redisTemplate.opsForHash().putAll(key, map); + } + + @Override + public void hDel(String key, Object... hashKey) { + redisTemplate.opsForHash().delete(key, hashKey); + } + + @Override + public Boolean hHasKey(String key, String hashKey) { + return redisTemplate.opsForHash().hasKey(key, hashKey); + } + + @Override + public Long hIncr(String key, String hashKey, Long delta) { + return redisTemplate.opsForHash().increment(key, hashKey, delta); + } + + @Override + public Long hDecr(String key, String hashKey, Long delta) { + return redisTemplate.opsForHash().increment(key, hashKey, -delta); + } + + @Override + public Set sMembers(String key) { + return redisTemplate.opsForSet().members(key); + } + + @Override + public Long sAdd(String key, Object... values) { + return redisTemplate.opsForSet().add(key, values); + } + + @Override + public Long sAdd(String key, long time, Object... values) { + Long count = redisTemplate.opsForSet().add(key, values); + expire(key, time); + return count; + } + + @Override + public Boolean sIsMember(String key, Object value) { + return redisTemplate.opsForSet().isMember(key, value); + } + + @Override + public Long sSize(String key) { + return redisTemplate.opsForSet().size(key); + } + + @Override + public Long sRemove(String key, Object... values) { + return redisTemplate.opsForSet().remove(key, values); + } + + @Override + public List lRange(String key, long start, long end) { + return redisTemplate.opsForList().range(key, start, end); + } + + @Override + public Long lSize(String key) { + return redisTemplate.opsForList().size(key); + } + + @Override + public Object lIndex(String key, long index) { + return redisTemplate.opsForList().index(key, index); + } + + @Override + public Long lPush(String key, Object value) { + return redisTemplate.opsForList().rightPush(key, value); + } + + @Override + public Long lPush(String key, Object value, long time) { + Long index = redisTemplate.opsForList().rightPush(key, value); + expire(key, time); + return index; + } + + @Override + public Long lPushAll(String key, Object... values) { + return redisTemplate.opsForList().rightPushAll(key, values); + } + + @Override + public Long lPushAll(String key, Long time, Object... values) { + Long count = redisTemplate.opsForList().rightPushAll(key, values); + expire(key, time); + return count; + } + + @Override + public Long lRemove(String key, long count, Object value) { + return redisTemplate.opsForList().remove(key, count, value); + } +} diff --git a/mall-common/src/main/resources/logback-spring.xml b/mall-common/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..51ef9da --- /dev/null +++ b/mall-common/src/main/resources/logback-spring.xml @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + DEBUG + + + + ${FILE_LOG_PATTERN} + UTF-8 + + + + ${LOG_FILE_PATH}/debug/${APP_NAME}-%d{yyyy-MM-dd}-%i.log + + ${LOG_FILE_MAX_SIZE:-10MB} + + ${LOG_FILE_MAX_HISTORY:-30} + + + + + + + + ERROR + ACCEPT + DENY + + + + ${FILE_LOG_PATTERN} + UTF-8 + + + + ${LOG_FILE_PATH}/error/${APP_NAME}-%d{yyyy-MM-dd}-%i.log + + ${LOG_FILE_MAX_SIZE:-10MB} + + ${LOG_FILE_MAX_HISTORY:-30} + + + + + + + DEBUG + + ${LOG_STASH_HOST}:4560 + + + + Asia/Shanghai + + + + + { + "project": "mall-swarm", + "level": "%level", + "service": "${APP_NAME:-}", + "pid": "${PID:-}", + "thread": "%thread", + "class": "%logger", + "message": "%message", + "stack_trace": "%exception{20}" + } + + + + + + + + 5 minutes + + + + + + + + ERROR + ACCEPT + DENY + + ${LOG_STASH_HOST}:4561 + + + + Asia/Shanghai + + + + + { + "project": "mall-swarm", + "level": "%level", + "service": "${APP_NAME:-}", + "pid": "${PID:-}", + "thread": "%thread", + "class": "%logger", + "message": "%message", + "stack_trace": "%exception{20}" + } + + + + + + + + 5 minutes + + + + + + + ${LOG_STASH_HOST}:4562 + + + + Asia/Shanghai + + + + + { + "project": "mall-swarm", + "level": "%level", + "service": "${APP_NAME:-}", + "pid": "${PID:-}", + "thread": "%thread", + "class": "%logger", + "message": "%message", + "stack_trace": "%exception{20}" + } + + + + + + + + 5 minutes + + + + + + + ${LOG_STASH_HOST}:4563 + + + + Asia/Shanghai + + + + + { + "project": "mall-swarm", + "level": "%level", + "service": "${APP_NAME:-}", + "class": "%logger", + "message": "%message" + } + + + + + + + + 5 minutes + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mall-config/.gitignore b/mall-config/.gitignore deleted file mode 100644 index a2a3040..0000000 --- a/mall-config/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/mall-config/src/main/resources/application-dev.yml b/mall-config/src/main/resources/application-dev.yml deleted file mode 100644 index 5c884f5..0000000 --- a/mall-config/src/main/resources/application-dev.yml +++ /dev/null @@ -1,4 +0,0 @@ -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ \ No newline at end of file diff --git a/mall-config/src/main/resources/application-native.yml b/mall-config/src/main/resources/application-native.yml deleted file mode 100644 index 5c884f5..0000000 --- a/mall-config/src/main/resources/application-native.yml +++ /dev/null @@ -1,4 +0,0 @@ -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ \ No newline at end of file diff --git a/mall-config/src/main/resources/application-prod.yml b/mall-config/src/main/resources/application-prod.yml deleted file mode 100644 index 9b788df..0000000 --- a/mall-config/src/main/resources/application-prod.yml +++ /dev/null @@ -1,6 +0,0 @@ -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - instance: - prefer-ip-address: true \ No newline at end of file diff --git a/mall-config/src/main/resources/application.yml b/mall-config/src/main/resources/application.yml deleted file mode 100644 index 5b4c008..0000000 --- a/mall-config/src/main/resources/application.yml +++ /dev/null @@ -1,18 +0,0 @@ -server: - port: 8301 -spring: - application: - name: mall-config - profiles: - active: native #使用本地配置,要使用git存储改为git即可 - cloud: - config: - server: - native: #本地仓库存储 - search-locations: classpath:/config/{application} - git: #Git仓库存储 - uri: https://gitee.com/macrozheng/mall-config.git - username: macro - password: 123456 - clone-on-start: true - search-paths: '{application}' diff --git a/mall-config/src/test/java/com/macro/mall/MallConfigApplicationTests.java b/mall-config/src/test/java/com/macro/mall/MallConfigApplicationTests.java deleted file mode 100644 index ca7dcf2..0000000 --- a/mall-config/src/test/java/com/macro/mall/MallConfigApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.macro.mall; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class MallConfigApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/mall-demo/pom.xml b/mall-demo/pom.xml index 0b9ff53..3d570da 100644 --- a/mall-demo/pom.xml +++ b/mall-demo/pom.xml @@ -25,17 +25,25 @@ org.springframework.boot spring-boot-starter-web - - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client - org.springframework.cloud spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-config + io.github.openfeign + feign-okhttp + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + jakarta.validation + jakarta.validation-api diff --git a/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java b/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java deleted file mode 100644 index 22b0fe4..0000000 --- a/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.macro.mall.demo.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.SecurityReference; -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; - -/** - * Swagger2API文档的配置 - */ -@Configuration -@EnableSwagger2 -public class Swagger2Config { - @Bean - public Docket createRestApi(){ - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .select() - .apis(RequestHandlerSelectors.basePackage("com.macro.mall.demo.controller")) - .paths(PathSelectors.any()) - .build() - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); - } - - private ApiInfo apiInfo() { - return new ApiInfoBuilder() - .title("mall-demo系统") - .description("SpringCloud版本中的一些示例") - .contact("macro") - .version("1.0") - .build(); - } - - private List securitySchemes() { - //设置请求头信息 - List result = new ArrayList<>(); - ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); - result.add(apiKey); - return result; - } - - private List securityContexts() { - //设置需要登录认证的路径 - List result = new ArrayList<>(); - result.add(getContextByPath("/feign/admin/getBrandList")); - result.add(getContextByPath("/feign/portal/cartList")); - return result; - } - - private SecurityContext getContextByPath(String pathRegex){ - return SecurityContext.builder() - .securityReferences(defaultAuth()) - .forPaths(PathSelectors.regex(pathRegex)) - .build(); - } - - private List defaultAuth() { - List result = new ArrayList<>(); - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - result.add(new SecurityReference("Authorization", authorizationScopes)); - return result; - } - -} diff --git a/mall-demo/src/main/java/com/macro/mall/demo/config/SwaggerConfig.java b/mall-demo/src/main/java/com/macro/mall/demo/config/SwaggerConfig.java new file mode 100644 index 0000000..f1159a2 --- /dev/null +++ b/mall-demo/src/main/java/com/macro/mall/demo/config/SwaggerConfig.java @@ -0,0 +1,42 @@ +package com.macro.mall.demo.config; + +import com.macro.mall.common.config.BaseSwaggerConfig; +import com.macro.mall.common.domain.SwaggerProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; +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; + +/** + * Swagger相关配置 + * Created by macro on 2019/4/8. + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig extends BaseSwaggerConfig { + + @Override + public SwaggerProperties swaggerProperties() { + return SwaggerProperties.builder() + .apiBasePackage("com.macro.mall.demo.controller") + .title("mall-demo系统") + .description("SpringCloud版本中的一些示例") + .contactName("macro") + .version("1.0") + .enableSecurity(true) + .build(); + } + +} diff --git a/mall-demo/src/main/java/com/macro/mall/demo/dto/UmsAdminLoginParam.java b/mall-demo/src/main/java/com/macro/mall/demo/dto/UmsAdminLoginParam.java index 98cd507..fbeb561 100644 --- a/mall-demo/src/main/java/com/macro/mall/demo/dto/UmsAdminLoginParam.java +++ b/mall-demo/src/main/java/com/macro/mall/demo/dto/UmsAdminLoginParam.java @@ -3,7 +3,6 @@ package com.macro.mall.demo.dto; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; -import org.hibernate.validator.constraints.NotEmpty; /** * 用户登录参数 diff --git a/mall-demo/src/main/resources/application.yml b/mall-demo/src/main/resources/application.yml index e31f536..a239517 100644 --- a/mall-demo/src/main/resources/application.yml +++ b/mall-demo/src/main/resources/application.yml @@ -17,3 +17,6 @@ management: #开启SpringBoot Admin的监控 endpoint: health: show-details: always +feign: + okhttp: + enabled: true diff --git a/mall-demo/src/main/resources/bootstrap-dev.yml b/mall-demo/src/main/resources/bootstrap-dev.yml index e36963e..365fbba 100644 --- a/mall-demo/src/main/resources/bootstrap-dev.yml +++ b/mall-demo/src/main/resources/bootstrap-dev.yml @@ -1,13 +1,8 @@ spring: cloud: - config: - profile: dev #启用环境名称 - label: master #分支名称 - name: demo #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ \ No newline at end of file + server-addr: http://localhost:8848 + config: + server-addr: http://localhost:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-demo/src/main/resources/bootstrap-prod.yml b/mall-demo/src/main/resources/bootstrap-prod.yml index 77ba38c..fc71e7a 100644 --- a/mall-demo/src/main/resources/bootstrap-prod.yml +++ b/mall-demo/src/main/resources/bootstrap-prod.yml @@ -1,15 +1,8 @@ spring: cloud: - config: - profile: prod #启用环境名称 - label: master #分支名称 - name: demo #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - instance: - prefer-ip-address: true \ No newline at end of file + server-addr: http://nacos-registry:8848 + config: + server-addr: http://nacos-registry:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-gateway/pom.xml b/mall-gateway/pom.xml index fb3d61c..2dbea68 100644 --- a/mall-gateway/pom.xml +++ b/mall-gateway/pom.xml @@ -16,13 +16,55 @@ - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client + com.macro.mall + mall-common + + + org.springframework.boot + spring-boot-starter-web + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config org.springframework.cloud spring-cloud-starter-gateway + + com.github.xiaoymin + knife4j-spring-boot-starter + + + org.springframework.security + spring-security-config + + + org.springframework.security + spring-security-oauth2-resource-server + + + org.springframework.security + spring-security-oauth2-client + + + org.springframework.security + spring-security-oauth2-jose + + + com.nimbusds + nimbus-jose-jwt + + + org.springframework.boot + spring-boot-starter-data-redis + diff --git a/mall-gateway/src/main/java/com/macro/mall/authorization/AuthorizationManager.java b/mall-gateway/src/main/java/com/macro/mall/authorization/AuthorizationManager.java new file mode 100644 index 0000000..423ab49 --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/authorization/AuthorizationManager.java @@ -0,0 +1,104 @@ +package com.macro.mall.authorization; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.common.domain.UserDto; +import com.macro.mall.config.IgnoreUrlsConfig; +import com.nimbusds.jose.JWSObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.ReactiveAuthorizationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.server.authorization.AuthorizationContext; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; +import reactor.core.publisher.Mono; + +import java.net.URI; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 鉴权管理器,用于判断是否有资源的访问权限 + * Created by macro on 2020/6/19. + */ +@Component +public class AuthorizationManager implements ReactiveAuthorizationManager { + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private IgnoreUrlsConfig ignoreUrlsConfig; + + @Override + public Mono check(Mono mono, AuthorizationContext authorizationContext) { + ServerHttpRequest request = authorizationContext.getExchange().getRequest(); + URI uri = request.getURI(); + PathMatcher pathMatcher = new AntPathMatcher(); + //白名单路径直接放行 + List ignoreUrls = ignoreUrlsConfig.getUrls(); + for (String ignoreUrl : ignoreUrls) { + if (pathMatcher.match(ignoreUrl, uri.getPath())) { + return Mono.just(new AuthorizationDecision(true)); + } + } + //对应跨域的预检请求直接放行 + if(request.getMethod()==HttpMethod.OPTIONS){ + return Mono.just(new AuthorizationDecision(true)); + } + //不同用户体系登录不允许互相访问 + try { + String token = request.getHeaders().getFirst(AuthConstant.JWT_TOKEN_HEADER); + if(StrUtil.isEmpty(token)){ + return Mono.just(new AuthorizationDecision(false)); + } + String realToken = token.replace(AuthConstant.JWT_TOKEN_PREFIX, ""); + JWSObject jwsObject = JWSObject.parse(realToken); + String userStr = jwsObject.getPayload().toString(); + UserDto userDto = JSONUtil.toBean(userStr, UserDto.class); + if (AuthConstant.ADMIN_CLIENT_ID.equals(userDto.getClientId()) && !pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) { + return Mono.just(new AuthorizationDecision(false)); + } + if (AuthConstant.PORTAL_CLIENT_ID.equals(userDto.getClientId()) && pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) { + return Mono.just(new AuthorizationDecision(false)); + } + } catch (ParseException e) { + e.printStackTrace(); + return Mono.just(new AuthorizationDecision(false)); + } + //非管理端路径直接放行 + if (!pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) { + return Mono.just(new AuthorizationDecision(true)); + } + //管理端路径需校验权限 + Map resourceRolesMap = redisTemplate.opsForHash().entries(AuthConstant.RESOURCE_ROLES_MAP_KEY); + Iterator iterator = resourceRolesMap.keySet().iterator(); + List authorities = new ArrayList<>(); + while (iterator.hasNext()) { + String pattern = (String) iterator.next(); + if (pathMatcher.match(pattern, uri.getPath())) { + authorities.addAll(Convert.toList(String.class, resourceRolesMap.get(pattern))); + } + } + authorities = authorities.stream().map(i -> i = AuthConstant.AUTHORITY_PREFIX + i).collect(Collectors.toList()); + //认证通过且角色匹配的用户可访问当前路径 + return mono + .filter(Authentication::isAuthenticated) + .flatMapIterable(Authentication::getAuthorities) + .map(GrantedAuthority::getAuthority) + .any(authorities::contains) + .map(AuthorizationDecision::new) + .defaultIfEmpty(new AuthorizationDecision(false)); + } + +} diff --git a/mall-gateway/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java b/mall-gateway/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java new file mode 100644 index 0000000..e3aef92 --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java @@ -0,0 +1,35 @@ +package com.macro.mall.component; + +import cn.hutool.json.JSONUtil; +import com.macro.mall.common.api.CommonResult; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.server.ServerAuthenticationEntryPoint; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.nio.charset.Charset; + +/** + * 自定义返回结果:没有登录或token过期时 + * Created by macro on 2020/6/18. + */ +@Component +public class RestAuthenticationEntryPoint implements ServerAuthenticationEntryPoint { + @Override + public Mono commence(ServerWebExchange exchange, AuthenticationException e) { + ServerHttpResponse response = exchange.getResponse(); + response.setStatusCode(HttpStatus.OK); + response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + response.getHeaders().set("Access-Control-Allow-Origin","*"); + response.getHeaders().set("Cache-Control","no-cache"); + String body= JSONUtil.toJsonStr(CommonResult.unauthorized(e.getMessage())); + DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8"))); + return response.writeWith(Mono.just(buffer)); + } +} diff --git a/mall-gateway/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java b/mall-gateway/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java new file mode 100644 index 0000000..81f425f --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java @@ -0,0 +1,36 @@ +package com.macro.mall.component; + +import cn.hutool.json.JSONUtil; +import com.macro.mall.common.api.CommonResult; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.nio.charset.Charset; + + +/** + * 自定义返回结果:没有权限访问时 + * Created by macro on 2018/4/26. + */ +@Component +public class RestfulAccessDeniedHandler implements ServerAccessDeniedHandler { + @Override + public Mono handle(ServerWebExchange exchange, AccessDeniedException denied) { + ServerHttpResponse response = exchange.getResponse(); + response.setStatusCode(HttpStatus.OK); + response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + response.getHeaders().set("Access-Control-Allow-Origin","*"); + response.getHeaders().set("Cache-Control","no-cache"); + String body= JSONUtil.toJsonStr(CommonResult.forbidden(denied.getMessage())); + DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8"))); + return response.writeWith(Mono.just(buffer)); + } +} diff --git a/mall-gateway/src/main/java/com/macro/mall/config/GlobalCorsConfig.java b/mall-gateway/src/main/java/com/macro/mall/config/GlobalCorsConfig.java index 4514bc5..cd7ac77 100644 --- a/mall-gateway/src/main/java/com/macro/mall/config/GlobalCorsConfig.java +++ b/mall-gateway/src/main/java/com/macro/mall/config/GlobalCorsConfig.java @@ -21,7 +21,7 @@ public class GlobalCorsConfig { config.addAllowedMethod("*"); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); - + config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser()); source.registerCorsConfiguration("/**", config); diff --git a/mall-gateway/src/main/java/com/macro/mall/config/IgnoreUrlsConfig.java b/mall-gateway/src/main/java/com/macro/mall/config/IgnoreUrlsConfig.java new file mode 100644 index 0000000..3e497d1 --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/config/IgnoreUrlsConfig.java @@ -0,0 +1,20 @@ +package com.macro.mall.config; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 网关白名单配置 + * Created by macro on 2020/6/17. + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Component +@ConfigurationProperties(prefix="secure.ignore") +public class IgnoreUrlsConfig { + private List urls; +} diff --git a/mall-gateway/src/main/java/com/macro/mall/config/RedisConfig.java b/mall-gateway/src/main/java/com/macro/mall/config/RedisConfig.java new file mode 100644 index 0000000..90bba12 --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/config/RedisConfig.java @@ -0,0 +1,19 @@ +package com.macro.mall.config; + +import com.macro.mall.common.config.BaseRedisConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * Redis相关配置 + * Created by macro on 2020/6/19. + */ +@Configuration +public class RedisConfig extends BaseRedisConfig { + +} diff --git a/mall-gateway/src/main/java/com/macro/mall/config/ResourceServerConfig.java b/mall-gateway/src/main/java/com/macro/mall/config/ResourceServerConfig.java new file mode 100644 index 0000000..bba28b5 --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/config/ResourceServerConfig.java @@ -0,0 +1,66 @@ +package com.macro.mall.config; + +import cn.hutool.core.util.ArrayUtil; +import com.macro.mall.authorization.AuthorizationManager; +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.component.RestAuthenticationEntryPoint; +import com.macro.mall.component.RestfulAccessDeniedHandler; +import com.macro.mall.filter.IgnoreUrlsRemoveJwtFilter; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.SecurityWebFiltersOrder; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; +import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter; +import org.springframework.security.web.server.SecurityWebFilterChain; +import reactor.core.publisher.Mono; + +/** + * 资源服务器配置 + * Created by macro on 2020/6/19. + */ +@AllArgsConstructor +@Configuration +@EnableWebFluxSecurity +public class ResourceServerConfig { + private final AuthorizationManager authorizationManager; + private final IgnoreUrlsConfig ignoreUrlsConfig; + private final RestfulAccessDeniedHandler restfulAccessDeniedHandler; + private final RestAuthenticationEntryPoint restAuthenticationEntryPoint; + private final IgnoreUrlsRemoveJwtFilter ignoreUrlsRemoveJwtFilter; + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.oauth2ResourceServer().jwt() + .jwtAuthenticationConverter(jwtAuthenticationConverter()); + //自定义处理JWT请求头过期或签名错误的结果 + http.oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint); + //对白名单路径,直接移除JWT请求头 + http.addFilterBefore(ignoreUrlsRemoveJwtFilter,SecurityWebFiltersOrder.AUTHENTICATION); + http.authorizeExchange() + .pathMatchers(ArrayUtil.toArray(ignoreUrlsConfig.getUrls(),String.class)).permitAll()//白名单配置 + .anyExchange().access(authorizationManager)//鉴权管理器配置 + .and().exceptionHandling() + .accessDeniedHandler(restfulAccessDeniedHandler)//处理未授权 + .authenticationEntryPoint(restAuthenticationEntryPoint)//处理未认证 + .and().csrf().disable(); + return http.build(); + } + + @Bean + public Converter> jwtAuthenticationConverter() { + JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); + jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX); + jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME); + JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); + jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter); + return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter); + } + +} diff --git a/mall-gateway/src/main/java/com/macro/mall/config/SwaggerResourceConfig.java b/mall-gateway/src/main/java/com/macro/mall/config/SwaggerResourceConfig.java new file mode 100644 index 0000000..c66ad3b --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/config/SwaggerResourceConfig.java @@ -0,0 +1,55 @@ +package com.macro.mall.config; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.config.GatewayProperties; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.support.NameUtils; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; +import springfox.documentation.swagger.web.SwaggerResource; +import springfox.documentation.swagger.web.SwaggerResourcesProvider; + +import java.util.ArrayList; +import java.util.List; + +/** + * Swagger资源配置 + * Created by macro on 2020/7/9. + */ +@Slf4j +@Component +@Primary +@AllArgsConstructor +public class SwaggerResourceConfig implements SwaggerResourcesProvider { + + private final RouteLocator routeLocator; + private final GatewayProperties gatewayProperties; + + @Override + public List get() { + List resources = new ArrayList<>(); + List routes = new ArrayList<>(); + //获取所有路由的ID + routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); + //过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResource + gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> { + route.getPredicates().stream() + .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) + .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(), + predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") + .replace("**", "v2/api-docs")))); + }); + + return resources; + } + + private SwaggerResource swaggerResource(String name, String location) { + log.info("name:{},location:{}", name, location); + SwaggerResource swaggerResource = new SwaggerResource(); + swaggerResource.setName(name); + swaggerResource.setLocation(location); + swaggerResource.setSwaggerVersion("2.0"); + return swaggerResource; + } +} diff --git a/mall-gateway/src/main/java/com/macro/mall/filter/AuthGlobalFilter.java b/mall-gateway/src/main/java/com/macro/mall/filter/AuthGlobalFilter.java new file mode 100644 index 0000000..13a71f2 --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/filter/AuthGlobalFilter.java @@ -0,0 +1,51 @@ +package com.macro.mall.filter; + +import cn.hutool.core.util.StrUtil; +import com.macro.mall.common.constant.AuthConstant; +import com.nimbusds.jose.JWSObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.text.ParseException; + +/** + * 将登录用户的JWT转化成用户信息的全局过滤器 + * Created by macro on 2020/6/17. + */ +@Component +public class AuthGlobalFilter implements GlobalFilter, Ordered { + + private static Logger LOGGER = LoggerFactory.getLogger(AuthGlobalFilter.class); + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + String token = exchange.getRequest().getHeaders().getFirst(AuthConstant.JWT_TOKEN_HEADER); + if (StrUtil.isEmpty(token)) { + return chain.filter(exchange); + } + try { + //从token中解析用户信息并设置到Header中去 + String realToken = token.replace(AuthConstant.JWT_TOKEN_PREFIX, ""); + JWSObject jwsObject = JWSObject.parse(realToken); + String userStr = jwsObject.getPayload().toString(); + LOGGER.info("AuthGlobalFilter.filter() user:{}",userStr); + ServerHttpRequest request = exchange.getRequest().mutate().header(AuthConstant.USER_TOKEN_HEADER, userStr).build(); + exchange = exchange.mutate().request(request).build(); + } catch (ParseException e) { + e.printStackTrace(); + } + return chain.filter(exchange); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/mall-gateway/src/main/java/com/macro/mall/filter/IgnoreUrlsRemoveJwtFilter.java b/mall-gateway/src/main/java/com/macro/mall/filter/IgnoreUrlsRemoveJwtFilter.java new file mode 100644 index 0000000..05a708b --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/filter/IgnoreUrlsRemoveJwtFilter.java @@ -0,0 +1,43 @@ +package com.macro.mall.filter; + +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.config.IgnoreUrlsConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.web.server.authentication.AuthenticationWebFilter; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +import java.net.URI; +import java.util.List; + +/** + * 白名单路径访问时需要移除JWT请求头 + * Created by macro on 2020/7/24. + */ +@Component +public class IgnoreUrlsRemoveJwtFilter implements WebFilter { + @Autowired + private IgnoreUrlsConfig ignoreUrlsConfig; + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + URI uri = request.getURI(); + PathMatcher pathMatcher = new AntPathMatcher(); + //白名单路径移除JWT请求头 + List ignoreUrls = ignoreUrlsConfig.getUrls(); + for (String ignoreUrl : ignoreUrls) { + if (pathMatcher.match(ignoreUrl, uri.getPath())) { + request = exchange.getRequest().mutate().header(AuthConstant.JWT_TOKEN_HEADER, "").build(); + exchange = exchange.mutate().request(request).build(); + return chain.filter(exchange); + } + } + return chain.filter(exchange); + } +} diff --git a/mall-gateway/src/main/java/com/macro/mall/handler/SwaggerHandler.java b/mall-gateway/src/main/java/com/macro/mall/handler/SwaggerHandler.java new file mode 100644 index 0000000..5f5a29e --- /dev/null +++ b/mall-gateway/src/main/java/com/macro/mall/handler/SwaggerHandler.java @@ -0,0 +1,58 @@ +package com.macro.mall.handler; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; +import springfox.documentation.swagger.web.*; + +import java.util.Optional; + +/** + * 自定义Swagger的各个配置节点 + * Created by macro on 2020/7/9. + */ +@RestController +public class SwaggerHandler { + + @Autowired(required = false) + private SecurityConfiguration securityConfiguration; + + @Autowired(required = false) + private UiConfiguration uiConfiguration; + + private final SwaggerResourcesProvider swaggerResources; + + @Autowired + public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { + this.swaggerResources = swaggerResources; + } + + /** + * Swagger安全配置,支持oauth和apiKey设置 + */ + @GetMapping("/swagger-resources/configuration/security") + public Mono> securityConfiguration() { + return Mono.just(new ResponseEntity<>( + Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); + } + + /** + * Swagger UI配置 + */ + @GetMapping("/swagger-resources/configuration/ui") + public Mono> uiConfiguration() { + return Mono.just(new ResponseEntity<>( + Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); + } + + /** + * Swagger资源配置,微服务中这各个服务的api-docs信息 + */ + @GetMapping("/swagger-resources") + public Mono swaggerResources() { + return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); + } +} diff --git a/mall-gateway/src/main/resources/application-dev.yml b/mall-gateway/src/main/resources/application-dev.yml deleted file mode 100644 index ee639c8..0000000 --- a/mall-gateway/src/main/resources/application-dev.yml +++ /dev/null @@ -1,5 +0,0 @@ -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ - registry-fetch-interval-seconds: 10 diff --git a/mall-gateway/src/main/resources/application-prod.yml b/mall-gateway/src/main/resources/application-prod.yml deleted file mode 100644 index 2950ce4..0000000 --- a/mall-gateway/src/main/resources/application-prod.yml +++ /dev/null @@ -1,7 +0,0 @@ -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - registry-fetch-interval-seconds: 10 - instance: - prefer-ip-address: true diff --git a/mall-gateway/src/main/resources/application.yml b/mall-gateway/src/main/resources/application.yml index c8bb3df..a1c7903 100644 --- a/mall-gateway/src/main/resources/application.yml +++ b/mall-gateway/src/main/resources/application.yml @@ -1,16 +1,77 @@ server: port: 8201 spring: - application: - name: mall-gateway - profiles: - active: dev cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true #使用小写service-id + routes: #配置路由路径 + - id: mall-auth + uri: lb://mall-auth + predicates: + - Path=/mall-auth/** + filters: + - StripPrefix=1 + - id: mall-admin + uri: lb://mall-admin + predicates: + - Path=/mall-admin/** + filters: + - StripPrefix=1 + - id: mall-portal + uri: lb://mall-portal + predicates: + - Path=/mall-portal/** + filters: + - StripPrefix=1 + - id: mall-search + uri: lb://mall-search + predicates: + - Path=/mall-search/** + filters: + - StripPrefix=1 + - id: mall-demo + uri: lb://mall-demo + predicates: + - Path=/mall-demo/** + filters: + - StripPrefix=1 + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: 'http://localhost:8201/mall-auth/rsa/publicKey' #配置RSA的公钥访问地址 + redis: + database: 0 + port: 6379 + host: localhost + password: +secure: + ignore: + urls: #配置白名单路径 + - "/doc.html" + - "/swagger-resources/**" + - "/swagger/**" + - "/**/v2/api-docs" + - "/**/*.js" + - "/**/*.css" + - "/**/*.png" + - "/**/*.ico" + - "/webjars/springfox-swagger-ui/**" + - "/actuator/**" + - "/mall-auth/oauth/token" + - "/mall-auth/rsa/publicKey" + - "/mall-search/**" + - "/mall-portal/sso/**" + - "/mall-portal/home/**" + - "/mall-portal/product/**" + - "/mall-portal/brand/**" + - "/mall-admin/admin/login" + - "/mall-admin/admin/register" + - "/mall-admin/admin/info" + - "/mall-admin/minio/upload" management: #开启SpringBoot Admin的监控 endpoints: web: @@ -19,6 +80,3 @@ management: #开启SpringBoot Admin的监控 endpoint: health: show-details: always -logging: - level: - org.springframework.cloud.gateway: debug diff --git a/mall-gateway/src/main/resources/bootstrap-dev.yml b/mall-gateway/src/main/resources/bootstrap-dev.yml new file mode 100644 index 0000000..365fbba --- /dev/null +++ b/mall-gateway/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,8 @@ +spring: + cloud: + nacos: + discovery: + server-addr: http://localhost:8848 + config: + server-addr: http://localhost:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-gateway/src/main/resources/bootstrap-prod.yml b/mall-gateway/src/main/resources/bootstrap-prod.yml new file mode 100644 index 0000000..fc71e7a --- /dev/null +++ b/mall-gateway/src/main/resources/bootstrap-prod.yml @@ -0,0 +1,8 @@ +spring: + cloud: + nacos: + discovery: + server-addr: http://nacos-registry:8848 + config: + server-addr: http://nacos-registry:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-gateway/src/main/resources/bootstrap.yml b/mall-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..b3900a3 --- /dev/null +++ b/mall-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + profiles: + active: dev + application: + name: mall-gateway \ No newline at end of file diff --git a/mall-mbg/pom.xml b/mall-mbg/pom.xml index ac12150..216b043 100644 --- a/mall-mbg/pom.xml +++ b/mall-mbg/pom.xml @@ -23,6 +23,14 @@ com.macro.mall mall-common + + com.github.pagehelper + pagehelper-spring-boot-starter + + + com.alibaba + druid-spring-boot-starter + org.mybatis.generator mybatis-generator-core diff --git a/mall-monitor/pom.xml b/mall-monitor/pom.xml index 82efca1..a5a8950 100644 --- a/mall-monitor/pom.xml +++ b/mall-monitor/pom.xml @@ -20,8 +20,8 @@ spring-boot-starter-web - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery de.codecentric diff --git a/mall-monitor/src/main/resources/application-dev.yml b/mall-monitor/src/main/resources/application-dev.yml index 0cdc0aa..a7c40c6 100644 --- a/mall-monitor/src/main/resources/application-dev.yml +++ b/mall-monitor/src/main/resources/application-dev.yml @@ -1,4 +1,5 @@ -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ +spring: + cloud: + nacos: + discovery: + server-addr: http://localhost:8848 diff --git a/mall-monitor/src/main/resources/application-prod.yml b/mall-monitor/src/main/resources/application-prod.yml index 321524e..17c0d7b 100644 --- a/mall-monitor/src/main/resources/application-prod.yml +++ b/mall-monitor/src/main/resources/application-prod.yml @@ -1,6 +1,5 @@ -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - instance: - prefer-ip-address: true +spring: + cloud: + nacos: + discovery: + server-addr: http://nacos-registry:8848 diff --git a/mall-monitor/src/main/resources/application.yml b/mall-monitor/src/main/resources/application.yml index 6490fa8..dade0d2 100644 --- a/mall-monitor/src/main/resources/application.yml +++ b/mall-monitor/src/main/resources/application.yml @@ -11,9 +11,3 @@ spring: ignored-services: ${spring.application.name} server: port: 8101 -eureka: - client: - register-with-eureka: true - fetch-registry: true - service-url: - defaultZone: http://localhost:8001/eureka/ diff --git a/mall-portal/pom.xml b/mall-portal/pom.xml index 5506137..7a424be 100644 --- a/mall-portal/pom.xml +++ b/mall-portal/pom.xml @@ -22,10 +22,6 @@ com.macro.mall mall-mbg - - com.macro.mall - mall-security - org.springframework.boot @@ -42,12 +38,20 @@ spring-boot-starter-amqp - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config org.springframework.cloud - spring-cloud-starter-config + spring-cloud-starter-openfeign + + + io.github.openfeign + feign-okhttp diff --git a/mall-portal/src/main/java/com/macro/mall/portal/MallPortalApplication.java b/mall-portal/src/main/java/com/macro/mall/portal/MallPortalApplication.java index 8c74689..4a1d40f 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/MallPortalApplication.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/MallPortalApplication.java @@ -3,7 +3,9 @@ package com.macro.mall.portal; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +@EnableFeignClients @EnableDiscoveryClient @SpringBootApplication(scanBasePackages = "com.macro.mall") public class MallPortalApplication { diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java b/mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java deleted file mode 100644 index 2a41f9c..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.macro.mall.portal.config; - -import com.macro.mall.portal.service.UmsMemberService; -import com.macro.mall.security.component.DynamicSecurityService; -import com.macro.mall.security.config.SecurityConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.access.ConfigAttribute; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.userdetails.UserDetailsService; - -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * mall-security模块相关配置 - * Created by macro on 2019/11/5. - */ -@Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class MallSecurityConfig extends SecurityConfig { - - @Autowired - private UmsMemberService memberService; - - @Bean - public UserDetailsService userDetailsService() { - //获取登录用户信息 - return username -> memberService.loadUserByUsername(username); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/RedisConfig.java b/mall-portal/src/main/java/com/macro/mall/portal/config/RedisConfig.java new file mode 100644 index 0000000..acc33d6 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/config/RedisConfig.java @@ -0,0 +1,15 @@ +package com.macro.mall.portal.config; + +import com.macro.mall.common.config.BaseRedisConfig; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Configuration; + +/** + * Redis配置类 + * Created by macro on 2020/3/2. + */ +@EnableCaching +@Configuration +public class RedisConfig extends BaseRedisConfig { + +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/SwaggerConfig.java b/mall-portal/src/main/java/com/macro/mall/portal/config/SwaggerConfig.java new file mode 100644 index 0000000..d340df8 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/config/SwaggerConfig.java @@ -0,0 +1,41 @@ +package com.macro.mall.portal.config; + +import com.macro.mall.common.config.BaseSwaggerConfig; +import com.macro.mall.common.domain.SwaggerProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; +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; + +/** + * Swagger2API文档的配置 + * Created by macro on 2018/4/26. + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig extends BaseSwaggerConfig { + + @Override + public SwaggerProperties swaggerProperties() { + return SwaggerProperties.builder() + .apiBasePackage("com.macro.mall.portal.controller") + .title("mall前台系统") + .description("mall前台相关接口文档") + .contactName("macro") + .version("1.0") + .enableSecurity(true) + .build(); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/HomeController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/HomeController.java index 4d9af1c..f78c16d 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/HomeController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/HomeController.java @@ -59,4 +59,22 @@ public class HomeController { List subjectList = homeService.getSubjectList(cateId,pageSize,pageNum); return CommonResult.success(subjectList); } + + @ApiOperation("分页获取人气推荐商品") + @RequestMapping(value = "/hotProductList", method = RequestMethod.GET) + @ResponseBody + public CommonResult> hotProductList(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, + @RequestParam(value = "pageSize", defaultValue = "6") Integer pageSize) { + List productList = homeService.hotProductList(pageNum,pageSize); + return CommonResult.success(productList); + } + + @ApiOperation("分页获取新品推荐商品") + @RequestMapping(value = "/newProductList", method = RequestMethod.GET) + @ResponseBody + public CommonResult> newProductList(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, + @RequestParam(value = "pageSize", defaultValue = "6") Integer pageSize) { + List productList = homeService.newProductList(pageNum,pageSize); + return CommonResult.success(productList); + } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberAttentionController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberAttentionController.java index c5947df..80ea510 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberAttentionController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberAttentionController.java @@ -1,11 +1,14 @@ package com.macro.mall.portal.controller; +import com.macro.mall.common.api.CommonPage; import com.macro.mall.common.api.CommonResult; import com.macro.mall.portal.domain.MemberBrandAttention; +import com.macro.mall.portal.domain.MemberProductCollection; import com.macro.mall.portal.service.MemberAttentionService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -36,8 +39,8 @@ public class MemberAttentionController { @ApiOperation("取消关注") @RequestMapping(value = "/delete", method = RequestMethod.POST) @ResponseBody - public CommonResult delete(Long memberId, Long brandId) { - int count = memberAttentionService.delete(memberId,brandId); + public CommonResult delete(Long brandId) { + int count = memberAttentionService.delete(brandId); if(count>0){ return CommonResult.success(count); }else{ @@ -46,10 +49,27 @@ public class MemberAttentionController { } @ApiOperation("显示关注列表") - @RequestMapping(value = "/list/{memberId}", method = RequestMethod.GET) + @RequestMapping(value = "/list", method = RequestMethod.GET) @ResponseBody - public CommonResult> list(@PathVariable Long memberId) { - List memberBrandAttentionList = memberAttentionService.list(memberId); - return CommonResult.success(memberBrandAttentionList); + public CommonResult> list(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize) { + Page page = memberAttentionService.list(pageNum,pageSize); + return CommonResult.success(CommonPage.restPage(page)); + } + + @ApiOperation("显示关注品牌详情") + @RequestMapping(value = "/detail", method = RequestMethod.GET) + @ResponseBody + public CommonResult detail(@RequestParam Long brandId) { + MemberBrandAttention memberBrandAttention = memberAttentionService.detail(brandId); + return CommonResult.success(memberBrandAttention); + } + + @ApiOperation("清空关注列表") + @RequestMapping(value = "/clear", method = RequestMethod.POST) + @ResponseBody + public CommonResult clear() { + memberAttentionService.clear(); + return CommonResult.success(null); } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberCollectionController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberCollectionController.java deleted file mode 100644 index 63d3fac..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberCollectionController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.macro.mall.portal.controller; - -import com.macro.mall.common.api.CommonResult; -import com.macro.mall.portal.domain.MemberProductCollection; -import com.macro.mall.portal.service.MemberCollectionService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 会员收藏管理Controller - * Created by macro on 2018/8/2. - */ -@Controller -@Api(tags = "MemberCollectionController", description = "会员收藏管理") -@RequestMapping("/member/collection") -public class MemberCollectionController { - @Autowired - private MemberCollectionService memberCollectionService; - - @ApiOperation("添加商品收藏") - @RequestMapping(value = "/addProduct", method = RequestMethod.POST) - @ResponseBody - public CommonResult addProduct(@RequestBody MemberProductCollection productCollection) { - int count = memberCollectionService.addProduct(productCollection); - if (count > 0) { - return CommonResult.success(count); - } else { - return CommonResult.failed(); - } - } - - @ApiOperation("删除收藏商品") - @RequestMapping(value = "/deleteProduct", method = RequestMethod.POST) - @ResponseBody - public CommonResult deleteProduct(Long memberId, Long productId) { - int count = memberCollectionService.deleteProduct(memberId, productId); - if (count > 0) { - return CommonResult.success(count); - } else { - return CommonResult.failed(); - } - } - - @ApiOperation("显示关注列表") - @RequestMapping(value = "/listProduct/{memberId}", method = RequestMethod.GET) - @ResponseBody - public CommonResult> listProduct(@PathVariable Long memberId) { - List memberProductCollectionList = memberCollectionService.listProduct(memberId); - return CommonResult.success(memberProductCollectionList); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberProductCollectionController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberProductCollectionController.java new file mode 100644 index 0000000..1c78787 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberProductCollectionController.java @@ -0,0 +1,75 @@ +package com.macro.mall.portal.controller; + +import com.macro.mall.common.api.CommonPage; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.portal.domain.MemberProductCollection; +import com.macro.mall.portal.service.MemberCollectionService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 会员收藏管理Controller + * Created by macro on 2018/8/2. + */ +@Controller +@Api(tags = "MemberCollectionController", description = "会员收藏管理") +@RequestMapping("/member/productCollection") +public class MemberProductCollectionController { + @Autowired + private MemberCollectionService memberCollectionService; + + @ApiOperation("添加商品收藏") + @RequestMapping(value = "/add", method = RequestMethod.POST) + @ResponseBody + public CommonResult add(@RequestBody MemberProductCollection productCollection) { + int count = memberCollectionService.add(productCollection); + if (count > 0) { + return CommonResult.success(count); + } else { + return CommonResult.failed(); + } + } + + @ApiOperation("删除收藏商品") + @RequestMapping(value = "/delete", method = RequestMethod.POST) + @ResponseBody + public CommonResult delete(Long productId) { + int count = memberCollectionService.delete(productId); + if (count > 0) { + return CommonResult.success(count); + } else { + return CommonResult.failed(); + } + } + + @ApiOperation("显示收藏列表") + @RequestMapping(value = "/list", method = RequestMethod.GET) + @ResponseBody + public CommonResult> list(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize) { + Page page = memberCollectionService.list(pageNum,pageSize); + return CommonResult.success(CommonPage.restPage(page)); + } + + @ApiOperation("显示收藏商品详情") + @RequestMapping(value = "/detail", method = RequestMethod.GET) + @ResponseBody + public CommonResult detail(@RequestParam Long productId) { + MemberProductCollection memberProductCollection = memberCollectionService.detail(productId); + return CommonResult.success(memberProductCollection); + } + + @ApiOperation("清空收藏列表") + @RequestMapping(value = "/clear", method = RequestMethod.POST) + @ResponseBody + public CommonResult clear() { + memberCollectionService.clear(); + return CommonResult.success(null); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberReadHistoryController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberReadHistoryController.java index 8393408..949897f 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberReadHistoryController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/MemberReadHistoryController.java @@ -1,11 +1,13 @@ package com.macro.mall.portal.controller; +import com.macro.mall.common.api.CommonPage; import com.macro.mall.common.api.CommonResult; import com.macro.mall.portal.domain.MemberReadHistory; import com.macro.mall.portal.service.MemberReadHistoryService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -46,11 +48,20 @@ public class MemberReadHistoryController { } } - @ApiOperation("展示浏览记录") + @ApiOperation("清空除浏览记录") + @RequestMapping(value = "/clear", method = RequestMethod.POST) + @ResponseBody + public CommonResult clear() { + memberReadHistoryService.clear(); + return CommonResult.success(null); + } + + @ApiOperation("分页获取用户浏览记录") @RequestMapping(value = "/list", method = RequestMethod.GET) @ResponseBody - public CommonResult> list(Long memberId) { - List memberReadHistoryList = memberReadHistoryService.list(memberId); - return CommonResult.success(memberReadHistoryList); + public CommonResult> list(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize) { + Page page = memberReadHistoryService.list(pageNum, pageSize); + return CommonResult.success(CommonPage.restPage(page)); } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsCartItemController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsCartItemController.java index 74af308..944e8a2 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsCartItemController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsCartItemController.java @@ -49,8 +49,8 @@ public class OmsCartItemController { @ApiOperation("获取某个会员的购物车列表,包括促销信息") @RequestMapping(value = "/list/promotion", method = RequestMethod.GET) @ResponseBody - public CommonResult> listPromotion() { - List cartPromotionItemList = cartItemService.listPromotion(memberService.getCurrentMember().getId()); + public CommonResult> listPromotion(@RequestParam(required = false) List cartIds) { + List cartPromotionItemList = cartItemService.listPromotion(memberService.getCurrentMember().getId(), cartIds); return CommonResult.success(cartPromotionItemList); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsPortalOrderController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsPortalOrderController.java index 6251704..80ab3f7 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsPortalOrderController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/OmsPortalOrderController.java @@ -1,15 +1,19 @@ package com.macro.mall.portal.controller; +import com.macro.mall.common.api.CommonPage; import com.macro.mall.common.api.CommonResult; import com.macro.mall.portal.domain.ConfirmOrderResult; +import com.macro.mall.portal.domain.OmsOrderDetail; import com.macro.mall.portal.domain.OrderParam; import com.macro.mall.portal.service.OmsPortalOrderService; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.Map; /** @@ -26,8 +30,8 @@ public class OmsPortalOrderController { @ApiOperation("根据购物车信息生成确认单信息") @RequestMapping(value = "/generateConfirmOrder", method = RequestMethod.POST) @ResponseBody - public CommonResult generateConfirmOrder() { - ConfirmOrderResult confirmOrderResult = portalOrderService.generateConfirmOrder(); + public CommonResult generateConfirmOrder(@RequestBody List cartIds) { + ConfirmOrderResult confirmOrderResult = portalOrderService.generateConfirmOrder(cartIds); return CommonResult.success(confirmOrderResult); } @@ -39,11 +43,11 @@ public class OmsPortalOrderController { return CommonResult.success(result, "下单成功"); } - @ApiOperation("支付成功的回调") + @ApiOperation("用户支付成功的回调") @RequestMapping(value = "/paySuccess", method = RequestMethod.POST) @ResponseBody - public CommonResult paySuccess(@RequestParam Long orderId) { - Integer count = portalOrderService.paySuccess(orderId); + public CommonResult paySuccess(@RequestParam Long orderId,@RequestParam Integer payType) { + Integer count = portalOrderService.paySuccess(orderId,payType); return CommonResult.success(count, "支付成功"); } @@ -62,4 +66,48 @@ public class OmsPortalOrderController { portalOrderService.sendDelayMessageCancelOrder(orderId); return CommonResult.success(null); } + + @ApiOperation("按状态分页获取用户订单列表") + @ApiImplicitParam(name = "status", value = "订单状态:-1->全部;0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭", + defaultValue = "-1", allowableValues = "-1,0,1,2,3,4", paramType = "query", dataType = "int") + @RequestMapping(value = "/list", method = RequestMethod.GET) + @ResponseBody + public CommonResult> list(@RequestParam Integer status, + @RequestParam(required = false, defaultValue = "1") Integer pageNum, + @RequestParam(required = false, defaultValue = "5") Integer pageSize) { + CommonPage orderPage = portalOrderService.list(status,pageNum,pageSize); + return CommonResult.success(orderPage); + } + + @ApiOperation("根据ID获取订单详情") + @RequestMapping(value = "/detail/{orderId}", method = RequestMethod.GET) + @ResponseBody + public CommonResult detail(@PathVariable Long orderId) { + OmsOrderDetail orderDetail = portalOrderService.detail(orderId); + return CommonResult.success(orderDetail); + } + + @ApiOperation("用户取消订单") + @RequestMapping(value = "/cancelUserOrder", method = RequestMethod.POST) + @ResponseBody + public CommonResult cancelUserOrder(Long orderId) { + portalOrderService.cancelOrder(orderId); + return CommonResult.success(null); + } + + @ApiOperation("用户确认收货") + @RequestMapping(value = "/confirmReceiveOrder", method = RequestMethod.POST) + @ResponseBody + public CommonResult confirmReceiveOrder(Long orderId) { + portalOrderService.confirmReceiveOrder(orderId); + return CommonResult.success(null); + } + + @ApiOperation("用户删除订单") + @RequestMapping(value = "/deleteOrder", method = RequestMethod.POST) + @ResponseBody + public CommonResult deleteOrder(Long orderId) { + portalOrderService.deleteOrder(orderId); + return CommonResult.success(null); + } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/PmsPortalProductController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/PmsPortalProductController.java new file mode 100644 index 0000000..0d173a8 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/PmsPortalProductController.java @@ -0,0 +1,60 @@ +package com.macro.mall.portal.controller; + +import com.macro.mall.common.api.CommonPage; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.model.PmsProduct; +import com.macro.mall.portal.domain.PmsPortalProductDetail; +import com.macro.mall.portal.domain.PmsProductCategoryNode; +import com.macro.mall.portal.service.PmsPortalProductService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 前台商品管理Controller + * Created by macro on 2020/4/6. + */ +@Controller +@Api(tags = "PmsPortalProductController", description = "前台商品管理") +@RequestMapping("/product") +public class PmsPortalProductController { + + @Autowired + private PmsPortalProductService portalProductService; + + @ApiOperation(value = "综合搜索、筛选、排序") + @ApiImplicitParam(name = "sort", value = "排序字段:0->按相关度;1->按新品;2->按销量;3->价格从低到高;4->价格从高到低", + defaultValue = "0", allowableValues = "0,1,2,3,4", paramType = "query", dataType = "integer") + @RequestMapping(value = "/search", method = RequestMethod.GET) + @ResponseBody + public CommonResult> search(@RequestParam(required = false) String keyword, + @RequestParam(required = false) Long brandId, + @RequestParam(required = false) Long productCategoryId, + @RequestParam(required = false, defaultValue = "0") Integer pageNum, + @RequestParam(required = false, defaultValue = "5") Integer pageSize, + @RequestParam(required = false, defaultValue = "0") Integer sort) { + List productList = portalProductService.search(keyword, brandId, productCategoryId, pageNum, pageSize, sort); + return CommonResult.success(CommonPage.restPage(productList)); + } + + @ApiOperation("以树形结构获取所有商品分类") + @RequestMapping(value = "/categoryTreeList", method = RequestMethod.GET) + @ResponseBody + public CommonResult> categoryTreeList() { + List list = portalProductService.categoryTreeList(); + return CommonResult.success(list); + } + + @ApiOperation("获取前台商品详情") + @RequestMapping(value = "/detail/{id}", method = RequestMethod.GET) + @ResponseBody + public CommonResult detail(@PathVariable Long id) { + PmsPortalProductDetail productDetail = portalProductService.detail(id); + return CommonResult.success(productDetail); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/PortalBrandController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/PortalBrandController.java new file mode 100644 index 0000000..5f976ce --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/PortalBrandController.java @@ -0,0 +1,54 @@ +package com.macro.mall.portal.controller; + +import com.macro.mall.common.api.CommonPage; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.model.PmsBrand; +import com.macro.mall.model.PmsProduct; +import com.macro.mall.portal.service.PortalBrandService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 首页品牌推荐管理Controller + * Created by macro on 2020/5/15. + */ +@Controller +@Api(tags = "PortalBrandController", description = "前台品牌管理") +@RequestMapping("/brand") +public class PortalBrandController { + + @Autowired + private PortalBrandService homeBrandService; + + @ApiOperation("分页获取推荐品牌") + @RequestMapping(value = "/recommendList", method = RequestMethod.GET) + @ResponseBody + public CommonResult> recommendList(@RequestParam(value = "pageSize", defaultValue = "6") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + List brandList = homeBrandService.recommendList(pageNum, pageSize); + return CommonResult.success(brandList); + } + + @ApiOperation("获取品牌详情") + @RequestMapping(value = "/detail/{brandId}", method = RequestMethod.GET) + @ResponseBody + public CommonResult detail(@PathVariable Long brandId) { + PmsBrand brand = homeBrandService.detail(brandId); + return CommonResult.success(brand); + } + + @ApiOperation("分页获取品牌相关商品") + @RequestMapping(value = "/productList", method = RequestMethod.GET) + @ResponseBody + public CommonResult> productList(@RequestParam Long brandId, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, + @RequestParam(value = "pageSize", defaultValue = "6") Integer pageSize) { + CommonPage result = homeBrandService.productList(brandId,pageNum, pageSize); + return CommonResult.success(result); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java index 843870e..661bd67 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java @@ -1,21 +1,18 @@ package com.macro.mall.portal.controller; import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.domain.UserDto; +import com.macro.mall.model.UmsMember; import com.macro.mall.portal.service.UmsMemberService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; - /** * 会员登录注册管理Controller * Created by macro on 2018/8/3. @@ -24,10 +21,6 @@ import java.util.Map; @Api(tags = "UmsMemberController", description = "会员登录注册管理") @RequestMapping("/sso") public class UmsMemberController { - @Value("${jwt.tokenHeader}") - private String tokenHeader; - @Value("${jwt.tokenHead}") - private String tokenHead; @Autowired private UmsMemberService memberService; @@ -47,14 +40,15 @@ public class UmsMemberController { @ResponseBody public CommonResult login(@RequestParam String username, @RequestParam String password) { - String token = memberService.login(username, password); - if (token == null) { - return CommonResult.validateFailed("用户名或密码错误"); - } - Map tokenMap = new HashMap<>(); - tokenMap.put("token", token); - tokenMap.put("tokenHead", tokenHead); - return CommonResult.success(tokenMap); + return memberService.login(username, password); + } + + @ApiOperation("获取会员信息") + @RequestMapping(value = "/info", method = RequestMethod.GET) + @ResponseBody + public CommonResult info() { + UmsMember member = memberService.getCurrentMember(); + return CommonResult.success(member); } @ApiOperation("获取验证码") @@ -75,19 +69,10 @@ public class UmsMemberController { return CommonResult.success(null,"密码修改成功"); } - - @ApiOperation(value = "刷新token") - @RequestMapping(value = "/refreshToken", method = RequestMethod.GET) + @ApiOperation("根据用户名获取通用用户信息") + @RequestMapping(value = "/loadByUsername", method = RequestMethod.GET) @ResponseBody - public CommonResult refreshToken(HttpServletRequest request) { - String token = request.getHeader(tokenHeader); - String refreshToken = memberService.refreshToken(token); - if (refreshToken == null) { - return CommonResult.failed("token已经过期!"); - } - Map tokenMap = new HashMap<>(); - tokenMap.put("token", refreshToken); - tokenMap.put("tokenHead", tokenHead); - return CommonResult.success(tokenMap); + public UserDto loadUserByUsername(@RequestParam String username) { + return memberService.loadUserByUsername(username); } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberCouponController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberCouponController.java index c76c5d5..f28c7d7 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberCouponController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberCouponController.java @@ -1,6 +1,7 @@ package com.macro.mall.portal.controller; import com.macro.mall.common.api.CommonResult; +import com.macro.mall.model.SmsCoupon; import com.macro.mall.model.SmsCouponHistory; import com.macro.mall.portal.domain.CartPromotionItem; import com.macro.mall.portal.domain.SmsCouponHistoryDetail; @@ -39,14 +40,24 @@ public class UmsMemberCouponController { return CommonResult.success(null,"领取成功"); } + @ApiOperation("获取用户优惠券历史列表") + @ApiImplicitParam(name = "useStatus", value = "优惠券筛选类型:0->未使用;1->已使用;2->已过期", + allowableValues = "0,1,2", paramType = "query", dataType = "integer") + @RequestMapping(value = "/listHistory", method = RequestMethod.GET) + @ResponseBody + public CommonResult> listHistory(@RequestParam(value = "useStatus", required = false) Integer useStatus) { + List couponHistoryList = memberCouponService.listHistory(useStatus); + return CommonResult.success(couponHistoryList); + } + @ApiOperation("获取用户优惠券列表") @ApiImplicitParam(name = "useStatus", value = "优惠券筛选类型:0->未使用;1->已使用;2->已过期", allowableValues = "0,1,2", paramType = "query", dataType = "integer") @RequestMapping(value = "/list", method = RequestMethod.GET) @ResponseBody - public CommonResult> list(@RequestParam(value = "useStatus", required = false) Integer useStatus) { - List couponHistoryList = memberCouponService.list(useStatus); - return CommonResult.success(couponHistoryList); + public CommonResult> list(@RequestParam(value = "useStatus", required = false) Integer useStatus) { + List couponList = memberCouponService.list(useStatus); + return CommonResult.success(couponList); } @ApiOperation("获取登录会员购物车的相关优惠券") @@ -55,8 +66,16 @@ public class UmsMemberCouponController { @RequestMapping(value = "/list/cart/{type}", method = RequestMethod.GET) @ResponseBody public CommonResult> listCart(@PathVariable Integer type) { - List cartPromotionItemList = cartItemService.listPromotion(memberService.getCurrentMember().getId()); + List cartPromotionItemList = cartItemService.listPromotion(memberService.getCurrentMember().getId(), null); List couponHistoryList = memberCouponService.listCart(cartPromotionItemList, type); return CommonResult.success(couponHistoryList); } + + @ApiOperation("获取当前商品相关优惠券") + @RequestMapping(value = "/listByProduct/{productId}", method = RequestMethod.GET) + @ResponseBody + public CommonResult> listByProduct(@PathVariable Long productId) { + List couponHistoryList = memberCouponService.listByProduct(productId); + return CommonResult.success(couponHistoryList); + } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberReceiveAddressController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberReceiveAddressController.java index 76cfb33..27470be 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberReceiveAddressController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberReceiveAddressController.java @@ -63,7 +63,7 @@ public class UmsMemberReceiveAddressController { return CommonResult.success(addressList); } - @ApiOperation("显示所有收货地址") + @ApiOperation("获取收货地址详情") @RequestMapping(value = "/{id}", method = RequestMethod.GET) @ResponseBody public CommonResult getItem(@PathVariable Long id) { diff --git a/mall-portal/src/main/java/com/macro/mall/portal/dao/PortalProductDao.java b/mall-portal/src/main/java/com/macro/mall/portal/dao/PortalProductDao.java index 0e3a296..9a68d3a 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/dao/PortalProductDao.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/dao/PortalProductDao.java @@ -1,5 +1,6 @@ package com.macro.mall.portal.dao; +import com.macro.mall.model.SmsCoupon; import com.macro.mall.portal.domain.CartProduct; import com.macro.mall.portal.domain.PromotionProduct; import org.apache.ibatis.annotations.Param; @@ -13,4 +14,5 @@ import java.util.List; public interface PortalProductDao { CartProduct getCartProduct(@Param("id") Long id); List getPromotionProductList(@Param("ids") List ids); + List getAvailableCouponList(@Param("productId") Long productId,@Param("productCategoryId")Long productCategoryId); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/dao/SmsCouponHistoryDao.java b/mall-portal/src/main/java/com/macro/mall/portal/dao/SmsCouponHistoryDao.java index 06b687c..238010e 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/dao/SmsCouponHistoryDao.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/dao/SmsCouponHistoryDao.java @@ -1,6 +1,8 @@ package com.macro.mall.portal.dao; +import com.macro.mall.model.SmsCoupon; import com.macro.mall.portal.domain.SmsCouponHistoryDetail; +import io.swagger.models.auth.In; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -11,4 +13,5 @@ import java.util.List; */ public interface SmsCouponHistoryDao { List getDetailList(@Param("memberId") Long memberId); + List getCouponList(@Param("memberId") Long memberId, @Param("useStatus")Integer useStatus); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberBrandAttention.java b/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberBrandAttention.java index c8f4fbe..9b2f5d6 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberBrandAttention.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberBrandAttention.java @@ -23,7 +23,6 @@ public class MemberBrandAttention { private String brandName; private String brandLogo; private String brandCity; - private Integer brandAttentionCount; private Date createTime; public String getId() { @@ -90,14 +89,6 @@ public class MemberBrandAttention { this.brandCity = brandCity; } - public Integer getBrandAttentionCount() { - return brandAttentionCount; - } - - public void setBrandAttentionCount(Integer brandAttentionCount) { - this.brandAttentionCount = brandAttentionCount; - } - public Date getCreateTime() { return createTime; } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberDetails.java b/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberDetails.java index ffca0d7..2d6f663 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberDetails.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/domain/MemberDetails.java @@ -1,61 +1,61 @@ -package com.macro.mall.portal.domain; - -import com.macro.mall.model.UmsMember; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Arrays; -import java.util.Collection; - -/** - * 会员详情封装 - * Created by macro on 2018/8/3. - */ -public class MemberDetails implements UserDetails { - private UmsMember umsMember; - - public MemberDetails(UmsMember umsMember) { - this.umsMember = umsMember; - } - - @Override - public Collection getAuthorities() { - //返回当前用户的权限 - return Arrays.asList(new SimpleGrantedAuthority("TEST")); - } - - @Override - public String getPassword() { - return umsMember.getPassword(); - } - - @Override - public String getUsername() { - return umsMember.getUsername(); - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return umsMember.getStatus()==1; - } - - public UmsMember getUmsMember() { - return umsMember; - } -} +//package com.macro.mall.portal.domain; +// +//import com.macro.mall.model.UmsMember; +//import org.springframework.security.core.GrantedAuthority; +//import org.springframework.security.core.authority.SimpleGrantedAuthority; +//import org.springframework.security.core.userdetails.UserDetails; +// +//import java.util.Arrays; +//import java.util.Collection; +// +///** +// * 会员详情封装 +// * Created by macro on 2018/8/3. +// */ +//public class MemberDetails implements UserDetails { +// private UmsMember umsMember; +// +// public MemberDetails(UmsMember umsMember) { +// this.umsMember = umsMember; +// } +// +// @Override +// public Collection getAuthorities() { +// //返回当前用户的权限 +// return Arrays.asList(new SimpleGrantedAuthority("TEST")); +// } +// +// @Override +// public String getPassword() { +// return umsMember.getPassword(); +// } +// +// @Override +// public String getUsername() { +// return umsMember.getUsername(); +// } +// +// @Override +// public boolean isAccountNonExpired() { +// return true; +// } +// +// @Override +// public boolean isAccountNonLocked() { +// return true; +// } +// +// @Override +// public boolean isCredentialsNonExpired() { +// return true; +// } +// +// @Override +// public boolean isEnabled() { +// return umsMember.getStatus()==1; +// } +// +// public UmsMember getUmsMember() { +// return umsMember; +// } +//} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/domain/OrderParam.java b/mall-portal/src/main/java/com/macro/mall/portal/domain/OrderParam.java index c5abbd8..9ffdab0 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/domain/OrderParam.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/domain/OrderParam.java @@ -1,48 +1,26 @@ package com.macro.mall.portal.domain; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + /** * 生成订单时传入的参数 * Created by macro on 2018/8/30. */ +@Data +@EqualsAndHashCode(callSuper = false) public class OrderParam { - //收货地址id + @ApiModelProperty("收货地址ID") private Long memberReceiveAddressId; - //优惠券id + @ApiModelProperty("优惠券ID") private Long couponId; - //使用的积分数 + @ApiModelProperty("使用的积分数") private Integer useIntegration; - //支付方式 + @ApiModelProperty("支付方式") private Integer payType; - - public Long getMemberReceiveAddressId() { - return memberReceiveAddressId; - } - - public void setMemberReceiveAddressId(Long memberReceiveAddressId) { - this.memberReceiveAddressId = memberReceiveAddressId; - } - - public Long getCouponId() { - return couponId; - } - - public void setCouponId(Long couponId) { - this.couponId = couponId; - } - - public Integer getPayType() { - return payType; - } - - public void setPayType(Integer payType) { - this.payType = payType; - } - - public Integer getUseIntegration() { - return useIntegration; - } - - public void setUseIntegration(Integer useIntegration) { - this.useIntegration = useIntegration; - } + @ApiModelProperty("被选中的购物车商品ID") + private List cartIds; } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/domain/PmsPortalProductDetail.java b/mall-portal/src/main/java/com/macro/mall/portal/domain/PmsPortalProductDetail.java new file mode 100644 index 0000000..10eeb20 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/domain/PmsPortalProductDetail.java @@ -0,0 +1,33 @@ +package com.macro.mall.portal.domain; + +import com.macro.mall.model.*; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * 前台商品详情 + * Created by macro on 2020/4/6. + */ +@Getter +@Setter +public class PmsPortalProductDetail{ + @ApiModelProperty("商品信息") + private PmsProduct product; + @ApiModelProperty("商品品牌") + private PmsBrand brand; + @ApiModelProperty("商品属性与参数") + private List productAttributeList; + @ApiModelProperty("手动录入的商品属性与参数值") + private List productAttributeValueList; + @ApiModelProperty("商品的sku库存信息") + private List skuStockList; + @ApiModelProperty("商品阶梯价格设置") + private List productLadderList; + @ApiModelProperty("商品满减价格设置") + private List productFullReductionList; + @ApiModelProperty("商品可用优惠券") + private List couponList; +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/domain/PmsProductCategoryNode.java b/mall-portal/src/main/java/com/macro/mall/portal/domain/PmsProductCategoryNode.java new file mode 100644 index 0000000..053009e --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/domain/PmsProductCategoryNode.java @@ -0,0 +1,17 @@ +package com.macro.mall.portal.domain; + +import com.macro.mall.model.PmsProductCategory; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * 商品分类,包含子分类 + * Created by macro on 2020/4/6. + */ +@Getter +@Setter +public class PmsProductCategoryNode extends PmsProductCategory { + private List children; +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberBrandAttentionRepository.java b/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberBrandAttentionRepository.java index 0339017..afb92b4 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberBrandAttentionRepository.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberBrandAttentionRepository.java @@ -1,6 +1,8 @@ package com.macro.mall.portal.repository; import com.macro.mall.portal.domain.MemberBrandAttention; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; import java.util.List; @@ -12,5 +14,6 @@ import java.util.List; public interface MemberBrandAttentionRepository extends MongoRepository { MemberBrandAttention findByMemberIdAndBrandId(Long memberId, Long brandId); int deleteByMemberIdAndBrandId(Long memberId,Long brandId); - List findByMemberId(Long memberId); + Page findByMemberId(Long memberId, Pageable pageable); + void deleteAllByMemberId(Long memberId); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberProductCollectionRepository.java b/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberProductCollectionRepository.java index 1a2abdd..d4fe60e 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberProductCollectionRepository.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberProductCollectionRepository.java @@ -1,6 +1,8 @@ package com.macro.mall.portal.repository; import com.macro.mall.portal.domain.MemberProductCollection; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; import java.util.List; @@ -12,5 +14,6 @@ import java.util.List; public interface MemberProductCollectionRepository extends MongoRepository { MemberProductCollection findByMemberIdAndProductId(Long memberId, Long productId); int deleteByMemberIdAndProductId(Long memberId,Long productId); - List findByMemberId(Long memberId); + Page findByMemberId(Long memberId, Pageable pageable); + void deleteAllByMemberId(Long memberId); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberReadHistoryRepository.java b/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberReadHistoryRepository.java index edd8f2b..7629e8d 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberReadHistoryRepository.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/repository/MemberReadHistoryRepository.java @@ -1,6 +1,8 @@ package com.macro.mall.portal.repository; import com.macro.mall.portal.domain.MemberReadHistory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; import java.util.List; @@ -10,5 +12,6 @@ import java.util.List; * Created by macro on 2018/8/3. */ public interface MemberReadHistoryRepository extends MongoRepository { - List findByMemberIdOrderByCreateTimeDesc(Long memberId); + Page findByMemberIdOrderByCreateTimeDesc(Long memberId, Pageable pageable); + void deleteAllByMemberId(Long memberId); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/AuthService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/AuthService.java new file mode 100644 index 0000000..a382e68 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/AuthService.java @@ -0,0 +1,20 @@ +package com.macro.mall.portal.service; + +import com.macro.mall.common.api.CommonResult; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.Map; + +/** + * 认证服务远程调用 + * Created by macro on 2020/7/19. + */ +@FeignClient("mall-auth") +public interface AuthService { + + @PostMapping(value = "/oauth/token") + CommonResult getAccessToken(@RequestParam Map parameters); + +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/HomeService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/HomeService.java index 762c6f0..d502e42 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/HomeService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/HomeService.java @@ -34,4 +34,14 @@ public interface HomeService { * @param cateId 专题分类id */ List getSubjectList(Long cateId, Integer pageSize, Integer pageNum); + + /** + * 分页获取人气推荐商品 + */ + List hotProductList(Integer pageNum, Integer pageSize); + + /** + * 分页获取新品推荐商品 + */ + List newProductList(Integer pageNum, Integer pageSize); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/MemberAttentionService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/MemberAttentionService.java index 977fd3b..6a64917 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/MemberAttentionService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/MemberAttentionService.java @@ -1,6 +1,7 @@ package com.macro.mall.portal.service; import com.macro.mall.portal.domain.MemberBrandAttention; +import org.springframework.data.domain.Page; import java.util.List; @@ -17,10 +18,20 @@ public interface MemberAttentionService { /** * 取消关注 */ - int delete(Long memberId, Long brandId); + int delete(Long brandId); /** * 获取用户关注列表 */ - List list(Long memberId); + Page list(Integer pageNum, Integer pageSize); + + /** + * 获取用户关注详情 + */ + MemberBrandAttention detail(Long brandId); + + /** + * 清空关注列表 + */ + void clear(); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/MemberCollectionService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/MemberCollectionService.java index 5b2d080..6bb7812 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/MemberCollectionService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/MemberCollectionService.java @@ -1,6 +1,7 @@ package com.macro.mall.portal.service; import com.macro.mall.portal.domain.MemberProductCollection; +import org.springframework.data.domain.Page; import java.util.List; @@ -9,9 +10,13 @@ import java.util.List; * Created by macro on 2018/8/2. */ public interface MemberCollectionService { - int addProduct(MemberProductCollection productCollection); + int add(MemberProductCollection productCollection); - int deleteProduct(Long memberId, Long productId); + int delete(Long productId); - List listProduct(Long memberId); + Page list(Integer pageNum, Integer pageSize); + + MemberProductCollection detail(Long productId); + + void clear(); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/MemberReadHistoryService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/MemberReadHistoryService.java index 66f38f2..f3fcc81 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/MemberReadHistoryService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/MemberReadHistoryService.java @@ -1,6 +1,7 @@ package com.macro.mall.portal.service; import com.macro.mall.portal.domain.MemberReadHistory; +import org.springframework.data.domain.Page; import java.util.List; @@ -20,7 +21,12 @@ public interface MemberReadHistoryService { int delete(List ids); /** - * 获取用户浏览历史记录 + * 分页获取用户浏览历史记录 */ - List list(Long memberId); + Page list(Integer pageNum, Integer pageSize); + + /** + * 清空浏览记录 + */ + void clear(); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/OmsCartItemService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/OmsCartItemService.java index ef401df..96da5dd 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/OmsCartItemService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/OmsCartItemService.java @@ -26,7 +26,7 @@ public interface OmsCartItemService { /** * 获取包含促销活动信息的购物车列表 */ - List listPromotion(Long memberId); + List listPromotion(Long memberId, List cartIds); /** * 修改某个购物车商品的数量 diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/OmsPortalOrderService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/OmsPortalOrderService.java index 46048f5..9aa3e19 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/OmsPortalOrderService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/OmsPortalOrderService.java @@ -1,9 +1,12 @@ package com.macro.mall.portal.service; +import com.macro.mall.common.api.CommonPage; import com.macro.mall.portal.domain.ConfirmOrderResult; +import com.macro.mall.portal.domain.OmsOrderDetail; import com.macro.mall.portal.domain.OrderParam; import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.Map; /** @@ -13,8 +16,9 @@ import java.util.Map; public interface OmsPortalOrderService { /** * 根据用户购物车信息生成确认单信息 + * @param cartIds */ - ConfirmOrderResult generateConfirmOrder(); + ConfirmOrderResult generateConfirmOrder(List cartIds); /** * 根据提交信息生成订单 @@ -26,7 +30,7 @@ public interface OmsPortalOrderService { * 支付成功后的回调 */ @Transactional - Integer paySuccess(Long orderId); + Integer paySuccess(Long orderId, Integer payType); /** * 自动取消超时订单 @@ -44,4 +48,24 @@ public interface OmsPortalOrderService { * 发送延迟消息取消订单 */ void sendDelayMessageCancelOrder(Long orderId); + + /** + * 确认收货 + */ + void confirmReceiveOrder(Long orderId); + + /** + * 分页获取用户订单 + */ + CommonPage list(Integer status, Integer pageNum, Integer pageSize); + + /** + * 根据订单ID获取订单详情 + */ + OmsOrderDetail detail(Long orderId); + + /** + * 用户根据订单ID删除订单 + */ + void deleteOrder(Long orderId); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/PmsPortalProductService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/PmsPortalProductService.java new file mode 100644 index 0000000..fdf3dea --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/PmsPortalProductService.java @@ -0,0 +1,28 @@ +package com.macro.mall.portal.service; + +import com.macro.mall.model.PmsProduct; +import com.macro.mall.portal.domain.PmsPortalProductDetail; +import com.macro.mall.portal.domain.PmsProductCategoryNode; + +import java.util.List; + +/** + * 前台商品管理Service + * Created by macro on 2020/4/6. + */ +public interface PmsPortalProductService { + /** + * 综合搜索商品 + */ + List search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize, Integer sort); + + /** + * 以树形结构获取所有商品分类 + */ + List categoryTreeList(); + + /** + * 获取前台商品详情 + */ + PmsPortalProductDetail detail(Long id); +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/PortalBrandService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/PortalBrandService.java new file mode 100644 index 0000000..256db28 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/PortalBrandService.java @@ -0,0 +1,28 @@ +package com.macro.mall.portal.service; + +import com.macro.mall.common.api.CommonPage; +import com.macro.mall.model.PmsBrand; +import com.macro.mall.model.PmsProduct; + +import java.util.List; + +/** + * 前台品牌管理Service + * Created by macro on 2020/5/15. + */ +public interface PortalBrandService { + /** + * 分页获取推荐品牌 + */ + List recommendList(Integer pageNum, Integer pageSize); + + /** + * 获取品牌详情 + */ + PmsBrand detail(Long brandId); + + /** + * 分页获取品牌关联商品 + */ + CommonPage productList(Long brandId, Integer pageNum, Integer pageSize); +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/RedisService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/RedisService.java deleted file mode 100644 index bc1bf81..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/RedisService.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.macro.mall.portal.service; - -/** - * redis操作Service, - * 对象和数组都以json形式进行存储 - * Created by macro on 2018/8/7. - */ -public interface RedisService { - /** - * 存储数据 - */ - void set(String key, String value); - - /** - * 获取数据 - */ - String get(String key); - - /** - * 设置超期时间 - */ - boolean expire(String key, long expire); - - /** - * 删除数据 - */ - void remove(String key); - - /** - * 自增操作 - * @param delta 自增步长 - */ - Long increment(String key, long delta); - -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCacheService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCacheService.java new file mode 100644 index 0000000..f5c0dd7 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCacheService.java @@ -0,0 +1,34 @@ +package com.macro.mall.portal.service; + +import com.macro.mall.model.UmsMember; + +/** + * 会员信息缓存业务类 + * Created by macro on 2020/3/14. + */ +public interface UmsMemberCacheService { + /** + * 删除会员用户缓存 + */ + void delMember(Long memberId); + + /** + * 获取会员用户缓存 + */ + UmsMember getMember(Long memberId); + + /** + * 设置会员用户缓存 + */ + void setMember(UmsMember member); + + /** + * 设置验证码 + */ + void setAuthCode(String telephone, String authCode); + + /** + * 获取验证码 + */ + String getAuthCode(String telephone); +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCouponService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCouponService.java index a34a1db..44ada98 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCouponService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberCouponService.java @@ -1,5 +1,6 @@ package com.macro.mall.portal.service; +import com.macro.mall.model.SmsCoupon; import com.macro.mall.model.SmsCouponHistory; import com.macro.mall.portal.domain.CartPromotionItem; import com.macro.mall.portal.domain.SmsCouponHistoryDetail; @@ -19,13 +20,22 @@ public interface UmsMemberCouponService { void add(Long couponId); /** - * 获取优惠券列表 - * @param useStatus 优惠券的使用状态 + * 获取优惠券历史列表 */ - List list(Integer useStatus); + List listHistory(Integer useStatus); /** * 根据购物车信息获取可用优惠券 */ List listCart(List cartItemList, Integer type); + + /** + * 获取当前商品相关优惠券 + */ + List listByProduct(Long productId); + + /** + * 获取用户优惠券列表 + */ + List list(Integer useStatus); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberReceiveAddressService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberReceiveAddressService.java index dcfab7b..3c70c8d 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberReceiveAddressService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberReceiveAddressService.java @@ -1,6 +1,7 @@ package com.macro.mall.portal.service; import com.macro.mall.model.UmsMemberReceiveAddress; +import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -25,6 +26,7 @@ public interface UmsMemberReceiveAddressService { * @param id 地址表的id * @param address 修改的收货地址信息 */ + @Transactional int update(Long id, UmsMemberReceiveAddress address); /** diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java index 0dfc499..42199f4 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java @@ -1,8 +1,8 @@ package com.macro.mall.portal.service; import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.domain.UserDto; import com.macro.mall.model.UmsMember; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.transaction.annotation.Transactional; /** @@ -51,15 +51,10 @@ public interface UmsMemberService { /** * 获取用户信息 */ - UserDetails loadUserByUsername(String username); + UserDto loadUserByUsername(String username); /** * 登录后获取token */ - String login(String username, String password); - - /** - * 刷新token - */ - String refreshToken(String token); + CommonResult login(String username, String password); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/HomeServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/HomeServiceImpl.java index 16d3d74..0f98a0a 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/HomeServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/HomeServiceImpl.java @@ -43,7 +43,7 @@ public class HomeServiceImpl implements HomeService { //获取首页广告 result.setAdvertiseList(getHomeAdvertiseList()); //获取推荐品牌 - result.setBrandList(homeDao.getRecommendBrandList(0,4)); + result.setBrandList(homeDao.getRecommendBrandList(0,6)); //获取秒杀信息 result.setHomeFlashPromotion(getHomeFlashPromotion()); //获取新品推荐 @@ -88,6 +88,18 @@ public class HomeServiceImpl implements HomeService { return subjectMapper.selectByExample(example); } + @Override + public List hotProductList(Integer pageNum, Integer pageSize) { + int offset = pageSize * (pageNum - 1); + return homeDao.getHotProductList(offset, pageSize); + } + + @Override + public List newProductList(Integer pageNum, Integer pageSize) { + int offset = pageSize * (pageNum - 1); + return homeDao.getNewProductList(offset, pageSize); + } + private HomeFlashPromotion getHomeFlashPromotion() { HomeFlashPromotion homeFlashPromotion = new HomeFlashPromotion(); //获取当前秒杀活动 diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberAttentionServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberAttentionServiceImpl.java index 42038ff..1a05d18 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberAttentionServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberAttentionServiceImpl.java @@ -1,11 +1,17 @@ package com.macro.mall.portal.service.impl; +import com.macro.mall.model.UmsMember; import com.macro.mall.portal.domain.MemberBrandAttention; import com.macro.mall.portal.repository.MemberBrandAttentionRepository; import com.macro.mall.portal.service.MemberAttentionService; +import com.macro.mall.portal.service.UmsMemberService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import java.util.Date; import java.util.List; /** @@ -16,10 +22,17 @@ import java.util.List; public class MemberAttentionServiceImpl implements MemberAttentionService { @Autowired private MemberBrandAttentionRepository memberBrandAttentionRepository; + @Autowired + private UmsMemberService memberService; @Override public int add(MemberBrandAttention memberBrandAttention) { int count = 0; + UmsMember member = memberService.getCurrentMember(); + memberBrandAttention.setMemberId(member.getId()); + memberBrandAttention.setMemberNickname(member.getNickname()); + memberBrandAttention.setMemberIcon(member.getIcon()); + memberBrandAttention.setCreateTime(new Date()); MemberBrandAttention findAttention = memberBrandAttentionRepository.findByMemberIdAndBrandId(memberBrandAttention.getMemberId(), memberBrandAttention.getBrandId()); if (findAttention == null) { memberBrandAttentionRepository.save(memberBrandAttention); @@ -29,12 +42,27 @@ public class MemberAttentionServiceImpl implements MemberAttentionService { } @Override - public int delete(Long memberId, Long brandId) { - return memberBrandAttentionRepository.deleteByMemberIdAndBrandId(memberId,brandId); + public int delete(Long brandId) { + UmsMember member = memberService.getCurrentMember(); + return memberBrandAttentionRepository.deleteByMemberIdAndBrandId(member.getId(),brandId); } @Override - public List list(Long memberId) { - return memberBrandAttentionRepository.findByMemberId(memberId); + public Page list(Integer pageNum, Integer pageSize) { + UmsMember member = memberService.getCurrentMember(); + Pageable pageable = PageRequest.of(pageNum-1,pageSize); + return memberBrandAttentionRepository.findByMemberId(member.getId(),pageable); + } + + @Override + public MemberBrandAttention detail(Long brandId) { + UmsMember member = memberService.getCurrentMember(); + return memberBrandAttentionRepository.findByMemberIdAndBrandId(member.getId(), brandId); + } + + @Override + public void clear() { + UmsMember member = memberService.getCurrentMember(); + memberBrandAttentionRepository.deleteAllByMemberId(member.getId()); } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberCollectionServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberCollectionServiceImpl.java index 7c02ecc..e79b3fd 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberCollectionServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberCollectionServiceImpl.java @@ -1,9 +1,14 @@ package com.macro.mall.portal.service.impl; +import com.macro.mall.model.UmsMember; import com.macro.mall.portal.domain.MemberProductCollection; import com.macro.mall.portal.repository.MemberProductCollectionRepository; import com.macro.mall.portal.service.MemberCollectionService; +import com.macro.mall.portal.service.UmsMemberService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; @@ -16,10 +21,16 @@ import java.util.List; public class MemberCollectionServiceImpl implements MemberCollectionService { @Autowired private MemberProductCollectionRepository productCollectionRepository; + @Autowired + private UmsMemberService memberService; @Override - public int addProduct(MemberProductCollection productCollection) { + public int add(MemberProductCollection productCollection) { int count = 0; + UmsMember member = memberService.getCurrentMember(); + productCollection.setMemberId(member.getId()); + productCollection.setMemberNickname(member.getNickname()); + productCollection.setMemberIcon(member.getIcon()); MemberProductCollection findCollection = productCollectionRepository.findByMemberIdAndProductId(productCollection.getMemberId(), productCollection.getProductId()); if (findCollection == null) { productCollectionRepository.save(productCollection); @@ -29,12 +40,27 @@ public class MemberCollectionServiceImpl implements MemberCollectionService { } @Override - public int deleteProduct(Long memberId, Long productId) { - return productCollectionRepository.deleteByMemberIdAndProductId(memberId, productId); + public int delete(Long productId) { + UmsMember member = memberService.getCurrentMember(); + return productCollectionRepository.deleteByMemberIdAndProductId(member.getId(), productId); } @Override - public List listProduct(Long memberId) { - return productCollectionRepository.findByMemberId(memberId); + public Page list(Integer pageNum, Integer pageSize) { + UmsMember member = memberService.getCurrentMember(); + Pageable pageable = PageRequest.of(pageNum - 1, pageSize); + return productCollectionRepository.findByMemberId(member.getId(), pageable); + } + + @Override + public MemberProductCollection detail(Long productId) { + UmsMember member = memberService.getCurrentMember(); + return productCollectionRepository.findByMemberIdAndProductId(member.getId(), productId); + } + + @Override + public void clear() { + UmsMember member = memberService.getCurrentMember(); + productCollectionRepository.deleteAllByMemberId(member.getId()); } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberReadHistoryServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberReadHistoryServiceImpl.java index d8ed9f5..7b5e884 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberReadHistoryServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/MemberReadHistoryServiceImpl.java @@ -1,9 +1,14 @@ package com.macro.mall.portal.service.impl; +import com.macro.mall.model.UmsMember; import com.macro.mall.portal.domain.MemberReadHistory; import com.macro.mall.portal.repository.MemberReadHistoryRepository; import com.macro.mall.portal.service.MemberReadHistoryService; +import com.macro.mall.portal.service.UmsMemberService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -18,8 +23,14 @@ import java.util.List; public class MemberReadHistoryServiceImpl implements MemberReadHistoryService { @Autowired private MemberReadHistoryRepository memberReadHistoryRepository; + @Autowired + private UmsMemberService memberService; @Override public int create(MemberReadHistory memberReadHistory) { + UmsMember member = memberService.getCurrentMember(); + memberReadHistory.setMemberId(member.getId()); + memberReadHistory.setMemberNickname(member.getNickname()); + memberReadHistory.setMemberIcon(member.getIcon()); memberReadHistory.setId(null); memberReadHistory.setCreateTime(new Date()); memberReadHistoryRepository.save(memberReadHistory); @@ -39,7 +50,15 @@ public class MemberReadHistoryServiceImpl implements MemberReadHistoryService { } @Override - public List list(Long memberId) { - return memberReadHistoryRepository.findByMemberIdOrderByCreateTimeDesc(memberId); + public Page list(Integer pageNum, Integer pageSize) { + UmsMember member = memberService.getCurrentMember(); + Pageable pageable = PageRequest.of(pageNum-1, pageSize); + return memberReadHistoryRepository.findByMemberIdOrderByCreateTimeDesc(member.getId(),pageable); + } + + @Override + public void clear() { + UmsMember member = memberService.getCurrentMember(); + memberReadHistoryRepository.deleteAllByMemberId(member.getId()); } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsCartItemServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsCartItemServiceImpl.java index 1f818e9..869678c 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsCartItemServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsCartItemServiceImpl.java @@ -1,5 +1,6 @@ package com.macro.mall.portal.service.impl; +import cn.hutool.core.collection.CollUtil; import com.macro.mall.mapper.OmsCartItemMapper; import com.macro.mall.model.OmsCartItem; import com.macro.mall.model.OmsCartItemExample; @@ -18,6 +19,7 @@ import org.springframework.util.StringUtils; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; /** * 购物车管理Service实现类 @@ -78,8 +80,11 @@ public class OmsCartItemServiceImpl implements OmsCartItemService { } @Override - public List listPromotion(Long memberId) { + public List listPromotion(Long memberId, List cartIds) { List cartItemList = list(memberId); + if(CollUtil.isNotEmpty(cartIds)){ + cartItemList = cartItemList.stream().filter(item->cartIds.contains(item.getId())).collect(Collectors.toList()); + } List cartPromotionItemList = new ArrayList<>(); if(!CollectionUtils.isEmpty(cartItemList)){ cartPromotionItemList = promotionService.calcCartPromotion(cartItemList); diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java index 6c7a33b..bc021e6 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java @@ -1,6 +1,11 @@ package com.macro.mall.portal.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import com.github.pagehelper.PageHelper; +import com.macro.mall.common.api.CommonPage; import com.macro.mall.common.exception.Asserts; +import com.macro.mall.common.service.RedisService; import com.macro.mall.mapper.*; import com.macro.mall.model.*; import com.macro.mall.portal.component.CancelOrderSender; @@ -18,6 +23,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; +import java.util.stream.Collectors; /** * 前台订单管理Service @@ -47,8 +53,10 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { private SmsCouponHistoryMapper couponHistoryMapper; @Autowired private RedisService redisService; - @Value("${redis.key.prefix.orderId}") - private String REDIS_KEY_PREFIX_ORDER_ID; + @Value("${redis.key.orderId}") + private String REDIS_KEY_ORDER_ID; + @Value("${redis.database}") + private String REDIS_DATABASE; @Autowired private PortalOrderDao portalOrderDao; @Autowired @@ -59,11 +67,11 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { private CancelOrderSender cancelOrderSender; @Override - public ConfirmOrderResult generateConfirmOrder() { + public ConfirmOrderResult generateConfirmOrder(List cartIds) { ConfirmOrderResult result = new ConfirmOrderResult(); //获取购物车信息 UmsMember currentMember = memberService.getCurrentMember(); - List cartPromotionItemList = cartItemService.listPromotion(currentMember.getId()); + List cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(),cartIds); result.setCartPromotionItemList(cartPromotionItemList); //获取用户收货地址列表 List memberReceiveAddressList = memberReceiveAddressService.list(); @@ -87,7 +95,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { List orderItemList = new ArrayList<>(); //获取购物车及优惠信息 UmsMember currentMember = memberService.getCurrentMember(); - List cartPromotionItemList = cartItemService.listPromotion(currentMember.getId()); + List cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(), orderParam.getCartIds()); for (CartPromotionItem cartPromotionItem : cartPromotionItemList) { //生成下单商品信息 OmsOrderItem orderItem = new OmsOrderItem(); @@ -128,7 +136,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { handleCouponAmount(orderItemList, couponHistoryDetail); } //判断是否使用积分 - if (orderParam.getUseIntegration() == null) { + if (orderParam.getUseIntegration() == null||orderParam.getUseIntegration().equals(0)) { //不使用积分 for (OmsOrderItem orderItem : orderItemList) { orderItem.setIntegrationAmount(new BigDecimal(0)); @@ -202,6 +210,11 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { order.setGrowth(calcGiftGrowth(orderItemList)); //生成订单号 order.setOrderSn(generateOrderSn(order)); + //设置自动收货天数 + List orderSettings = orderSettingMapper.selectByExample(new OmsOrderSettingExample()); + if(CollUtil.isNotEmpty(orderSettings)){ + order.setAutoConfirmDay(orderSettings.get(0).getConfirmOvertime()); + } // TODO: 2018/9/3 bill_*,delivery_* //插入order表和order_item表 orderMapper.insert(order); @@ -230,12 +243,13 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { } @Override - public Integer paySuccess(Long orderId) { + public Integer paySuccess(Long orderId, Integer payType) { //修改订单支付状态 OmsOrder order = new OmsOrder(); order.setId(orderId); order.setStatus(1); order.setPaymentTime(new Date()); + order.setPayType(payType); orderMapper.updateByPrimaryKeySelective(order); //恢复所有下单商品的锁定库存,扣减真实库存 OmsOrderDetail orderDetail = portalOrderDao.getDetail(orderId); @@ -274,7 +288,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { @Override public void cancelOrder(Long orderId) { - //查询为付款的取消订单 + //查询未付款的取消订单 OmsOrderExample example = new OmsOrderExample(); example.createCriteria().andIdEqualTo(orderId).andStatusEqualTo(0).andDeleteStatusEqualTo(0); List cancelOrderList = orderMapper.selectByExample(example); @@ -312,14 +326,100 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { cancelOrderSender.sendMessage(orderId, delayTimes); } + @Override + public void confirmReceiveOrder(Long orderId) { + UmsMember member = memberService.getCurrentMember(); + OmsOrder order = orderMapper.selectByPrimaryKey(orderId); + if(!member.getId().equals(order.getMemberId())){ + Asserts.fail("不能确认他人订单!"); + } + if(order.getStatus()!=2){ + Asserts.fail("该订单还未发货!"); + } + order.setStatus(3); + order.setConfirmStatus(1); + order.setReceiveTime(new Date()); + orderMapper.updateByPrimaryKey(order); + } + + @Override + public CommonPage list(Integer status, Integer pageNum, Integer pageSize) { + if(status==-1){ + status = null; + } + UmsMember member = memberService.getCurrentMember(); + PageHelper.startPage(pageNum,pageSize); + OmsOrderExample orderExample = new OmsOrderExample(); + OmsOrderExample.Criteria criteria = orderExample.createCriteria(); + criteria.andDeleteStatusEqualTo(0) + .andMemberIdEqualTo(member.getId()); + if(status!=null){ + criteria.andStatusEqualTo(status); + } + orderExample.setOrderByClause("create_time desc"); + List orderList = orderMapper.selectByExample(orderExample); + CommonPage orderPage = CommonPage.restPage(orderList); + //设置分页信息 + CommonPage resultPage = new CommonPage<>(); + resultPage.setPageNum(orderPage.getPageNum()); + resultPage.setPageSize(orderPage.getPageSize()); + resultPage.setTotal(orderPage.getTotal()); + resultPage.setTotalPage(orderPage.getTotalPage()); + if(CollUtil.isEmpty(orderList)){ + return resultPage; + } + //设置数据信息 + List orderIds = orderList.stream().map(OmsOrder::getId).collect(Collectors.toList()); + OmsOrderItemExample orderItemExample = new OmsOrderItemExample(); + orderItemExample.createCriteria().andOrderIdIn(orderIds); + List orderItemList = orderItemMapper.selectByExample(orderItemExample); + List orderDetailList = new ArrayList<>(); + for (OmsOrder omsOrder : orderList) { + OmsOrderDetail orderDetail = new OmsOrderDetail(); + BeanUtil.copyProperties(omsOrder,orderDetail); + List relatedItemList = orderItemList.stream().filter(item -> item.getOrderId().equals(orderDetail.getId())).collect(Collectors.toList()); + orderDetail.setOrderItemList(relatedItemList); + orderDetailList.add(orderDetail); + } + resultPage.setList(orderDetailList); + return resultPage; + } + + @Override + public OmsOrderDetail detail(Long orderId) { + OmsOrder omsOrder = orderMapper.selectByPrimaryKey(orderId); + OmsOrderItemExample example = new OmsOrderItemExample(); + example.createCriteria().andOrderIdEqualTo(orderId); + List orderItemList = orderItemMapper.selectByExample(example); + OmsOrderDetail orderDetail = new OmsOrderDetail(); + BeanUtil.copyProperties(omsOrder,orderDetail); + orderDetail.setOrderItemList(orderItemList); + return orderDetail; + } + + @Override + public void deleteOrder(Long orderId) { + UmsMember member = memberService.getCurrentMember(); + OmsOrder order = orderMapper.selectByPrimaryKey(orderId); + if(!member.getId().equals(order.getMemberId())){ + Asserts.fail("不能删除他人订单!"); + } + if(order.getStatus()==3||order.getStatus()==4){ + order.setDeleteStatus(1); + orderMapper.updateByPrimaryKey(order); + }else{ + Asserts.fail("只能删除已完成或已关闭的订单!"); + } + } + /** * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id */ private String generateOrderSn(OmsOrder order) { StringBuilder sb = new StringBuilder(); String date = new SimpleDateFormat("yyyyMMdd").format(new Date()); - String key = REDIS_KEY_PREFIX_ORDER_ID + date; - Long increment = redisService.increment(key, 1); + String key = REDIS_DATABASE+":"+ REDIS_KEY_ORDER_ID + date; + Long increment = redisService.incr(key, 1); sb.append(date); sb.append(String.format("%02d", order.getSourceType())); sb.append(String.format("%02d", order.getPayType())); @@ -405,10 +505,10 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService { StringBuilder sb = new StringBuilder(); for (OmsOrderItem orderItem : orderItemList) { sb.append(orderItem.getPromotionName()); - sb.append(","); + sb.append(";"); } String result = sb.toString(); - if (result.endsWith(",")) { + if (result.endsWith(";")) { result = result.substring(0, result.length() - 1); } return result; diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java index 72657df..0be2dce 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java @@ -48,6 +48,8 @@ public class OmsPromotionServiceImpl implements OmsPromotionService { //商品原价-促销价 PmsSkuStock skuStock = getOriginalPrice(promotionProduct, item.getProductSkuId()); BigDecimal originalPrice = skuStock.getPrice(); + //单品促销使用原价 + cartPromotionItem.setPrice(originalPrice); cartPromotionItem.setReduceAmount(originalPrice.subtract(skuStock.getPromotionPrice())); cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock()); cartPromotionItem.setIntegration(promotionProduct.getGiftPoint()); diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/PmsPortalProductServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/PmsPortalProductServiceImpl.java new file mode 100644 index 0000000..d29eaa0 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/PmsPortalProductServiceImpl.java @@ -0,0 +1,142 @@ +package com.macro.mall.portal.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.github.pagehelper.PageHelper; +import com.macro.mall.mapper.*; +import com.macro.mall.model.*; +import com.macro.mall.portal.dao.PortalProductDao; +import com.macro.mall.portal.domain.PmsPortalProductDetail; +import com.macro.mall.portal.domain.PmsProductCategoryNode; +import com.macro.mall.portal.service.PmsPortalProductService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 前台订单管理Service实现类 + * Created by macro on 2020/4/6. + */ +@Service +public class PmsPortalProductServiceImpl implements PmsPortalProductService { + @Autowired + private PmsProductMapper productMapper; + @Autowired + private PmsProductCategoryMapper productCategoryMapper; + @Autowired + private PmsBrandMapper brandMapper; + @Autowired + private PmsProductAttributeMapper productAttributeMapper; + @Autowired + private PmsProductAttributeValueMapper productAttributeValueMapper; + @Autowired + private PmsSkuStockMapper skuStockMapper; + @Autowired + private PmsProductLadderMapper productLadderMapper; + @Autowired + private PmsProductFullReductionMapper productFullReductionMapper; + @Autowired + private PortalProductDao portalProductDao; + + @Override + public List search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize, Integer sort) { + PageHelper.startPage(pageNum, pageSize); + PmsProductExample example = new PmsProductExample(); + PmsProductExample.Criteria criteria = example.createCriteria(); + criteria.andDeleteStatusEqualTo(0); + if (StrUtil.isNotEmpty(keyword)) { + criteria.andNameLike("%" + keyword + "%"); + } + if (brandId != null) { + criteria.andBrandIdEqualTo(brandId); + } + if (productCategoryId != null) { + criteria.andProductCategoryIdEqualTo(productCategoryId); + } + //1->按新品;2->按销量;3->价格从低到高;4->价格从高到低 + if (sort == 1) { + example.setOrderByClause("id desc"); + } else if (sort == 2) { + example.setOrderByClause("sale desc"); + } else if (sort == 3) { + example.setOrderByClause("price asc"); + } else if (sort == 4) { + example.setOrderByClause("price desc"); + } + return productMapper.selectByExample(example); + } + + @Override + public List categoryTreeList() { + PmsProductCategoryExample example = new PmsProductCategoryExample(); + List allList = productCategoryMapper.selectByExample(example); + List result = allList.stream() + .filter(item -> item.getParentId().equals(0L)) + .map(item -> covert(item, allList)).collect(Collectors.toList()); + return result; + } + + @Override + public PmsPortalProductDetail detail(Long id) { + PmsPortalProductDetail result = new PmsPortalProductDetail(); + //获取商品信息 + PmsProduct product = productMapper.selectByPrimaryKey(id); + result.setProduct(product); + //获取品牌信息 + PmsBrand brand = brandMapper.selectByPrimaryKey(product.getBrandId()); + result.setBrand(brand); + //获取商品属性信息 + PmsProductAttributeExample attributeExample = new PmsProductAttributeExample(); + attributeExample.createCriteria().andProductAttributeCategoryIdEqualTo(product.getProductAttributeCategoryId()); + List productAttributeList = productAttributeMapper.selectByExample(attributeExample); + result.setProductAttributeList(productAttributeList); + //获取商品属性值信息 + if(CollUtil.isNotEmpty(productAttributeList)){ + List attributeIds = productAttributeList.stream().map(PmsProductAttribute::getId).collect(Collectors.toList()); + PmsProductAttributeValueExample attributeValueExample = new PmsProductAttributeValueExample(); + attributeValueExample.createCriteria().andProductIdEqualTo(product.getId()) + .andProductAttributeIdIn(attributeIds); + List productAttributeValueList = productAttributeValueMapper.selectByExample(attributeValueExample); + result.setProductAttributeValueList(productAttributeValueList); + } + //获取商品SKU库存信息 + PmsSkuStockExample skuExample = new PmsSkuStockExample(); + skuExample.createCriteria().andProductIdEqualTo(product.getId()); + List skuStockList = skuStockMapper.selectByExample(skuExample); + result.setSkuStockList(skuStockList); + //商品阶梯价格设置 + if(product.getPromotionType()==3){ + PmsProductLadderExample ladderExample = new PmsProductLadderExample(); + ladderExample.createCriteria().andProductIdEqualTo(product.getId()); + List productLadderList = productLadderMapper.selectByExample(ladderExample); + result.setProductLadderList(productLadderList); + } + //商品满减价格设置 + if(product.getPromotionType()==4){ + PmsProductFullReductionExample fullReductionExample = new PmsProductFullReductionExample(); + fullReductionExample.createCriteria().andProductIdEqualTo(product.getId()); + List productFullReductionList = productFullReductionMapper.selectByExample(fullReductionExample); + result.setProductFullReductionList(productFullReductionList); + } + //商品可用优惠券 + result.setCouponList(portalProductDao.getAvailableCouponList(product.getId(),product.getProductCategoryId())); + return result; + } + + + /** + * 初始对象转化为节点对象 + */ + private PmsProductCategoryNode covert(PmsProductCategory item, List allList) { + PmsProductCategoryNode node = new PmsProductCategoryNode(); + BeanUtils.copyProperties(item, node); + List children = allList.stream() + .filter(subItem -> subItem.getParentId().equals(item.getId())) + .map(subItem -> covert(subItem, allList)).collect(Collectors.toList()); + node.setChildren(children); + return node; + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/PortalBrandServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/PortalBrandServiceImpl.java new file mode 100644 index 0000000..a95bebf --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/PortalBrandServiceImpl.java @@ -0,0 +1,50 @@ +package com.macro.mall.portal.service.impl; + +import com.github.pagehelper.PageHelper; +import com.macro.mall.common.api.CommonPage; +import com.macro.mall.mapper.PmsBrandMapper; +import com.macro.mall.mapper.PmsProductMapper; +import com.macro.mall.model.PmsBrand; +import com.macro.mall.model.PmsProduct; +import com.macro.mall.model.PmsProductExample; +import com.macro.mall.portal.dao.HomeDao; +import com.macro.mall.portal.service.PortalBrandService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 前台品牌管理Service实现类 + * Created by macro on 2020/5/15. + */ +@Service +public class PortalBrandServiceImpl implements PortalBrandService { + @Autowired + private HomeDao homeDao; + @Autowired + private PmsBrandMapper brandMapper; + @Autowired + private PmsProductMapper productMapper; + + @Override + public List recommendList(Integer pageNum, Integer pageSize) { + int offset = (pageNum - 1) * pageSize; + return homeDao.getRecommendBrandList(offset, pageSize); + } + + @Override + public PmsBrand detail(Long brandId) { + return brandMapper.selectByPrimaryKey(brandId); + } + + @Override + public CommonPage productList(Long brandId, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum,pageSize); + PmsProductExample example = new PmsProductExample(); + example.createCriteria().andDeleteStatusEqualTo(0) + .andBrandIdEqualTo(brandId); + List productList = productMapper.selectByExample(example); + return CommonPage.restPage(productList); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/RedisServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/RedisServiceImpl.java deleted file mode 100644 index 8426397..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/RedisServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.macro.mall.portal.service.impl; - -import com.macro.mall.portal.service.RedisService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Service; - -import java.util.concurrent.TimeUnit; - -/** - * redis操作Service的实现类 - * Created by macro on 2018/8/7. - */ -@Service -public class RedisServiceImpl implements RedisService { - @Autowired - private StringRedisTemplate stringRedisTemplate; - - @Override - public void set(String key, String value) { - stringRedisTemplate.opsForValue().set(key, value); - } - - @Override - public String get(String key) { - return stringRedisTemplate.opsForValue().get(key); - } - - @Override - public boolean expire(String key, long expire) { - return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS); - } - - @Override - public void remove(String key) { - stringRedisTemplate.delete(key); - } - - @Override - public Long increment(String key, long delta) { - return stringRedisTemplate.opsForValue().increment(key,delta); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCacheServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCacheServiceImpl.java new file mode 100644 index 0000000..42812fe --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCacheServiceImpl.java @@ -0,0 +1,62 @@ +package com.macro.mall.portal.service.impl; + +import com.macro.mall.common.annotation.CacheException; +import com.macro.mall.common.service.RedisService; +import com.macro.mall.mapper.UmsMemberMapper; +import com.macro.mall.model.UmsMember; +import com.macro.mall.portal.service.UmsMemberCacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * UmsMemberCacheService实现类 + * Created by macro on 2020/3/14. + */ +@Service +public class UmsMemberCacheServiceImpl implements UmsMemberCacheService { + @Autowired + private RedisService redisService; + @Value("${redis.database}") + private String REDIS_DATABASE; + @Value("${redis.expire.common}") + private Long REDIS_EXPIRE; + @Value("${redis.expire.authCode}") + private Long REDIS_EXPIRE_AUTH_CODE; + @Value("${redis.key.member}") + private String REDIS_KEY_MEMBER; + @Value("${redis.key.authCode}") + private String REDIS_KEY_AUTH_CODE; + + @Override + public void delMember(Long memberId) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + memberId; + redisService.del(key); + } + + @Override + public UmsMember getMember(Long memberId) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + memberId; + return (UmsMember) redisService.get(key); + } + + @Override + public void setMember(UmsMember member) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_MEMBER + ":" + member.getId(); + redisService.set(key, member, REDIS_EXPIRE); + } + + @CacheException + @Override + public void setAuthCode(String telephone, String authCode) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_AUTH_CODE + ":" + telephone; + redisService.set(key, authCode, REDIS_EXPIRE_AUTH_CODE); + } + + @CacheException + @Override + public String getAuthCode(String telephone) { + String key = REDIS_DATABASE + ":" + REDIS_KEY_AUTH_CODE + ":" + telephone; + return (String) redisService.get(key); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCouponServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCouponServiceImpl.java index d38c872..19c05c8 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCouponServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberCouponServiceImpl.java @@ -1,8 +1,8 @@ package com.macro.mall.portal.service.impl; +import cn.hutool.core.collection.CollUtil; import com.macro.mall.common.exception.Asserts; -import com.macro.mall.mapper.SmsCouponHistoryMapper; -import com.macro.mall.mapper.SmsCouponMapper; +import com.macro.mall.mapper.*; import com.macro.mall.model.*; import com.macro.mall.portal.dao.SmsCouponHistoryDao; import com.macro.mall.portal.domain.CartPromotionItem; @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; +import java.util.stream.Collectors; /** * 会员优惠券管理Service实现类 @@ -32,6 +33,12 @@ public class UmsMemberCouponServiceImpl implements UmsMemberCouponService { private SmsCouponHistoryMapper couponHistoryMapper; @Autowired private SmsCouponHistoryDao couponHistoryDao; + @Autowired + private SmsCouponProductRelationMapper couponProductRelationMapper; + @Autowired + private SmsCouponProductCategoryRelationMapper couponProductCategoryRelationMapper; + @Autowired + private PmsProductMapper productMapper; @Override public void add(Long couponId) { UmsMember currentMember = memberService.getCurrentMember(); @@ -93,7 +100,7 @@ public class UmsMemberCouponServiceImpl implements UmsMemberCouponService { } @Override - public List list(Integer useStatus) { + public List listHistory(Integer useStatus) { UmsMember currentMember = memberService.getCurrentMember(); SmsCouponHistoryExample couponHistoryExample=new SmsCouponHistoryExample(); SmsCouponHistoryExample.Criteria criteria = couponHistoryExample.createCriteria(); @@ -162,6 +169,48 @@ public class UmsMemberCouponServiceImpl implements UmsMemberCouponService { } } + @Override + public List listByProduct(Long productId) { + List allCouponIds = new ArrayList<>(); + //获取指定商品优惠券 + SmsCouponProductRelationExample cprExample = new SmsCouponProductRelationExample(); + cprExample.createCriteria().andProductIdEqualTo(productId); + List cprList = couponProductRelationMapper.selectByExample(cprExample); + if(CollUtil.isNotEmpty(cprList)){ + List couponIds = cprList.stream().map(SmsCouponProductRelation::getCouponId).collect(Collectors.toList()); + allCouponIds.addAll(couponIds); + } + //获取指定分类优惠券 + PmsProduct product = productMapper.selectByPrimaryKey(productId); + SmsCouponProductCategoryRelationExample cpcrExample = new SmsCouponProductCategoryRelationExample(); + cpcrExample.createCriteria().andProductCategoryIdEqualTo(product.getProductCategoryId()); + List cpcrList = couponProductCategoryRelationMapper.selectByExample(cpcrExample); + if(CollUtil.isNotEmpty(cpcrList)){ + List couponIds = cpcrList.stream().map(SmsCouponProductCategoryRelation::getCouponId).collect(Collectors.toList()); + allCouponIds.addAll(couponIds); + } + if(CollUtil.isEmpty(allCouponIds)){ + return new ArrayList<>(); + } + //所有优惠券 + SmsCouponExample couponExample = new SmsCouponExample(); + couponExample.createCriteria().andEndTimeGreaterThan(new Date()) + .andStartTimeLessThan(new Date()) + .andUseTypeEqualTo(0); + couponExample.or(couponExample.createCriteria() + .andEndTimeGreaterThan(new Date()) + .andStartTimeLessThan(new Date()) + .andUseTypeNotEqualTo(0) + .andIdIn(allCouponIds)); + return couponMapper.selectByExample(couponExample); + } + + @Override + public List list(Integer useStatus) { + UmsMember member = memberService.getCurrentMember(); + return couponHistoryDao.getCouponList(member.getId(),useStatus); + } + private BigDecimal calcTotalAmount(List cartItemList) { BigDecimal total = new BigDecimal("0"); for (CartPromotionItem item : cartItemList) { diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberReceiveAddressServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberReceiveAddressServiceImpl.java index e7bafda..29c6c14 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberReceiveAddressServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberReceiveAddressServiceImpl.java @@ -43,6 +43,16 @@ public class UmsMemberReceiveAddressServiceImpl implements UmsMemberReceiveAddre UmsMember currentMember = memberService.getCurrentMember(); UmsMemberReceiveAddressExample example = new UmsMemberReceiveAddressExample(); example.createCriteria().andMemberIdEqualTo(currentMember.getId()).andIdEqualTo(id); + if(address.getDefaultStatus()==1){ + //先将原来的默认地址去除 + UmsMemberReceiveAddress record= new UmsMemberReceiveAddress(); + record.setDefaultStatus(0); + UmsMemberReceiveAddressExample updateExample = new UmsMemberReceiveAddressExample(); + updateExample.createCriteria() + .andMemberIdEqualTo(currentMember.getId()) + .andDefaultStatusEqualTo(1); + addressMapper.updateByExampleSelective(record,updateExample); + } return addressMapper.updateByExampleSelective(address,example); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java index 49ee902..bb67824 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java @@ -1,5 +1,14 @@ package com.macro.mall.portal.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.BCrypt; +import cn.hutool.json.JSONUtil; +import com.macro.mall.common.api.CommonResult; +import com.macro.mall.common.api.ResultCode; +import com.macro.mall.common.constant.AuthConstant; +import com.macro.mall.common.domain.UserDto; import com.macro.mall.common.exception.Asserts; import com.macro.mall.mapper.UmsMemberLevelMapper; import com.macro.mall.mapper.UmsMemberMapper; @@ -7,30 +16,20 @@ import com.macro.mall.model.UmsMember; import com.macro.mall.model.UmsMemberExample; import com.macro.mall.model.UmsMemberLevel; import com.macro.mall.model.UmsMemberLevelExample; -import com.macro.mall.portal.domain.MemberDetails; -import com.macro.mall.portal.service.RedisService; +import com.macro.mall.portal.service.AuthService; +import com.macro.mall.portal.service.UmsMemberCacheService; import com.macro.mall.portal.service.UmsMemberService; -import com.macro.mall.security.util.JwtTokenUtil; +import org.apache.catalina.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.Date; -import java.util.List; -import java.util.Random; +import javax.servlet.http.HttpServletRequest; +import java.util.*; /** * 会员管理Service实现类 @@ -40,19 +39,19 @@ import java.util.Random; public class UmsMemberServiceImpl implements UmsMemberService { private static final Logger LOGGER = LoggerFactory.getLogger(UmsMemberServiceImpl.class); @Autowired - private PasswordEncoder passwordEncoder; - @Autowired - private JwtTokenUtil jwtTokenUtil; - @Autowired private UmsMemberMapper memberMapper; @Autowired private UmsMemberLevelMapper memberLevelMapper; @Autowired - private RedisService redisService; - @Value("${redis.key.prefix.authCode}") + private UmsMemberCacheService memberCacheService; + @Value("${redis.key.authCode}") private String REDIS_KEY_PREFIX_AUTH_CODE; - @Value("${redis.key.expire.authCode}") + @Value("${redis.expire.authCode}") private Long AUTH_CODE_EXPIRE_SECONDS; + @Autowired + private AuthService authService; + @Autowired + private HttpServletRequest request; @Override public UmsMember getByUsername(String username) { @@ -88,7 +87,7 @@ public class UmsMemberServiceImpl implements UmsMemberService { UmsMember umsMember = new UmsMember(); umsMember.setUsername(username); umsMember.setPhone(telephone); - umsMember.setPassword(passwordEncoder.encode(password)); + umsMember.setPassword(BCrypt.hashpw(password)); umsMember.setCreateTime(new Date()); umsMember.setStatus(1); //获取默认会员等级并设置 @@ -109,9 +108,7 @@ public class UmsMemberServiceImpl implements UmsMemberService { for(int i=0;i<6;i++){ sb.append(random.nextInt(10)); } - //验证码绑定手机号并存储到redis - redisService.set(REDIS_KEY_PREFIX_AUTH_CODE+telephone,sb.toString()); - redisService.expire(REDIS_KEY_PREFIX_AUTH_CODE+telephone,AUTH_CODE_EXPIRE_SECONDS); + memberCacheService.setAuthCode(telephone,sb.toString()); return sb.toString(); } @@ -128,16 +125,26 @@ public class UmsMemberServiceImpl implements UmsMemberService { Asserts.fail("验证码错误"); } UmsMember umsMember = memberList.get(0); - umsMember.setPassword(passwordEncoder.encode(password)); + umsMember.setPassword(BCrypt.hashpw(password)); memberMapper.updateByPrimaryKeySelective(umsMember); + memberCacheService.delMember(umsMember.getId()); } @Override public UmsMember getCurrentMember() { - SecurityContext ctx = SecurityContextHolder.getContext(); - Authentication auth = ctx.getAuthentication(); - MemberDetails memberDetails = (MemberDetails) auth.getPrincipal(); - return memberDetails.getUmsMember(); + String userStr = request.getHeader(AuthConstant.USER_TOKEN_HEADER); + if(StrUtil.isEmpty(userStr)){ + Asserts.fail(ResultCode.UNAUTHORIZED); + } + UserDto userDto = JSONUtil.toBean(userStr, UserDto.class); + UmsMember member = memberCacheService.getMember(userDto.getId()); + if(member!=null){ + return member; + }else{ + member = getById(userDto.getId()); + memberCacheService.setMember(member); + return member; + } } @Override @@ -146,38 +153,33 @@ public class UmsMemberServiceImpl implements UmsMemberService { record.setId(id); record.setIntegration(integration); memberMapper.updateByPrimaryKeySelective(record); + memberCacheService.delMember(id); } @Override - public UserDetails loadUserByUsername(String username) { + public UserDto loadUserByUsername(String username) { UmsMember member = getByUsername(username); if(member!=null){ - return new MemberDetails(member); + UserDto userDto = new UserDto(); + BeanUtil.copyProperties(member,userDto); + userDto.setRoles(CollUtil.toList("前台会员")); + return userDto; } - throw new UsernameNotFoundException("用户名或密码错误"); + return null; } @Override - public String login(String username, String password) { - String token = null; - //密码需要客户端加密后传递 - try { - UserDetails userDetails = loadUserByUsername(username); - if(!passwordEncoder.matches(password,userDetails.getPassword())){ - throw new BadCredentialsException("密码不正确"); - } - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - token = jwtTokenUtil.generateToken(userDetails); - } catch (AuthenticationException e) { - LOGGER.warn("登录异常:{}", e.getMessage()); + public CommonResult login(String username, String password) { + if(StrUtil.isEmpty(username)||StrUtil.isEmpty(password)){ + Asserts.fail("用户名或密码不能为空!"); } - return token; - } - - @Override - public String refreshToken(String token) { - return jwtTokenUtil.refreshHeadToken(token); + Map params = new HashMap<>(); + params.put("client_id", AuthConstant.PORTAL_CLIENT_ID); + params.put("client_secret","123456"); + params.put("grant_type","password"); + params.put("username",username); + params.put("password",password); + return authService.getAccessToken(params); } //对输入的验证码进行校验 @@ -185,7 +187,7 @@ public class UmsMemberServiceImpl implements UmsMemberService { if(StringUtils.isEmpty(authCode)){ return false; } - String realAuthCode = redisService.get(REDIS_KEY_PREFIX_AUTH_CODE + telephone); + String realAuthCode = memberCacheService.getAuthCode(telephone); return authCode.equals(realAuthCode); } diff --git a/mall-portal/src/main/resources/application.yml b/mall-portal/src/main/resources/application.yml index 1bab897..03b5955 100644 --- a/mall-portal/src/main/resources/application.yml +++ b/mall-portal/src/main/resources/application.yml @@ -24,12 +24,6 @@ spring: database: 0 # Redis数据库索引(默认为0) port: 6379 # Redis服务器连接端口 password: # Redis服务器连接密码(默认为空) - jedis: - pool: - max-active: 8 # 连接池最大连接数(使用负值表示没有限制) - max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) - max-idle: 8 # 连接池中的最大空闲连接 - min-idle: 0 # 连接池中的最小空闲连接 timeout: 3000ms # 连接超时时间(毫秒) rabbitmq: host: localhost @@ -37,7 +31,6 @@ spring: virtual-host: /mall username: mall password: mall - publisher-confirms: true #如果对异步消息需要回调必须设置为true mybatis: mapper-locations: - classpath:dao/*.xml @@ -50,38 +43,26 @@ management: #开启SpringBoot Admin的监控 endpoint: health: show-details: always -jwt: - tokenHeader: Authorization #JWT存储的请求头 - secret: mall-portal-secret #JWT加解密使用的密钥 - expiration: 604800 #JWT的超期限时间(60*60*24) - tokenHead: Bearer #JWT负载中拿到开头 -secure: - ignored: - urls: #安全路径白名单 - - /swagger-ui.html - - /swagger-resources/** - - /swagger/** - - /**/v2/api-docs - - /**/*.js - - /**/*.css - - /**/*.png - - /**/*.ico - - /webjars/springfox-swagger-ui/** - - /druid/** - - /actuator/** - - /sso/** - - /home/** -# 自定义redis键值 + +# 自定义redis key redis: + database: mall key: - prefix: - authCode: "portal:authCode:" - orderId: "portal:orderId:" - expire: - authCode: 90 # 验证码超期时间 -# 自定义消息队列名称 + authCode: 'ums:authCode' + orderId: 'oms:orderId' + member: 'ums:member' + expire: + authCode: 90 # 验证码超期时间 + common: 86400 # 24小时 + +# 消息队列定义 rabbitmq: queue: name: cancelOrder: cancelOrderQueue - +feign: + okhttp: + enabled: true +ribbon: + ConnectTimeout: 3000 #服务请求连接超时时间(毫秒) + ReadTimeout: 3000 #服务请求处理超时时间(毫秒) diff --git a/mall-portal/src/main/resources/bootstrap-dev.yml b/mall-portal/src/main/resources/bootstrap-dev.yml index 6f75d09..365fbba 100644 --- a/mall-portal/src/main/resources/bootstrap-dev.yml +++ b/mall-portal/src/main/resources/bootstrap-dev.yml @@ -1,13 +1,8 @@ spring: cloud: - config: - profile: dev #启用环境名称 - label: master #分支名称 - name: portal #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ \ No newline at end of file + server-addr: http://localhost:8848 + config: + server-addr: http://localhost:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-portal/src/main/resources/bootstrap-prod.yml b/mall-portal/src/main/resources/bootstrap-prod.yml index 9ef2dde..fc71e7a 100644 --- a/mall-portal/src/main/resources/bootstrap-prod.yml +++ b/mall-portal/src/main/resources/bootstrap-prod.yml @@ -1,15 +1,8 @@ spring: cloud: - config: - profile: prod #启用环境名称 - label: master #分支名称 - name: portal #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - instance: - prefer-ip-address: true \ No newline at end of file + server-addr: http://nacos-registry:8848 + config: + server-addr: http://nacos-registry:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-portal/src/main/resources/dao/PortalProductDao.xml b/mall-portal/src/main/resources/dao/PortalProductDao.xml index c5d4607..6ba886a 100644 --- a/mall-portal/src/main/resources/dao/PortalProductDao.xml +++ b/mall-portal/src/main/resources/dao/PortalProductDao.xml @@ -72,4 +72,31 @@ #{id} + \ No newline at end of file diff --git a/mall-portal/src/main/resources/dao/SmsCouponHistoryDao.xml b/mall-portal/src/main/resources/dao/SmsCouponHistoryDao.xml index 895f22f..28c19a4 100644 --- a/mall-portal/src/main/resources/dao/SmsCouponHistoryDao.xml +++ b/mall-portal/src/main/resources/dao/SmsCouponHistoryDao.xml @@ -33,4 +33,21 @@ WHERE ch.member_id = #{memberId} AND ch.use_status = 0 + + \ No newline at end of file diff --git a/mall-registry/.gitignore b/mall-registry/.gitignore deleted file mode 100644 index a2a3040..0000000 --- a/mall-registry/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/mall-registry/pom.xml b/mall-registry/pom.xml deleted file mode 100644 index 4bd37d7..0000000 --- a/mall-registry/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - com.macro.mall - mall-registry - 1.0-SNAPSHOT - mall-registry - mall-registry project for mall - - - com.macro.mall - mall-swarm - 1.0-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-starter-netflix-eureka-server - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.spotify - docker-maven-plugin - ${docker.maven.plugin.version} - - - build-image - package - - build - - - - - mall/${project.artifactId}:${project.version} - ${docker.host} - java:8 - ["java", "-jar", "-Dspring.profiles.active=prod","/${project.build.finalName}.jar"] - - - / - ${project.build.directory} - ${project.build.finalName}.jar - - - - - - - - diff --git a/mall-registry/src/main/java/com/macro/mall/MallRegistryApplication.java b/mall-registry/src/main/java/com/macro/mall/MallRegistryApplication.java deleted file mode 100644 index 1139c8c..0000000 --- a/mall-registry/src/main/java/com/macro/mall/MallRegistryApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.macro.mall; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; - -@EnableEurekaServer -@SpringBootApplication -public class MallRegistryApplication { - - public static void main(String[] args) { - SpringApplication.run(MallRegistryApplication.class, args); - } - -} diff --git a/mall-registry/src/main/resources/application.yml b/mall-registry/src/main/resources/application.yml deleted file mode 100644 index 1c16d1c..0000000 --- a/mall-registry/src/main/resources/application.yml +++ /dev/null @@ -1,13 +0,0 @@ -server: - port: 8001 -spring: - application: - name: mall-registry -eureka: - instance: - hostname: localhost - client: - fetch-registry: false - register-with-eureka: false - server: - enable-self-preservation: false diff --git a/mall-registry/src/test/java/com/macro/mall/MallRegistryApplicationTests.java b/mall-registry/src/test/java/com/macro/mall/MallRegistryApplicationTests.java deleted file mode 100644 index dc59b8e..0000000 --- a/mall-registry/src/test/java/com/macro/mall/MallRegistryApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.macro.mall; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -class MallRegistryApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/mall-search/pom.xml b/mall-search/pom.xml index 37cde16..e05e15a 100644 --- a/mall-search/pom.xml +++ b/mall-search/pom.xml @@ -21,6 +21,12 @@ com.macro.mall mall-mbg + + + org.springframework.boot + spring-boot-starter-data-redis + + org.springframework.boot @@ -31,12 +37,12 @@ spring-boot-starter-data-elasticsearch - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery - org.springframework.cloud - spring-cloud-starter-config + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config diff --git a/mall-search/src/main/java/com/macro/mall/search/config/Swagger2Config.java b/mall-search/src/main/java/com/macro/mall/search/config/SwaggerConfig.java similarity index 59% rename from mall-search/src/main/java/com/macro/mall/search/config/Swagger2Config.java rename to mall-search/src/main/java/com/macro/mall/search/config/SwaggerConfig.java index a89caeb..670535a 100644 --- a/mall-search/src/main/java/com/macro/mall/search/config/Swagger2Config.java +++ b/mall-search/src/main/java/com/macro/mall/search/config/SwaggerConfig.java @@ -1,5 +1,7 @@ package com.macro.mall.search.config; +import com.macro.mall.common.config.BaseSwaggerConfig; +import com.macro.mall.common.domain.SwaggerProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; @@ -16,23 +18,17 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; */ @Configuration @EnableSwagger2 -public class Swagger2Config { - @Bean - public Docket createRestApi(){ - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .select() - .apis(RequestHandlerSelectors.basePackage("com.macro.mall.search.controller")) - .paths(PathSelectors.any()) - .build(); - } +public class SwaggerConfig extends BaseSwaggerConfig { - private ApiInfo apiInfo() { - return new ApiInfoBuilder() + @Override + public SwaggerProperties swaggerProperties() { + return SwaggerProperties.builder() + .apiBasePackage("com.macro.mall.search.controller") .title("mall搜索系统") - .description("mall搜索模块") - .contact("macro") + .description("mall搜索相关接口文档") + .contactName("macro") .version("1.0") + .enableSecurity(false) .build(); } } diff --git a/mall-search/src/main/java/com/macro/mall/search/service/impl/EsProductServiceImpl.java b/mall-search/src/main/java/com/macro/mall/search/service/impl/EsProductServiceImpl.java index 0008749..004fb94 100644 --- a/mall-search/src/main/java/com/macro/mall/search/service/impl/EsProductServiceImpl.java +++ b/mall-search/src/main/java/com/macro/mall/search/service/impl/EsProductServiceImpl.java @@ -5,7 +5,6 @@ import com.macro.mall.search.domain.EsProduct; import com.macro.mall.search.domain.EsProductRelatedInfo; import com.macro.mall.search.repository.EsProductRepository; import com.macro.mall.search.service.EsProductService; -import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; @@ -14,10 +13,10 @@ import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.AggregationBuilders; -import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter; -import org.elasticsearch.search.aggregations.bucket.nested.InternalNested; -import org.elasticsearch.search.aggregations.bucket.terms.LongTerms; -import org.elasticsearch.search.aggregations.bucket.terms.StringTerms; +import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter; +import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested; +import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms; +import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; @@ -28,7 +27,10 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; @@ -39,6 +41,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** @@ -53,7 +56,7 @@ public class EsProductServiceImpl implements EsProductService { @Autowired private EsProductRepository productRepository; @Autowired - private ElasticsearchTemplate elasticsearchTemplate; + private ElasticsearchRestTemplate elasticsearchRestTemplate; @Override public int importAll() { List esProductList = productDao.getAllEsProductList(null); @@ -157,7 +160,12 @@ public class EsProductServiceImpl implements EsProductService { nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC)); NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build(); LOGGER.info("DSL:{}", searchQuery.getQuery().toString()); - return productRepository.search(searchQuery); + SearchHits searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class); + if(searchHits.getTotalHits()<=0){ + return new PageImpl<>(null,pageable,0); + } + List searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList()); + return new PageImpl<>(searchProductList,pageable,searchHits.getTotalHits()); } @Override @@ -178,20 +186,30 @@ public class EsProductServiceImpl implements EsProductService { filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("keywords", keyword), ScoreFunctionBuilders.weightFactorFunction(2))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("brandId", brandId), - ScoreFunctionBuilders.weightFactorFunction(10))); + ScoreFunctionBuilders.weightFactorFunction(5))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("productCategoryId", productCategoryId), - ScoreFunctionBuilders.weightFactorFunction(6))); + ScoreFunctionBuilders.weightFactorFunction(3))); FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()]; filterFunctionBuilders.toArray(builders); FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders) .scoreMode(FunctionScoreQuery.ScoreMode.SUM) .setMinScore(2); + //用于过滤掉相同的商品 + BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); + boolQueryBuilder.mustNot(QueryBuilders.termQuery("id",id)); + //构建查询条件 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); builder.withQuery(functionScoreQueryBuilder); + builder.withFilter(boolQueryBuilder); builder.withPageable(pageable); NativeSearchQuery searchQuery = builder.build(); LOGGER.info("DSL:{}", searchQuery.getQuery().toString()); - return productRepository.search(searchQuery); + SearchHits searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class); + if(searchHits.getTotalHits()<=0){ + return new PageImpl<>(null,pageable,0); + } + List searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList()); + return new PageImpl<>(searchProductList,pageable,searchHits.getTotalHits()); } return new PageImpl<>(null); } @@ -220,16 +238,14 @@ public class EsProductServiceImpl implements EsProductService { .field("attrValueList.name")))); builder.addAggregation(aggregationBuilder); NativeSearchQuery searchQuery = builder.build(); - return elasticsearchTemplate.query(searchQuery, response -> { - LOGGER.info("DSL:{}",searchQuery.getQuery().toString()); - return convertProductRelatedInfo(response); - }); + SearchHits searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class); + return convertProductRelatedInfo(searchHits); } /** * 将返回结果转换为对象 */ - private EsProductRelatedInfo convertProductRelatedInfo(SearchResponse response) { + private EsProductRelatedInfo convertProductRelatedInfo(SearchHits response) { EsProductRelatedInfo productRelatedInfo = new EsProductRelatedInfo(); Map aggregationMap = response.getAggregations().getAsMap(); //设置品牌 @@ -248,14 +264,14 @@ public class EsProductServiceImpl implements EsProductService { productRelatedInfo.setProductCategoryNames(productCategoryNameList); //设置参数 Aggregation productAttrs = aggregationMap.get("allAttrValues"); - List attrIds = ((LongTerms) ((InternalFilter) ((InternalNested) productAttrs).getProperty("productAttrs")).getProperty("attrIds")).getBuckets(); + List attrIds = ((ParsedLongTerms) ((ParsedFilter) ((ParsedNested) productAttrs).getAggregations().get("productAttrs")).getAggregations().get("attrIds")).getBuckets(); List attrList = new ArrayList<>(); for (Terms.Bucket attrId : attrIds) { EsProductRelatedInfo.ProductAttr attr = new EsProductRelatedInfo.ProductAttr(); attr.setAttrId((Long) attrId.getKey()); List attrValueList = new ArrayList<>(); - List attrValues = ((StringTerms) attrId.getAggregations().get("attrValues")).getBuckets(); - List attrNames = ((StringTerms) attrId.getAggregations().get("attrNames")).getBuckets(); + List attrValues = ((ParsedStringTerms) attrId.getAggregations().get("attrValues")).getBuckets(); + List attrNames = ((ParsedStringTerms) attrId.getAggregations().get("attrNames")).getBuckets(); for (Terms.Bucket attrValue : attrValues) { attrValueList.add(attrValue.getKeyAsString()); } diff --git a/mall-search/src/main/resources/application.yml b/mall-search/src/main/resources/application.yml index e732a8d..91f581c 100644 --- a/mall-search/src/main/resources/application.yml +++ b/mall-search/src/main/resources/application.yml @@ -18,8 +18,9 @@ spring: elasticsearch: repositories: enabled: true - cluster-nodes: 127.0.0.1:9300 - cluster-name: elasticsearch + elasticsearch: + rest: + uris: 127.0.0.1:9200 mybatis: mapper-locations: - classpath:dao/*.xml diff --git a/mall-search/src/main/resources/bootstrap-dev.yml b/mall-search/src/main/resources/bootstrap-dev.yml index aa84ef6..365fbba 100644 --- a/mall-search/src/main/resources/bootstrap-dev.yml +++ b/mall-search/src/main/resources/bootstrap-dev.yml @@ -1,13 +1,8 @@ spring: cloud: - config: - profile: dev #启用环境名称 - label: master #分支名称 - name: search #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://localhost:8001/eureka/ \ No newline at end of file + server-addr: http://localhost:8848 + config: + server-addr: http://localhost:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-search/src/main/resources/bootstrap-prod.yml b/mall-search/src/main/resources/bootstrap-prod.yml index 3ddb957..fc71e7a 100644 --- a/mall-search/src/main/resources/bootstrap-prod.yml +++ b/mall-search/src/main/resources/bootstrap-prod.yml @@ -1,15 +1,8 @@ spring: cloud: - config: - profile: prod #启用环境名称 - label: master #分支名称 - name: search #配置文件名称 + nacos: discovery: - enabled: true - service-id: mall-config -eureka: - client: - service-url: - defaultZone: http://mall-registry:8001/eureka/ - instance: - prefer-ip-address: true \ No newline at end of file + server-addr: http://nacos-registry:8848 + config: + server-addr: http://nacos-registry:8848 + file-extension: yaml \ No newline at end of file diff --git a/mall-search/src/test/java/com/macro/mall/search/MallSearchApplicationTests.java b/mall-search/src/test/java/com/macro/mall/search/MallSearchApplicationTests.java index ab1f90e..7de5d73 100644 --- a/mall-search/src/test/java/com/macro/mall/search/MallSearchApplicationTests.java +++ b/mall-search/src/test/java/com/macro/mall/search/MallSearchApplicationTests.java @@ -2,14 +2,13 @@ package com.macro.mall.search; import com.macro.mall.search.dao.EsProductDao; import com.macro.mall.search.domain.EsProduct; -import com.macro.mall.search.repository.EsProductRepository; -import org.elasticsearch.action.search.SearchResponse; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.core.ResultsExtractor; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @@ -21,7 +20,7 @@ public class MallSearchApplicationTests { @Autowired private EsProductDao productDao; @Autowired - private ElasticsearchTemplate elasticsearchTemplate; + private ElasticsearchRestTemplate elasticsearchTemplate; @Test public void contextLoads() { } @@ -32,8 +31,9 @@ public class MallSearchApplicationTests { } @Test public void testEsProductMapping(){ - elasticsearchTemplate.putMapping(EsProduct.class); - Map mapping = elasticsearchTemplate.getMapping(EsProduct.class); + IndexOperations indexOperations = elasticsearchTemplate.indexOps(EsProduct.class); + indexOperations.putMapping(indexOperations.createMapping(EsProduct.class)); + Map mapping = indexOperations.getMapping(); System.out.println(mapping); } diff --git a/mall-security/.gitignore b/mall-security/.gitignore deleted file mode 100644 index a2a3040..0000000 --- a/mall-security/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/** -!**/src/test/** - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ - -### VS Code ### -.vscode/ diff --git a/mall-security/pom.xml b/mall-security/pom.xml deleted file mode 100644 index c74d8b7..0000000 --- a/mall-security/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - 4.0.0 - com.macro.mall - mall-security - 1.0-SNAPSHOT - jar - - mall-security - mall-security project for mall - - - com.macro.mall - mall-swarm - 1.0-SNAPSHOT - - - - - com.macro.mall - mall-common - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-security - - - io.jsonwebtoken - jjwt - - - - diff --git a/mall-security/src/main/java/com/macro/mall/security/component/DynamicAccessDecisionManager.java b/mall-security/src/main/java/com/macro/mall/security/component/DynamicAccessDecisionManager.java deleted file mode 100644 index 36dfec2..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/DynamicAccessDecisionManager.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.macro.mall.security.component; - -import cn.hutool.core.collection.CollUtil; -import org.springframework.security.access.AccessDecisionManager; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.ConfigAttribute; -import org.springframework.security.authentication.InsufficientAuthenticationException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; -import java.util.Iterator; - -/** - * 动态权限决策管理器,用于判断用户是否有访问权限 - * Created by macro on 2020/2/7. - */ -public class DynamicAccessDecisionManager implements AccessDecisionManager { - - @Override - public void decide(Authentication authentication, Object object, - Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { - // 当接口未被配置资源时直接放行 - if (CollUtil.isEmpty(configAttributes)) { - return; - } - Iterator iterator = configAttributes.iterator(); - while (iterator.hasNext()) { - ConfigAttribute configAttribute = iterator.next(); - //将访问所需资源或用户拥有资源进行比对 - String needAuthority = configAttribute.getAttribute(); - for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { - if (needAuthority.trim().equals(grantedAuthority.getAuthority())) { - return; - } - } - } - throw new AccessDeniedException("抱歉,您没有访问权限"); - } - - @Override - public boolean supports(ConfigAttribute configAttribute) { - return true; - } - - @Override - public boolean supports(Class aClass) { - return true; - } - -} diff --git a/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityFilter.java b/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityFilter.java deleted file mode 100644 index ae49b8b..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityFilter.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.macro.mall.security.component; - -import com.macro.mall.security.config.IgnoreUrlsConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpMethod; -import org.springframework.security.access.SecurityMetadataSource; -import org.springframework.security.access.intercept.AbstractSecurityInterceptor; -import org.springframework.security.access.intercept.InterceptorStatusToken; -import org.springframework.security.web.FilterInvocation; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; - -/** - * 动态权限过滤器,用于实现基于路径的动态权限过滤 - * Created by macro on 2020/2/7. - */ -public class DynamicSecurityFilter extends AbstractSecurityInterceptor implements Filter { - - @Autowired - private DynamicSecurityMetadataSource dynamicSecurityMetadataSource; - @Autowired - private IgnoreUrlsConfig ignoreUrlsConfig; - - @Autowired - public void setMyAccessDecisionManager(DynamicAccessDecisionManager dynamicAccessDecisionManager) { - super.setAccessDecisionManager(dynamicAccessDecisionManager); - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain); - //OPTIONS请求直接放行 - if(request.getMethod().equals(HttpMethod.OPTIONS.toString())){ - fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); - return; - } - //白名单请求直接放行 - PathMatcher pathMatcher = new AntPathMatcher(); - for (String path : ignoreUrlsConfig.getUrls()) { - if(pathMatcher.match(path,request.getRequestURI())){ - fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); - return; - } - } - //此处会调用AccessDecisionManager中的decide方法进行鉴权操作 - InterceptorStatusToken token = super.beforeInvocation(fi); - try { - fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); - } finally { - super.afterInvocation(token, null); - } - } - - @Override - public void destroy() { - } - - @Override - public Class getSecureObjectClass() { - return FilterInvocation.class; - } - - @Override - public SecurityMetadataSource obtainSecurityMetadataSource() { - return dynamicSecurityMetadataSource; - } - -} diff --git a/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityMetadataSource.java b/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityMetadataSource.java deleted file mode 100644 index 7bae7ef..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityMetadataSource.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.macro.mall.security.component; - -import cn.hutool.core.util.URLUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.ConfigAttribute; -import org.springframework.security.web.FilterInvocation; -import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; - -import javax.annotation.PostConstruct; -import java.util.*; - -/** - * 动态权限数据源,用于获取动态权限规则 - * Created by macro on 2020/2/7. - */ -public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { - - private static Map configAttributeMap = null; - @Autowired - private DynamicSecurityService dynamicSecurityService; - - @PostConstruct - public void loadDataSource() { - configAttributeMap = dynamicSecurityService.loadDataSource(); - } - - public void clearDataSource() { - configAttributeMap.clear(); - configAttributeMap = null; - } - - @Override - public Collection getAttributes(Object o) throws IllegalArgumentException { - if (configAttributeMap == null) this.loadDataSource(); - List configAttributes = new ArrayList<>(); - //获取当前访问的路径 - String url = ((FilterInvocation) o).getRequestUrl(); - String path = URLUtil.getPath(url); - PathMatcher pathMatcher = new AntPathMatcher(); - Iterator iterator = configAttributeMap.keySet().iterator(); - //获取访问该路径所需资源 - while (iterator.hasNext()) { - String pattern = iterator.next(); - if (pathMatcher.match(pattern, path)) { - configAttributes.add(configAttributeMap.get(pattern)); - } - } - // 未设置操作请求权限,返回空集合 - return configAttributes; - } - - @Override - public Collection getAllConfigAttributes() { - return null; - } - - @Override - public boolean supports(Class aClass) { - return true; - } - -} diff --git a/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityService.java b/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityService.java deleted file mode 100644 index 1246672..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.macro.mall.security.component; - -import org.springframework.security.access.ConfigAttribute; - -import java.util.Map; - -/** - * 动态权限相关业务类 - * Created by macro on 2020/2/7. - */ -public interface DynamicSecurityService { - /** - * 加载资源ANT通配符和资源对应MAP - */ - Map loadDataSource(); -} diff --git a/mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java b/mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java deleted file mode 100644 index bddd916..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.macro.mall.security.component; - -import com.macro.mall.security.util.JwtTokenUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * JWT登录授权过滤器 - * Created by macro on 2018/4/26. - */ -public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class); - @Autowired - private UserDetailsService userDetailsService; - @Autowired - private JwtTokenUtil jwtTokenUtil; - @Value("${jwt.tokenHeader}") - private String tokenHeader; - @Value("${jwt.tokenHead}") - private String tokenHead; - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, - FilterChain chain) throws ServletException, IOException { - String authHeader = request.getHeader(this.tokenHeader); - if (authHeader != null && authHeader.startsWith(this.tokenHead)) { - String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " - String username = jwtTokenUtil.getUserNameFromToken(authToken); - LOGGER.info("checking username:{}", username); - if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { - UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); - if (jwtTokenUtil.validateToken(authToken, userDetails)) { - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - LOGGER.info("authenticated user:{}", username); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } - } - chain.doFilter(request, response); - } -} diff --git a/mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java b/mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java deleted file mode 100644 index 5bd8536..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.macro.mall.security.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.stereotype.Component; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 自定义返回结果:未登录或登录过期 - * Created by macro on 2018/5/14. - */ -public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - response.setHeader("Access-Control-Allow-Origin", "*"); - response.setHeader("Cache-Control","no-cache"); - response.setCharacterEncoding("UTF-8"); - response.setContentType("application/json"); - response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage()))); - response.getWriter().flush(); - } -} diff --git a/mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java b/mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java deleted file mode 100644 index 1d0795d..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.macro.mall.security.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.stereotype.Component; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 自定义返回结果:没有权限访问时 - * Created by macro on 2018/4/26. - */ -public class RestfulAccessDeniedHandler implements AccessDeniedHandler{ - @Override - public void handle(HttpServletRequest request, - HttpServletResponse response, - AccessDeniedException e) throws IOException, ServletException { - response.setHeader("Access-Control-Allow-Origin", "*"); - response.setHeader("Cache-Control","no-cache"); - response.setCharacterEncoding("UTF-8"); - response.setContentType("application/json"); - response.getWriter().println(JSONUtil.parse(CommonResult.forbidden(e.getMessage()))); - response.getWriter().flush(); - } -} diff --git a/mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java b/mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java deleted file mode 100644 index a380184..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.macro.mall.security.config; - -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.util.ArrayList; -import java.util.List; - -/** - * 用于配置不需要保护的资源路径 - * Created by macro on 2018/11/5. - */ -@Getter -@Setter -@ConfigurationProperties(prefix = "secure.ignored") -public class IgnoreUrlsConfig { - - private List urls = new ArrayList<>(); - -} diff --git a/mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java b/mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java deleted file mode 100644 index a16d7fe..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.macro.mall.security.config; - -import com.macro.mall.security.component.*; -import com.macro.mall.security.util.JwtTokenUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - - -/** - * 对SpringSecurity的配置的扩展,支持自定义白名单资源路径和查询用户逻辑 - * Created by macro on 2019/11/5. - */ -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - @Autowired(required = false) - private DynamicSecurityService dynamicSecurityService; - - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { - ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity - .authorizeRequests(); - //不需要保护的资源路径允许访问 - for (String url : ignoreUrlsConfig().getUrls()) { - registry.antMatchers(url).permitAll(); - } - //允许跨域请求的OPTIONS请求 - registry.antMatchers(HttpMethod.OPTIONS) - .permitAll(); - // 任何请求需要身份认证 - registry.and() - .authorizeRequests() - .anyRequest() - .authenticated() - // 关闭跨站请求防护及不使用session - .and() - .csrf() - .disable() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - // 自定义权限拒绝处理类 - .and() - .exceptionHandling() - .accessDeniedHandler(restfulAccessDeniedHandler()) - .authenticationEntryPoint(restAuthenticationEntryPoint()) - // 自定义权限拦截器JWT过滤器 - .and() - .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); - //有动态权限配置时添加动态权限校验过滤器 - if(dynamicSecurityService!=null){ - registry.and().addFilterBefore(dynamicSecurityFilter(), FilterSecurityInterceptor.class); - } - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService()) - .passwordEncoder(passwordEncoder()); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() { - return new JwtAuthenticationTokenFilter(); - } - - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - - @Bean - public RestfulAccessDeniedHandler restfulAccessDeniedHandler() { - return new RestfulAccessDeniedHandler(); - } - - @Bean - public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { - return new RestAuthenticationEntryPoint(); - } - - @Bean - public IgnoreUrlsConfig ignoreUrlsConfig() { - return new IgnoreUrlsConfig(); - } - - @Bean - public JwtTokenUtil jwtTokenUtil() { - return new JwtTokenUtil(); - } - - @ConditionalOnBean(name = "dynamicSecurityService") - @Bean - public DynamicAccessDecisionManager dynamicAccessDecisionManager() { - return new DynamicAccessDecisionManager(); - } - - - @ConditionalOnBean(name = "dynamicSecurityService") - @Bean - public DynamicSecurityFilter dynamicSecurityFilter() { - return new DynamicSecurityFilter(); - } - - @ConditionalOnBean(name = "dynamicSecurityService") - @Bean - public DynamicSecurityMetadataSource dynamicSecurityMetadataSource() { - return new DynamicSecurityMetadataSource(); - } - -} diff --git a/mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java b/mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java deleted file mode 100644 index 81eb969..0000000 --- a/mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.macro.mall.security.util; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -/** - * JwtToken生成的工具类 - * JWT token的格式:header.payload.signature - * header的格式(算法、token的类型): - * {"alg": "HS512","typ": "JWT"} - * payload的格式(用户名、创建时间、生成时间): - * {"sub":"wang","created":1489079981393,"exp":1489684781} - * signature的生成算法: - * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) - * Created by macro on 2018/4/26. - */ -public class JwtTokenUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); - private static final String CLAIM_KEY_USERNAME = "sub"; - private static final String CLAIM_KEY_CREATED = "created"; - @Value("${jwt.secret}") - private String secret; - @Value("${jwt.expiration}") - private Long expiration; - @Value("${jwt.tokenHead}") - private String tokenHead; - - /** - * 根据负责生成JWT的token - */ - private String generateToken(Map claims) { - return Jwts.builder() - .setClaims(claims) - .setExpiration(generateExpirationDate()) - .signWith(SignatureAlgorithm.HS512, secret) - .compact(); - } - - /** - * 从token中获取JWT中的负载 - */ - private Claims getClaimsFromToken(String token) { - Claims claims = null; - try { - claims = Jwts.parser() - .setSigningKey(secret) - .parseClaimsJws(token) - .getBody(); - } catch (Exception e) { - LOGGER.info("JWT格式验证失败:{}", token); - } - return claims; - } - - /** - * 生成token的过期时间 - */ - private Date generateExpirationDate() { - return new Date(System.currentTimeMillis() + expiration * 1000); - } - - /** - * 从token中获取登录用户名 - */ - public String getUserNameFromToken(String token) { - String username; - try { - Claims claims = getClaimsFromToken(token); - username = claims.getSubject(); - } catch (Exception e) { - username = null; - } - return username; - } - - /** - * 验证token是否还有效 - * - * @param token 客户端传入的token - * @param userDetails 从数据库中查询出来的用户信息 - */ - public boolean validateToken(String token, UserDetails userDetails) { - String username = getUserNameFromToken(token); - return username.equals(userDetails.getUsername()) && !isTokenExpired(token); - } - - /** - * 判断token是否已经失效 - */ - private boolean isTokenExpired(String token) { - Date expiredDate = getExpiredDateFromToken(token); - return expiredDate.before(new Date()); - } - - /** - * 从token中获取过期时间 - */ - private Date getExpiredDateFromToken(String token) { - Claims claims = getClaimsFromToken(token); - return claims.getExpiration(); - } - - /** - * 根据用户信息生成token - */ - public String generateToken(UserDetails userDetails) { - Map claims = new HashMap<>(); - claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); - claims.put(CLAIM_KEY_CREATED, new Date()); - return generateToken(claims); - } - - /** - * 当原来的token没过期时是可以刷新的 - * - * @param oldToken 带tokenHead的token - */ - public String refreshHeadToken(String oldToken) { - if(StrUtil.isEmpty(oldToken)){ - return null; - } - String token = oldToken.substring(tokenHead.length()); - if(StrUtil.isEmpty(token)){ - return null; - } - //token校验不通过 - Claims claims = getClaimsFromToken(token); - if(claims==null){ - return null; - } - //如果token已经过期,不支持刷新 - if(isTokenExpired(token)){ - return null; - } - //如果token在30分钟之内刚刷新过,返回原token - if(tokenRefreshJustBefore(token,30*60)){ - return token; - }else{ - claims.put(CLAIM_KEY_CREATED, new Date()); - return generateToken(claims); - } - } - - /** - * 判断token在指定时间内是否刚刚刷新过 - * @param token 原token - * @param time 指定时间(秒) - */ - private boolean tokenRefreshJustBefore(String token, int time) { - Claims claims = getClaimsFromToken(token); - Date created = claims.get(CLAIM_KEY_CREATED, Date.class); - Date refreshDate = new Date(); - //刷新时间在创建时间的指定时间内 - if(refreshDate.after(created)&&refreshDate.before(DateUtil.offsetSecond(created,time))){ - return true; - } - return false; - } -} diff --git a/pom.xml b/pom.xml index 4c0a5c9..3fd67c1 100644 --- a/pom.xml +++ b/pom.xml @@ -12,47 +12,46 @@ mall-common mall-mbg - mall-security mall-demo mall-admin mall-search mall-portal - mall-registry mall-monitor mall-gateway - mall-config + mall-auth org.springframework.boot spring-boot-starter-parent - 2.1.7.RELEASE + 2.3.0.RELEASE UTF-8 UTF-8 - 1.8 true - http://192.168.6.132:2375 + http://192.168.3.101:2375 1.1.0 1.8 - Greenwich.SR2 + Hoxton.SR5 + 2.2.0.RELEASE 1.2.10 5.1.8 1.1.10 4.5.7 - 2.7.0 1.3.7 3.4.6 - 8.0.15 - 2.1.5.RELEASE + 8.0.16 + 2.3.0.RELEASE 0.9.0 2.5.0 5.3 - 2.1.5 - 3.0.10 + 2.2.3 + 7.1.0 + 2.0.4 + 8.16 1.0-SNAPSHOT 1.0-SNAPSHOT 1.0-SNAPSHOT @@ -72,6 +71,19 @@ spring-boot-starter-test test + + cn.hutool + hutool-all + + + org.projectlombok + lombok + + + org.springframework.boot + spring-boot-configuration-processor + true + @@ -84,6 +96,14 @@ pom import + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + com.macro.mall @@ -126,16 +146,16 @@ hutool-all ${hutool.version} - + - io.springfox - springfox-swagger2 - ${swagger2.version} + com.github.xiaoymin + knife4j-micro-spring-boot-starter + ${knife4j.version} - io.springfox - springfox-swagger-ui - ${swagger2.version} + com.github.xiaoymin + knife4j-spring-boot-starter + ${knife4j.version} @@ -167,6 +187,12 @@ jjwt ${jjwt.version} + + + com.nimbusds + nimbus-jose-jwt + ${nimbus-jose-jwt.version} + com.aliyun.oss