From 533de3cdbc984e22ccbb302d724e3ed6432231be Mon Sep 17 00:00:00 2001 From: wol <1293433164@qq.com> Date: Sun, 22 Dec 2024 21:45:21 +0800 Subject: [PATCH] 103 --- weblog-springboot-103/pom.xml | 211 ++++++++++++++++++ .../weblog-module-admin/.gitignore | 33 +++ .../weblog-module-admin/pom.xml | 78 +++++++ .../admin/config/Knife4jAdminConfig.java | 53 +++++ .../weblog/admin/config/MinioConfig.java | 27 +++ .../weblog/admin/config/MinioProperties.java | 21 ++ .../admin/config/WebSecurityConfig.java | 65 ++++++ .../controller/AdminArticleController.java | 39 ++++ .../AdminBlogSettingsController.java | 48 ++++ .../controller/AdminCategoryController.java | 67 ++++++ .../admin/controller/AdminFileController.java | 38 ++++ .../admin/controller/AdminTagController.java | 65 ++++++ .../admin/controller/AdminUserController.java | 46 ++++ .../admin/convert/BlogSettingsConvert.java | 36 +++ .../weblog/admin/model/package-info.java | 7 + .../model/vo/article/PublishArticleReqVO.java | 45 ++++ .../blogsettings/FindBlogSettingsRspVO.java | 40 ++++ .../blogsettings/UpdateBlogSettingsReqVO.java | 47 ++++ .../model/vo/category/AddCategoryReqVO.java | 30 +++ .../vo/category/DeleteCategoryReqVO.java | 29 +++ .../category/FindCategoryPageListReqVO.java | 43 ++++ .../category/FindCategoryPageListRspVO.java | 40 ++++ .../admin/model/vo/file/UploadFileRspVO.java | 27 +++ .../admin/model/vo/tag/AddTagReqVO.java | 30 +++ .../admin/model/vo/tag/DeleteTagReqVO.java | 27 +++ .../model/vo/tag/FindTagPageListReqVO.java | 40 ++++ .../model/vo/tag/FindTagPageListRspVO.java | 37 +++ .../admin/model/vo/tag/SearchTagsReqVO.java | 27 +++ .../model/vo/user/FindUserInfoRspVO.java | 28 +++ .../vo/user/UpdateAdminUserPasswordReqVO.java | 31 +++ .../quanxiaoha/weblog/admin/package-info.java | 7 + .../admin/service/AdminArticleService.java | 20 ++ .../service/AdminBlogSettingsService.java | 26 +++ .../admin/service/AdminCategoryService.java | 45 ++++ .../admin/service/AdminFileService.java | 20 ++ .../weblog/admin/service/AdminTagService.java | 45 ++++ .../admin/service/AdminUserService.java | 25 +++ .../service/impl/AdminArticleServiceImpl.java | 164 ++++++++++++++ .../impl/AdminBlogSettingsServiceImpl.java | 61 +++++ .../impl/AdminCategoryServiceImpl.java | 157 +++++++++++++ .../service/impl/AdminFileServiceImpl.java | 55 +++++ .../service/impl/AdminTagServiceImpl.java | 139 ++++++++++++ .../service/impl/AdminUserServiceImpl.java | 62 +++++ .../weblog/admin/service/package-info.java | 7 + .../weblog/admin/utils/MinioUtil.java | 75 +++++++ .../WeblogModuleAdminApplicationTests.java | 25 +++ .../weblog-module-common/.gitignore | 33 +++ .../weblog-module-common/pom.xml | 69 ++++++ .../weblog/common/aspect/ApiOperationLog.java | 17 ++ .../common/aspect/ApiOperationLogAspect.java | 102 +++++++++ .../common/config/InsertBatchMapper.java | 19 ++ .../common/config/InsertBatchSqlInjector.java | 26 +++ .../weblog/common/config/JacksonConfig.java | 60 +++++ .../common/config/MybatisPlusConfig.java | 37 +++ .../domain/dos/ArticleCategoryRelDO.java | 30 +++ .../common/domain/dos/ArticleContentDO.java | 31 +++ .../weblog/common/domain/dos/ArticleDO.java | 42 ++++ .../common/domain/dos/ArticleTagRelDO.java | 30 +++ .../common/domain/dos/BlogSettingsDO.java | 46 ++++ .../weblog/common/domain/dos/CategoryDO.java | 36 +++ .../weblog/common/domain/dos/TagDO.java | 36 +++ .../weblog/common/domain/dos/UserDO.java | 38 ++++ .../weblog/common/domain/dos/UserRoleDO.java | 20 ++ .../mapper/ArticleCategoryRelMapper.java | 14 ++ .../domain/mapper/ArticleContentMapper.java | 14 ++ .../common/domain/mapper/ArticleMapper.java | 14 ++ .../domain/mapper/ArticleTagRelMapper.java | 14 ++ .../domain/mapper/BlogSettingsMapper.java | 18 ++ .../common/domain/mapper/CategoryMapper.java | 54 +++++ .../common/domain/mapper/TagMapper.java | 58 +++++ .../common/domain/mapper/UserMapper.java | 33 +++ .../common/domain/mapper/UserRoleMapper.java | 27 +++ .../weblog/common/domain/package-info.java | 7 + .../weblog/common/enums/ResponseCodeEnum.java | 40 ++++ .../exception/BaseExceptionInterface.java | 13 ++ .../weblog/common/exception/BizException.java | 24 ++ .../exception/GlobalExceptionHandler.java | 92 ++++++++ .../weblog/common/model/BasePageQuery.java | 23 ++ .../weblog/common/model/package-info.java | 7 + .../weblog/common/model/vo/SelectRspVO.java | 28 +++ .../weblog/common/package-info.java | 7 + .../weblog/common/utils/JsonUtil.java | 31 +++ .../weblog/common/utils/PageResponse.java | 60 +++++ .../weblog/common/utils/Response.java | 77 +++++++ .../WeblogModuleCommonApplicationTests.java | 23 ++ .../weblog-module-jwt/.gitignore | 33 +++ .../weblog-module-jwt/pom.xml | 74 ++++++ .../JwtAuthenticationSecurityConfig.java | 58 +++++ .../jwt/config/PasswordEncoderConfig.java | 27 +++ .../UsernameOrPasswordNullException.java | 19 ++ .../jwt/filter/JwtAuthenticationFilter.java | 59 +++++ .../jwt/filter/TokenAuthenticationFilter.java | 107 +++++++++ .../jwt/handler/RestAccessDeniedHandler.java | 32 +++ .../handler/RestAuthenticationEntryPoint.java | 38 ++++ .../RestAuthenticationFailureHandler.java | 43 ++++ .../RestAuthenticationSuccessHandler.java | 47 ++++ .../weblog/jwt/model/LoginRspVO.java | 25 +++ .../jwt/service/UserDetailServiceImpl.java | 63 ++++++ .../weblog/jwt/utils/JwtTokenHelper.java | 146 ++++++++++++ .../weblog/jwt/utils/ResultUtil.java | 73 ++++++ .../jwt/WeblogModuleJwtApplicationTests.java | 16 ++ weblog-springboot-103/weblog-web/.gitignore | 33 +++ weblog-springboot-103/weblog-web/pom.xml | 79 +++++++ .../weblog/web/WeblogWebApplication.java | 15 ++ .../weblog/web/config/Knife4jConfig.java | 53 +++++ .../weblog/web/controller/TestController.java | 54 +++++ .../com/quanxiaoha/weblog/web/model/User.java | 50 +++++ .../src/main/resources/application-dev.yml | 27 +++ .../src/main/resources/application-prod.yml | 27 +++ .../src/main/resources/application.yml | 18 ++ .../src/main/resources/logback-weblog.xml | 46 ++++ .../src/main/resources/spy.properties | 24 ++ .../weblog/web/WeblogWebApplicationTests.java | 86 +++++++ 113 files changed, 5010 insertions(+) create mode 100644 weblog-springboot-103/pom.xml create mode 100644 weblog-springboot-103/weblog-module-admin/.gitignore create mode 100644 weblog-springboot-103/weblog-module-admin/pom.xml create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioConfig.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioProperties.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminArticleController.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminBlogSettingsController.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminFileController.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/BlogSettingsConvert.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/PublishArticleReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/FindBlogSettingsRspVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/UpdateBlogSettingsReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/file/UploadFileRspVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/DeleteTagReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListRspVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/SearchTagsReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminArticleService.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminBlogSettingsService.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminFileService.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminArticleServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminBlogSettingsServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminFileServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/utils/MinioUtil.java create mode 100644 weblog-springboot-103/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java create mode 100644 weblog-springboot-103/weblog-module-common/.gitignore create mode 100644 weblog-springboot-103/weblog-module-common/pom.xml create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchSqlInjector.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/JacksonConfig.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/MybatisPlusConfig.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleCategoryRelDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleContentDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleTagRelDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/BlogSettingsDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/CategoryDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/TagDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserRoleDO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleCategoryRelMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleContentMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleTagRelMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/BlogSettingsMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/CategoryMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/TagMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserRoleMapper.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/package-info.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/ResponseCodeEnum.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BaseExceptionInterface.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BizException.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/GlobalExceptionHandler.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/BasePageQuery.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/package-info.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/vo/SelectRspVO.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/package-info.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/JsonUtil.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/PageResponse.java create mode 100644 weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/Response.java create mode 100644 weblog-springboot-103/weblog-module-common/src/test/java/com/quanxiaoha/weblog/common/WeblogModuleCommonApplicationTests.java create mode 100644 weblog-springboot-103/weblog-module-jwt/.gitignore create mode 100644 weblog-springboot-103/weblog-module-jwt/pom.xml create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/JwtAuthenticationSecurityConfig.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/PasswordEncoderConfig.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/exception/UsernameOrPasswordNullException.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/JwtAuthenticationFilter.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/TokenAuthenticationFilter.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAccessDeniedHandler.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationEntryPoint.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationFailureHandler.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationSuccessHandler.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/model/LoginRspVO.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/service/UserDetailServiceImpl.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/JwtTokenHelper.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/ResultUtil.java create mode 100644 weblog-springboot-103/weblog-module-jwt/src/test/java/com/quanxiaoha/weblog/jwt/WeblogModuleJwtApplicationTests.java create mode 100644 weblog-springboot-103/weblog-web/.gitignore create mode 100644 weblog-springboot-103/weblog-web/pom.xml create mode 100644 weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/WeblogWebApplication.java create mode 100644 weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/config/Knife4jConfig.java create mode 100644 weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/TestController.java create mode 100644 weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/User.java create mode 100644 weblog-springboot-103/weblog-web/src/main/resources/application-dev.yml create mode 100644 weblog-springboot-103/weblog-web/src/main/resources/application-prod.yml create mode 100644 weblog-springboot-103/weblog-web/src/main/resources/application.yml create mode 100644 weblog-springboot-103/weblog-web/src/main/resources/logback-weblog.xml create mode 100644 weblog-springboot-103/weblog-web/src/main/resources/spy.properties create mode 100644 weblog-springboot-103/weblog-web/src/test/java/com/quanxiaoha/weblog/web/WeblogWebApplicationTests.java diff --git a/weblog-springboot-103/pom.xml b/weblog-springboot-103/pom.xml new file mode 100644 index 0000000..5173976 --- /dev/null +++ b/weblog-springboot-103/pom.xml @@ -0,0 +1,211 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + + 2.6.3 + + + + com.quanxiaoha + weblog-springboot + ${revision} + weblog-springboot + + 前后端分离博客 Weblog By 犬小哈 + + + pom + + + + + weblog-web + + weblog-module-admin + + weblog-module-common + + weblog-module-jwt + + + + + + + 0.0.1-SNAPSHOT + 1.8 + UTF-8 + + ${java.version} + ${java.version} + + + 1.18.28 + 31.1-jre + 3.12.0 + 2.15.2 + 4.3.0 + 3.5.2 + 3.9.1 + 0.11.2 + 8.2.1 + 1.5.5.Final + + + + + + + com.quanxiaoha + weblog-module-admin + ${revision} + + + + com.quanxiaoha + weblog-module-common + ${revision} + + + + com.quanxiaoha + weblog-module-jwt + ${revision} + + + + + com.google.guava + guava + ${guava.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + ${knife4j.version} + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + p6spy + p6spy + ${p6spy.version} + + + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + + + + + io.minio + minio + ${minio.version} + + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + org.projectlombok + lombok + ${lombok.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + + + + + + + + + aliyunmaven + aliyun + https://maven.aliyun.com/repository/public + + + diff --git a/weblog-springboot-103/weblog-module-admin/.gitignore b/weblog-springboot-103/weblog-module-admin/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/weblog-springboot-103/weblog-module-admin/pom.xml b/weblog-springboot-103/weblog-module-admin/pom.xml new file mode 100644 index 0000000..536651a --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + + com.quanxiaoha + weblog-springboot + ${revision} + + + com.quanxiaoha + weblog-module-admin + weblog-module-admin + weblog-admin (负责管理后台相关功能) + + + + com.quanxiaoha + weblog-module-common + + + + com.quanxiaoha + weblog-module-jwt + + + + + org.projectlombok + lombok + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-security + + + + + jakarta.validation + jakarta.validation-api + + + org.hibernate.validator + hibernate-validator + + + + + io.minio + minio + + + + org.mapstruct + mapstruct + + + + + + \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java new file mode 100644 index 0000000..3c2b2da --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java @@ -0,0 +1,53 @@ +package com.quanxiaoha.weblog.admin.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-16 7:53 + * @description: Knife4j 配置 + **/ +@Configuration +@EnableSwagger2WebMvc +@Profile("dev") // 只在 dev 环境中开启 +public class Knife4jAdminConfig { + + @Bean("adminApi") + public Docket createApiDoc() { + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(buildApiInfo()) + // 分组名称 + .groupName("Admin 后台接口") + .select() + // 这里指定 Controller 扫描包路径 + .apis(RequestHandlerSelectors.basePackage("com.quanxiaoha.weblog.admin.controller")) + .paths(PathSelectors.any()) + .build(); + return docket; + } + + /** + * 构建 API 信息 + * @return + */ + private ApiInfo buildApiInfo() { + return new ApiInfoBuilder() + .title("Weblog 博客 Admin 后台接口文档") // 标题 + .description("Weblog 是一款由 Spring Boot + Vue 3.2 + Vite 4.3 开发的前后端分离博客。") // 描述 + .termsOfServiceUrl("https://www.quanxiaoha.com/") // API 服务条款 + .contact(new Contact("犬小哈", "https://www.quanxiaoha.com", "871361652@qq.com")) // 联系人 + .version("1.0") // 版本号 + .build(); + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioConfig.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioConfig.java new file mode 100644 index 0000000..1083984 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioConfig.java @@ -0,0 +1,27 @@ +package com.quanxiaoha.weblog.admin.config; + +import io.minio.MinioClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-05-11 8:49 + * @description: TODO + **/ +@Configuration +public class MinioConfig { + @Autowired + private MinioProperties minioProperties; + + @Bean + public MinioClient minioClient() { + // 构建 Minio 客户端 + return MinioClient.builder() + .endpoint(minioProperties.getEndpoint()) + .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()) + .build(); + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioProperties.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioProperties.java new file mode 100644 index 0000000..c72af04 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioProperties.java @@ -0,0 +1,21 @@ +package com.quanxiaoha.weblog.admin.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-05-11 8:49 + * @description: TODO + **/ +@ConfigurationProperties(prefix = "minio") +@Component +@Data +public class MinioProperties { + private String endpoint; + private String accessKey; + private String secretKey; + private String bucketName; +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java new file mode 100644 index 0000000..f5fbac2 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java @@ -0,0 +1,65 @@ +package com.quanxiaoha.weblog.admin.config; + +import com.quanxiaoha.weblog.jwt.config.JwtAuthenticationSecurityConfig; +import com.quanxiaoha.weblog.jwt.filter.TokenAuthenticationFilter; +import com.quanxiaoha.weblog.jwt.handler.RestAccessDeniedHandler; +import com.quanxiaoha.weblog.jwt.handler.RestAuthenticationEntryPoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-23 15:48 + * @description: Spring Security 配置类 + **/ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig; + @Autowired + private RestAuthenticationEntryPoint authEntryPoint; + @Autowired + private RestAccessDeniedHandler deniedHandler; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable(). // 禁用 csrf + formLogin().disable() // 禁用表单登录 + .apply(jwtAuthenticationSecurityConfig) // 设置用户登录认证相关配置 + .and() + .authorizeHttpRequests() + .mvcMatchers("/admin/**").authenticated() // 认证所有以 /admin 为前缀的 URL 资源 + .anyRequest().permitAll() // 其他都需要放行,无需认证 + .and() + .httpBasic().authenticationEntryPoint(authEntryPoint) // 处理用户未登录访问受保护的资源的情况 + .and() + .exceptionHandling().accessDeniedHandler(deniedHandler) // 处理登录成功后访问受保护的资源,但是权限不够的情况 + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 前后端分离,无需创建会话 + .and() + .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) // 将 Token 校验过滤器添加到用户认证过滤器之前 + ; + } + + /** + * Token 校验过滤器 + * @return + */ + @Bean + public TokenAuthenticationFilter tokenAuthenticationFilter() { + return new TokenAuthenticationFilter(); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminArticleController.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminArticleController.java new file mode 100644 index 0000000..bd0ea4d --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminArticleController.java @@ -0,0 +1,39 @@ +package com.quanxiaoha.weblog.admin.controller; + +import com.quanxiaoha.weblog.admin.model.vo.article.PublishArticleReqVO; +import com.quanxiaoha.weblog.admin.service.AdminArticleService; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import com.quanxiaoha.weblog.common.utils.Response; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:01 + * @description: 文章模块 + **/ +@RestController +@RequestMapping("/admin/article") +@Api(tags = "Admin 文章模块") +public class AdminArticleController { + + @Autowired + private AdminArticleService articleService; + + @PostMapping("/publish") + @ApiOperation(value = "文章发布") + @ApiOperationLog(description = "文章发布") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response publishArticle(@RequestBody @Validated PublishArticleReqVO publishArticleReqVO) { + return articleService.publishArticle(publishArticleReqVO); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminBlogSettingsController.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminBlogSettingsController.java new file mode 100644 index 0000000..17fd3be --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminBlogSettingsController.java @@ -0,0 +1,48 @@ +package com.quanxiaoha.weblog.admin.controller; + +import com.quanxiaoha.weblog.admin.model.vo.blogsettings.UpdateBlogSettingsReqVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminBlogSettingsService; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import com.quanxiaoha.weblog.common.utils.Response; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:01 + * @description: 博客设置 + **/ +@RestController +@RequestMapping("/admin/blog/settings") +@Api(tags = "Admin 博客设置模块") +public class AdminBlogSettingsController { + + @Autowired + private AdminBlogSettingsService blogSettingsService; + + @PostMapping("/update") + @ApiOperation(value = "博客基础信息修改") + @ApiOperationLog(description = "博客基础信息修改") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response updateBlogSettings(@RequestBody @Validated UpdateBlogSettingsReqVO updateBlogSettingsReqVO) { + return blogSettingsService.updateBlogSettings(updateBlogSettingsReqVO); + } + + @PostMapping("/detail") + @ApiOperation(value = "获取博客设置详情") + @ApiOperationLog(description = "获取博客设置详情") + public Response findDetail() { + return blogSettingsService.findDetail(); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java new file mode 100644 index 0000000..74225d8 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java @@ -0,0 +1,67 @@ +package com.quanxiaoha.weblog.admin.controller; + +import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminCategoryService; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import com.quanxiaoha.weblog.common.utils.PageResponse; +import com.quanxiaoha.weblog.common.utils.Response; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:01 + * @description: 分类 + **/ +@RestController +@RequestMapping("/admin/category") +@Api(tags = "Admin 分类模块") +public class AdminCategoryController { + + @Autowired + private AdminCategoryService categoryService; + + @PostMapping("/add") + @ApiOperation(value = "添加分类") + @ApiOperationLog(description = "添加分类") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response addCategory(@RequestBody @Validated AddCategoryReqVO addCategoryReqVO) { + return categoryService.addCategory(addCategoryReqVO); + } + + @PostMapping("/list") + @ApiOperation(value = "分类分页数据获取") + @ApiOperationLog(description = "分类分页数据获取") + public PageResponse findCategoryPageList(@RequestBody @Validated FindCategoryPageListReqVO findCategoryPageListReqVO) { + return categoryService.findCategoryPageList(findCategoryPageListReqVO); + } + + @PostMapping("/delete") + @ApiOperation(value = "删除分类") + @ApiOperationLog(description = "删除分类") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response deleteCategory(@RequestBody @Validated DeleteCategoryReqVO deleteCategoryReqVO) { + return categoryService.deleteCategory(deleteCategoryReqVO); + } + + @PostMapping("/select/list") + @ApiOperation(value = "分类 Select 下拉列表数据获取") + @ApiOperationLog(description = "分类 Select 下拉列表数据获取") + public Response findCategorySelectList() { + return categoryService.findCategorySelectList(); + } + + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminFileController.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminFileController.java new file mode 100644 index 0000000..9caccb5 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminFileController.java @@ -0,0 +1,38 @@ +package com.quanxiaoha.weblog.admin.controller; + +import com.quanxiaoha.weblog.admin.service.AdminFileService; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import com.quanxiaoha.weblog.common.utils.Response; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:01 + * @description: 文件模块 + **/ +@RestController +@RequestMapping("/admin") +@Api(tags = "Admin 文件模块") +public class AdminFileController { + + @Autowired + private AdminFileService fileService; + + @PostMapping("/file/upload") + @ApiOperation(value = "文件上传") + @ApiOperationLog(description = "文件上传") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response uploadFile(@RequestParam MultipartFile file) { + return fileService.uploadFile(file); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java new file mode 100644 index 0000000..08dea58 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java @@ -0,0 +1,65 @@ +package com.quanxiaoha.weblog.admin.controller; + +import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.DeleteTagReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.FindTagPageListReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.SearchTagsReqVO; +import com.quanxiaoha.weblog.admin.service.AdminTagService; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import com.quanxiaoha.weblog.common.utils.PageResponse; +import com.quanxiaoha.weblog.common.utils.Response; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:01 + * @description: 标签模块 + **/ +@RestController +@RequestMapping("/admin/tag") +@Api(tags = "Admin 标签模块") +public class AdminTagController { + + @Autowired + private AdminTagService tagService; + + @PostMapping("/add") + @ApiOperation(value = "添加标签") + @ApiOperationLog(description = "添加标签") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response addTags(@RequestBody @Validated AddTagReqVO addTagReqVO) { + return tagService.addTags(addTagReqVO); + } + + @PostMapping("/list") + @ApiOperation(value = "标签分页数据获取") + @ApiOperationLog(description = "标签分页数据获取") + public PageResponse findTagPageList(@RequestBody @Validated FindTagPageListReqVO findTagPageListReqVO) { + return tagService.findTagPageList(findTagPageListReqVO); + } + + @PostMapping("/delete") + @ApiOperation(value = "删除标签") + @ApiOperationLog(description = "删除标签") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response deleteTag(@RequestBody @Validated DeleteTagReqVO deleteTagReqVO) { + return tagService.deleteTag(deleteTagReqVO); + } + + @PostMapping("/search") + @ApiOperation(value = "标签模糊查询") + @ApiOperationLog(description = "标签模糊查询") + public Response searchTags(@RequestBody @Validated SearchTagsReqVO searchTagsReqVO) { + return tagService.searchTags(searchTagsReqVO); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java new file mode 100644 index 0000000..65d49ac --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java @@ -0,0 +1,46 @@ +package com.quanxiaoha.weblog.admin.controller; + +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import com.quanxiaoha.weblog.common.utils.Response; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:01 + * @description: 用户 + **/ +@RestController +@RequestMapping("/admin") +@Api(tags = "Admin 用户模块") +public class AdminUserController { + + @Autowired + private AdminUserService userService; + + @PostMapping("/password/update") + @ApiOperation(value = "修改用户密码") + @ApiOperationLog(description = "修改用户密码") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response updatePassword(@RequestBody @Validated UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO) { + return userService.updatePassword(updateAdminUserPasswordReqVO); + } + + @PostMapping("/user/info") + @ApiOperation(value = "获取用户信息") + @ApiOperationLog(description = "获取用户信息") + public Response findUserInfo() { + return userService.findUserInfo(); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/BlogSettingsConvert.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/BlogSettingsConvert.java new file mode 100644 index 0000000..2dcec5f --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/BlogSettingsConvert.java @@ -0,0 +1,36 @@ +package com.quanxiaoha.weblog.admin.convert; + +import com.quanxiaoha.weblog.admin.model.vo.blogsettings.FindBlogSettingsRspVO; +import com.quanxiaoha.weblog.admin.model.vo.blogsettings.UpdateBlogSettingsReqVO; +import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023/10/8 14:57 + * @description: 博客设置转换 + **/ +@Mapper +public interface BlogSettingsConvert { + /** + * 初始化 convert 实例 + */ + BlogSettingsConvert INSTANCE = Mappers.getMapper(BlogSettingsConvert.class); + + /** + * 将 VO 转化为 DO + * @param bean + * @return + */ + BlogSettingsDO convertVO2DO(UpdateBlogSettingsReqVO bean); + + /** + * 将 DO 转化为 VO + * @param bean + * @return + */ + FindBlogSettingsRspVO convertDO2VO(BlogSettingsDO bean); + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java new file mode 100644 index 0000000..e84aac5 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java @@ -0,0 +1,7 @@ +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: TODO + **/ +package com.quanxiaoha.weblog.admin.model; \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/PublishArticleReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/PublishArticleReqVO.java new file mode 100644 index 0000000..357ab07 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/PublishArticleReqVO.java @@ -0,0 +1,45 @@ +package com.quanxiaoha.weblog.admin.model.vo.article; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.NotEmpty; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 文章发布 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "发布文章 VO") +public class PublishArticleReqVO { + + @NotBlank(message = "文章标题不能为空") + @Length(min = 1, max = 40, message = "文章标题字数需大于 1 小于 40") + private String title; + + @NotBlank(message = "文章内容不能为空") + private String content; + + @NotBlank(message = "文章封面不能为空") + private String cover; + + private String summary; + + @NotNull(message = "文章分类不能为空") + private Long categoryId; + + @NotEmpty(message = "文章标签不能为空") + private List tags; +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/FindBlogSettingsRspVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/FindBlogSettingsRspVO.java new file mode 100644 index 0000000..0d15bd2 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/FindBlogSettingsRspVO.java @@ -0,0 +1,40 @@ +package com.quanxiaoha.weblog.admin.model.vo.blogsettings; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 博客基础信息 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FindBlogSettingsRspVO { + + private String logo; + + private String name; + + private String author; + + private String introduction; + + private String avatar; + + private String githubHomepage; + + private String csdnHomepage; + + private String giteeHomepage; + + private String zhihuHomepage; +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/UpdateBlogSettingsReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/UpdateBlogSettingsReqVO.java new file mode 100644 index 0000000..eb0c9de --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/UpdateBlogSettingsReqVO.java @@ -0,0 +1,47 @@ +package com.quanxiaoha.weblog.admin.model.vo.blogsettings; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 博客基础信息修改 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = " 博客基础信息修改 VO") +public class UpdateBlogSettingsReqVO { + + @NotBlank(message = "博客 LOGO 不能为空") + private String logo; + + @NotBlank(message = "博客名称不能为空") + private String name; + + @NotBlank(message = "博客作者不能为空") + private String author; + + @NotBlank(message = "博客介绍语不能为空") + private String introduction; + + @NotBlank(message = "博客头像不能为空") + private String avatar; + + private String githubHomepage; + + private String csdnHomepage; + + private String giteeHomepage; + + private String zhihuHomepage; +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java new file mode 100644 index 0000000..ff250e1 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java @@ -0,0 +1,30 @@ +package com.quanxiaoha.weblog.admin.model.vo.category; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 分类新增 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "添加分类 VO") +public class AddCategoryReqVO { + + @NotBlank(message = "分类名称不能为空") + @Length(min = 1, max = 20, message = "分类名称字数限制 1 ~ 20 之间") + private String name; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java new file mode 100644 index 0000000..26e55a1 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java @@ -0,0 +1,29 @@ +package com.quanxiaoha.weblog.admin.model.vo.category; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 删除分类 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "删除分类 VO") +public class DeleteCategoryReqVO { + + @NotNull(message = "分类 ID 不能为空") + private Long id; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java new file mode 100644 index 0000000..3a26532 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java @@ -0,0 +1,43 @@ +package com.quanxiaoha.weblog.admin.model.vo.category; + +import com.quanxiaoha.weblog.common.model.BasePageQuery; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 分类分页 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "查询分类分页数据入参 VO") +public class FindCategoryPageListReqVO extends BasePageQuery { + + /** + * 分类名称 + */ + private String name; + + /** + * 创建的起始日期 + */ + private LocalDate startDate; + + /** + * 创建的结束日期 + */ + private LocalDate endDate; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java new file mode 100644 index 0000000..b49b5a0 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java @@ -0,0 +1,40 @@ +package com.quanxiaoha.weblog.admin.model.vo.category; + +import com.quanxiaoha.weblog.common.model.BasePageQuery; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 分类分页 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FindCategoryPageListRspVO { + + /** + * 分类 ID + */ + private Long id; + + /** + * 分类名称 + */ + private String name; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/file/UploadFileRspVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/file/UploadFileRspVO.java new file mode 100644 index 0000000..683baaf --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/file/UploadFileRspVO.java @@ -0,0 +1,27 @@ +package com.quanxiaoha.weblog.admin.model.vo.file; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 上传文件 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class UploadFileRspVO { + + /** + * 文件的访问链接 + */ + private String url; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java new file mode 100644 index 0000000..36d0a48 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java @@ -0,0 +1,30 @@ +package com.quanxiaoha.weblog.admin.model.vo.tag; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 标签新增 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "添加标签 VO") +public class AddTagReqVO { + + @NotEmpty(message = "标签集合不能为空") + private List tags; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/DeleteTagReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/DeleteTagReqVO.java new file mode 100644 index 0000000..acd775d --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/DeleteTagReqVO.java @@ -0,0 +1,27 @@ +package com.quanxiaoha.weblog.admin.model.vo.tag; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 删除标签 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "删除标签 VO") +public class DeleteTagReqVO { + + @NotNull(message = "标签 ID 不能为空") + private Long id; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListReqVO.java new file mode 100644 index 0000000..12951fc --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListReqVO.java @@ -0,0 +1,40 @@ +package com.quanxiaoha.weblog.admin.model.vo.tag; + +import com.quanxiaoha.weblog.common.model.BasePageQuery; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 标签分页 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "查询标签分页数据入参 VO") +public class FindTagPageListReqVO extends BasePageQuery { + + /** + * 标签名称 + */ + private String name; + + /** + * 创建的起始日期 + */ + private LocalDate startDate; + + /** + * 创建的结束日期 + */ + private LocalDate endDate; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListRspVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListRspVO.java new file mode 100644 index 0000000..6835637 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListRspVO.java @@ -0,0 +1,37 @@ +package com.quanxiaoha.weblog.admin.model.vo.tag; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 标签分页 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FindTagPageListRspVO { + + /** + * 标签 ID + */ + private Long id; + + /** + * 标签名称 + */ + private String name; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/SearchTagsReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/SearchTagsReqVO.java new file mode 100644 index 0000000..0045454 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/SearchTagsReqVO.java @@ -0,0 +1,27 @@ +package com.quanxiaoha.weblog.admin.model.vo.tag; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 标签模糊查询 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "标签模糊查询 VO") +public class SearchTagsReqVO { + + @NotBlank(message = "标签查询关键词不能为空") + private String key; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java new file mode 100644 index 0000000..13fcb86 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java @@ -0,0 +1,28 @@ +package com.quanxiaoha.weblog.admin.model.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: 查询用户信息 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FindUserInfoRspVO { + /** + * 用户名 + */ + private String username; + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java new file mode 100644 index 0000000..1107969 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java @@ -0,0 +1,31 @@ +package com.quanxiaoha.weblog.admin.model.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import javax.validation.constraints.*; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:07 + * @description: TODO + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "修改用户密码 VO") +public class UpdateAdminUserPasswordReqVO { + + @NotBlank(message = "用户名不能为空") + @ApiModelProperty(value = "用户名") + private String username; + + @NotBlank(message = "密码不能为空") + @ApiModelProperty(value = "密码") + private String password; +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java new file mode 100644 index 0000000..8a825e4 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java @@ -0,0 +1,7 @@ +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-16 9:28 + * @description: TODO + **/ +package com.quanxiaoha.weblog.admin; \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminArticleService.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminArticleService.java new file mode 100644 index 0000000..664d10e --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminArticleService.java @@ -0,0 +1,20 @@ +package com.quanxiaoha.weblog.admin.service; + +import com.quanxiaoha.weblog.admin.model.vo.article.PublishArticleReqVO; +import com.quanxiaoha.weblog.common.utils.Response; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: 文章 + **/ +public interface AdminArticleService { + /** + * 发布文章 + * @param publishArticleReqVO + * @return + */ + Response publishArticle(PublishArticleReqVO publishArticleReqVO); + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminBlogSettingsService.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminBlogSettingsService.java new file mode 100644 index 0000000..80350a9 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminBlogSettingsService.java @@ -0,0 +1,26 @@ +package com.quanxiaoha.weblog.admin.service; + +import com.quanxiaoha.weblog.admin.model.vo.blogsettings.UpdateBlogSettingsReqVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.common.utils.Response; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +public interface AdminBlogSettingsService { + /** + * 更新博客设置信息 + * @param updateBlogSettingsReqVO + * @return + */ + Response updateBlogSettings(UpdateBlogSettingsReqVO updateBlogSettingsReqVO); + + /** + * 获取博客设置详情 + * @return + */ + Response findDetail(); +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java new file mode 100644 index 0000000..a16de2b --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java @@ -0,0 +1,45 @@ +package com.quanxiaoha.weblog.admin.service; + +import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.common.utils.PageResponse; +import com.quanxiaoha.weblog.common.utils.Response; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +public interface AdminCategoryService { + /** + * 添加分类 + * @param addCategoryReqVO + * @return + */ + Response addCategory(AddCategoryReqVO addCategoryReqVO); + + /** + * 分类分页数据查询 + * @param findCategoryPageListReqVO + * @return + */ + PageResponse findCategoryPageList(FindCategoryPageListReqVO findCategoryPageListReqVO); + + /** + * 删除分类 + * @param deleteCategoryReqVO + * @return + */ + Response deleteCategory(DeleteCategoryReqVO deleteCategoryReqVO); + + /** + * 获取文章分类的 Select 列表数据 + * @return + */ + Response findCategorySelectList(); + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminFileService.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminFileService.java new file mode 100644 index 0000000..3219e63 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminFileService.java @@ -0,0 +1,20 @@ +package com.quanxiaoha.weblog.admin.service; + +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.common.utils.Response; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +public interface AdminFileService { + /** + * 上传文件 + * @param file + * @return + */ + Response uploadFile(MultipartFile file); +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java new file mode 100644 index 0000000..5fe2f49 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java @@ -0,0 +1,45 @@ +package com.quanxiaoha.weblog.admin.service; + +import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.DeleteTagReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.FindTagPageListReqVO; +import com.quanxiaoha.weblog.admin.model.vo.tag.SearchTagsReqVO; +import com.quanxiaoha.weblog.common.utils.PageResponse; +import com.quanxiaoha.weblog.common.utils.Response; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +public interface AdminTagService { + + /** + * 添加标签集合 + * @param addTagReqVO + * @return + */ + Response addTags(AddTagReqVO addTagReqVO); + + /** + * 查询标签分页 + * @param findTagPageListReqVO + * @return + */ + PageResponse findTagPageList(FindTagPageListReqVO findTagPageListReqVO); + + /** + * 删除标签 + * @param deleteTagReqVO + * @return + */ + Response deleteTag(DeleteTagReqVO deleteTagReqVO); + + /** + * 根据标签关键词模糊查询 + * @param searchTagsReqVO + * @return + */ + Response searchTags(SearchTagsReqVO searchTagsReqVO); +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java new file mode 100644 index 0000000..53a26fe --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java @@ -0,0 +1,25 @@ +package com.quanxiaoha.weblog.admin.service; + +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.common.utils.Response; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +public interface AdminUserService { + /** + * 修改密码 + * @param updateAdminUserPasswordReqVO + * @return + */ + Response updatePassword(UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO); + + /** + * 获取当前登录用户信息 + * @return + */ + Response findUserInfo(); +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminArticleServiceImpl.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminArticleServiceImpl.java new file mode 100644 index 0000000..24cc877 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminArticleServiceImpl.java @@ -0,0 +1,164 @@ +package com.quanxiaoha.weblog.admin.service.impl; + +import com.google.common.collect.Lists; +import com.quanxiaoha.weblog.admin.model.vo.article.PublishArticleReqVO; +import com.quanxiaoha.weblog.admin.service.AdminArticleService; +import com.quanxiaoha.weblog.common.domain.dos.*; +import com.quanxiaoha.weblog.common.domain.mapper.*; +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.exception.BizException; +import com.quanxiaoha.weblog.common.utils.Response; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: 文章 + **/ +@Service +@Slf4j +public class AdminArticleServiceImpl implements AdminArticleService { + + @Autowired + private ArticleMapper articleMapper; + @Autowired + private ArticleContentMapper articleContentMapper; + @Autowired + private ArticleCategoryRelMapper articleCategoryRelMapper; + @Autowired + private CategoryMapper categoryMapper; + @Autowired + private TagMapper tagMapper; + @Autowired + private ArticleTagRelMapper articleTagRelMapper; + + /** + * 发布文章 + * + * @param publishArticleReqVO + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Response publishArticle(PublishArticleReqVO publishArticleReqVO) { + // 1. VO 转 ArticleDO, 并保存 + ArticleDO articleDO = ArticleDO.builder() + .title(publishArticleReqVO.getTitle()) + .cover(publishArticleReqVO.getCover()) + .summary(publishArticleReqVO.getSummary()) + .createTime(LocalDateTime.now()) + .updateTime(LocalDateTime.now()) + .build(); + articleMapper.insert(articleDO); + + // 拿到插入记录的主键 ID + Long articleId = articleDO.getId(); + + // 2. VO 转 ArticleContentDO,并保存 + ArticleContentDO articleContentDO = ArticleContentDO.builder() + .articleId(articleId) + .content(publishArticleReqVO.getContent()) + .build(); + articleContentMapper.insert(articleContentDO); + + // 3. 处理文章关联的分类 + Long categoryId = publishArticleReqVO.getCategoryId(); + + // 3.1 校验提交的分类是否真实存在 + CategoryDO categoryDO = categoryMapper.selectById(categoryId); + if (Objects.isNull(categoryDO)) { + log.warn("==> 分类不存在, categoryId: {}", categoryId); + throw new BizException(ResponseCodeEnum.CATEGORY_NOT_EXISTED); + } + + ArticleCategoryRelDO articleCategoryRelDO = ArticleCategoryRelDO.builder() + .articleId(articleId) + .categoryId(categoryId) + .build(); + articleCategoryRelMapper.insert(articleCategoryRelDO); + + // 4. 保存文章关联的标签集合 + List publishTags = publishArticleReqVO.getTags(); + insertTags(articleId, publishTags); + + return Response.success(); + } + + /** + * 保存标签 + * @param articleId + * @param publishTags + */ + private void insertTags(Long articleId, List publishTags) { + // 筛选提交的标签(表中不存在的标签) + List notExistTags = null; + // 筛选提交的标签(表中已存在的标签) + List existedTags = null; + + // 查询出所有标签 + List tagDOS = tagMapper.selectList(null); + + // 如果表中还没有添加任何标签 + if (CollectionUtils.isEmpty(tagDOS)) { + notExistTags = publishTags; + } else { + List tagIds = tagDOS.stream().map(tagDO -> String.valueOf(tagDO.getId())).collect(Collectors.toList()); + // 表中已添加相关标签,则需要筛选 + // 通过标签 ID 来筛选,包含对应 ID 则表示提交的标签是表中存在的 + existedTags = publishTags.stream().filter(publishTag -> tagIds.contains(publishTag)).collect(Collectors.toList()); + // 否则则是不存在的 + notExistTags = publishTags.stream().filter(publishTag -> !tagIds.contains(publishTag)).collect(Collectors.toList()); + } + + // 将提交的上来的,已存在于表中的标签,文章-标签关联关系入库 + if (!CollectionUtils.isEmpty(existedTags)) { + List articleTagRelDOS = Lists.newArrayList(); + existedTags.forEach(tagId -> { + ArticleTagRelDO articleTagRelDO = ArticleTagRelDO.builder() + .articleId(articleId) + .tagId(Long.valueOf(tagId)) + .build(); + articleTagRelDOS.add(articleTagRelDO); + }); + // 批量插入 + articleTagRelMapper.insertBatchSomeColumn(articleTagRelDOS); + } + + // 将提交的上来的,不存在于表中的标签,入库保存 + if (!CollectionUtils.isEmpty(notExistTags)) { + // 需要先将标签入库,拿到对应标签 ID 后,再把文章-标签关联关系入库 + List articleTagRelDOS = Lists.newArrayList(); + notExistTags.forEach(tagName -> { + TagDO tagDO = TagDO.builder() + .name(tagName) + .createTime(LocalDateTime.now()) + .updateTime(LocalDateTime.now()) + .build(); + + tagMapper.insert(tagDO); + + // 拿到保存的标签 ID + Long tagId = tagDO.getId(); + + // 文章-标签关联关系 + ArticleTagRelDO articleTagRelDO = ArticleTagRelDO.builder() + .articleId(articleId) + .tagId(tagId) + .build(); + articleTagRelDOS.add(articleTagRelDO); + }); + // 批量插入 + articleTagRelMapper.insertBatchSomeColumn(articleTagRelDOS); + } + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminBlogSettingsServiceImpl.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminBlogSettingsServiceImpl.java new file mode 100644 index 0000000..d244b99 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminBlogSettingsServiceImpl.java @@ -0,0 +1,61 @@ +package com.quanxiaoha.weblog.admin.service.impl; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.quanxiaoha.weblog.admin.convert.BlogSettingsConvert; +import com.quanxiaoha.weblog.admin.model.vo.blogsettings.FindBlogSettingsRspVO; +import com.quanxiaoha.weblog.admin.model.vo.blogsettings.UpdateBlogSettingsReqVO; +import com.quanxiaoha.weblog.admin.model.vo.user.FindUserInfoRspVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminBlogSettingsService; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; +import com.quanxiaoha.weblog.common.domain.mapper.BlogSettingsMapper; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.utils.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +@Service +public class AdminBlogSettingsServiceImpl extends ServiceImpl implements AdminBlogSettingsService { + + @Autowired + private BlogSettingsMapper blogSettingsMapper; + + @Override + public Response updateBlogSettings(UpdateBlogSettingsReqVO updateBlogSettingsReqVO) { + // VO 转 DO + BlogSettingsDO blogSettingsDO = BlogSettingsConvert.INSTANCE.convertVO2DO(updateBlogSettingsReqVO); + blogSettingsDO.setId(1L); + + // 保存或更新(当数据库中存在 ID 为 1 的记录时,则执行更新操作,否则执行插入操作) + saveOrUpdate(blogSettingsDO); + return Response.success(); + } + + /** + * 获取博客设置详情 + * + * @return + */ + @Override + public Response findDetail() { + // 查询 ID 为 1 的记录 + BlogSettingsDO blogSettingsDO = blogSettingsMapper.selectById(1L); + + // DO 转 VO + FindBlogSettingsRspVO vo = BlogSettingsConvert.INSTANCE.convertDO2VO(blogSettingsDO); + + return Response.success(vo); + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java new file mode 100644 index 0000000..849f95b --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java @@ -0,0 +1,157 @@ +package com.quanxiaoha.weblog.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.injector.methods.SelectPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO; +import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListRspVO; +import com.quanxiaoha.weblog.admin.model.vo.user.FindUserInfoRspVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminCategoryService; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.common.domain.dos.CategoryDO; +import com.quanxiaoha.weblog.common.domain.mapper.CategoryMapper; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.exception.BizException; +import com.quanxiaoha.weblog.common.model.vo.SelectRspVO; +import com.quanxiaoha.weblog.common.utils.PageResponse; +import com.quanxiaoha.weblog.common.utils.Response; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +@Service +@Slf4j +public class AdminCategoryServiceImpl implements AdminCategoryService { + + @Autowired + private CategoryMapper categoryMapper; + + /** + * 添加分类 + * + * @param addCategoryReqVO + * @return + */ + @Override + public Response addCategory(AddCategoryReqVO addCategoryReqVO) { + String categoryName = addCategoryReqVO.getName(); + + // 先判断该分类是否已经存在 + CategoryDO categoryDO = categoryMapper.selectByName(categoryName); + + if (Objects.nonNull(categoryDO)) { + log.warn("分类名称: {}, 此已存在", categoryName); + throw new BizException(ResponseCodeEnum.CATEGORY_NAME_IS_EXISTED); + } + + // 构建 DO 类 + CategoryDO insertCategoryDO = CategoryDO.builder() + .name(addCategoryReqVO.getName().trim()) + .build(); + + // 执行 insert + categoryMapper.insert(insertCategoryDO); + + return Response.success(); + } + + /** + * 分类分页数据查询 + * + * @param findCategoryPageListReqVO + * @return + */ + @Override + public PageResponse findCategoryPageList(FindCategoryPageListReqVO findCategoryPageListReqVO) { + // 获取当前页、以及每页需要展示的数据数量 + Long current = findCategoryPageListReqVO.getCurrent(); + Long size = findCategoryPageListReqVO.getSize(); + String name = findCategoryPageListReqVO.getName(); + LocalDate startDate = findCategoryPageListReqVO.getStartDate(); + LocalDate endDate = findCategoryPageListReqVO.getEndDate(); + + // 执行分页查询 + Page categoryDOPage = categoryMapper.selectPageList(current, size, name, startDate, endDate); + + List categoryDOS = categoryDOPage.getRecords(); + + // DO 转 VO + List vos = null; + if (!CollectionUtils.isEmpty(categoryDOS)) { + vos = categoryDOS.stream() + .map(categoryDO -> FindCategoryPageListRspVO.builder() + .id(categoryDO.getId()) + .name(categoryDO.getName()) + .createTime(categoryDO.getCreateTime()) + .build()) + .collect(Collectors.toList()); + } + + return PageResponse.success(categoryDOPage, vos); + } + + /** + * 删除分类 + * + * @param deleteCategoryReqVO + * @return + */ + @Override + public Response deleteCategory(DeleteCategoryReqVO deleteCategoryReqVO) { + // 分类 ID + Long categoryId = deleteCategoryReqVO.getId(); + + // 删除分类 + categoryMapper.deleteById(categoryId); + + return Response.success(); + } + + /** + * 获取文章分类的 Select 列表数据 + * + * @return + */ + @Override + public Response findCategorySelectList() { + // 查询所有分类 + List categoryDOS = categoryMapper.selectList(null); + + // DO 转 VO + List selectRspVOS = null; + // 如果分类数据不为空 + if (!CollectionUtils.isEmpty(categoryDOS)) { + // 将分类 ID 作为 Value 值,将分类名称作为 label 展示 + selectRspVOS = categoryDOS.stream() + .map(categoryDO -> SelectRspVO.builder() + .label(categoryDO.getName()) + .value(categoryDO.getId()) + .build()) + .collect(Collectors.toList()); + } + + return Response.success(selectRspVOS); + } + +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminFileServiceImpl.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminFileServiceImpl.java new file mode 100644 index 0000000..85b224b --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminFileServiceImpl.java @@ -0,0 +1,55 @@ +package com.quanxiaoha.weblog.admin.service.impl; + +import com.quanxiaoha.weblog.admin.model.vo.file.UploadFileRspVO; +import com.quanxiaoha.weblog.admin.model.vo.user.FindUserInfoRspVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminFileService; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.admin.utils.MinioUtil; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.exception.BizException; +import com.quanxiaoha.weblog.common.utils.Response; +import io.minio.MinioClient; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: 文件上传 + **/ +@Service +@Slf4j +public class AdminFileServiceImpl implements AdminFileService { + + @Autowired + private MinioUtil minioUtil; + + /** + * 上传文件 + * + * @param file + * @return + */ + @Override + public Response uploadFile(MultipartFile file) { + try { + // 上传文件 + String url = minioUtil.uploadFile(file); + + // 构建成功返参,将图片的访问链接返回 + return Response.success(UploadFileRspVO.builder().url(url).build()); + } catch (Exception e) { + log.error("==> 上传文件至 Minio 错误: ", e); + // 手动抛出业务异常,提示 “文件上传失败” + throw new BizException(ResponseCodeEnum.FILE_UPLOAD_FAILED); + } + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java new file mode 100644 index 0000000..12d9322 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java @@ -0,0 +1,139 @@ +package com.quanxiaoha.weblog.admin.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.quanxiaoha.weblog.admin.model.vo.tag.*; +import com.quanxiaoha.weblog.admin.service.AdminTagService; +import com.quanxiaoha.weblog.common.domain.dos.TagDO; +import com.quanxiaoha.weblog.common.domain.mapper.TagMapper; +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.model.vo.SelectRspVO; +import com.quanxiaoha.weblog.common.utils.PageResponse; +import com.quanxiaoha.weblog.common.utils.Response; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +@Service +@Slf4j +public class AdminTagServiceImpl extends ServiceImpl implements AdminTagService { + + @Autowired + private TagMapper tagMapper; + + /** + * 添加标签集合 + * + * @param addTagReqVO + * @return + */ + @Override + public Response addTags(AddTagReqVO addTagReqVO) { + // vo 转 do + List tagDOS = addTagReqVO.getTags().stream() + .map(tagName -> TagDO.builder() + .name(tagName.trim()) // 去掉前后空格 + .createTime(LocalDateTime.now()) + .updateTime(LocalDateTime.now()) + .build()) + .collect(Collectors.toList()); + + // 批量插入 + try { + saveBatch(tagDOS); + } catch (Exception e) { + log.warn("该标签已存在", e); + } + + return Response.success(); + } + + /** + * 查询标签分页 + * + * @param findTagPageListReqVO + * @return + */ + @Override + public PageResponse findTagPageList(FindTagPageListReqVO findTagPageListReqVO) { + // 分页参数、条件参数 + Long current = findTagPageListReqVO.getCurrent(); + Long size = findTagPageListReqVO.getSize(); + String name = findTagPageListReqVO.getName(); + LocalDate startDate = findTagPageListReqVO.getStartDate(); + LocalDate endDate = findTagPageListReqVO.getEndDate(); + + // 分页查询 + Page page = tagMapper.selectPageList(current, size, name, startDate, endDate); + + List records = page.getRecords(); + + // do 转 vo + List vos = null; + if (!CollectionUtils.isEmpty(records)) { + vos = records.stream().map(tagDO -> FindTagPageListRspVO.builder() + .id(tagDO.getId()) + .name(tagDO.getName()) + .createTime(tagDO.getCreateTime()) + .build()).collect(Collectors.toList()); + } + + return PageResponse.success(page, vos); + } + + /** + * 删除标签 + * + * @param deleteTagReqVO + * @return + */ + @Override + public Response deleteTag(DeleteTagReqVO deleteTagReqVO) { + // 标签 ID + Long tagId = deleteTagReqVO.getId(); + + // 根据标签 ID 删除 + int count = tagMapper.deleteById(tagId); + + return count == 1 ? Response.success() : Response.fail(ResponseCodeEnum.TAG_NOT_EXISTED); + } + + /** + * 根据标签关键词模糊查询 + * + * @param searchTagsReqVO + * @return + */ + @Override + public Response searchTags(SearchTagsReqVO searchTagsReqVO) { + String key = searchTagsReqVO.getKey(); + + // 执行模糊查询 + List tagDOS = tagMapper.selectByKey(key); + + // do 转 vo + List vos = null; + if (!CollectionUtils.isEmpty(tagDOS)) { + vos = tagDOS.stream() + .map(tagDO -> SelectRspVO.builder() + .label(tagDO.getName()) + .value(tagDO.getId()) + .build()) + .collect(Collectors.toList()); + } + + return Response.success(vos); + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java new file mode 100644 index 0000000..5bf44ff --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java @@ -0,0 +1,62 @@ +package com.quanxiaoha.weblog.admin.service.impl; + +import com.quanxiaoha.weblog.admin.model.vo.user.FindUserInfoRspVO; +import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; +import com.quanxiaoha.weblog.admin.service.AdminUserService; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.utils.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:03 + * @description: TODO + **/ +@Service +public class AdminUserServiceImpl implements AdminUserService { + + @Autowired + private UserMapper userMapper; + @Autowired + private PasswordEncoder passwordEncoder; + + /** + * 修改密码 + * @param updateAdminUserPasswordReqVO + * @return + */ + @Override + public Response updatePassword(UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO) { + // 拿到用户名、密码 + String username = updateAdminUserPasswordReqVO.getUsername(); + String password = updateAdminUserPasswordReqVO.getPassword(); + + // 加密密码 + String encodePassword = passwordEncoder.encode(password); + + // 更新到数据库 + int count = userMapper.updatePasswordByUsername(username, encodePassword); + + return count == 1 ? Response.success() : Response.fail(ResponseCodeEnum.USERNAME_NOT_FOUND); + } + + /** + * 获取当前登录用户信息 + * @return + */ + @Override + public Response findUserInfo() { + // 获取存储在 ThreadLocal 中的用户信息 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + // 拿到用户名 + String username = authentication.getName(); + + return Response.success(FindUserInfoRspVO.builder().username(username).build()); + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java new file mode 100644 index 0000000..25284f5 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java @@ -0,0 +1,7 @@ +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-15 14:02 + * @description: TODO + **/ +package com.quanxiaoha.weblog.admin.service; \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/utils/MinioUtil.java b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/utils/MinioUtil.java new file mode 100644 index 0000000..4bec268 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/utils/MinioUtil.java @@ -0,0 +1,75 @@ +package com.quanxiaoha.weblog.admin.utils; + +import com.quanxiaoha.weblog.admin.config.MinioProperties; +import com.quanxiaoha.weblog.common.exception.BizException; +import io.minio.MinioClient; +import io.minio.PutObjectArgs; +import io.minio.errors.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-05-11 9:02 + * @description: TODO + **/ +@Component +@Slf4j +public class MinioUtil { + + @Autowired + private MinioProperties minioProperties; + + @Autowired + private MinioClient minioClient; + + /** + * 上传文件 + * @param file + * @return + * @throws Exception + */ + public String uploadFile(MultipartFile file) throws Exception { + // 判断文件是否为空 + if (file == null || file.getSize() == 0) { + log.error("==> 上传文件异常:文件大小为空 ..."); + throw new RuntimeException("文件大小不能为空"); + } + + // 文件的原始名称 + String originalFileName = file.getOriginalFilename(); + // 文件的 Content-Type + String contentType = file.getContentType(); + + // 生成存储对象的名称(将 UUID 字符串中的 - 替换成空字符串) + String key = UUID.randomUUID().toString().replace("-", ""); + // 获取文件的后缀,如 .jpg + String suffix = originalFileName.substring(originalFileName.lastIndexOf(".")); + + // 拼接上文件后缀,即为要存储的文件名 + String objectName = String.format("%s%s", key, suffix); + + log.info("==> 开始上传文件至 Minio, ObjectName: {}", objectName); + + // 上传文件至 Minio + minioClient.putObject(PutObjectArgs.builder() + .bucket(minioProperties.getBucketName()) + .object(objectName) + .stream(file.getInputStream(), file.getSize(), -1) + .contentType(contentType) + .build()); + + // 返回文件的访问链接 + String url = String.format("%s/%s/%s", minioProperties.getEndpoint(), minioProperties.getBucketName(), objectName); + log.info("==> 上传文件至 Minio 成功,访问路径: {}", url); + return url; + } +} diff --git a/weblog-springboot-103/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java b/weblog-springboot-103/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java new file mode 100644 index 0000000..1b6daf7 --- /dev/null +++ b/weblog-springboot-103/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java @@ -0,0 +1,25 @@ +package com.quanxiaoha.weblog.admin; + +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import com.quanxiaoha.weblog.common.domain.dos.UserDO; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +import java.time.LocalDateTime; + +@SpringBootTest(classes = WeblogModuleAdminApplicationTests.Application.class) +class WeblogModuleAdminApplicationTests { + // @Import({ + // DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + // DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + // MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + // }) + public static class Application { + } + +} diff --git a/weblog-springboot-103/weblog-module-common/.gitignore b/weblog-springboot-103/weblog-module-common/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/weblog-springboot-103/weblog-module-common/pom.xml b/weblog-springboot-103/weblog-module-common/pom.xml new file mode 100644 index 0000000..9ef9da3 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + com.quanxiaoha + weblog-springboot + ${revision} + + + com.quanxiaoha + weblog-module-common + weblog-module-common + weblog-module-common (此模块用于存放一些通用的功能) + + + + org.springframework.boot + spring-boot-starter-web + + + + org.projectlombok + lombok + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.baomidou + mybatis-plus-boot-starter + + + + + mysql + mysql-connector-java + + + + p6spy + p6spy + + + + org.springframework.boot + spring-boot-starter-security + + + diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java new file mode 100644 index 0000000..38eeb0f --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java @@ -0,0 +1,17 @@ +package com.quanxiaoha.weblog.common.aspect; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +@Documented +public @interface ApiOperationLog { + /** + * API 功能描述 + * + * @return + */ + String description() default ""; + +} + diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java new file mode 100644 index 0000000..ef199b4 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java @@ -0,0 +1,102 @@ + +package com.quanxiaoha.weblog.common.aspect; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.quanxiaoha.weblog.common.utils.JsonUtil; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.MDC; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Aspect +@Component +@Slf4j +public class ApiOperationLogAspect { + + /** 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码 */ + @Pointcut("@annotation(com.quanxiaoha.weblog.common.aspect.ApiOperationLog)") + public void apiOperationLog() {} + + /** + * 环绕 + * @param joinPoint + * @return + * @throws Throwable + */ + @Around("apiOperationLog()") + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { + try { + // 请求开始时间 + long startTime = System.currentTimeMillis(); + + // MDC + MDC.put("traceId", UUID.randomUUID().toString()); + + // 获取被请求的类和方法 + String className = joinPoint.getTarget().getClass().getSimpleName(); + String methodName = joinPoint.getSignature().getName(); + + // 请求入参 + Object[] args = joinPoint.getArgs(); + // 入参转 JSON 字符串 + String argsJsonStr = Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(", ")); + + // 功能描述信息 + String description = getApiOperationLogDescription(joinPoint); + + // 打印请求相关参数 + log.info("====== 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} =================================== ", + description, argsJsonStr, className, methodName); + + // 执行切点方法 + Object result = joinPoint.proceed(); + + // 执行耗时 + long executionTime = System.currentTimeMillis() - startTime; + + // 打印出参等相关信息 + log.info("====== 请求结束: [{}], 耗时: {}ms, 出参: {} =================================== ", + description, executionTime, JsonUtil.toJsonString(result)); + + return result; + } finally { + MDC.clear(); + } + } + + /** + * 获取注解的描述信息 + * @param joinPoint + * @return + */ + private String getApiOperationLogDescription(ProceedingJoinPoint joinPoint) { + // 1. 从 ProceedingJoinPoint 获取 MethodSignature + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + + // 2. 使用 MethodSignature 获取当前被注解的 Method + Method method = signature.getMethod(); + + // 3. 从 Method 中提取 LogExecution 注解 + ApiOperationLog apiOperationLog = method.getAnnotation(ApiOperationLog.class); + + // 4. 从 LogExecution 注解中获取 description 属性 + return apiOperationLog.description(); + } + + /** + * 转 JSON 字符串 + * @return + */ + private Function toJsonStr() { + return arg -> JsonUtil.toJsonString(arg); + } + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchMapper.java new file mode 100644 index 0000000..7399554 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchMapper.java @@ -0,0 +1,19 @@ +package com.quanxiaoha.weblog.common.config; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-06-13 22:50 + * @description: 批量插入 + **/ +public interface InsertBatchMapper extends BaseMapper { + + // 批量插入 + int insertBatchSomeColumn(@Param("list") List batchList); + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchSqlInjector.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchSqlInjector.java new file mode 100644 index 0000000..69426f9 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchSqlInjector.java @@ -0,0 +1,26 @@ +package com.quanxiaoha.weblog.common.config; + +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn; + +import java.util.List; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-06-13 22:46 + * @description: 批量插入 SQL 注入器 + **/ +public class InsertBatchSqlInjector extends DefaultSqlInjector { + + @Override + public List getMethodList(Class mapperClass, TableInfo tableInfo) { + // super.getMethodList() 保留 Mybatis Plus 自带的方法 + List methodList = super.getMethodList(mapperClass, tableInfo); + // 添加自定义方法:批量插入,方法名为 insertBatchSomeColumn + methodList.add(new InsertBatchSomeColumn()); + return methodList; + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/JacksonConfig.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/JacksonConfig.java new file mode 100644 index 0000000..1fc357d --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/JacksonConfig.java @@ -0,0 +1,60 @@ +package com.quanxiaoha.weblog.common.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.TimeZone; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-17 16:08 + * @description: 自定义 Jackson + **/ +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + // 初始化一个 ObjectMapper 对象,用于自定义 Jackson 的行为 + ObjectMapper objectMapper = new ObjectMapper(); + + // 忽略未知属性 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + // JavaTimeModule 用于指定序列化和反序列化规则 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + + // 支持 LocalDateTime、LocalDate、LocalTime + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); + javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); + + objectMapper.registerModule(javaTimeModule); + + // 设置时区 + objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + + // 设置凡是为 null 的字段,返参中均不返回,请根据项目组约定是否开启 + // objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + return objectMapper; + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/MybatisPlusConfig.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/MybatisPlusConfig.java new file mode 100644 index 0000000..c3d434d --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/MybatisPlusConfig.java @@ -0,0 +1,37 @@ +package com.quanxiaoha.weblog.common.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 16:52 + * @description: Mybatis Plus 配置文件 + **/ +@Configuration +@MapperScan("com.quanxiaoha.weblog.common.domain.mapper") +public class MybatisPlusConfig { + + /** + * 分页插件 + * @return + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor(){ + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + return interceptor; + } + + /** + * 自定义批量插入 SQL 注入器 + */ + @Bean + public InsertBatchSqlInjector insertBatchSqlInjector() { + return new InsertBatchSqlInjector(); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleCategoryRelDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleCategoryRelDO.java new file mode 100644 index 0000000..3305af8 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleCategoryRelDO.java @@ -0,0 +1,30 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 文章 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_article_category_rel") +public class ArticleCategoryRelDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long articleId; + + private Long categoryId; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleContentDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleContentDO.java new file mode 100644 index 0000000..106169d --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleContentDO.java @@ -0,0 +1,31 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 文章内容 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_article_content") +public class ArticleContentDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long articleId; + + private String content; + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleDO.java new file mode 100644 index 0000000..ebe3a7c --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleDO.java @@ -0,0 +1,42 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 文章 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_article") +public class ArticleDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private String title; + + private String cover; + + private String summary; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; + + private Boolean isDeleted; + + private Long readNum; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleTagRelDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleTagRelDO.java new file mode 100644 index 0000000..a10ff5f --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleTagRelDO.java @@ -0,0 +1,30 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 文章 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_article_tag_rel") +public class ArticleTagRelDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long articleId; + + private Long tagId; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/BlogSettingsDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/BlogSettingsDO.java new file mode 100644 index 0000000..362d5dc --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/BlogSettingsDO.java @@ -0,0 +1,46 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 博客设置 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_blog_settings") +public class BlogSettingsDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private String logo; + + private String name; + + private String author; + + private String introduction; + + private String avatar; + + private String githubHomepage; + + private String csdnHomepage; + + private String giteeHomepage; + + private String zhihuHomepage; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/CategoryDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/CategoryDO.java new file mode 100644 index 0000000..cd11f96 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/CategoryDO.java @@ -0,0 +1,36 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 分类 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_category") +public class CategoryDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private String name; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; + + private Boolean isDeleted; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/TagDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/TagDO.java new file mode 100644 index 0000000..2e8e1d5 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/TagDO.java @@ -0,0 +1,36 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 标签 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_tag") +public class TagDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private String name; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; + + private Boolean isDeleted; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserDO.java new file mode 100644 index 0000000..bfa6ac2 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserDO.java @@ -0,0 +1,38 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:01 + * @description: 用户 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("t_user") +public class UserDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private String username; + + private String password; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; + + private Boolean isDeleted; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserRoleDO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserRoleDO.java new file mode 100644 index 0000000..fbd6ed8 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserRoleDO.java @@ -0,0 +1,20 @@ +package com.quanxiaoha.weblog.common.domain.dos; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; +import lombok.Data; + +import java.util.Date; + +@Data +@Builder +@TableName("t_user_role") +public class UserRoleDO { + @TableId(type = IdType.AUTO) + private Long id; + private String username; + private String role; + private Date createTime; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleCategoryRelMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleCategoryRelMapper.java new file mode 100644 index 0000000..c8b341a --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleCategoryRelMapper.java @@ -0,0 +1,14 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.quanxiaoha.weblog.common.domain.dos.ArticleCategoryRelDO; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: 文章分类关联 + **/ +public interface ArticleCategoryRelMapper extends BaseMapper { + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleContentMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleContentMapper.java new file mode 100644 index 0000000..ed20866 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleContentMapper.java @@ -0,0 +1,14 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.quanxiaoha.weblog.common.domain.dos.ArticleContentDO; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: 文章 + **/ +public interface ArticleContentMapper extends BaseMapper { + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleMapper.java new file mode 100644 index 0000000..83d28f0 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleMapper.java @@ -0,0 +1,14 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.quanxiaoha.weblog.common.domain.dos.ArticleDO; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: 文章 + **/ +public interface ArticleMapper extends BaseMapper { + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleTagRelMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleTagRelMapper.java new file mode 100644 index 0000000..b1bb207 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleTagRelMapper.java @@ -0,0 +1,14 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.quanxiaoha.weblog.common.config.InsertBatchMapper; +import com.quanxiaoha.weblog.common.domain.dos.ArticleTagRelDO; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: 文章标签关联 + **/ +public interface ArticleTagRelMapper extends InsertBatchMapper { + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/BlogSettingsMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/BlogSettingsMapper.java new file mode 100644 index 0000000..d7a70c9 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/BlogSettingsMapper.java @@ -0,0 +1,18 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; +import com.quanxiaoha.weblog.common.domain.dos.UserDO; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: TODO + **/ +public interface BlogSettingsMapper extends BaseMapper { +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/CategoryMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/CategoryMapper.java new file mode 100644 index 0000000..9a7f701 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/CategoryMapper.java @@ -0,0 +1,54 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.quanxiaoha.weblog.common.domain.dos.CategoryDO; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: TODO + **/ +public interface CategoryMapper extends BaseMapper { + + /** + * 查询分类分页数据 + * @return + */ + default Page selectPageList(long current, long size, String name, LocalDate startDate, LocalDate endDate) { + // 分页对象(查询第几页、每页多少数据) + Page page = new Page<>(current, size); + + // 构建查询条件 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + wrapper + .like(StringUtils.isNotBlank(name), CategoryDO::getName, name.trim()) // like 模块查询 + .ge(Objects.nonNull(startDate), CategoryDO::getCreateTime, startDate) // 大于等于 startDate + .le(Objects.nonNull(endDate), CategoryDO::getCreateTime, endDate) // 小于等于 endDate + .orderByDesc(CategoryDO::getCreateTime); // 按创建时间倒叙 + + return selectPage(page, wrapper); + } + + /** + * 根据用户名查询 + * @param categoryName + * @return + */ + default CategoryDO selectByName(String categoryName) { + // 构建查询条件 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(CategoryDO::getName, categoryName); + + // 执行查询 + return selectOne(wrapper); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/TagMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/TagMapper.java new file mode 100644 index 0000000..0ea02ae --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/TagMapper.java @@ -0,0 +1,58 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.quanxiaoha.weblog.common.domain.dos.CategoryDO; +import com.quanxiaoha.weblog.common.domain.dos.TagDO; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: TODO + **/ +public interface TagMapper extends BaseMapper { + + /** + * 分页查询 + * @param current + * @param size + * @param name + * @param startDate + * @param endDate + * @return + */ + default Page selectPageList(long current, long size, String name, LocalDate startDate, LocalDate endDate) { + // 分页对象 + Page page = new Page<>(current, size); + + // 构建查询条件 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper + .like(Objects.nonNull(name), TagDO::getName, name) // 模糊查询 + .ge(Objects.nonNull(startDate), TagDO::getCreateTime, startDate) // 大于等于开始时间 + .le(Objects.nonNull(endDate), TagDO::getCreateTime, endDate) // 小于等于结束时间 + .orderByDesc(TagDO::getCreateTime); // order by create_time desc + + return selectPage(page, wrapper); + } + + /** + * 根据标签模糊查询 + * @param key + * @return + */ + default List selectByKey(String key) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + // 构造模糊查询的条件 + wrapper.like(TagDO::getName, key).orderByDesc(TagDO::getCreateTime); + + return selectList(wrapper); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserMapper.java new file mode 100644 index 0000000..e0f5cd8 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserMapper.java @@ -0,0 +1,33 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.quanxiaoha.weblog.common.domain.dos.UserDO; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: TODO + **/ +public interface UserMapper extends BaseMapper { + default UserDO findByUsername(String username) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserDO::getUsername, username); + return selectOne(wrapper); + } + + default int updatePasswordByUsername(String username, String password) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + // 设置要更新的字段 + wrapper.set(UserDO::getPassword, password); + wrapper.set(UserDO::getUpdateTime, LocalDateTime.now()); + // 更新条件 + wrapper.eq(UserDO::getUsername, username); + + return update(null, wrapper); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserRoleMapper.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserRoleMapper.java new file mode 100644 index 0000000..553bd70 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserRoleMapper.java @@ -0,0 +1,27 @@ +package com.quanxiaoha.weblog.common.domain.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.quanxiaoha.weblog.common.domain.dos.UserRoleDO; + +import java.util.List; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 17:06 + * @description: TODO + **/ +public interface UserRoleMapper extends BaseMapper { + /** + * 根据用户名查询 + * @param username + * @return + */ + default List selectByUsername(String username) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserRoleDO::getUsername, username); + + return selectList(wrapper); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/package-info.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/package-info.java new file mode 100644 index 0000000..948fa16 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/package-info.java @@ -0,0 +1,7 @@ +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-22 16:57 + * @description: TODO + **/ +package com.quanxiaoha.weblog.common.domain; \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/ResponseCodeEnum.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/ResponseCodeEnum.java new file mode 100644 index 0000000..080c1eb --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/ResponseCodeEnum.java @@ -0,0 +1,40 @@ +package com.quanxiaoha.weblog.common.enums; + +import com.quanxiaoha.weblog.common.exception.BaseExceptionInterface; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-15 10:33 + * @description: 响应异常码 + **/ +@Getter +@AllArgsConstructor +public enum ResponseCodeEnum implements BaseExceptionInterface { + + // ----------- 通用异常状态码 ----------- + SYSTEM_ERROR("10000", "出错啦,后台小哥正在努力修复中..."), + PARAM_NOT_VALID("10001", "参数错误"), + + + // ----------- 业务异常状态码 ----------- + LOGIN_FAIL("20000", "登录失败"), + USERNAME_OR_PWD_ERROR("20001", "用户名或密码错误"), + UNAUTHORIZED("20002", "无访问权限,请先登录!"), + USERNAME_NOT_FOUND("20003", "该用户不存在"), + FORBIDDEN("20004", "演示账号仅支持查询操作!"), + CATEGORY_NAME_IS_EXISTED("20005", "该分类已存在,请勿重复添加!"), + TAG_CANT_DUPLICATE("20006", "请勿添加表中已存在的标签!"), + TAG_NOT_EXISTED("20007", "该标签不存在!"), + FILE_UPLOAD_FAILED("20008", "文件上传失败!"), + CATEGORY_NOT_EXISTED("20009", "提交的分类不存在!"), + ; + + // 异常码 + private String errorCode; + // 错误信息 + private String errorMessage; + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BaseExceptionInterface.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BaseExceptionInterface.java new file mode 100644 index 0000000..ad51d50 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BaseExceptionInterface.java @@ -0,0 +1,13 @@ +package com.quanxiaoha.weblog.common.exception; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-15 9:54 + * @description: 通用异常接口 + **/ +public interface BaseExceptionInterface { + String getErrorCode(); + + String getErrorMessage(); +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BizException.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BizException.java new file mode 100644 index 0000000..cf618c2 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BizException.java @@ -0,0 +1,24 @@ +package com.quanxiaoha.weblog.common.exception; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-15 9:52 + * @description: 业务异常 + **/ +@Getter +@Setter +public class BizException extends RuntimeException { + // 异常码 + private String errorCode; + // 错误信息 + private String errorMessage; + + public BizException(BaseExceptionInterface baseExceptionInterface) { + this.errorCode = baseExceptionInterface.getErrorCode(); + this.errorMessage = baseExceptionInterface.getErrorMessage(); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/GlobalExceptionHandler.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..6cb4e03 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/GlobalExceptionHandler.java @@ -0,0 +1,92 @@ +package com.quanxiaoha.weblog.common.exception; + +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.utils.Response; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.bind.BindResult; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.util.Optional; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-15 10:14 + * @description: 全局异常处理 + **/ +@ControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + /** + * 捕获自定义业务异常 + * @return + */ + @ExceptionHandler({ BizException.class }) + @ResponseBody + public Response handleBizException(HttpServletRequest request, BizException e) { + log.warn("{} request fail, errorCode: {}, errorMessage: {}", request.getRequestURI(), e.getErrorCode(), e.getErrorMessage()); + return Response.fail(e); + } + + /** + * 捕获参数校验异常 + * @return + */ + @ExceptionHandler({ MethodArgumentNotValidException.class }) + @ResponseBody + public Response handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) { + // 参数错误异常码 + String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode(); + + // 获取 BindingResult + BindingResult bindingResult = e.getBindingResult(); + + StringBuilder sb = new StringBuilder(); + + // 获取校验不通过的字段,并组合错误信息,格式为: email 邮箱格式不正确, 当前值: '123124qq.com'; + Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors -> { + errors.forEach(error -> + sb.append(error.getField()) + .append(" ") + .append(error.getDefaultMessage()) + .append(", 当前值: '") + .append(error.getRejectedValue()) + .append("'; ") + + ); + }); + + // 错误信息 + String errorMessage = sb.toString(); + + log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage); + + return Response.fail(errorCode, errorMessage); + } + + @ExceptionHandler({ AccessDeniedException.class }) + public void throwAccessDeniedException(AccessDeniedException e) throws AccessDeniedException { + log.info("============= 捕获到 AccessDeniedException"); + throw e; + } + + /** + * 其他类型异常 + * @param request + * @param e + * @return + */ + @ExceptionHandler({ Exception.class }) + @ResponseBody + public Response handleOtherException(HttpServletRequest request, Exception e) { + log.error("{} request error, ", request.getRequestURI(), e); + return Response.fail(ResponseCodeEnum.SYSTEM_ERROR); + } +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/BasePageQuery.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/BasePageQuery.java new file mode 100644 index 0000000..15e8d22 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/BasePageQuery.java @@ -0,0 +1,23 @@ +package com.quanxiaoha.weblog.common.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-19 8:54 + * @description: TODO + **/ +@Data +public class BasePageQuery { + /** + * 当前页码, 默认第一页 + */ + private Long current = 1L; + /** + * 每页展示的数据数量,默认每页展示 10 条数据 + */ + private Long size = 10L; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/package-info.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/package-info.java new file mode 100644 index 0000000..ab657b0 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/package-info.java @@ -0,0 +1,7 @@ +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-09-19 8:53 + * @description: TODO + **/ +package com.quanxiaoha.weblog.common.model; \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/vo/SelectRspVO.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/vo/SelectRspVO.java new file mode 100644 index 0000000..56fa4cb --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/vo/SelectRspVO.java @@ -0,0 +1,28 @@ +package com.quanxiaoha.weblog.common.model.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023/9/20 16:02 + * @description: TODO + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class SelectRspVO { + /** + * Select 下拉列表的展示文字 + */ + private String label; + + /** + * Select 下拉列表的 value 值,如 ID 等 + */ + private Object value; +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/package-info.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/package-info.java new file mode 100644 index 0000000..f36a31e --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/package-info.java @@ -0,0 +1,7 @@ +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-10 9:20 + * @description: TODO + **/ +package com.quanxiaoha.weblog.common; \ No newline at end of file diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/JsonUtil.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/JsonUtil.java new file mode 100644 index 0000000..bc2f4c7 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/JsonUtil.java @@ -0,0 +1,31 @@ +package com.quanxiaoha.weblog.common.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-14 16:27 + * @description: JSON 工具类 + **/ +@Slf4j +public class JsonUtil { + + private static final ObjectMapper INSTANCE = new ObjectMapper(); + + public static String toJsonString(Object obj) { + try { + return INSTANCE.writeValueAsString(obj); + } catch (JsonProcessingException e) { + // todo Jackson 出参打印包含 Java 8 新日期出错问题 + return obj.toString(); + } + } + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/PageResponse.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/PageResponse.java new file mode 100644 index 0000000..f9cb8b6 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/PageResponse.java @@ -0,0 +1,60 @@ +package com.quanxiaoha.weblog.common.utils; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.quanxiaoha.weblog.common.exception.BaseExceptionInterface; +import com.quanxiaoha.weblog.common.exception.BizException; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; +import java.util.Objects; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-11 19:50 + * @description: 分页响应参数工具类 + **/ +@Data +public class PageResponse extends Response> { + + /** + * 总记录数 + */ + private long total = 0L; + + /** + * 每页显示的记录数,默认每页显示 10 条 + */ + private long size = 10L; + + /** + * 当前页码 + */ + private long current; + + /** + * 总页数 + */ + private long pages; + + /** + * 成功响应 + * @param page Mybatis Plus 提供的分页接口 + * @param data + * @return + * @param + */ + public static PageResponse success(IPage page, List data) { + PageResponse response = new PageResponse<>(); + response.setSuccess(true); + response.setCurrent(Objects.isNull(page) ? 1L : page.getCurrent()); + response.setSize(Objects.isNull(page) ? 10L : page.getSize()); + response.setPages(Objects.isNull(page) ? 0L : page.getPages()); + response.setTotal(Objects.isNull(page) ? 0L : page.getTotal()); + response.setData(data); + return response; + } + + +} diff --git a/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/Response.java b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/Response.java new file mode 100644 index 0000000..dfa1743 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/Response.java @@ -0,0 +1,77 @@ +package com.quanxiaoha.weblog.common.utils; + +import com.quanxiaoha.weblog.common.exception.BaseExceptionInterface; +import com.quanxiaoha.weblog.common.exception.BizException; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-11 19:50 + * @description: 响应参数工具类 + **/ +@Data +public class Response implements Serializable { + + // 是否成功,默认为 true + private boolean success = true; + // 响应消息 + private String message; + // 异常码 + private String errorCode; + // 响应数据 + private T data; + + // =================================== 成功响应 =================================== + public static Response success() { + Response response = new Response<>(); + return response; + } + + public static Response success(T data) { + Response response = new Response<>(); + response.setData(data); + return response; + } + + // =================================== 失败响应 =================================== + public static Response fail() { + Response response = new Response<>(); + response.setSuccess(false); + return response; + } + + public static Response fail(String errorMessage) { + Response response = new Response<>(); + response.setSuccess(false); + response.setMessage(errorMessage); + return response; + } + + public static Response fail(String errorCode, String errorMessage) { + Response response = new Response<>(); + response.setSuccess(false); + response.setErrorCode(errorCode); + response.setMessage(errorMessage); + return response; + } + + public static Response fail(BizException bizException) { + Response response = new Response<>(); + response.setSuccess(false); + response.setErrorCode(bizException.getErrorCode()); + response.setMessage(bizException.getErrorMessage()); + return response; + } + + public static Response fail(BaseExceptionInterface baseExceptionInterface) { + Response response = new Response<>(); + response.setSuccess(false); + response.setErrorCode(baseExceptionInterface.getErrorCode()); + response.setMessage(baseExceptionInterface.getErrorMessage()); + return response; + } + +} diff --git a/weblog-springboot-103/weblog-module-common/src/test/java/com/quanxiaoha/weblog/common/WeblogModuleCommonApplicationTests.java b/weblog-springboot-103/weblog-module-common/src/test/java/com/quanxiaoha/weblog/common/WeblogModuleCommonApplicationTests.java new file mode 100644 index 0000000..3f5ed89 --- /dev/null +++ b/weblog-springboot-103/weblog-module-common/src/test/java/com/quanxiaoha/weblog/common/WeblogModuleCommonApplicationTests.java @@ -0,0 +1,23 @@ +package com.quanxiaoha.weblog.common; + +import com.quanxiaoha.weblog.common.domain.dos.UserDO; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Date; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = WeblogModuleCommonApplicationTests.Application.class) +@Slf4j +class WeblogModuleCommonApplicationTests { + + public static class Application { + } + + @Test + public void test() { + } + +} diff --git a/weblog-springboot-103/weblog-module-jwt/.gitignore b/weblog-springboot-103/weblog-module-jwt/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/weblog-springboot-103/weblog-module-jwt/pom.xml b/weblog-springboot-103/weblog-module-jwt/pom.xml new file mode 100644 index 0000000..f538850 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + com.quanxiaoha + weblog-springboot + ${revision} + + + com.quanxiaoha + weblog-module-jwt + weblog-module-jwt + weblog-module-jwt (JWT 模块,管理用户认证、鉴权) + + + + + org.projectlombok + lombok + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.springframework.boot + spring-boot-starter-security + + + + + io.jsonwebtoken + jjwt-api + + + io.jsonwebtoken + jjwt-impl + + + io.jsonwebtoken + jjwt-jackson + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.apache.commons + commons-lang3 + + + + + com.quanxiaoha + weblog-module-common + + + + com.fasterxml.jackson.core + jackson-core + + + + diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/JwtAuthenticationSecurityConfig.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/JwtAuthenticationSecurityConfig.java new file mode 100644 index 0000000..52d7c16 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/JwtAuthenticationSecurityConfig.java @@ -0,0 +1,58 @@ +package com.quanxiaoha.weblog.jwt.config; + +import com.quanxiaoha.weblog.jwt.filter.JwtAuthenticationFilter; +import com.quanxiaoha.weblog.jwt.handler.RestAuthenticationFailureHandler; +import com.quanxiaoha.weblog.jwt.handler.RestAuthenticationSuccessHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 16:45 + * @description: 认证功能相关配置 + **/ +@Configuration +public class JwtAuthenticationSecurityConfig extends SecurityConfigurerAdapter { + + @Autowired + private RestAuthenticationSuccessHandler restAuthenticationSuccessHandler; + + @Autowired + private RestAuthenticationFailureHandler restAuthenticationFailureHandler; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private UserDetailsService userDetailsService; + + @Override + public void configure(HttpSecurity httpSecurity) throws Exception { + // 自定义的用于 JWT 身份验证的过滤器 + JwtAuthenticationFilter filter = new JwtAuthenticationFilter(); + filter.setAuthenticationManager(httpSecurity.getSharedObject(AuthenticationManager.class)); + + // 设置登录认证对应的处理类(成功处理、失败处理) + filter.setAuthenticationSuccessHandler(restAuthenticationSuccessHandler); + filter.setAuthenticationFailureHandler(restAuthenticationFailureHandler); + + // 直接使用 DaoAuthenticationProvider, 它是 Spring Security 提供的默认的身份验证提供者之一 + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + // 设置 userDetailService,用于获取用户的详细信息 + provider.setUserDetailsService(userDetailsService); + // 设置加密算法 + provider.setPasswordEncoder(passwordEncoder); + httpSecurity.authenticationProvider(provider); + // 将这个过滤器添加到 UsernamePasswordAuthenticationFilter 之前执行 + httpSecurity.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/PasswordEncoderConfig.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/PasswordEncoderConfig.java new file mode 100644 index 0000000..f2614d9 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/PasswordEncoderConfig.java @@ -0,0 +1,27 @@ +package com.quanxiaoha.weblog.jwt.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 9:17 + * @description: 密码加密 + **/ +@Component +public class PasswordEncoderConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + // BCrypt 是一种安全且适合密码存储的哈希算法,它在进行哈希时会自动加入“盐”,增加密码的安全性。 + return new BCryptPasswordEncoder(); + } + + public static void main(String[] args) { + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + System.out.println(encoder.encode("111")); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/exception/UsernameOrPasswordNullException.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/exception/UsernameOrPasswordNullException.java new file mode 100644 index 0000000..e50ba96 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/exception/UsernameOrPasswordNullException.java @@ -0,0 +1,19 @@ +package com.quanxiaoha.weblog.jwt.exception; + +import org.springframework.security.core.AuthenticationException; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 17:11 + * @description: 用户名或者密码为空异常 + **/ +public class UsernameOrPasswordNullException extends AuthenticationException { + public UsernameOrPasswordNullException(String msg, Throwable cause) { + super(msg, cause); + } + + public UsernameOrPasswordNullException(String msg) { + super(msg); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/JwtAuthenticationFilter.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/JwtAuthenticationFilter.java new file mode 100644 index 0000000..736c914 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/JwtAuthenticationFilter.java @@ -0,0 +1,59 @@ +package com.quanxiaoha.weblog.jwt.filter; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.quanxiaoha.weblog.jwt.exception.UsernameOrPasswordNullException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 9:36 + * @description: 用户认证过滤器 + **/ +@Slf4j +public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + + /** + * 指定用户登录的访问地址 + */ + public JwtAuthenticationFilter() { + super(new AntPathRequestMatcher("/login", "POST")); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + ObjectMapper mapper = new ObjectMapper(); + // 解析提交的 JSON 数据 + JsonNode jsonNode = mapper.readTree(request.getInputStream()); + JsonNode usernameNode = jsonNode.get("username"); + JsonNode passwordNode = jsonNode.get("password"); + + // 判断用户名、密码是否为空 + if (Objects.isNull(usernameNode) || Objects.isNull(passwordNode) + || StringUtils.isBlank(usernameNode.textValue()) || StringUtils.isBlank(passwordNode.textValue())) { + throw new UsernameOrPasswordNullException("用户名或密码不能为空"); + } + + String username = usernameNode.textValue(); + String password = passwordNode.textValue(); + + // 将用户名、密码封装到 Token 中 + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken + = new UsernamePasswordAuthenticationToken(username, password); + return getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/TokenAuthenticationFilter.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/TokenAuthenticationFilter.java new file mode 100644 index 0000000..3560521 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/filter/TokenAuthenticationFilter.java @@ -0,0 +1,107 @@ +package com.quanxiaoha.weblog.jwt.filter; + +import com.quanxiaoha.weblog.jwt.utils.JwtTokenHelper; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.SignatureException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.CredentialsExpiredException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +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.UserDetailsService; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.stereotype.Component; +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; +import java.util.Objects; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-27 16:58 + * @description: Token 校验过滤器 + **/ +@Slf4j +public class TokenAuthenticationFilter extends OncePerRequestFilter { + + @Value("${jwt.tokenPrefix}") + private String tokenPrefix; + + @Value("${jwt.tokenHeaderKey}") + private String tokenHeaderKey; + + @Autowired + private JwtTokenHelper jwtTokenHelper; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private AuthenticationEntryPoint authenticationEntryPoint; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String requestURI = request.getRequestURI(); + + if (requestURI.startsWith("/admin")) { + // 从请求头中获取 key 为 Authorization 的值 + String header = request.getHeader(tokenHeaderKey); + + // 判断 value 值是否以 Bearer 开头 + if (StringUtils.startsWith(header, tokenPrefix)) { + // 截取 Token 令牌 + String token = StringUtils.substring(header, 7); + log.info("Token: {}", token); + + // 判空 Token + if (StringUtils.isNotBlank(token)) { + try { + // 校验 Token 是否可用, 若解析异常,针对不同异常做出不同的响应参数 + jwtTokenHelper.validateToken(token); + } catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException e) { + // 抛出异常,统一让 AuthenticationEntryPoint 处理响应参数 + authenticationEntryPoint.commence(request, response, new AuthenticationServiceException("Token 不可用")); + return; + } catch (ExpiredJwtException e) { + authenticationEntryPoint.commence(request, response, new AuthenticationServiceException("Token 已失效")); + return; + } + + // 从 Token 中解析出用户名 + String username = jwtTokenHelper.getUsernameByToken(token); + + if (StringUtils.isNotBlank(username) + && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) { + // 根据用户名获取用户详情信息 + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + + // 将用户信息存入 authentication,方便后续校验 + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, + userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + // 将 authentication 存入 ThreadLocal,方便后续获取用户信息 + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + } + + // 继续执行写一个过滤器 + filterChain.doFilter(request, response); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAccessDeniedHandler.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAccessDeniedHandler.java new file mode 100644 index 0000000..7575512 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAccessDeniedHandler.java @@ -0,0 +1,32 @@ +package com.quanxiaoha.weblog.jwt.handler; + +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.utils.Response; +import com.quanxiaoha.weblog.jwt.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +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; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-27 17:32 + * @description: 登录成功访问收保护的资源,但是权限不够 + **/ +@Slf4j +@Component +public class RestAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + log.warn("登录成功访问收保护的资源,但是权限不够: ", accessDeniedException); + // 预留,后面引入多角色时会用到 + ResultUtil.fail(response, Response.fail(ResponseCodeEnum.FORBIDDEN)); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationEntryPoint.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationEntryPoint.java new file mode 100644 index 0000000..850ca63 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationEntryPoint.java @@ -0,0 +1,38 @@ +package com.quanxiaoha.weblog.jwt.handler; + +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.utils.Response; +import com.quanxiaoha.weblog.jwt.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.InsufficientAuthenticationException; +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; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-27 17:27 + * @description: 用户未登录访问受保护的资源 + **/ +@Slf4j +@Component +public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + log.warn("用户未登录访问受保护的资源: ", authException); + if (authException instanceof InsufficientAuthenticationException) { + ResultUtil.fail(response, HttpStatus.UNAUTHORIZED.value(), Response.fail(ResponseCodeEnum.UNAUTHORIZED)); + } + + ResultUtil.fail(response, HttpStatus.UNAUTHORIZED.value(), Response.fail(authException.getMessage())); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationFailureHandler.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationFailureHandler.java new file mode 100644 index 0000000..82ff738 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationFailureHandler.java @@ -0,0 +1,43 @@ +package com.quanxiaoha.weblog.jwt.handler; + +import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; +import com.quanxiaoha.weblog.common.utils.Response; +import com.quanxiaoha.weblog.jwt.exception.UsernameOrPasswordNullException; +import com.quanxiaoha.weblog.jwt.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 15:19 + * @description: 认证失败处理器 + **/ +@Component +@Slf4j +public class RestAuthenticationFailureHandler implements AuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + log.warn("AuthenticationException: ", exception); + if (exception instanceof UsernameOrPasswordNullException) { + // 用户名或密码为空 + ResultUtil.fail(response, Response.fail(exception.getMessage())); + } else if (exception instanceof BadCredentialsException) { + // 用户名或密码错误 + ResultUtil.fail(response, Response.fail(ResponseCodeEnum.USERNAME_OR_PWD_ERROR)); + } + + // 登录失败 + ResultUtil.fail(response, Response.fail(ResponseCodeEnum.LOGIN_FAIL)); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationSuccessHandler.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationSuccessHandler.java new file mode 100644 index 0000000..d57015a --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationSuccessHandler.java @@ -0,0 +1,47 @@ +package com.quanxiaoha.weblog.jwt.handler; + +import com.quanxiaoha.weblog.common.utils.Response; +import com.quanxiaoha.weblog.jwt.model.LoginRspVO; +import com.quanxiaoha.weblog.jwt.utils.JwtTokenHelper; +import com.quanxiaoha.weblog.jwt.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 15:19 + * @description: 认证成功处理器 + **/ +@Component +@Slf4j +public class RestAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + @Autowired + private JwtTokenHelper jwtTokenHelper; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + // 从 authentication 对象中获取用户的 UserDetails 实例,这里是获取用户的用户名 + UserDetails userDetails = (UserDetails) authentication.getPrincipal(); + + // 通过用户名生成 Token + String username = userDetails.getUsername(); + String token = jwtTokenHelper.generateToken(username); + + // 返回 Token + LoginRspVO loginRspVO = LoginRspVO.builder().token(token).build(); + + ResultUtil.ok(response, Response.success(loginRspVO)); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/model/LoginRspVO.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/model/LoginRspVO.java new file mode 100644 index 0000000..b8c8e3e --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/model/LoginRspVO.java @@ -0,0 +1,25 @@ +package com.quanxiaoha.weblog.jwt.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 9:43 + * @description: 用户登录 + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class LoginRspVO { + + /** + * Token 值 + */ + private String token; + +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/service/UserDetailServiceImpl.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/service/UserDetailServiceImpl.java new file mode 100644 index 0000000..f9f72af --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/service/UserDetailServiceImpl.java @@ -0,0 +1,63 @@ +package com.quanxiaoha.weblog.jwt.service; + +import com.quanxiaoha.weblog.common.domain.dos.UserDO; +import com.quanxiaoha.weblog.common.domain.dos.UserRoleDO; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import com.quanxiaoha.weblog.common.domain.mapper.UserRoleMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.User; +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 org.springframework.util.CollectionUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 9:14 + * @description: TODO + **/ +@Service +@Slf4j +public class UserDetailServiceImpl implements UserDetailsService { + + @Autowired + private UserMapper userMapper; + @Autowired + private UserRoleMapper userRoleMapper; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 从数据库中查询 + UserDO userDO = userMapper.findByUsername(username); + + // 判断用户是否存在 + if (Objects.isNull(userDO)) { + throw new UsernameNotFoundException("该用户不存在"); + } + + // 用户角色 + List roleDOS = userRoleMapper.selectByUsername(username); + + String[] roleArr = null; + + if (!CollectionUtils.isEmpty(roleDOS)) { + List roles = roleDOS.stream().map(p -> p.getRole()).collect(Collectors.toList()); + roleArr = roles.toArray(new String[roles.size()]); + } + + // authorities 用于指定角色 + return User.withUsername(userDO.getUsername()) + .password(userDO.getPassword()) + .authorities(roleArr) + .build(); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/JwtTokenHelper.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/JwtTokenHelper.java new file mode 100644 index 0000000..3e67020 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/JwtTokenHelper.java @@ -0,0 +1,146 @@ +package com.quanxiaoha.weblog.jwt.utils; + +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SignatureException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.CredentialsExpiredException; +import org.springframework.stereotype.Component; + +import java.security.Key; +import java.sql.Date; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Base64; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-24 8:16 + * @description: JWT Token 工具类 + **/ +@Component +public class JwtTokenHelper implements InitializingBean { + + /** + * 签发人 + */ + @Value("${jwt.issuer}") + private String issuer; + + /** + * Token 失效时间(分钟) + */ + @Value("${jwt.tokenExpireTime}") + private Long tokenExpireTime; + /** + * 秘钥 + */ + private Key key; + + /** + * JWT 解析 + */ + private JwtParser jwtParser; + + /** + * 解码配置文件中配置的 Base 64 编码 key 为秘钥 + * @param base64Key + */ + @Value("${jwt.secret}") + public void setBase64Key(String base64Key) { + key = Keys.hmacShaKeyFor(Base64.getDecoder().decode(base64Key)); + } + + + /** + * 初始化 JwtParser + * @throws Exception + */ + @Override + public void afterPropertiesSet() throws Exception { + // 考虑到不同服务器之间可能存在时钟偏移,setAllowedClockSkewSeconds 用于设置能够容忍的最大的时钟误差 + jwtParser = Jwts.parserBuilder().requireIssuer(issuer) + .setSigningKey(key).setAllowedClockSkewSeconds(10) + .build(); + } + + /** + * 生成 Token + * @param username + * @return + */ + public String generateToken(String username) { + LocalDateTime now = LocalDateTime.now(); + // 设置 Token 失效时间 + LocalDateTime expireTime = now.plusMinutes(tokenExpireTime); + + return Jwts.builder().setSubject(username) + .setIssuer(issuer) + .setIssuedAt(Date.from(now.atZone(ZoneId.systemDefault()).toInstant())) + .setExpiration(Date.from(expireTime.atZone(ZoneId.systemDefault()).toInstant())) + .signWith(key) + .compact(); + } + + /** + * 解析 Token + * @param token + * @return + */ + public Jws parseToken(String token) { + try { + return jwtParser.parseClaimsJws(token); + } catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException e) { + throw new BadCredentialsException("Token 不可用", e); + } catch (ExpiredJwtException e) { + throw new CredentialsExpiredException("Token 失效", e); + } + } + + /** + * 校验 Token 是否可用 + * @param token + * @return + */ + public void validateToken(String token) { + jwtParser.parseClaimsJws(token); + } + + /** + * 解析 Token 获取用户名 + * @param token + * @return + */ + public String getUsernameByToken(String token) { + try { + Claims claims = jwtParser.parseClaimsJws(token).getBody(); + String username = claims.getSubject(); + return username; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 生成一个 Base64 的安全秘钥 + * @return + */ + private static String generateBase64Key() { + // 生成安全秘钥 + Key secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS512); + + // 将密钥进行 Base64 编码 + String base64Key = Base64.getEncoder().encodeToString(secretKey.getEncoded()); + + return base64Key; + } + + public static void main(String[] args) { + String key = generateBase64Key(); + System.out.println("key: " + key); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/ResultUtil.java b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/ResultUtil.java new file mode 100644 index 0000000..2102e41 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/utils/ResultUtil.java @@ -0,0 +1,73 @@ +package com.quanxiaoha.weblog.jwt.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.quanxiaoha.weblog.common.utils.Response; +import org.springframework.http.HttpStatus; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-04-18 15:05 + * @description: 响参工具 + **/ +public class ResultUtil { + + /** + * 成功响参 + * @param response + * @param result + * @throws IOException + */ + public static void ok(HttpServletResponse response, Response result) throws IOException { + response.setCharacterEncoding("UTF-8"); + response.setStatus(HttpStatus.OK.value()); + response.setContentType("application/json"); + PrintWriter writer = response.getWriter(); + + ObjectMapper mapper = new ObjectMapper(); + writer.write(mapper.writeValueAsString(result)); + writer.flush(); + writer.close(); + } + + /** + * 失败响参 + * @param response + * @param result + * @throws IOException + */ + public static void fail(HttpServletResponse response, Response result) throws IOException { + response.setCharacterEncoding("UTF-8"); + response.setStatus(HttpStatus.OK.value()); + response.setContentType("application/json"); + PrintWriter writer = response.getWriter(); + + ObjectMapper mapper = new ObjectMapper(); + writer.write(mapper.writeValueAsString(result)); + writer.flush(); + writer.close(); + } + + /** + * 失败响参 + * @param response + * @param status 可指定响应码,如 401 等 + * @param result + * @throws IOException + */ + public static void fail(HttpServletResponse response, int status, Response result) throws IOException { + response.setCharacterEncoding("UTF-8"); + response.setStatus(status); + response.setContentType("application/json"); + PrintWriter writer = response.getWriter(); + + ObjectMapper mapper = new ObjectMapper(); + writer.write(mapper.writeValueAsString(result)); + writer.flush(); + writer.close(); + } +} diff --git a/weblog-springboot-103/weblog-module-jwt/src/test/java/com/quanxiaoha/weblog/jwt/WeblogModuleJwtApplicationTests.java b/weblog-springboot-103/weblog-module-jwt/src/test/java/com/quanxiaoha/weblog/jwt/WeblogModuleJwtApplicationTests.java new file mode 100644 index 0000000..1e5a164 --- /dev/null +++ b/weblog-springboot-103/weblog-module-jwt/src/test/java/com/quanxiaoha/weblog/jwt/WeblogModuleJwtApplicationTests.java @@ -0,0 +1,16 @@ +package com.quanxiaoha.weblog.jwt; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = WeblogModuleJwtApplicationTests.Application.class) +class WeblogModuleJwtApplicationTests { + + public static class Application { + } + + @Test + void contextLoads() { + } + +} diff --git a/weblog-springboot-103/weblog-web/.gitignore b/weblog-springboot-103/weblog-web/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/weblog-springboot-103/weblog-web/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/weblog-springboot-103/weblog-web/pom.xml b/weblog-springboot-103/weblog-web/pom.xml new file mode 100644 index 0000000..46371d4 --- /dev/null +++ b/weblog-springboot-103/weblog-web/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + + com.quanxiaoha + weblog-springboot + ${revision} + + + com.quanxiaoha + weblog-web + weblog-web + weblog-web (入口项目,负责博客前台展示相关功能,打包也放在这个模块负责) + + + + com.quanxiaoha + weblog-module-common + + + + com.quanxiaoha + weblog-module-admin + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + + + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/WeblogWebApplication.java b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/WeblogWebApplication.java new file mode 100644 index 0000000..ff25423 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/WeblogWebApplication.java @@ -0,0 +1,15 @@ +package com.quanxiaoha.weblog.web; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan({"com.quanxiaoha.weblog.*"}) // 多模块项目中,必需手动指定扫描 com.quanxiaoha.weblog 包下面的所有类 +public class WeblogWebApplication { + + public static void main(String[] args) { + SpringApplication.run(WeblogWebApplication.class, args); + } + +} diff --git a/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/config/Knife4jConfig.java b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/config/Knife4jConfig.java new file mode 100644 index 0000000..e0edb26 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/config/Knife4jConfig.java @@ -0,0 +1,53 @@ +package com.quanxiaoha.weblog.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-16 7:53 + * @description: Knife4j 配置 + **/ +@Configuration +@EnableSwagger2WebMvc +@Profile("dev") // 只在 dev 环境中开启 +public class Knife4jConfig { + + @Bean("webApi") + public Docket createApiDoc() { + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(buildApiInfo()) + // 分组名称 + .groupName("Web 前台接口") + .select() + // 这里指定 Controller 扫描包路径 + .apis(RequestHandlerSelectors.basePackage("com.quanxiaoha.weblog.web.controller")) + .paths(PathSelectors.any()) + .build(); + return docket; + } + + /** + * 构建 API 信息 + * @return + */ + private ApiInfo buildApiInfo() { + return new ApiInfoBuilder() + .title("Weblog 博客前台接口文档") // 标题 + .description("Weblog 是一款由 Spring Boot + Vue 3.2 + Vite 4.3 开发的前后端分离博客。") // 描述 + .termsOfServiceUrl("https://www.quanxiaoha.com/") // API 服务条款 + .contact(new Contact("犬小哈", "https://www.quanxiaoha.com", "871361652@qq.com")) // 联系人 + .version("1.0") // 版本号 + .build(); + } +} diff --git a/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/TestController.java b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/TestController.java new file mode 100644 index 0000000..8025706 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/TestController.java @@ -0,0 +1,54 @@ +package com.quanxiaoha.weblog.web.controller; + +import com.quanxiaoha.weblog.common.utils.JsonUtil; +import com.quanxiaoha.weblog.common.utils.Response; +import com.quanxiaoha.weblog.web.model.User; +import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Date; + + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-10 10:34 + * @description: TODO + **/ +@RestController +@Slf4j +@Api(tags = "首页模块") +public class TestController { + + @PostMapping("/test") + @ApiOperationLog(description = "测试接口") + @ApiOperation(value = "测试接口") + public Response test(@RequestBody @Validated User user) { + // 打印入参 + log.info(JsonUtil.toJsonString(user)); + + // 设置三种日期字段值 + user.setCreateTime(LocalDateTime.now()); + user.setUpdateDate(LocalDate.now()); + user.setTime(LocalTime.now()); + + return Response.success(user); + } + + public static void main(String[] args) { + LocalDateTime now = LocalDateTime.now(); + User user = new User(); + user.setCreateTime(now); + System.out.println(JsonUtil.toJsonString(user)); + } + +} diff --git a/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/User.java b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/User.java new file mode 100644 index 0000000..07216dd --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/User.java @@ -0,0 +1,50 @@ +package com.quanxiaoha.weblog.web.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.*; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Date; + +/** + * @author: 犬小哈 + * @url: www.quanxiaoha.com + * @date: 2023-08-10 10:35 + * @description: TODO + **/ +@Data +@ApiModel(value = "用户实体类") +public class User { + // 用户名 + @NotBlank(message = "用户名不能为空") // 注解确保用户名不为空 + @ApiModelProperty(value = "用户名") + private String username; + // 性别 + @NotNull(message = "性别不能为空") // 注解确保性别不为空 + @ApiModelProperty(value = "用户性别") + private Integer sex; + + // 年龄 + @NotNull(message = "年龄不能为空") + @Min(value = 18, message = "年龄必须大于或等于 18") // 注解确保年龄大于等于 18 + @Max(value = 100, message = "年龄必须小于或等于 100") // 注解确保年龄小于等于 100 + @ApiModelProperty(value = "年龄") + private Integer age; + + // 邮箱 + @NotBlank(message = "邮箱不能为空") + @Email(message = "邮箱格式不正确") // 注解确保邮箱格式正确 + @ApiModelProperty(value = "邮箱") + private String email; + + // 创建时间 + private LocalDateTime createTime; + // 更新日期 + private LocalDate updateDate; + // 时间 + private LocalTime time; +} \ No newline at end of file diff --git a/weblog-springboot-103/weblog-web/src/main/resources/application-dev.yml b/weblog-springboot-103/weblog-web/src/main/resources/application-dev.yml new file mode 100644 index 0000000..bc01d83 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/resources/application-dev.yml @@ -0,0 +1,27 @@ +spring: + datasource: + # 指定数据库驱动类 + driver-class-name: com.p6spy.engine.spy.P6SpyDriver + # 数据库连接信息 + url: jdbc:p6spy:mysql://127.0.0.1:3306/weblog?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull + username: root + password: 123456 + hikari: # 数据库连接池使用 Hikari + minimum-idle: 5 # 连接池中最小空闲连接数 + maximum-pool-size: 20 # 连接池中允许的最大连接数 + auto-commit: true # 是否自动提交事务 + idle-timeout: 30000 # 连接在连接池中闲置的最长时间,超过这个时间会被释放。 + pool-name: Weblog-HikariCP # 自定义连接池的名字 + max-lifetime: 1800000 # 连接在连接池中的最大存活时间,超过这个时间会被强制关闭。 + connection-timeout: 30000 # 连接的超时时间 + connection-test-query: SELECT 1 # 用于测试连接是否可用的SQL查询 + + +#================================================================= +# minio (上传图片需要,需配置成自己的地址) +#================================================================= +minio: + endpoint: http://127.0.0.1:9000 + accessKey: quanxiaoha + secretKey: quanxiaoha + bucketName: weblog diff --git a/weblog-springboot-103/weblog-web/src/main/resources/application-prod.yml b/weblog-springboot-103/weblog-web/src/main/resources/application-prod.yml new file mode 100644 index 0000000..c424af0 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/resources/application-prod.yml @@ -0,0 +1,27 @@ +server: + port: 8082 +spring: + datasource: + # 指定数据库驱动类 + driver-class-name: com.mysql.cj.jdbc.Driver + # 数据库连接信息 + url: jdbc:mysql://172.17.0.1:3306/weblog?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull + username: root + password: 123456 + hikari: # 数据库连接池使用 Hikari + minimum-idle: 5 # 连接池中最小空闲连接数 + maximum-pool-size: 20 # 连接池中允许的最大连接数 + auto-commit: true # 是否自动提交事务 + idle-timeout: 30000 # 连接在连接池中闲置的最长时间,超过这个时间会被释放。 + pool-name: Weblog-HikariCP # 自定义连接池的名字 + max-lifetime: 1800000 # 连接在连接池中的最大存活时间,超过这个时间会被强制关闭。 + connection-timeout: 30000 # 连接的超时时间 + connection-test-query: SELECT 1 # 用于测试连接是否可用的SQL查询 + + +#================================================================= +# log 日志 +#================================================================= +logging: + config: classpath:logback-weblog.xml + diff --git a/weblog-springboot-103/weblog-web/src/main/resources/application.yml b/weblog-springboot-103/weblog-web/src/main/resources/application.yml new file mode 100644 index 0000000..dd9f9c9 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/resources/application.yml @@ -0,0 +1,18 @@ +spring: + profiles: + # 默认激活 dev 环境 + active: dev + +jwt: + # 签发人 + issuer: quanxiaoha + # 秘钥 + secret: jElxcSUj38+Bnh73T68lNs0DfBSit6U3whQlcGO2XwnI+Bo3g4xsiCIPg8PV/L0fQMis08iupNwhe2PzYLB9Xg== + # token 过期时间(单位:分钟) 24*60 + tokenExpireTime: 1440 + # token 请求头中的 key 值 + tokenHeaderKey: Authorization + # token 请求头中的 value 值前缀 + tokenPrefix: Bearer + + diff --git a/weblog-springboot-103/weblog-web/src/main/resources/logback-weblog.xml b/weblog-springboot-103/weblog-web/src/main/resources/logback-weblog.xml new file mode 100644 index 0000000..85ffc3f --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/resources/logback-weblog.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + ${LOG_FILE}-%i.log + + 30 + + + 10MB + + + + + ${FILE_LOG_PATTERN} + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/weblog-springboot-103/weblog-web/src/main/resources/spy.properties b/weblog-springboot-103/weblog-web/src/main/resources/spy.properties new file mode 100644 index 0000000..f035706 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/main/resources/spy.properties @@ -0,0 +1,24 @@ +#3.2.1???? +modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory +#3.2.1????????? +#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory +# ??????? +logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger +#???????? +appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger +# ???????? sql +#appender=com.p6spy.engine.spy.appender.Slf4JLogger +# ?? p6spy driver ?? +deregisterdrivers=true +# ??JDBC URL?? +useprefix=true +# ???? Log ??,????????error,info,batch,debug,statement,commit,rollback,result,resultset. +excludecategories=info,debug,result,commit,resultset +# ???? +dateformat=yyyy-MM-dd HH:mm:ss +# ??????? +#driverlist=org.h2.Driver +# ?????SQL?? +outagedetection=true +# ?SQL???? 2 ? +outagedetectioninterval=2 \ No newline at end of file diff --git a/weblog-springboot-103/weblog-web/src/test/java/com/quanxiaoha/weblog/web/WeblogWebApplicationTests.java b/weblog-springboot-103/weblog-web/src/test/java/com/quanxiaoha/weblog/web/WeblogWebApplicationTests.java new file mode 100644 index 0000000..5c1def7 --- /dev/null +++ b/weblog-springboot-103/weblog-web/src/test/java/com/quanxiaoha/weblog/web/WeblogWebApplicationTests.java @@ -0,0 +1,86 @@ +package com.quanxiaoha.weblog.web; + +import com.quanxiaoha.weblog.admin.config.MinioProperties; +import com.quanxiaoha.weblog.common.domain.dos.UserDO; +import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; +import io.minio.MinioClient; +import io.minio.PutObjectArgs; +import io.minio.errors.*; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.time.LocalDateTime; +import java.util.UUID; + +@SpringBootTest +@Slf4j +class WeblogWebApplicationTests { + + @Autowired + private UserMapper userMapper; + + @Autowired + private MinioProperties minioProperties; + + @Autowired + private MinioClient minioClient; + + + @Test + void testLog() { + log.info("这是一行 Info 级别日志"); + log.warn("这是一行 Warn 级别日志"); + log.error("这是一行 Error 级别日志"); + + // 占位符 + String author = "犬小哈"; + log.info("这是一行带有占位符日志,作者:{}", author); + } + + @Test + void insertTest() { + // 构建数据库实体类 + UserDO userDO = UserDO.builder() + .username("犬小哈") + .password("123456") + .createTime(LocalDateTime.now()) + .updateTime(LocalDateTime.now()) + .isDeleted(false) + .build(); + + userMapper.insert(userDO); + } + + @Test + void uploadFile2MinioTest() throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException { + File file = new File("D:\\Backup\\Documents\\My Pictures\\111.jpg"); + String originalFileName = file.getName(); + String contentType = "image/jpeg"; + + String key = UUID.randomUUID().toString().replace("-", ""); + String suffix = originalFileName.substring(originalFileName.lastIndexOf(".")); + + String objectName = String.format("%s%s", key, suffix); + + log.info("==> 开始上传文件至 Minio, ObjectName: {}", objectName); + minioClient.putObject(PutObjectArgs.builder() + .bucket(minioProperties.getBucketName()) + .object(objectName) + .stream(new FileInputStream(file), file.length(), -1) + .contentType(contentType) + .build()); + + String url = String.format("%s/%s/%s", minioProperties.getEndpoint(), minioProperties.getBucketName(), objectName); + log.info("==> 上传文件至 Minio 成功,访问路径: {}", url); + } + +}