├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── doubao.sql ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── douyuehan │ │ └── doubao │ │ ├── DoubaoApplication.java │ │ ├── common │ │ ├── api │ │ │ ├── ApiErrorCode.java │ │ │ ├── ApiResult.java │ │ │ └── IErrorCode.java │ │ ├── exception │ │ │ ├── ApiAsserts.java │ │ │ ├── ApiException.java │ │ │ └── GlobalExceptionHandler.java │ │ └── mybatisplus │ │ │ └── MybatisPlusConfig.java │ │ ├── config │ │ └── GlobalWebMvcConfigurer.java │ │ ├── controller │ │ ├── BaseController.java │ │ ├── BmsBillboardController.java │ │ ├── BmsCommentController.java │ │ ├── BmsPostController.java │ │ ├── BmsPromotionController.java │ │ ├── BmsRelationshipController.java │ │ ├── BmsSearchController.java │ │ ├── BmsTagController.java │ │ ├── BmsTipController.java │ │ └── UmsUserController.java │ │ ├── jwt │ │ ├── JwtAuthenticationFilter.java │ │ └── JwtUtil.java │ │ ├── mapper │ │ ├── BmsBillboardMapper.java │ │ ├── BmsCommentMapper.java │ │ ├── BmsFollowMapper.java │ │ ├── BmsPromotionMapper.java │ │ ├── BmsTagMapper.java │ │ ├── BmsTipMapper.java │ │ ├── BmsTopicMapper.java │ │ ├── BmsTopicTagMapper.java │ │ └── UmsUserMapper.java │ │ ├── model │ │ ├── dto │ │ │ ├── CommentDTO.java │ │ │ ├── CreateTopicDTO.java │ │ │ ├── LoginDTO.java │ │ │ └── RegisterDTO.java │ │ ├── entity │ │ │ ├── BmsBillboard.java │ │ │ ├── BmsComment.java │ │ │ ├── BmsFollow.java │ │ │ ├── BmsPost.java │ │ │ ├── BmsPromotion.java │ │ │ ├── BmsTag.java │ │ │ ├── BmsTip.java │ │ │ ├── BmsTopicTag.java │ │ │ └── UmsUser.java │ │ └── vo │ │ │ ├── CommentVO.java │ │ │ ├── PostVO.java │ │ │ └── ProfileVO.java │ │ ├── service │ │ ├── IBmsBillboardService.java │ │ ├── IBmsCommentService.java │ │ ├── IBmsFollowService.java │ │ ├── IBmsPostService.java │ │ ├── IBmsPromotionService.java │ │ ├── IBmsTagService.java │ │ ├── IBmsTipService.java │ │ ├── IBmsTopicTagService.java │ │ ├── IUmsUserService.java │ │ └── impl │ │ │ ├── IBmsBillboardServiceImpl.java │ │ │ ├── IBmsCommentServiceImpl.java │ │ │ ├── IBmsFollowServiceImpl.java │ │ │ ├── IBmsPostServiceImpl.java │ │ │ ├── IBmsPromotionServiceImpl.java │ │ │ ├── IBmsTagServiceImpl.java │ │ │ ├── IBmsTipServiceImpl.java │ │ │ ├── IBmsTopicTagServiceImpl.java │ │ │ └── IUmsUserServiceImpl.java │ │ └── utils │ │ └── MD5Utils.java └── resources │ ├── application-dev.yaml │ ├── application-prod.yaml │ ├── application.yaml │ └── mapper │ ├── BmsCommentMapper.xml │ ├── BmsPostMapper.xml │ ├── BmsPostTagMapper.xml │ └── BmsTipMapper.xml └── test └── java └── com └── douyuehan └── doubao └── DoubaoApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/songboriceman/doubao_community_backend/896ec3669aa1d8d57014a8ab44623f5f88570b7f/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 豆宝社区项目实战视频教程简介 2 | 本项目实战视频教程全部免费,配套代码完全开源。手把手从零开始搭建一个目前应用最广泛的Springboot+Vue前后端分离多用户社区项目。本项目难度适中,为便于大家学习,每一集视频教程对应在Github上的每一次提交。 3 | 4 | ### 致谢 5 | 本项目大量借鉴了[极光社区项目](https://github.com/haoyu21/aurora),在此感谢原作者的无私开源。本项目在其基础上做了一些增删,删除了一些未完成的模块(活动,旅游),新增了评论功能,简化了后端认证与授权功能。最主要的工作是将原项目从零开始开始搭建,各个功能的实现分解成几十步来完成,便于大家更好的学习。 6 | 7 | ### 在线体验 8 | 9 | http://kamiba.gitee.io/doubao_deploy_frontend 10 | 11 | ### 代码开源地址 12 | [前端](https://github.com/songboriceman/doubao_community_frontend) 13 | [后端](https://github.com/songboriceman/doubao_community_backend) 14 | 15 | ### 视频教程地址 16 | [视频教程](https://www.bilibili.com/video/BV1Wz4y1U7vC) 17 | 18 | ### 项目主要业务及实现的功能 19 | 本项目类似一个简版的掘金这样的技术社区,实现了多个用户注册,登录,发帖,回帖,评论,关注,用户中心等功能。 20 | 21 | ### 前端技术栈 22 | Vue 23 | 24 | Vuex 25 | 26 | Vue Router 27 | 28 | Axios 29 | 30 | Bulma 31 | 32 | Buefy 33 | 34 | Element 35 | 36 | Vditor 37 | 38 | DarkReader 39 | 40 | ### 后端技术栈 41 | Spring Boot 42 | 43 | Mysql 44 | 45 | Mybatis 46 | 47 | MyBatis-Plus 48 | 49 | Spring Security 50 | 51 | JWT 52 | 53 | Lombok 54 | 55 | ### 项目实战大纲: 56 | 01.豆宝社区项目介绍 57 | 58 | 02.豆宝社区项目所需的基础知识 59 | 60 | 03.前端项目搭建 61 | 62 | 04.前端公告板功能实现 63 | 64 | 05.初始化springboot后端项目 65 | 66 | 06.初始化后端数据库,springboot配置mybatis连接 67 | 68 | 07.后端项目目录结构初始化 69 | 70 | 08.后端公告板接口功能实现01 71 | 72 | 09.后端公告板接口功能实现02 73 | 74 | 10.前端端公告板接口功能实现 75 | 76 | 11.实现跨域,前后端接口联调 77 | 78 | 12.每日一句功能前端界面实现01 79 | 80 | 13.每日一句功能前端界面实现02 81 | 82 | 14.每日一句功能前端接口实现 83 | 84 | 15.每日一句功能后端接口实现 85 | 86 | 16.(非常重要)善用github提交记录进行项目学习 87 | 88 | 17.推广链接功能 前后端实现 89 | 90 | 18.用户注册前端实现 91 | 92 | 19.用户注册后端实现 93 | 94 | 20.jwt以及web通信流程 95 | 96 | 21.用户登录后端实现 97 | 98 | 22.vuex简介 99 | 100 | 23.js-cookie介绍 101 | 102 | 24.用户登录前端实现 103 | 104 | 25.前端侧边栏,马上入驻,社区登入功能 105 | 106 | 26.前端在axios请求拦截器中在请求头中加入jwt 107 | 108 | 27.后端设置请求拦截器检查用户请求头中是否包含jwt01 109 | 110 | 28.后端设置请求拦截器检查用户请求头中是否包含jwt02 111 | 112 | 29.前端header实现01 113 | 114 | 30.前端header实现02 115 | 116 | 31.退出登录 117 | 118 | 32.前端页脚功能实现 119 | 120 | 33.帖子列表功能前端 121 | 122 | 34.帖子列表功能后端 123 | 124 | 35.帖子分页功能实现 125 | 126 | 36.前端实现发表帖子功能 127 | 128 | 37.后端实现发表帖子功能 129 | 130 | 38.前端实现帖子详情功能 131 | 132 | 39.后端实现帖子详情功能 133 | 134 | 40.帖子详情右侧边栏帖子作者详情功能实现(前端) 135 | 136 | 41.帖子详情右侧边栏帖子作者详情用户关注功能实现(后端) 137 | 138 | 42.随便看看模块前端实现 139 | 140 | 43.随便看看模块后端实现 141 | 142 | 44.评论列表功能前端实现 143 | 144 | 45.评论列表功能后端实现 145 | 146 | 46.添加评论功能前端实现 147 | 148 | 47.添加评论功能后端实现 149 | 150 | 48.帖子更新与删除功能前后端实现 151 | 152 | 49.显示某个标签的全部文章功能前端 153 | 154 | 50.显示某个标签的全部文章功能后端实现 155 | 156 | 51.帖子搜索功能前端实现 157 | 158 | 52.帖子搜索功能前端实现 159 | 160 | 53.用户中心功能前端实现 161 | 162 | 54.用户中心功能前端实现 163 | 164 | 55.用户个人信息修改 165 | 166 | 56.前端发帖,留言等页面登录权限验证 167 | 168 | 57.后端发帖,留言等需要登录页面的权限验证 169 | 170 | 58.项目总结及遗留问题说明 171 | 172 | 59.(重要的说明)如何利用github上开源的项目代码提交记录更有效的学习本项目 173 | 174 | ### 豆约翰团队: 175 | 一群热爱分享技术,拥有多年开发经验及培训经验的老司机组成 176 | 177 | ### 擅长的领域: 178 | java,python,前端,c++,.net 179 | 180 | ### 项目部分截图 181 | #### PC 182 | #### 首页 183 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/30def8066ef8414ea4230f468139df09~tplv-k3u1fbpfcp-zoom-1.image) 184 | #### 发表文章 185 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0b27ea7463b4459ebffae7963926e0d7~tplv-k3u1fbpfcp-zoom-1.image) 186 | 187 | #### 文章详情及评论页面 188 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5474e766b4374b2dacd11f0dbe933f0d~tplv-k3u1fbpfcp-zoom-1.image) 189 | 190 | #### 个人中心 191 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5175ad7e76c245f8a76cd828117507c9~tplv-k3u1fbpfcp-zoom-1.image) 192 | #### 用户设置 193 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6e7a774f6bd14a7f9f573718844f0055~tplv-k3u1fbpfcp-zoom-1.image) 194 | #### 移动端 195 | #### 首页 196 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4d198980de974b65b642582db908d355~tplv-k3u1fbpfcp-zoom-1.image) 197 | #### 用户中心 198 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1b31f1509f854616982c726405a8835e~tplv-k3u1fbpfcp-zoom-1.image) 199 | #### 详情页 200 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e548602a256f4e16b6d51e31abccd7b6~tplv-k3u1fbpfcp-zoom-1.image) 201 | 202 | ### 技术讨论群 203 | 204 | 为方便同学们讨论项目中的技术,建了一个QQ群: 205 | 206 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9e0650ef53de41f4aed16d3644f5be34~tplv-k3u1fbpfcp-zoom-1.image) 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /doubao.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Type : MySQL 6 | Source Server Version : 80022 7 | Source Host : localhost:3306 8 | Source Schema : doubao 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 80022 12 | File Encoding : 65001 13 | */ 14 | 15 | SET NAMES utf8mb4; 16 | SET FOREIGN_KEY_CHECKS = 0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for bms_billboard 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `bms_billboard`; 22 | CREATE TABLE `bms_billboard` ( 23 | `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', 24 | `content` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '公告', 25 | `create_time` datetime NULL DEFAULT NULL COMMENT '公告时间', 26 | `show` tinyint(1) NULL DEFAULT NULL COMMENT '1:展示中,0:过期', 27 | PRIMARY KEY (`id`) USING BTREE 28 | ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COMMENT = '全站公告' ROW_FORMAT = DYNAMIC; 29 | 30 | -- ---------------------------- 31 | -- Records of bms_billboard 32 | -- ---------------------------- 33 | INSERT INTO `bms_billboard` VALUES (2, 'R1.0 开始已实现护眼模式 ,妈妈再也不用担心我的眼睛了。', '2020-11-19 17:16:19', 0); 34 | INSERT INTO `bms_billboard` VALUES (4, '系统已更新至最新版1.0.1', NULL, 1); 35 | 36 | 37 | -- ---------------------------- 38 | -- Table structure for bms_follow 39 | -- ---------------------------- 40 | DROP TABLE IF EXISTS `bms_follow`; 41 | CREATE TABLE `bms_follow` ( 42 | `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', 43 | `parent_id` varchar(20) CHARACTER SET utf8mb4 NULL DEFAULT NULL COMMENT '被关注人ID', 44 | `follower_id` varchar(20) CHARACTER SET utf8mb4 NULL DEFAULT NULL COMMENT '关注人ID', 45 | PRIMARY KEY (`id`) USING BTREE 46 | ) ENGINE = InnoDB AUTO_INCREMENT = 130 CHARACTER SET = utf8mb4 COMMENT = '用户关注' ROW_FORMAT = DYNAMIC; 47 | 48 | -- ---------------------------- 49 | -- Records of bms_follow 50 | -- ---------------------------- 51 | INSERT INTO `bms_follow` VALUES (65, '1329723594994229250', '1317498859501797378'); 52 | INSERT INTO `bms_follow` VALUES (85, '1332912847614083073', '1332636310897664002'); 53 | INSERT INTO `bms_follow` VALUES (129, '1349290158897311745', '1349618748226658305'); 54 | 55 | -- ---------------------------- 56 | -- Table structure for bms_post 57 | -- ---------------------------- 58 | DROP TABLE IF EXISTS `bms_post`; 59 | CREATE TABLE `bms_post` ( 60 | `id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', 61 | `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '标题', 62 | `content` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'markdown内容', 63 | `user_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '作者ID', 64 | `comments` int NOT NULL DEFAULT 0 COMMENT '评论统计', 65 | `collects` int NOT NULL DEFAULT 0 COMMENT '收藏统计', 66 | `view` int NOT NULL DEFAULT 0 COMMENT '浏览统计', 67 | `top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶,1-是,0-否', 68 | `essence` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否加精,1-是,0-否', 69 | `section_id` int NULL DEFAULT 0 COMMENT '专栏ID', 70 | `create_time` datetime NOT NULL COMMENT '发布时间', 71 | `modify_time` datetime NULL DEFAULT NULL COMMENT '修改时间', 72 | UNIQUE INDEX `title`(`title`) USING BTREE, 73 | INDEX `user_id`(`user_id`) USING BTREE, 74 | INDEX `create_time`(`create_time`) USING BTREE 75 | ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '话题表' ROW_FORMAT = DYNAMIC; 76 | 77 | -- ---------------------------- 78 | -- Records of bms_post 79 | -- ---------------------------- 80 | INSERT INTO `bms_post` VALUES ('1333447953558765569', '1', '12\n2\n\n', '1349290158897311745', 0, 0, 77, b'0', b'0', 0, '2020-12-01 00:29:01', '2020-12-03 23:56:51'); 81 | INSERT INTO `bms_post` VALUES ('1349362401438392322', '2021 健康,快乐', '2021的`FLAG`\n\n1. 技能进步\n2. 没有烦恼\n3. 发财 :smile:\n\n', '1349290158897311745', 0, 0, 21, b'0', b'0', 0, '2021-01-13 22:27:21', '2021-01-14 17:30:13'); 82 | INSERT INTO `bms_post` VALUES ('1334481725322297346', 'hello,spring-security', ':hibiscus: spring-security\n\n', '1349290158897311745', 0, 0, 46, b'0', b'0', 0, '2020-12-03 20:56:51', NULL); 83 | INSERT INTO `bms_post` VALUES ('1332650453142827009', '哈哈哈,helloworld', '这是第一篇哦\n\n> hi :handshake: 你好\n\n`hello world`\n\n:+1: 很好\n', '1349290158897311745', 0, 0, 29, b'0', b'0', 1, '2020-11-28 19:40:02', '2020-11-28 19:46:39'); 84 | INSERT INTO `bms_post` VALUES ('1333432347031646209', '哈哈哈,换了个dark主题', '主题更换为Dark\n\n', '1349290158897311745', 0, 0, 6, b'0', b'0', 0, '2020-11-30 23:27:00', NULL); 85 | INSERT INTO `bms_post` VALUES ('1333668258587750401', '嘿嘿,测试一下啊', '大家好\n`Hello everyone!`\n\n\n\n', '1349290158897311745', 0, 0, 7, b'0', b'0', 0, '2020-12-01 15:04:26', '2020-12-01 16:49:14'); 86 | INSERT INTO `bms_post` VALUES ('1332682473151635458', '我要发财', '2021 冲冲冲!!!\n\n', '1349290158897311745', 0, 0, 94, b'0', b'0', 2, '2020-11-28 21:47:16', '2020-11-30 19:40:22'); 87 | INSERT INTO `bms_post` VALUES ('1333695976536748034', '最新版本介绍,同步更新!', '

一款基于SpringBoot构建的智慧社区系统

\n\n

\n\"GitHub\n\"GitHub\n

\n\n### Hi there :wave:\n\n\n\n[![1020317774\'s github stats](https://github-readme-stats.vercel.app/api?username=1020317774&show_icons=true&count_private=true)](https://github.com/1020317774)\n\n[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=1020317774&layout=compact)](https://github.com/1020317774)\n---------\n\n> 作者:王一晨\n> github:[https://github.com/1020317774](https://github.com/1020317774)\n\n## 技术栈\n\n- [x] SpringBoot 2.X\n- [x] Mysql 8.X\n- [x] Mybatis\n- [x] MybatisPlus\n- [x] Redis\n- [x] Jwt\n- [x] FastJson\n- [x] Hutool\n- [x] Lombok\n- [ ] ElasticSearch\n\n……\n\n## 安装指导\n\n- 克隆\n\n```java\ngit clone https://github.com/1020317774/rhapsody-admin.git\n```\n\n- 修改`application.properties`选择环境\n- 修改多环境配置中的redis参数和数据库\n- 启动`BootApplication`\n- 访问[`http://127.0.0.1:10000`](http://127.0.0.1:10000)\n\n', '1349290158897311745', 0, 0, 45, b'1', b'1', 0, '2020-12-01 16:54:34', '2020-12-01 17:05:00'); 88 | INSERT INTO `bms_post` VALUES ('1349631541260595202', '权限部分 OK', '1. 创建 ok\n2. 修改 ok\n3. 删除 ok\n\n', '1349290158897311745', 0, 0, 17, b'0', b'0', 0, '2021-01-14 16:16:49', '2021-01-14 16:18:53'); 89 | INSERT INTO `bms_post` VALUES ('1333676096156528641', '测试', '测试\n\n', '1349290158897311745', 0, 0, 38, b'0', b'0', 0, '2020-12-01 15:35:34', NULL); 90 | INSERT INTO `bms_post` VALUES ('1332681213400817665', '聚合查询并统计', '* [x] SQL:\n\n```sql\nSELECT s.*,\nCOUNT(t.id) AS topics\nFROM section s\nLEFT JOIN topic t\nON s.id = t.section_id\nGROUP BY s.title\n```\n\n', '1349290158897311745', 0, 0, 55, b'0', b'0', 1, '2020-11-28 21:42:16', '2020-11-29 15:00:42'); 91 | INSERT INTO `bms_post` VALUES ('1335149981733449729', '视频嵌入', ':+1:\n\n[https://www.bilibili.com/video/BV1w64y1f7w3](https://www.bilibili.com/video/BV1w64y1f7w3)\n\n[1](https://www.bilibili.com/video/BV1tp4y1x72w)\n\n```\n.vditor-reset pre > code\n```\n\n```\npublic class HelloWorld {\n\npublic static void main(String[] args) {\n System.out.println(\"Hello World!\");\n}\n}\n```\n\n', '1349290158897311745', 0, 0, 41, b'0', b'0', 0, '2020-12-05 17:12:16', '2021-01-14 13:06:16'); 92 | 93 | 94 | -- ---------------------------- 95 | -- Table structure for bms_comment 96 | -- ---------------------------- 97 | DROP TABLE IF EXISTS `bms_comment`; 98 | CREATE TABLE `bms_comment` ( 99 | `id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', 100 | `content` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '内容', 101 | `user_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '作者ID', 102 | `topic_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'topic_id', 103 | `create_time` datetime NOT NULL COMMENT '发布时间', 104 | `modify_time` datetime NULL DEFAULT NULL COMMENT '修改时间', 105 | PRIMARY KEY (`id`) USING BTREE 106 | ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '评论表' ROW_FORMAT = DYNAMIC; 107 | 108 | -- ---------------------------- 109 | -- Table structure for bms_tag 110 | -- ---------------------------- 111 | DROP TABLE IF EXISTS `bms_tag`; 112 | CREATE TABLE `bms_tag` ( 113 | `id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '标签ID', 114 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '标签', 115 | `topic_count` int NOT NULL DEFAULT 0 COMMENT '关联话题', 116 | PRIMARY KEY (`id`) USING BTREE, 117 | UNIQUE INDEX `name`(`name`) USING BTREE 118 | ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '标签表' ROW_FORMAT = DYNAMIC; 119 | 120 | -- ---------------------------- 121 | -- Records of bms_tag 122 | -- ---------------------------- 123 | INSERT INTO `bms_tag` VALUES ('1332650453377708034', 'java', 1); 124 | INSERT INTO `bms_tag` VALUES ('1332681213568589825', 'css', 1); 125 | INSERT INTO `bms_tag` VALUES ('1332681213631504385', 'mongodb', 1); 126 | INSERT INTO `bms_tag` VALUES ('1332682473218744321', 'python', 1); 127 | INSERT INTO `bms_tag` VALUES ('1332913064463794178', 'vue', 2); 128 | INSERT INTO `bms_tag` VALUES ('1332913064530903041', 'react', 1); 129 | INSERT INTO `bms_tag` VALUES ('1333432347107143681', 'node', 1); 130 | INSERT INTO `bms_tag` VALUES ('1333432347107143682', 'mysql', 1); 131 | INSERT INTO `bms_tag` VALUES ('1333447953697177602', 'flask', 2); 132 | INSERT INTO `bms_tag` VALUES ('1333676096320106498', 'spring', 1); 133 | INSERT INTO `bms_tag` VALUES ('1333695976742268930', 'django', 1); 134 | INSERT INTO `bms_tag` VALUES ('1334481725519429634', 'security', 1); 135 | INSERT INTO `bms_tag` VALUES ('1349362401597775874', 'tensorflow', 1); 136 | INSERT INTO `bms_tag` VALUES ('1349631541306732545', 'pytorch', 1); 137 | 138 | 139 | -- ---------------------------- 140 | -- Table structure for bms_post_tag 141 | -- ---------------------------- 142 | DROP TABLE IF EXISTS `bms_post_tag`; 143 | CREATE TABLE `bms_post_tag` ( 144 | `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', 145 | `tag_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '标签ID', 146 | `topic_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '话题ID', 147 | PRIMARY KEY (`id`) USING BTREE, 148 | INDEX `tag_id`(`tag_id`) USING BTREE, 149 | INDEX `topic_id`(`topic_id`) USING BTREE 150 | ) ENGINE = InnoDB AUTO_INCREMENT = 52 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '话题-标签 中间表' ROW_FORMAT = DYNAMIC; 151 | 152 | -- ---------------------------- 153 | -- Records of bms_post_tag 154 | -- ---------------------------- 155 | INSERT INTO `bms_post_tag` VALUES (36, '1332650453377708034', '1332650453142827009'); 156 | INSERT INTO `bms_post_tag` VALUES (37, '1332681213568589825', '1332681213400817665'); 157 | INSERT INTO `bms_post_tag` VALUES (38, '1332681213631504385', '1332681213400817665'); 158 | INSERT INTO `bms_post_tag` VALUES (39, '1332682473218744321', '1332682473151635458'); 159 | INSERT INTO `bms_post_tag` VALUES (40, '1332913064463794178', '1332913064396685314'); 160 | INSERT INTO `bms_post_tag` VALUES (41, '1332913064530903041', '1332913064396685314'); 161 | INSERT INTO `bms_post_tag` VALUES (42, '1333432347107143681', '1333432347031646209'); 162 | INSERT INTO `bms_post_tag` VALUES (43, '1333432347107143682', '1333432347031646209'); 163 | INSERT INTO `bms_post_tag` VALUES (44, '1333447953697177602', '1333447953558765569'); 164 | INSERT INTO `bms_post_tag` VALUES (45, '1332913064463794178', '1333668258587750401'); 165 | INSERT INTO `bms_post_tag` VALUES (46, '1333676096320106498', '1333676096156528641'); 166 | INSERT INTO `bms_post_tag` VALUES (47, '1333695976742268930', '1333695976536748034'); 167 | INSERT INTO `bms_post_tag` VALUES (48, '1334481725519429634', '1334481725322297346'); 168 | INSERT INTO `bms_post_tag` VALUES (49, '1333447953697177602', '1335149981733449729'); 169 | INSERT INTO `bms_post_tag` VALUES (50, '1349362401597775874', '1349362401438392322'); 170 | INSERT INTO `bms_post_tag` VALUES (51, '1349631541306732545', '1349631541260595202'); 171 | 172 | -- ---------------------------- 173 | -- Table structure for bms_promotion 174 | -- ---------------------------- 175 | DROP TABLE IF EXISTS `bms_promotion`; 176 | CREATE TABLE `bms_promotion` ( 177 | `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', 178 | `title` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL COMMENT '广告标题', 179 | `link` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL COMMENT '广告链接', 180 | `description` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL COMMENT '说明', 181 | PRIMARY KEY (`id`) USING BTREE 182 | ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COMMENT = '广告推广表' ROW_FORMAT = DYNAMIC; 183 | 184 | -- ---------------------------- 185 | -- Records of bms_promotion 186 | -- ---------------------------- 187 | INSERT INTO `bms_promotion` VALUES (1, '开发者头条', 'https://juejin.cn/', '开发者头条'); 188 | INSERT INTO `bms_promotion` VALUES (2, '并发编程网', 'https://juejin.cn/', '并发编程网'); 189 | INSERT INTO `bms_promotion` VALUES (3, '掘金', 'https://juejin.cn/', '掘金'); 190 | 191 | 192 | -- ---------------------------- 193 | -- Table structure for bms_tip 194 | -- ---------------------------- 195 | DROP TABLE IF EXISTS `bms_tip`; 196 | CREATE TABLE `bms_tip` ( 197 | `id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', 198 | `content` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '内容', 199 | `author` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '作者', 200 | `type` tinyint NOT NULL COMMENT '1:使用,0:过期', 201 | PRIMARY KEY (`id`) USING BTREE 202 | ) ENGINE = InnoDB AUTO_INCREMENT = 24864 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '每日赠言' ROW_FORMAT = DYNAMIC; 203 | 204 | -- ---------------------------- 205 | -- Records of bms_tip 206 | -- ---------------------------- 207 | INSERT INTO `bms_tip` VALUES (1, '多锉出快锯,多做长知识。', '佚名', 1); 208 | INSERT INTO `bms_tip` VALUES (2, '未来总留着什么给对它抱有信心的人。', '佚名', 1); 209 | INSERT INTO `bms_tip` VALUES (3, '一个人的智慧不够用,两个人的智慧用不完。', '谚语', 1); 210 | INSERT INTO `bms_tip` VALUES (4, '十个指头按不住十个跳蚤', '傣族', 1); 211 | INSERT INTO `bms_tip` VALUES (5, '言不信者,行不果。', '墨子', 1); 212 | INSERT INTO `bms_tip` VALUES (6, '攀援而登,箕踞而遨,则几数州之土壤,皆在衽席之下。', '柳宗元', 1); 213 | INSERT INTO `bms_tip` VALUES (7, '美德大都包含在良好的习惯之内。', '帕利克', 1); 214 | INSERT INTO `bms_tip` VALUES (8, '人有不及,可以情恕。', '《晋书》', 1); 215 | INSERT INTO `bms_tip` VALUES (9, '明·吴惟顺', '法不传六耳', 1); 216 | INSERT INTO `bms_tip` VALUES (10, '真正的朋友应该说真话,不管那话多么尖锐。', '奥斯特洛夫斯基', 1); 217 | INSERT INTO `bms_tip` VALUES (11, '时间是一切财富中最宝贵的财富。', '德奥弗拉斯多', 1); 218 | INSERT INTO `bms_tip` VALUES (12, '看人下菜碟', '民谚', 1); 219 | INSERT INTO `bms_tip` VALUES (13, '如果不是怕别人反感,女人决不会保持完整的严肃。', '拉罗什福科', 1); 220 | INSERT INTO `bms_tip` VALUES (14, '爱是春暖花开时对你满满的笑意', '佚名', 1); 221 | INSERT INTO `bms_tip` VALUES (15, '希望是坚韧的拐杖,忍耐是旅行袋,携带它们,人可以登上永恒之旅。', '罗素', 1); 222 | INSERT INTO `bms_tip` VALUES (18, '天国般的幸福,存在于对真爱的希望。', '佚名', 1); 223 | INSERT INTO `bms_tip` VALUES (19, '我们现在必须完全保持党的纪律,否则一切都会陷入污泥中。', '马克思', 1); 224 | INSERT INTO `bms_tip` VALUES (20, '在科学上没有平坦的大道,只有不畏劳苦沿着陡峭山路攀登的人,才有希望达到光辉的顶点。', '马克思', 1); 225 | INSERT INTO `bms_tip` VALUES (21, '懒惰的马嫌路远', '蒙古', 1); 226 | INSERT INTO `bms_tip` VALUES (22, '别忘记热水是由冷水烧成的', '非洲', 1); 227 | 228 | 229 | -- ---------------------------- 230 | -- Table structure for ums_user 231 | -- ---------------------------- 232 | DROP TABLE IF EXISTS `ums_user`; 233 | CREATE TABLE `ums_user` ( 234 | `id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户ID', 235 | `username` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户名', 236 | `alias` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户昵称', 237 | `password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '密码', 238 | `avatar` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像', 239 | `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', 240 | `mobile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机', 241 | `score` int NOT NULL DEFAULT 0 COMMENT '积分', 242 | `token` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'token', 243 | `bio` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '个人简介', 244 | `active` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否激活,1:是,0:否', 245 | `status` bit(1) NULL DEFAULT b'1' COMMENT '状态,1:使用,0:停用', 246 | `role_id` int NULL DEFAULT NULL COMMENT '用户角色', 247 | `create_time` datetime NOT NULL COMMENT '加入时间', 248 | `modify_time` datetime NULL DEFAULT NULL COMMENT '修改时间', 249 | PRIMARY KEY (`id`) USING BTREE, 250 | UNIQUE INDEX `user_name`(`username`) USING BTREE, 251 | INDEX `user_email`(`email`) USING BTREE, 252 | INDEX `user_create_time`(`create_time`) USING BTREE 253 | ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC; 254 | 255 | -- ---------------------------- 256 | -- Records of ums_user 257 | -- ---------------------------- 258 | INSERT INTO `ums_user` VALUES ('1349290158897311745', 'admin', 'admin', '$2a$10$8qx711TBg/2hxfL7N.sxf.0ROMhR/iuPhQx33IFqGd7PLgt5nGJTO', 'https://s3.ax1x.com/2020/12/01/DfHNo4.jpg', '23456@qq.com', NULL, 2, '', '自由职业者', b'1', b'1', NULL, '2021-01-13 17:40:17', NULL); 259 | INSERT INTO `ums_user` VALUES ('1349618748226658305', 'zhangsan', 'zhangsan', '$2a$10$7K3yYv8sMV5Xsc2facXTcuyDo8JQ4FJHvjZ7qtWYcJdei3Q6Fvqdm', 'https://s3.ax1x.com/2020/12/01/DfHNo4.jpg', '23456@qq.com', NULL, 0, '', '自由职业者', b'1', b'1', NULL, '2021-01-14 15:25:59', NULL); 260 | 261 | SET FOREIGN_KEY_CHECKS = 1; 262 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.8.RELEASE 9 | 10 | 11 | com.douyuehan 12 | doubao 13 | 0.0.1-SNAPSHOT 14 | doubao 15 | Demo project for Spring Boot 16 | 17 | 1.8 18 | UTF-8 19 | UTF-8 20 | 3.4.2 21 | 1.2.75 22 | 5.5.7 23 | 0.9.1 24 | 5.1.1 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | 39 | org.projectlombok 40 | lombok 41 | true 42 | 43 | 44 | 45 | 46 | io.jsonwebtoken 47 | jjwt 48 | ${jwt.version} 49 | 50 | 51 | 52 | com.vdurmont 53 | emoji-java 54 | ${emoji-java.version} 55 | 56 | 57 | 58 | org.apache.commons 59 | commons-pool2 60 | 61 | 62 | 63 | cn.hutool 64 | hutool-all 65 | ${hutool.version} 66 | 67 | 68 | 69 | mysql 70 | mysql-connector-java 71 | runtime 72 | 73 | 74 | 75 | com.baomidou 76 | mybatis-plus-boot-starter 77 | ${mybatis-plus.version} 78 | 79 | 80 | 81 | com.alibaba 82 | fastjson 83 | ${fastjson.version} 84 | 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-configuration-processor 89 | true 90 | 91 | 92 | 93 | 94 | org.hibernate.validator 95 | hibernate-validator 96 | 97 | 98 | 99 | org.springframework.boot 100 | spring-boot-starter-test 101 | test 102 | 103 | 104 | org.junit.vintage 105 | junit-vintage-engine 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | org.springframework.boot 115 | spring-boot-maven-plugin 116 | 117 | 118 | 119 | org.projectlombok 120 | lombok 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/DoubaoApplication.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao; 2 | 3 | import com.douyuehan.doubao.jwt.JwtAuthenticationFilter; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.builder.SpringApplicationBuilder; 8 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 9 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 10 | import org.springframework.cache.annotation.EnableCaching; 11 | import org.springframework.context.annotation.Bean; 12 | 13 | @MapperScan("com.douyuehan.doubao.mapper") 14 | @SpringBootApplication 15 | public class DoubaoApplication extends SpringBootServletInitializer { 16 | @Override 17 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 18 | return builder.sources(DoubaoApplication.class); 19 | } 20 | @Bean 21 | public FilterRegistrationBean jwtFilter() { 22 | final FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 23 | JwtAuthenticationFilter filter = new JwtAuthenticationFilter(); 24 | registrationBean.setFilter(filter); 25 | return registrationBean; 26 | } 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(DoubaoApplication.class, args); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/api/ApiErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.api; 2 | 3 | 4 | public enum ApiErrorCode implements IErrorCode { 5 | 6 | /** 7 | * 成功 8 | */ 9 | SUCCESS(200, "操作成功"), 10 | /** 11 | * 失败 12 | */ 13 | FAILED(-1, "操作失败"), 14 | /** 15 | * 未登录,Token过期 16 | */ 17 | UNAUTHORIZED(401, "暂未登录或token已经过期"), 18 | /** 19 | * 权限不足 20 | */ 21 | FORBIDDEN(403, "权限不足"), 22 | /** 23 | * 参数校验错误 24 | */ 25 | VALIDATE_FAILED(404, "参数检验失败"); 26 | 27 | private final Integer code; 28 | private final String message; 29 | 30 | ApiErrorCode(int code, String message) { 31 | this.code = code; 32 | this.message = message; 33 | } 34 | 35 | @Override 36 | public Integer getCode() { 37 | return code; 38 | } 39 | 40 | @Override 41 | public String getMessage() { 42 | return message; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "ApiErrorCode{" + 48 | "code=" + code + 49 | ", message='" + message + '\'' + 50 | '}'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/api/ApiResult.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.api; 2 | 3 | 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | import java.util.Optional; 9 | 10 | 11 | @Data 12 | @NoArgsConstructor 13 | public class ApiResult implements Serializable { 14 | 15 | private static final long serialVersionUID = -4153430394359594346L; 16 | /** 17 | * 业务状态码 18 | */ 19 | private long code; 20 | /** 21 | * 结果集 22 | */ 23 | private T data; 24 | /** 25 | * 接口描述 26 | */ 27 | private String message; 28 | 29 | /** 30 | * 全参 31 | * 32 | * @param code 业务状态码 33 | * @param message 描述 34 | * @param data 结果集 35 | */ 36 | public ApiResult(long code, String message, T data) { 37 | this.code = code; 38 | this.message = message; 39 | this.data = data; 40 | } 41 | 42 | public ApiResult(IErrorCode errorCode) { 43 | errorCode = Optional.ofNullable(errorCode).orElse(ApiErrorCode.FAILED); 44 | this.code = errorCode.getCode(); 45 | this.message = errorCode.getMessage(); 46 | } 47 | 48 | /** 49 | * 成功 50 | * 51 | * @param data 结果集 52 | * @return {code:200,message:操作成功,data:自定义} 53 | */ 54 | public static ApiResult success() { 55 | return new ApiResult(ApiErrorCode.SUCCESS.getCode(), ApiErrorCode.SUCCESS.getMessage(), null); 56 | } 57 | 58 | /** 59 | * 成功 60 | * 61 | * @param data 结果集 62 | * @return {code:200,message:操作成功,data:自定义} 63 | */ 64 | public static ApiResult success(T data) { 65 | return new ApiResult(ApiErrorCode.SUCCESS.getCode(), ApiErrorCode.SUCCESS.getMessage(), data); 66 | } 67 | 68 | /** 69 | * 成功 70 | * 71 | * @param data 结果集 72 | * @param message 自定义提示信息 73 | * @return {code:200,message:自定义,data:自定义} 74 | */ 75 | public static ApiResult success(T data, String message) { 76 | return new ApiResult(ApiErrorCode.SUCCESS.getCode(), message, data); 77 | } 78 | 79 | /** 80 | * 失败返回结果 81 | */ 82 | public static ApiResult failed() { 83 | return failed(ApiErrorCode.FAILED); 84 | } 85 | 86 | /** 87 | * 失败返回结果 88 | * 89 | * @param message 提示信息 90 | * @return {code:枚举ApiErrorCode取,message:自定义,data:null} 91 | */ 92 | public static ApiResult failed(String message) { 93 | return new ApiResult(ApiErrorCode.FAILED.getCode(), message, null); 94 | } 95 | 96 | /** 97 | * 失败 98 | * 99 | * @param errorCode 错误码 100 | * @return {code:封装接口取,message:封装接口取,data:null} 101 | */ 102 | public static ApiResult failed(IErrorCode errorCode) { 103 | return new ApiResult(errorCode.getCode(), errorCode.getMessage(), null); 104 | } 105 | 106 | /** 107 | * 失败返回结果 108 | * 109 | * @param errorCode 错误码 110 | * @param message 错误信息 111 | * @return {code:枚举ApiErrorCode取,message:自定义,data:null} 112 | */ 113 | public static ApiResult failed(IErrorCode errorCode, String message) { 114 | return new ApiResult(errorCode.getCode(), message, null); 115 | } 116 | 117 | /** 118 | * 参数验证失败返回结果 119 | */ 120 | public static ApiResult validateFailed() { 121 | return failed(ApiErrorCode.VALIDATE_FAILED); 122 | } 123 | 124 | /** 125 | * 参数验证失败返回结果 126 | * 127 | * @param message 提示信息 128 | */ 129 | public static ApiResult validateFailed(String message) { 130 | return new ApiResult(ApiErrorCode.VALIDATE_FAILED.getCode(), message, null); 131 | } 132 | 133 | /** 134 | * 未登录返回结果 135 | */ 136 | public static ApiResult unauthorized(T data) { 137 | return new ApiResult(ApiErrorCode.UNAUTHORIZED.getCode(), ApiErrorCode.UNAUTHORIZED.getMessage(), data); 138 | } 139 | 140 | /** 141 | * 未授权返回结果 142 | */ 143 | public static ApiResult forbidden(T data) { 144 | return new ApiResult(ApiErrorCode.FORBIDDEN.getCode(), ApiErrorCode.FORBIDDEN.getMessage(), data); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/api/IErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.api; 2 | 3 | 4 | public interface IErrorCode { 5 | /** 6 | * 错误编码: -1失败;200成功 7 | * 8 | * @return 错误编码 9 | */ 10 | Integer getCode(); 11 | 12 | /** 13 | * 错误描述 14 | * 15 | * @return 错误描述 16 | */ 17 | String getMessage(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/exception/ApiAsserts.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.exception; 2 | 3 | import com.douyuehan.doubao.common.api.IErrorCode; 4 | 5 | 6 | public class ApiAsserts { 7 | /** 8 | * 抛失败异常 9 | * 10 | * @param message 说明 11 | */ 12 | public static void fail(String message) { 13 | throw new ApiException(message); 14 | } 15 | 16 | /** 17 | * 抛失败异常 18 | * 19 | * @param errorCode 状态码 20 | */ 21 | public static void fail(IErrorCode errorCode) { 22 | throw new ApiException(errorCode); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/exception/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.exception; 2 | 3 | import com.douyuehan.doubao.common.api.IErrorCode; 4 | 5 | 6 | public class ApiException extends RuntimeException { 7 | private IErrorCode errorCode; 8 | 9 | public ApiException(IErrorCode errorCode) { 10 | super(errorCode.getMessage()); 11 | this.errorCode = errorCode; 12 | } 13 | 14 | public ApiException(String message) { 15 | super(message); 16 | } 17 | 18 | public IErrorCode getErrorCode() { 19 | return errorCode; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.exception;//package com.knox.aurora.common.exception; 2 | 3 | import com.douyuehan.doubao.common.api.ApiResult; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | 8 | import java.util.Map; 9 | 10 | @ControllerAdvice 11 | public class GlobalExceptionHandler { 12 | /** 13 | * 捕获自定义异常 14 | */ 15 | @ResponseBody 16 | @ExceptionHandler(value = ApiException.class) 17 | public ApiResult> handle(ApiException e) { 18 | if (e.getErrorCode() != null) { 19 | return ApiResult.failed(e.getErrorCode()); 20 | } 21 | return ApiResult.failed(e.getMessage()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/common/mybatisplus/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.common.mybatisplus; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; 5 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 6 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 7 | import org.mybatis.spring.annotation.MapperScan; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | 12 | @Configuration 13 | @MapperScan("com.douyuehan.doubao.mapper") 14 | public class MybatisPlusConfig { 15 | 16 | /** 17 | * 新的分页插件,一缓和二缓遵循mybatis的规则, 18 | * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除) 19 | */ 20 | @Bean 21 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 22 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 23 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 24 | return interceptor; 25 | } 26 | 27 | @Bean 28 | public ConfigurationCustomizer configurationCustomizer() { 29 | return configuration -> configuration.setUseDeprecatedExecutor(false); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/config/GlobalWebMvcConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.cors.CorsConfiguration; 6 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 7 | import org.springframework.web.filter.CorsFilter; 8 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | 11 | 12 | @Configuration 13 | public class GlobalWebMvcConfigurer implements WebMvcConfigurer { 14 | 15 | /** 16 | * 跨域 17 | */ 18 | @Override 19 | public void addCorsMappings(CorsRegistry registry) { 20 | registry.addMapping("/**") 21 | .allowedOrigins("*") 22 | .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") 23 | .allowCredentials(true) 24 | .maxAge(3600) 25 | .allowedHeaders("*"); 26 | } 27 | 28 | @Bean 29 | public CorsFilter corsFilter() { 30 | CorsConfiguration config = new CorsConfiguration(); 31 | //允许所有域名进行跨域调用 32 | config.addAllowedOrigin("*"); 33 | //允许跨越发送cookie 34 | config.setAllowCredentials(true); 35 | //放行全部原始头信息 36 | config.addAllowedHeader("*"); 37 | //允许所有请求方法跨域调用 38 | config.addAllowedMethod("*"); 39 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 40 | source.registerCorsConfiguration("/**", config); 41 | return new CorsFilter(source); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | public class BaseController { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsBillboardController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.douyuehan.doubao.common.api.ApiResult; 5 | import com.douyuehan.doubao.model.entity.BmsBillboard; 6 | import com.douyuehan.doubao.service.IBmsBillboardService; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | @RestController 15 | @RequestMapping("/billboard") 16 | public class BmsBillboardController extends BaseController { 17 | 18 | @Resource 19 | private IBmsBillboardService bmsBillboardService; 20 | 21 | @GetMapping("/show") 22 | public ApiResult getNotices(){ 23 | List list = bmsBillboardService.list(new 24 | LambdaQueryWrapper().eq(BmsBillboard::isShow,true)); 25 | return ApiResult.success(list.get(list.size()- 1)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsCommentController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.douyuehan.doubao.common.api.ApiResult; 4 | import com.douyuehan.doubao.model.dto.CommentDTO; 5 | import com.douyuehan.doubao.model.entity.BmsComment; 6 | import com.douyuehan.doubao.model.entity.UmsUser; 7 | import com.douyuehan.doubao.model.vo.CommentVO; 8 | import com.douyuehan.doubao.service.IBmsCommentService; 9 | import com.douyuehan.doubao.service.IUmsUserService; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.List; 14 | 15 | import static com.douyuehan.doubao.jwt.JwtUtil.USER_NAME; 16 | 17 | 18 | @RestController 19 | @RequestMapping("/comment") 20 | public class BmsCommentController extends BaseController { 21 | 22 | @Resource 23 | private IBmsCommentService bmsCommentService; 24 | @Resource 25 | private IUmsUserService umsUserService; 26 | 27 | @GetMapping("/get_comments") 28 | public ApiResult> getCommentsByTopicID(@RequestParam(value = "topicid", defaultValue = "1") String topicid) { 29 | List lstBmsComment = bmsCommentService.getCommentsByTopicID(topicid); 30 | return ApiResult.success(lstBmsComment); 31 | } 32 | @PostMapping("/add_comment") 33 | public ApiResult add_comment(@RequestHeader(value = USER_NAME) String userName, 34 | @RequestBody CommentDTO dto) { 35 | UmsUser user = umsUserService.getUserByUsername(userName); 36 | BmsComment comment = bmsCommentService.create(dto, user); 37 | return ApiResult.success(comment); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsPostController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.douyuehan.doubao.common.api.ApiResult; 5 | import com.douyuehan.doubao.model.dto.CreateTopicDTO; 6 | import com.douyuehan.doubao.model.entity.BmsPost; 7 | import com.douyuehan.doubao.model.entity.UmsUser; 8 | import com.douyuehan.doubao.model.vo.PostVO; 9 | import com.douyuehan.doubao.service.IBmsPostService; 10 | import com.douyuehan.doubao.service.IUmsUserService; 11 | import com.vdurmont.emoji.EmojiParser; 12 | import org.springframework.util.Assert; 13 | import org.springframework.web.bind.annotation.*; 14 | import javax.annotation.Resource; 15 | import javax.validation.Valid; 16 | 17 | import java.util.Date; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | import static com.douyuehan.doubao.jwt.JwtUtil.USER_NAME; 22 | 23 | 24 | @RestController 25 | @RequestMapping("/post") 26 | public class BmsPostController extends BaseController { 27 | 28 | @Resource 29 | private IBmsPostService iBmsPostService; 30 | @Resource 31 | private IUmsUserService umsUserService; 32 | 33 | @GetMapping("/list") 34 | public ApiResult> list(@RequestParam(value = "tab", defaultValue = "latest") String tab, 35 | @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, 36 | @RequestParam(value = "size", defaultValue = "10") Integer pageSize) { 37 | Page list = iBmsPostService.getList(new Page<>(pageNo, pageSize), tab); 38 | return ApiResult.success(list); 39 | } 40 | 41 | @RequestMapping(value = "/create", method = RequestMethod.POST) 42 | public ApiResult create(@RequestHeader(value = USER_NAME) String userName 43 | , @RequestBody CreateTopicDTO dto) { 44 | UmsUser user = umsUserService.getUserByUsername(userName); 45 | BmsPost topic = iBmsPostService.create(dto, user); 46 | return ApiResult.success(topic); 47 | } 48 | @GetMapping() 49 | public ApiResult> view(@RequestParam("id") String id) { 50 | Map map = iBmsPostService.viewTopic(id); 51 | return ApiResult.success(map); 52 | } 53 | 54 | @GetMapping("/recommend") 55 | public ApiResult> getRecommend(@RequestParam("topicId") String id) { 56 | List topics = iBmsPostService.getRecommend(id); 57 | return ApiResult.success(topics); 58 | } 59 | 60 | @PostMapping("/update") 61 | public ApiResult update(@RequestHeader(value = USER_NAME) String userName, @Valid @RequestBody BmsPost post) { 62 | UmsUser umsUser = umsUserService.getUserByUsername(userName); 63 | Assert.isTrue(umsUser.getId().equals(post.getUserId()), "非本人无权修改"); 64 | post.setModifyTime(new Date()); 65 | post.setContent(EmojiParser.parseToAliases(post.getContent())); 66 | iBmsPostService.updateById(post); 67 | return ApiResult.success(post); 68 | } 69 | 70 | @DeleteMapping("/delete/{id}") 71 | public ApiResult delete(@RequestHeader(value = USER_NAME) String userName, @PathVariable("id") String id) { 72 | UmsUser umsUser = umsUserService.getUserByUsername(userName); 73 | BmsPost byId = iBmsPostService.getById(id); 74 | Assert.notNull(byId, "来晚一步,话题已不存在"); 75 | Assert.isTrue(byId.getUserId().equals(umsUser.getId()), "你为什么可以删除别人的话题???"); 76 | iBmsPostService.removeById(id); 77 | return ApiResult.success(null,"删除成功"); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsPromotionController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.douyuehan.doubao.common.api.ApiResult; 4 | import com.douyuehan.doubao.model.entity.BmsPromotion; 5 | import com.douyuehan.doubao.service.IBmsPromotionService; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import javax.annotation.Resource; 11 | import java.util.List; 12 | 13 | 14 | @RestController 15 | @RequestMapping("/promotion") 16 | public class BmsPromotionController extends BaseController { 17 | 18 | @Resource 19 | private IBmsPromotionService bmsPromotionService; 20 | 21 | @GetMapping("/all") 22 | public ApiResult> list() { 23 | List list = bmsPromotionService.list(); 24 | return ApiResult.success(list); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsRelationshipController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.douyuehan.doubao.common.api.ApiResult; 5 | import com.douyuehan.doubao.common.exception.ApiAsserts; 6 | import com.douyuehan.doubao.model.entity.BmsFollow; 7 | import com.douyuehan.doubao.model.entity.UmsUser; 8 | import com.douyuehan.doubao.service.IBmsFollowService; 9 | import com.douyuehan.doubao.service.IUmsUserService; 10 | import org.springframework.util.ObjectUtils; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | import static com.douyuehan.doubao.jwt.JwtUtil.USER_NAME; 19 | 20 | @RestController 21 | @RequestMapping("/relationship") 22 | public class BmsRelationshipController extends BaseController { 23 | 24 | @Resource 25 | private IBmsFollowService bmsFollowService; 26 | 27 | @Resource 28 | private IUmsUserService umsUserService; 29 | 30 | @GetMapping("/subscribe/{userId}") 31 | public ApiResult handleFollow(@RequestHeader(value = USER_NAME) String userName 32 | , @PathVariable("userId") String parentId) { 33 | UmsUser umsUser = umsUserService.getUserByUsername(userName); 34 | if (parentId.equals(umsUser.getId())) { 35 | ApiAsserts.fail("您脸皮太厚了,怎么可以关注自己呢 😮"); 36 | } 37 | BmsFollow one = bmsFollowService.getOne( 38 | new LambdaQueryWrapper() 39 | .eq(BmsFollow::getParentId, parentId) 40 | .eq(BmsFollow::getFollowerId, umsUser.getId())); 41 | if (!ObjectUtils.isEmpty(one)) { 42 | ApiAsserts.fail("已关注"); 43 | } 44 | 45 | BmsFollow follow = new BmsFollow(); 46 | follow.setParentId(parentId); 47 | follow.setFollowerId(umsUser.getId()); 48 | bmsFollowService.save(follow); 49 | return ApiResult.success(null, "关注成功"); 50 | } 51 | 52 | @GetMapping("/unsubscribe/{userId}") 53 | public ApiResult handleUnFollow(@RequestHeader(value = USER_NAME) String userName 54 | , @PathVariable("userId") String parentId) { 55 | UmsUser umsUser = umsUserService.getUserByUsername(userName); 56 | BmsFollow one = bmsFollowService.getOne( 57 | new LambdaQueryWrapper() 58 | .eq(BmsFollow::getParentId, parentId) 59 | .eq(BmsFollow::getFollowerId, umsUser.getId())); 60 | if (ObjectUtils.isEmpty(one)) { 61 | ApiAsserts.fail("未关注!"); 62 | } 63 | bmsFollowService.remove(new LambdaQueryWrapper().eq(BmsFollow::getParentId, parentId) 64 | .eq(BmsFollow::getFollowerId, umsUser.getId())); 65 | return ApiResult.success(null, "取关成功"); 66 | } 67 | 68 | @GetMapping("/validate/{topicUserId}") 69 | public ApiResult> isFollow(@RequestHeader(value = USER_NAME) String userName 70 | , @PathVariable("topicUserId") String topicUserId) { 71 | UmsUser umsUser = umsUserService.getUserByUsername(userName); 72 | Map map = new HashMap<>(16); 73 | map.put("hasFollow", false); 74 | if (!ObjectUtils.isEmpty(umsUser)) { 75 | BmsFollow one = bmsFollowService.getOne(new LambdaQueryWrapper() 76 | .eq(BmsFollow::getParentId, topicUserId) 77 | .eq(BmsFollow::getFollowerId, umsUser.getId())); 78 | if (!ObjectUtils.isEmpty(one)) { 79 | map.put("hasFollow", true); 80 | } 81 | } 82 | return ApiResult.success(map); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsSearchController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.douyuehan.doubao.common.api.ApiResult; 5 | import com.douyuehan.doubao.model.vo.PostVO; 6 | import com.douyuehan.doubao.service.IBmsPostService; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import javax.annotation.Resource; 13 | 14 | @RestController 15 | @RequestMapping("/search") 16 | public class BmsSearchController extends BaseController { 17 | 18 | @Resource 19 | private IBmsPostService postService; 20 | 21 | @GetMapping 22 | public ApiResult> searchList(@RequestParam("keyword") String keyword, 23 | @RequestParam("pageNum") Integer pageNum, 24 | @RequestParam("pageSize") Integer pageSize) { 25 | Page results = postService.searchByKey(keyword, new Page<>(pageNum, pageSize)); 26 | return ApiResult.success(results); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsTagController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.douyuehan.doubao.common.api.ApiResult; 6 | import com.douyuehan.doubao.model.entity.BmsPost; 7 | import com.douyuehan.doubao.model.entity.BmsTag; 8 | import com.douyuehan.doubao.service.IBmsTagService; 9 | import org.springframework.util.Assert; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | @RestController 17 | @RequestMapping("/tag") 18 | public class BmsTagController extends BaseController { 19 | 20 | @Resource 21 | private IBmsTagService bmsTagService; 22 | 23 | @GetMapping("/{name}") 24 | public ApiResult> getTopicsByTag( 25 | @PathVariable("name") String tagName, 26 | @RequestParam(value = "page", defaultValue = "1") Integer page, 27 | @RequestParam(value = "size", defaultValue = "10") Integer size) { 28 | 29 | Map map = new HashMap<>(16); 30 | 31 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 32 | wrapper.eq(BmsTag::getName, tagName); 33 | BmsTag one = bmsTagService.getOne(wrapper); 34 | Assert.notNull(one, "话题不存在,或已被管理员删除"); 35 | Page topics = bmsTagService.selectTopicsByTagId(new Page<>(page, size), one.getId()); 36 | // 其他热门标签 37 | Page hotTags = bmsTagService.page(new Page<>(1, 10), 38 | new LambdaQueryWrapper() 39 | .notIn(BmsTag::getName, tagName) 40 | .orderByDesc(BmsTag::getTopicCount)); 41 | 42 | map.put("topics", topics); 43 | map.put("hotTags", hotTags); 44 | 45 | return ApiResult.success(map); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/BmsTipController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.douyuehan.doubao.common.api.ApiResult; 5 | import com.douyuehan.doubao.model.entity.BmsBillboard; 6 | import com.douyuehan.doubao.model.entity.BmsTip; 7 | import com.douyuehan.doubao.service.IBmsBillboardService; 8 | import com.douyuehan.doubao.service.IBmsTipService; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import javax.annotation.Resource; 14 | 15 | @RestController 16 | @RequestMapping("/tip") 17 | public class BmsTipController extends BaseController { 18 | @Resource 19 | private IBmsTipService bmsTipService; 20 | 21 | @GetMapping("/today") 22 | public ApiResult getRandomTip() { 23 | BmsTip tip = bmsTipService.getRandomTip(); 24 | return ApiResult.success(tip); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/controller/UmsUserController.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.controller; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.douyuehan.doubao.common.api.ApiResult; 7 | import com.douyuehan.doubao.model.dto.LoginDTO; 8 | import com.douyuehan.doubao.model.dto.RegisterDTO; 9 | import com.douyuehan.doubao.model.entity.BmsPost; 10 | import com.douyuehan.doubao.model.entity.UmsUser; 11 | import com.douyuehan.doubao.service.IBmsPostService; 12 | import com.douyuehan.doubao.service.IUmsUserService; 13 | import org.springframework.util.ObjectUtils; 14 | import org.springframework.web.bind.annotation.*; 15 | import org.springframework.util.Assert; 16 | import javax.annotation.Resource; 17 | import javax.validation.Valid; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | import static com.douyuehan.doubao.jwt.JwtUtil.USER_NAME; 22 | 23 | 24 | @RestController 25 | @RequestMapping("/ums/user") 26 | public class UmsUserController extends BaseController { 27 | @Resource 28 | private IUmsUserService iUmsUserService; 29 | @Resource 30 | private IBmsPostService iBmsPostService; 31 | 32 | @RequestMapping(value = "/register", method = RequestMethod.POST) 33 | public ApiResult> register(@Valid @RequestBody RegisterDTO dto) { 34 | UmsUser user = iUmsUserService.executeRegister(dto); 35 | if (ObjectUtils.isEmpty(user)) { 36 | return ApiResult.failed("账号注册失败"); 37 | } 38 | Map map = new HashMap<>(16); 39 | map.put("user", user); 40 | return ApiResult.success(map); 41 | } 42 | 43 | @RequestMapping(value = "/login", method = RequestMethod.POST) 44 | public ApiResult> login(@Valid @RequestBody LoginDTO dto) { 45 | String token = iUmsUserService.executeLogin(dto); 46 | if (ObjectUtils.isEmpty(token)) { 47 | return ApiResult.failed("账号密码错误"); 48 | } 49 | Map map = new HashMap<>(16); 50 | map.put("token", token); 51 | return ApiResult.success(map, "登录成功"); 52 | } 53 | 54 | @RequestMapping(value = "/info", method = RequestMethod.GET) 55 | public ApiResult getUser(@RequestHeader(value = USER_NAME) String userName) { 56 | UmsUser user = iUmsUserService.getUserByUsername(userName); 57 | return ApiResult.success(user); 58 | } 59 | 60 | @RequestMapping(value = "/logout", method = RequestMethod.GET) 61 | public ApiResult logOut() { 62 | return ApiResult.success(null, "注销成功"); 63 | } 64 | 65 | @GetMapping("/{username}") 66 | public ApiResult> getUserByName(@PathVariable("username") String username, 67 | @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, 68 | @RequestParam(value = "size", defaultValue = "10") Integer size) { 69 | Map map = new HashMap<>(16); 70 | UmsUser user = iUmsUserService.getUserByUsername(username); 71 | Assert.notNull(user, "用户不存在"); 72 | Page page = iBmsPostService.page(new Page<>(pageNo, size), 73 | new LambdaQueryWrapper().eq(BmsPost::getUserId, user.getId())); 74 | map.put("user", user); 75 | map.put("topics", page); 76 | return ApiResult.success(map); 77 | } 78 | @PostMapping("/update") 79 | public ApiResult updateUser(@RequestBody UmsUser umsUser) { 80 | iUmsUserService.updateById(umsUser); 81 | return ApiResult.success(umsUser); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/jwt/JwtAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.jwt; 2 | 3 | import org.springframework.util.AntPathMatcher; 4 | import org.springframework.util.PathMatcher; 5 | import org.springframework.web.filter.OncePerRequestFilter; 6 | 7 | import javax.servlet.FilterChain; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | 16 | public class JwtAuthenticationFilter extends OncePerRequestFilter { 17 | private static final PathMatcher pathMatcher = new AntPathMatcher(); 18 | 19 | @Override 20 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 21 | 22 | try { 23 | if(isProtectedUrl(request)) { 24 | // System.out.println(request.getMethod()); 25 | if(!request.getMethod().equals("OPTIONS")) 26 | request = JwtUtil.validateTokenAndAddUserIdToHeader(request); 27 | } 28 | } catch (Exception e) { 29 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); 30 | return; 31 | } 32 | filterChain.doFilter(request, response); 33 | } 34 | 35 | private boolean isProtectedUrl(HttpServletRequest request) { 36 | List protectedPaths = new ArrayList(); 37 | protectedPaths.add("/ums/user/info"); 38 | protectedPaths.add("/ums/user/update"); 39 | protectedPaths.add("/post/create"); 40 | protectedPaths.add("/post/update"); 41 | protectedPaths.add("/post/delete/*"); 42 | protectedPaths.add("/comment/add_comment"); 43 | protectedPaths.add("/relationship/subscribe/*"); 44 | protectedPaths.add("/relationship/unsubscribe/*"); 45 | protectedPaths.add("/relationship/validate/*"); 46 | 47 | boolean bFind = false; 48 | for( String passedPath : protectedPaths ) { 49 | bFind = pathMatcher.match(passedPath, request.getServletPath()); 50 | if( bFind ) { 51 | break; 52 | } 53 | } 54 | return bFind; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/jwt/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.jwt; 2 | 3 | import io.jsonwebtoken.Jwts; 4 | import io.jsonwebtoken.SignatureAlgorithm; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletRequestWrapper; 10 | import java.util.*; 11 | 12 | public class JwtUtil { 13 | private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class); 14 | public static final long EXPIRATION_TIME = 3600_000_000L; // 1000 hour 15 | public static final String SECRET = "ThisIsASecret";//please change to your own encryption secret. 16 | public static final String TOKEN_PREFIX = "Bearer "; 17 | public static final String HEADER_STRING = "Authorization"; 18 | public static final String USER_NAME = "userName"; 19 | 20 | public static String generateToken(String userId) { 21 | HashMap map = new HashMap<>(); 22 | //you can put any data in the map 23 | map.put(USER_NAME, userId); 24 | String jwt = Jwts.builder() 25 | .setClaims(map) 26 | .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) 27 | .signWith(SignatureAlgorithm.HS512, SECRET) 28 | .compact(); 29 | return jwt; //jwt前面一般都会加Bearer 30 | } 31 | 32 | public static HttpServletRequest validateTokenAndAddUserIdToHeader(HttpServletRequest request) { 33 | String token = request.getHeader(HEADER_STRING); 34 | if (token != null) { 35 | // parse the token. 36 | try { 37 | Map body = Jwts.parser() 38 | .setSigningKey(SECRET) 39 | .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) 40 | .getBody(); 41 | return new CustomHttpServletRequest(request, body); 42 | } catch (Exception e) { 43 | logger.info(e.getMessage()); 44 | throw new TokenValidationException(e.getMessage()); 45 | } 46 | } else { 47 | throw new TokenValidationException("Missing token"); 48 | } 49 | } 50 | 51 | public static class CustomHttpServletRequest extends HttpServletRequestWrapper { 52 | private Map claims; 53 | 54 | public CustomHttpServletRequest(HttpServletRequest request, Map claims) { 55 | super(request); 56 | this.claims = new HashMap<>(); 57 | claims.forEach((k, v) -> this.claims.put(k, String.valueOf(v))); 58 | } 59 | 60 | @Override 61 | public Enumeration getHeaders(String name) { 62 | if (claims != null && claims.containsKey(name)) { 63 | return Collections.enumeration(Arrays.asList(claims.get(name))); 64 | } 65 | return super.getHeaders(name); 66 | } 67 | 68 | } 69 | 70 | static class TokenValidationException extends RuntimeException { 71 | public TokenValidationException(String msg) { 72 | super(msg); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsBillboardMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsBillboard; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface BmsBillboardMapper extends BaseMapper { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsCommentMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsComment; 5 | import com.douyuehan.doubao.model.vo.CommentVO; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | 12 | @Repository 13 | public interface BmsCommentMapper extends BaseMapper { 14 | 15 | /** 16 | * getCommentsByTopicID 17 | * 18 | * @param topicid 19 | * @return 20 | */ 21 | List getCommentsByTopicID(@Param("topicid") String topicid); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsFollowMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsFollow; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface BmsFollowMapper extends BaseMapper { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsPromotionMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsPromotion; 5 | import org.springframework.stereotype.Repository; 6 | 7 | 8 | @Repository 9 | public interface BmsPromotionMapper extends BaseMapper { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsTagMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsTag; 5 | import org.springframework.stereotype.Repository; 6 | 7 | 8 | @Repository 9 | public interface BmsTagMapper extends BaseMapper { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsTipMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsTip; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface BmsTipMapper extends BaseMapper { 9 | BmsTip getRandomTip(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsTopicMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.douyuehan.doubao.model.entity.BmsPost; 6 | import com.douyuehan.doubao.model.vo.PostVO; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | 12 | @Repository 13 | public interface BmsTopicMapper extends BaseMapper { 14 | /** 15 | * 分页查询首页话题列表 16 | *

17 | * 18 | * @param page 19 | * @param tab 20 | * @return 21 | */ 22 | Page selectListAndPage(@Param("page") Page page, @Param("tab") String tab); 23 | 24 | /** 25 | * 获取详情页推荐 26 | * 27 | * @param id 28 | * @return 29 | */ 30 | List selectRecommend(@Param("id") String id); 31 | /** 32 | * 全文检索 33 | * 34 | * @param page 35 | * @param keyword 36 | * @return 37 | */ 38 | Page searchByKey(@Param("page") Page page, @Param("keyword") String keyword); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/BmsTopicTagMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.BmsTopicTag; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Set; 9 | 10 | 11 | @Repository 12 | public interface BmsTopicTagMapper extends BaseMapper { 13 | /** 14 | * 根据标签获取话题ID集合 15 | * 16 | * @param id 17 | * @return 18 | */ 19 | Set getTopicIdsByTagId(@Param("id") String id); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/mapper/UmsUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.douyuehan.doubao.model.entity.UmsUser; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * 用户 9 | * 10 | * @author Knox 2020/11/7 11 | */ 12 | @Repository 13 | public interface UmsUserMapper extends BaseMapper { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/dto/CommentDTO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | 8 | @Data 9 | public class CommentDTO implements Serializable { 10 | private static final long serialVersionUID = -5957433707110390852L; 11 | 12 | 13 | private String topic_id; 14 | 15 | /** 16 | * 内容 17 | */ 18 | private String content; 19 | 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/dto/CreateTopicDTO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | @Data 9 | public class CreateTopicDTO implements Serializable { 10 | private static final long serialVersionUID = -5957433707110390852L; 11 | 12 | /** 13 | * 标题 14 | */ 15 | private String title; 16 | 17 | /** 18 | * 内容 19 | */ 20 | private String content; 21 | 22 | /** 23 | * 标签 24 | */ 25 | private List tags; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/dto/LoginDTO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.dto; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | import javax.validation.constraints.Size; 7 | 8 | 9 | @Data 10 | public class LoginDTO { 11 | 12 | @NotBlank(message = "用户名不能为空") 13 | @Size(min = 2, max = 15, message = "登录用户名长度在2-15") 14 | private String username; 15 | 16 | @NotBlank(message = "密码不能为空") 17 | @Size(min = 6, max = 20, message = "登录密码长度在6-20") 18 | private String password; 19 | 20 | private Boolean rememberMe; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/dto/RegisterDTO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.dto; 2 | 3 | import lombok.Data; 4 | import org.hibernate.validator.constraints.Length; 5 | 6 | import javax.validation.constraints.Email; 7 | import javax.validation.constraints.NotEmpty; 8 | 9 | 10 | @Data 11 | public class RegisterDTO { 12 | 13 | @NotEmpty(message = "请输入账号") 14 | @Length(min = 2, max = 15, message = "长度在2-15") 15 | private String name; 16 | 17 | @NotEmpty(message = "请输入密码") 18 | @Length(min = 6, max = 20, message = "长度在6-20") 19 | private String pass; 20 | 21 | @NotEmpty(message = "请再次输入密码") 22 | @Length(min = 6, max = 20, message = "长度在6-20") 23 | private String checkPass; 24 | 25 | @NotEmpty(message = "请输入电子邮箱") 26 | @Email(message = "邮箱格式不正确") 27 | private String email; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsBillboard.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | 14 | @Data 15 | @Builder 16 | @Accessors(chain = true) 17 | @TableName("bms_billboard") 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class BmsBillboard implements Serializable { 21 | 22 | private static final long serialVersionUID = 1L; 23 | 24 | /** 25 | * 主键 26 | */ 27 | @TableId(type = IdType.AUTO) 28 | private Integer id; 29 | 30 | /** 31 | * 公告牌 32 | */ 33 | @TableField("content") 34 | private String content; 35 | 36 | /** 37 | * 公告时间 38 | */ 39 | @TableField(value = "create_time", fill = FieldFill.INSERT) 40 | private Date createTime; 41 | 42 | /** 43 | * 1:展示中,0:过期 44 | */ 45 | @Builder.Default 46 | @TableField("`show`") 47 | private boolean show = false; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsComment.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | 14 | @Data 15 | @Builder 16 | @TableName("bms_comment") 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class BmsComment implements Serializable { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | /** 24 | * 主键 25 | */ 26 | @TableId(value = "id", type = IdType.ASSIGN_ID) 27 | private String id; 28 | /** 29 | * 内容 30 | */ 31 | @NotBlank(message = "内容不可以为空") 32 | @TableField(value = "content") 33 | private String content; 34 | 35 | 36 | /** 37 | * 作者ID 38 | */ 39 | @TableField("user_id") 40 | private String userId; 41 | 42 | /** 43 | * topicID 44 | */ 45 | @TableField("topic_id") 46 | private String topicId; 47 | 48 | /** 49 | * 创建时间 50 | */ 51 | @TableField(value = "create_time", fill = FieldFill.INSERT) 52 | private Date createTime; 53 | 54 | /** 55 | * 修改时间 56 | */ 57 | @TableField(value = "modify_time", fill = FieldFill.UPDATE) 58 | private Date modifyTime; 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsFollow.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | @Data 12 | @TableName("bms_follow") 13 | public class BmsFollow implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * 主键 19 | */ 20 | @TableId(type = IdType.AUTO) 21 | private Integer id; 22 | 23 | /** 24 | * 被关注人id 25 | */ 26 | @TableField("parent_id") 27 | private String parentId; 28 | 29 | /** 30 | * 关注人id 31 | */ 32 | @TableField("follower_id") 33 | private String followerId; 34 | 35 | public BmsFollow() { 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsPost.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | 14 | @Data 15 | @Builder 16 | @TableName("bms_post") 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class BmsPost implements Serializable { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | /** 24 | * 主键 25 | */ 26 | @TableId(value = "id", type = IdType.ASSIGN_ID) 27 | private String id; 28 | /** 29 | * 标题 30 | */ 31 | @NotBlank(message = "标题不可以为空") 32 | @TableField(value = "title") 33 | private String title; 34 | /** 35 | * markdown 36 | */ 37 | @NotBlank(message = "内容不可以为空") 38 | @TableField("`content`") 39 | private String content; 40 | 41 | /** 42 | * 作者ID 43 | */ 44 | @TableField("user_id") 45 | private String userId; 46 | 47 | /** 48 | * 评论数 49 | */ 50 | @TableField("comments") 51 | @Builder.Default 52 | private Integer comments = 0; 53 | 54 | /** 55 | * 收藏数 56 | */ 57 | @TableField("collects") 58 | @Builder.Default 59 | private Integer collects = 0; 60 | 61 | /** 62 | * 浏览数 63 | */ 64 | @TableField("view") 65 | @Builder.Default 66 | private Integer view = 0; 67 | 68 | /** 69 | * 专栏ID,默认不分栏 70 | */ 71 | @TableField("section_id") 72 | @Builder.Default 73 | private Integer sectionId = 0; 74 | 75 | /** 76 | * 置顶 77 | */ 78 | @TableField("top") 79 | @Builder.Default 80 | private Boolean top = false; 81 | 82 | /** 83 | * 加精 84 | */ 85 | @TableField("essence") 86 | @Builder.Default 87 | private Boolean essence = false; 88 | 89 | /** 90 | * 创建时间 91 | */ 92 | @TableField(value = "create_time", fill = FieldFill.INSERT) 93 | private Date createTime; 94 | 95 | /** 96 | * 修改时间 97 | */ 98 | @TableField(value = "modify_time", fill = FieldFill.UPDATE) 99 | private Date modifyTime; 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsPromotion.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | 12 | 13 | @Data 14 | @TableName("bms_promotion") 15 | @Accessors(chain = true) 16 | public class BmsPromotion implements Serializable { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | /** 21 | * 主键 22 | */ 23 | @TableId(value = "id", type = IdType.AUTO) 24 | private Integer id; 25 | 26 | /** 27 | * 广告标题 28 | */ 29 | @TableField("title") 30 | private String title; 31 | 32 | /** 33 | * 广告链接 34 | */ 35 | @TableField("link") 36 | private String link; 37 | 38 | /** 39 | * 说明 40 | */ 41 | @TableField("`description`") 42 | private String description; 43 | 44 | public BmsPromotion() { 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsTag.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.io.Serializable; 12 | 13 | 14 | @Data 15 | @Builder 16 | @TableName("bms_tag") 17 | @Accessors(chain = true) 18 | public class BmsTag implements Serializable { 19 | private static final long serialVersionUID = 3257790983905872243L; 20 | 21 | @TableId(type = IdType.ASSIGN_ID) 22 | private String id; 23 | 24 | @TableField("name") 25 | private String name; 26 | /** 27 | * 当前标签下的话题个数 28 | */ 29 | @TableField("topic_count") 30 | @Builder.Default 31 | private Integer topicCount = 1; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsTip.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | 11 | @Data 12 | @NoArgsConstructor 13 | @TableName("bms_tip") 14 | public class BmsTip implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | /** 19 | * 主键 20 | */ 21 | private Integer id; 22 | 23 | /** 24 | * 内容 25 | */ 26 | @TableField("`content`") 27 | private String content; 28 | 29 | /** 30 | * 作者 31 | */ 32 | private String author; 33 | 34 | /** 35 | * 1:使用,0:过期 36 | */ 37 | private boolean type; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/BmsTopicTag.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | 12 | 13 | @Data 14 | @TableName("bms_post_tag") 15 | @Accessors(chain = true) 16 | public class BmsTopicTag implements Serializable { 17 | private static final long serialVersionUID = -5028599844989220715L; 18 | 19 | @TableId(type = IdType.AUTO) 20 | private Integer id; 21 | 22 | @TableField("tag_id") 23 | private String tagId; 24 | 25 | @TableField("topic_id") 26 | private String topicId; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/entity/UmsUser.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.io.Serializable; 12 | import java.util.Date; 13 | 14 | 15 | @Data 16 | @Builder 17 | @TableName("ums_user") 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Accessors(chain = true) 21 | public class UmsUser implements Serializable { 22 | private static final long serialVersionUID = -5051120337175047163L; 23 | 24 | @TableId(value = "id", type = IdType.ASSIGN_ID) 25 | private String id; 26 | 27 | @TableField("username") 28 | private String username; 29 | 30 | @TableField("alias") 31 | private String alias; 32 | 33 | @JsonIgnore() 34 | @TableField("password") 35 | private String password; 36 | 37 | @Builder.Default 38 | @TableField("avatar") 39 | private String avatar = "https://s3.ax1x.com/2020/12/01/DfHNo4.jpg"; 40 | 41 | @TableField("email") 42 | private String email; 43 | 44 | @TableField("mobile") 45 | private String mobile; 46 | 47 | @Builder.Default 48 | @TableField("bio") 49 | private String bio = "自由职业者"; 50 | 51 | @Builder.Default 52 | @TableField("score") 53 | private Integer score = 0; 54 | 55 | @JsonIgnore 56 | @TableField("token") 57 | private String token; 58 | 59 | @Builder.Default 60 | @TableField("active") 61 | private Boolean active = true; 62 | 63 | /** 64 | * 状态。1:使用,0:已停用 65 | */ 66 | @Builder.Default 67 | @TableField("`status`") 68 | private Boolean status = true; 69 | 70 | /** 71 | * 用户角色 72 | */ 73 | @TableField("role_id") 74 | private Integer roleId; 75 | 76 | @TableField(value = "create_time", fill = FieldFill.INSERT) 77 | private Date createTime; 78 | 79 | @TableField(value = "modify_time", fill = FieldFill.INSERT_UPDATE) 80 | private Date modifyTime; 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/vo/CommentVO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | 8 | @Data 9 | public class CommentVO { 10 | 11 | private String id; 12 | 13 | private String content; 14 | 15 | private String topicId; 16 | 17 | private String userId; 18 | 19 | private String username; 20 | 21 | private Date createTime; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/vo/PostVO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.vo; 2 | 3 | import com.douyuehan.doubao.model.entity.BmsTag; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class PostVO implements Serializable { 17 | private static final long serialVersionUID = -261082150965211545L; 18 | 19 | /** 20 | * 文章ID 21 | */ 22 | private String id; 23 | /** 24 | * 用户ID 25 | */ 26 | private String userId; 27 | /** 28 | * 头像 29 | */ 30 | private String avatar; 31 | /** 32 | * 用户昵称 33 | */ 34 | private String alias; 35 | /** 36 | * 账号 37 | */ 38 | private String username; 39 | /** 40 | * 标题 41 | */ 42 | private String title; 43 | /** 44 | * 评论统计 45 | */ 46 | private Integer comments; 47 | /** 48 | * 置顶 49 | */ 50 | private Boolean top; 51 | /** 52 | * 加精 53 | */ 54 | private Boolean essence; 55 | /** 56 | * 收藏次數 57 | */ 58 | private Integer collects; 59 | /** 60 | * 话题关联标签 61 | */ 62 | private List tags; 63 | /** 64 | * 浏览量 65 | */ 66 | private Integer view; 67 | /** 68 | * 创建时间 69 | */ 70 | private Date createTime; 71 | /** 72 | * 修改时间 73 | */ 74 | private Date modifyTime; 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/model/vo/ProfileVO.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.model.vo; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class ProfileVO { 7 | 8 | /** 9 | * 用户ID 10 | */ 11 | private String id; 12 | 13 | /** 14 | * 用户名 15 | */ 16 | private String username; 17 | 18 | /** 19 | * 别称 20 | */ 21 | private String alias; 22 | 23 | /** 24 | * 头像 25 | */ 26 | private String avatar; 27 | 28 | /** 29 | * 关注数 30 | */ 31 | private Integer followCount; 32 | 33 | /** 34 | * 关注者数 35 | */ 36 | private Integer followerCount; 37 | 38 | /** 39 | * 文章数 40 | */ 41 | private Integer topicCount; 42 | 43 | /** 44 | * 专栏数 45 | */ 46 | private Integer columns; 47 | 48 | /** 49 | * 评论数 50 | */ 51 | private Integer commentCount; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsBillboardService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.entity.BmsBillboard; 5 | 6 | public interface IBmsBillboardService extends IService { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsCommentService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.dto.CommentDTO; 5 | import com.douyuehan.doubao.model.entity.BmsComment; 6 | import com.douyuehan.doubao.model.entity.UmsUser; 7 | import com.douyuehan.doubao.model.vo.CommentVO; 8 | 9 | import java.util.List; 10 | 11 | 12 | public interface IBmsCommentService extends IService { 13 | /** 14 | * 15 | * 16 | * @param topicid 17 | * @return {@link BmsComment} 18 | */ 19 | List getCommentsByTopicID(String topicid); 20 | 21 | BmsComment create(CommentDTO dto, UmsUser principal); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsFollowService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.entity.BmsFollow; 5 | 6 | 7 | public interface IBmsFollowService extends IService { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsPostService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.douyuehan.doubao.model.dto.CreateTopicDTO; 6 | import com.douyuehan.doubao.model.entity.BmsPost; 7 | import com.douyuehan.doubao.model.entity.UmsUser; 8 | import com.douyuehan.doubao.model.vo.PostVO; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | 14 | public interface IBmsPostService extends IService { 15 | 16 | /** 17 | * 获取首页话题列表 18 | * 19 | * @param page 20 | * @param tab 21 | * @return 22 | */ 23 | Page getList(Page page, String tab); 24 | /** 25 | * 发布 26 | * 27 | * @param dto 28 | * @param principal 29 | * @return 30 | */ 31 | BmsPost create(CreateTopicDTO dto, UmsUser principal); 32 | 33 | /** 34 | * 查看话题详情 35 | * 36 | * @param id 37 | * @return 38 | */ 39 | Map viewTopic(String id); 40 | /** 41 | * 获取随机推荐10篇 42 | * 43 | * @param id 44 | * @return 45 | */ 46 | List getRecommend(String id); 47 | /** 48 | * 关键字检索 49 | * 50 | * @param keyword 51 | * @param page 52 | * @return 53 | */ 54 | Page searchByKey(String keyword, Page page); 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsPromotionService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.entity.BmsPromotion; 5 | 6 | 7 | public interface IBmsPromotionService extends IService { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsTagService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.douyuehan.doubao.model.entity.BmsPost; 6 | import com.douyuehan.doubao.model.entity.BmsTag; 7 | 8 | import java.util.List; 9 | 10 | 11 | public interface IBmsTagService extends IService { 12 | /** 13 | * 插入标签 14 | * 15 | * @param tags 16 | * @return 17 | */ 18 | List insertTags(List tags); 19 | /** 20 | * 获取标签关联话题 21 | * 22 | * @param topicPage 23 | * @param id 24 | * @return 25 | */ 26 | Page selectTopicsByTagId(Page topicPage, String id); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsTipService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.entity.BmsTip; 5 | 6 | public interface IBmsTipService extends IService { 7 | BmsTip getRandomTip(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IBmsTopicTagService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.entity.BmsTag; 5 | import com.douyuehan.doubao.model.entity.BmsTopicTag; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | public interface IBmsTopicTagService extends IService { 11 | 12 | /** 13 | * 获取Topic Tag 关联记录 14 | * 15 | * @param topicId TopicId 16 | * @return 17 | */ 18 | List selectByTopicId(String topicId); 19 | /** 20 | * 创建中间关系 21 | * 22 | * @param id 23 | * @param tags 24 | * @return 25 | */ 26 | void createTopicTag(String id, List tags); 27 | /** 28 | * 获取标签换脸话题ID集合 29 | * 30 | * @param id 31 | * @return 32 | */ 33 | Set selectTopicIdsByTagId(String id); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/IUmsUserService.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.douyuehan.doubao.model.dto.LoginDTO; 5 | import com.douyuehan.doubao.model.dto.RegisterDTO; 6 | import com.douyuehan.doubao.model.entity.UmsUser; 7 | import com.douyuehan.doubao.model.vo.ProfileVO; 8 | 9 | 10 | public interface IUmsUserService extends IService { 11 | 12 | /** 13 | * 注册功能 14 | * 15 | * @param dto 16 | * @return 注册对象 17 | */ 18 | UmsUser executeRegister(RegisterDTO dto); 19 | /** 20 | * 获取用户信息 21 | * 22 | * @param username 23 | * @return dbUser 24 | */ 25 | UmsUser getUserByUsername(String username); 26 | /** 27 | * 用户登录 28 | * 29 | * @param dto 30 | * @return 生成的JWT的token 31 | */ 32 | String executeLogin(LoginDTO dto); 33 | /** 34 | * 获取用户信息 35 | * 36 | * @param id 用户ID 37 | * @return 38 | */ 39 | ProfileVO getUserProfile(String id); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsBillboardServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.douyuehan.doubao.mapper.BmsBillboardMapper; 5 | import com.douyuehan.doubao.model.entity.BmsBillboard; 6 | import com.douyuehan.doubao.service.IBmsBillboardService; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | public class IBmsBillboardServiceImpl extends ServiceImpl implements IBmsBillboardService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsCommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.douyuehan.doubao.mapper.BmsCommentMapper; 5 | import com.douyuehan.doubao.model.dto.CommentDTO; 6 | import com.douyuehan.doubao.model.entity.BmsComment; 7 | import com.douyuehan.doubao.model.entity.UmsUser; 8 | import com.douyuehan.doubao.model.vo.CommentVO; 9 | import com.douyuehan.doubao.service.IBmsCommentService; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Date; 16 | import java.util.List; 17 | 18 | 19 | @Slf4j 20 | @Service 21 | public class IBmsCommentServiceImpl extends ServiceImpl implements IBmsCommentService { 22 | @Override 23 | public List getCommentsByTopicID(String topicid) { 24 | List lstBmsComment = new ArrayList(); 25 | try { 26 | lstBmsComment = this.baseMapper.getCommentsByTopicID(topicid); 27 | } catch (Exception e) { 28 | log.info("lstBmsComment失败"); 29 | } 30 | return lstBmsComment; 31 | } 32 | 33 | @Override 34 | public BmsComment create(CommentDTO dto, UmsUser user) { 35 | BmsComment comment = BmsComment.builder() 36 | .userId(user.getId()) 37 | .content(dto.getContent()) 38 | .topicId(dto.getTopic_id()) 39 | .createTime(new Date()) 40 | .build(); 41 | this.baseMapper.insert(comment); 42 | return comment; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsFollowServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.douyuehan.doubao.mapper.BmsFollowMapper; 5 | import com.douyuehan.doubao.model.entity.BmsFollow; 6 | import com.douyuehan.doubao.service.IBmsFollowService; 7 | import org.springframework.stereotype.Service; 8 | 9 | 10 | @Service 11 | public class IBmsFollowServiceImpl extends ServiceImpl implements IBmsFollowService { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsPostServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.douyuehan.doubao.mapper.BmsTagMapper; 8 | import com.douyuehan.doubao.mapper.BmsTopicMapper; 9 | import com.douyuehan.doubao.mapper.UmsUserMapper; 10 | import com.douyuehan.doubao.model.dto.CreateTopicDTO; 11 | import com.douyuehan.doubao.model.entity.BmsPost; 12 | import com.douyuehan.doubao.model.entity.BmsTag; 13 | import com.douyuehan.doubao.model.entity.BmsTopicTag; 14 | import com.douyuehan.doubao.model.entity.UmsUser; 15 | import com.douyuehan.doubao.model.vo.PostVO; 16 | import com.douyuehan.doubao.model.vo.ProfileVO; 17 | import com.douyuehan.doubao.service.IBmsPostService; 18 | import com.douyuehan.doubao.service.IBmsTagService; 19 | import com.douyuehan.doubao.service.IUmsUserService; 20 | import com.vdurmont.emoji.EmojiParser; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.context.annotation.Lazy; 23 | import org.springframework.stereotype.Service; 24 | import org.springframework.transaction.annotation.Transactional; 25 | import org.springframework.util.Assert; 26 | import org.springframework.util.ObjectUtils; 27 | 28 | import javax.annotation.Resource; 29 | import java.util.*; 30 | import java.util.stream.Collectors; 31 | 32 | 33 | @Service 34 | public class IBmsPostServiceImpl extends ServiceImpl implements IBmsPostService { 35 | @Resource 36 | private BmsTagMapper bmsTagMapper; 37 | @Resource 38 | private UmsUserMapper umsUserMapper; 39 | 40 | @Autowired 41 | @Lazy 42 | private IBmsTagService iBmsTagService; 43 | 44 | @Autowired 45 | private IUmsUserService iUmsUserService; 46 | 47 | @Autowired 48 | private com.douyuehan.doubao.service.IBmsTopicTagService IBmsTopicTagService; 49 | @Override 50 | public Page getList(Page page, String tab) { 51 | // 查询话题 52 | Page iPage = this.baseMapper.selectListAndPage(page, tab); 53 | // 查询话题的标签 54 | setTopicTags(iPage); 55 | return iPage; 56 | } 57 | 58 | @Override 59 | @Transactional(rollbackFor = Exception.class) 60 | public BmsPost create(CreateTopicDTO dto, UmsUser user) { 61 | BmsPost topic1 = this.baseMapper.selectOne(new LambdaQueryWrapper().eq(BmsPost::getTitle, dto.getTitle())); 62 | Assert.isNull(topic1, "话题已存在,请修改"); 63 | 64 | // 封装 65 | BmsPost topic = BmsPost.builder() 66 | .userId(user.getId()) 67 | .title(dto.getTitle()) 68 | .content(EmojiParser.parseToAliases(dto.getContent())) 69 | .createTime(new Date()) 70 | .build(); 71 | this.baseMapper.insert(topic); 72 | 73 | // 用户积分增加 74 | int newScore = user.getScore() + 1; 75 | umsUserMapper.updateById(user.setScore(newScore)); 76 | 77 | // 标签 78 | if (!ObjectUtils.isEmpty(dto.getTags())) { 79 | // 保存标签 80 | List tags = iBmsTagService.insertTags(dto.getTags()); 81 | // 处理标签与话题的关联 82 | IBmsTopicTagService.createTopicTag(topic.getId(), tags); 83 | } 84 | 85 | return topic; 86 | } 87 | 88 | @Override 89 | public Map viewTopic(String id) { 90 | Map map = new HashMap<>(16); 91 | BmsPost topic = this.baseMapper.selectById(id); 92 | Assert.notNull(topic, "当前话题不存在,或已被作者删除"); 93 | // 查询话题详情 94 | topic.setView(topic.getView() + 1); 95 | this.baseMapper.updateById(topic); 96 | // emoji转码 97 | topic.setContent(EmojiParser.parseToUnicode(topic.getContent())); 98 | map.put("topic", topic); 99 | // 标签 100 | QueryWrapper wrapper = new QueryWrapper<>(); 101 | wrapper.lambda().eq(BmsTopicTag::getTopicId, topic.getId()); 102 | Set set = new HashSet<>(); 103 | for (BmsTopicTag articleTag : IBmsTopicTagService.list(wrapper)) { 104 | set.add(articleTag.getTagId()); 105 | } 106 | List tags = iBmsTagService.listByIds(set); 107 | map.put("tags", tags); 108 | 109 | // 作者 110 | 111 | ProfileVO user = iUmsUserService.getUserProfile(topic.getUserId()); 112 | map.put("user", user); 113 | 114 | return map; 115 | } 116 | 117 | @Override 118 | public List getRecommend(String id) { 119 | return this.baseMapper.selectRecommend(id); 120 | } 121 | @Override 122 | public Page searchByKey(String keyword, Page page) { 123 | // 查询话题 124 | Page iPage = this.baseMapper.searchByKey(page, keyword); 125 | // 查询话题的标签 126 | setTopicTags(iPage); 127 | return iPage; 128 | } 129 | 130 | private void setTopicTags(Page iPage) { 131 | iPage.getRecords().forEach(topic -> { 132 | List topicTags = IBmsTopicTagService.selectByTopicId(topic.getId()); 133 | if (!topicTags.isEmpty()) { 134 | List tagIds = topicTags.stream().map(BmsTopicTag::getTagId).collect(Collectors.toList()); 135 | List tags = bmsTagMapper.selectBatchIds(tagIds); 136 | topic.setTags(tags); 137 | } 138 | }); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsPromotionServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.douyuehan.doubao.mapper.BmsPromotionMapper; 5 | import com.douyuehan.doubao.model.entity.BmsPromotion; 6 | import com.douyuehan.doubao.service.IBmsPromotionService; 7 | import org.springframework.stereotype.Service; 8 | 9 | 10 | @Service 11 | public class IBmsPromotionServiceImpl extends ServiceImpl implements IBmsPromotionService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsTagServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.douyuehan.doubao.mapper.BmsTagMapper; 7 | import com.douyuehan.doubao.model.entity.BmsPost; 8 | import com.douyuehan.doubao.model.entity.BmsTag; 9 | import com.douyuehan.doubao.service.IBmsTagService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Set; 16 | 17 | /** 18 | * Tag 实现类 19 | * 20 | * @author Knox 2020/11/7 21 | */ 22 | @Service 23 | public class IBmsTagServiceImpl extends ServiceImpl implements IBmsTagService { 24 | 25 | @Autowired 26 | private com.douyuehan.doubao.service.IBmsTopicTagService IBmsTopicTagService; 27 | 28 | @Autowired 29 | private com.douyuehan.doubao.service.IBmsPostService IBmsPostService; 30 | 31 | 32 | @Override 33 | public List insertTags(List tagNames) { 34 | List tagList = new ArrayList<>(); 35 | for (String tagName : tagNames) { 36 | BmsTag tag = this.baseMapper.selectOne(new LambdaQueryWrapper().eq(BmsTag::getName, tagName)); 37 | if (tag == null) { 38 | tag = BmsTag.builder().name(tagName).build(); 39 | this.baseMapper.insert(tag); 40 | } else { 41 | tag.setTopicCount(tag.getTopicCount() + 1); 42 | this.baseMapper.updateById(tag); 43 | } 44 | tagList.add(tag); 45 | } 46 | return tagList; 47 | } 48 | 49 | @Override 50 | public Page selectTopicsByTagId(Page topicPage, String id) { 51 | 52 | // 获取关联的话题ID 53 | Set ids = IBmsTopicTagService.selectTopicIdsByTagId(id); 54 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 55 | wrapper.in(BmsPost::getId, ids); 56 | 57 | return IBmsPostService.page(topicPage, wrapper); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsTipServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.douyuehan.doubao.mapper.BmsBillboardMapper; 5 | import com.douyuehan.doubao.mapper.BmsTipMapper; 6 | import com.douyuehan.doubao.model.entity.BmsBillboard; 7 | import com.douyuehan.doubao.model.entity.BmsTip; 8 | import com.douyuehan.doubao.service.IBmsBillboardService; 9 | import com.douyuehan.doubao.service.IBmsTipService; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Slf4j 14 | @Service 15 | public class IBmsTipServiceImpl extends ServiceImpl implements IBmsTipService { 17 | 18 | @Override 19 | public BmsTip getRandomTip() { 20 | BmsTip todayTip = null; 21 | try { 22 | todayTip = this.baseMapper.getRandomTip(); 23 | } catch (Exception e) { 24 | log.info("tip转化失败"); 25 | } 26 | return todayTip; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IBmsTopicTagServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.douyuehan.doubao.mapper.BmsTopicTagMapper; 7 | import com.douyuehan.doubao.model.entity.BmsTag; 8 | import com.douyuehan.doubao.model.entity.BmsTopicTag; 9 | import com.douyuehan.doubao.service.IBmsTopicTagService; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | 17 | @Service 18 | @Transactional(rollbackFor = Exception.class) 19 | public class IBmsTopicTagServiceImpl extends ServiceImpl implements IBmsTopicTagService { 20 | 21 | @Override 22 | public List selectByTopicId(String topicId) { 23 | QueryWrapper wrapper = new QueryWrapper<>(); 24 | wrapper.lambda().eq(BmsTopicTag::getTopicId, topicId); 25 | return this.baseMapper.selectList(wrapper); 26 | } 27 | @Override 28 | public void createTopicTag(String id, List tags) { 29 | // 先删除topicId对应的所有记录 30 | this.baseMapper.delete(new LambdaQueryWrapper().eq(BmsTopicTag::getTopicId, id)); 31 | 32 | // 循环保存对应关联 33 | tags.forEach(tag -> { 34 | BmsTopicTag topicTag = new BmsTopicTag(); 35 | topicTag.setTopicId(id); 36 | topicTag.setTagId(tag.getId()); 37 | this.baseMapper.insert(topicTag); 38 | }); 39 | } 40 | @Override 41 | public Set selectTopicIdsByTagId(String id) { 42 | return this.baseMapper.getTopicIdsByTagId(id); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/service/impl/IUmsUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.douyuehan.doubao.common.exception.ApiAsserts; 6 | import com.douyuehan.doubao.jwt.JwtUtil; 7 | import com.douyuehan.doubao.mapper.BmsFollowMapper; 8 | import com.douyuehan.doubao.mapper.BmsTopicMapper; 9 | import com.douyuehan.doubao.mapper.UmsUserMapper; 10 | import com.douyuehan.doubao.model.dto.LoginDTO; 11 | import com.douyuehan.doubao.model.dto.RegisterDTO; 12 | import com.douyuehan.doubao.model.entity.BmsFollow; 13 | import com.douyuehan.doubao.model.entity.BmsPost; 14 | import com.douyuehan.doubao.model.entity.UmsUser; 15 | import com.douyuehan.doubao.model.vo.ProfileVO; 16 | import com.douyuehan.doubao.service.IUmsUserService; 17 | import com.douyuehan.doubao.utils.MD5Utils; 18 | import lombok.extern.slf4j.Slf4j; 19 | import org.springframework.beans.BeanUtils; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.stereotype.Service; 22 | import org.springframework.transaction.annotation.Transactional; 23 | import org.springframework.util.ObjectUtils; 24 | import java.util.Date; 25 | 26 | 27 | 28 | @Slf4j 29 | @Service 30 | @Transactional(rollbackFor = Exception.class) 31 | public class IUmsUserServiceImpl extends ServiceImpl implements IUmsUserService { 32 | 33 | @Autowired 34 | private BmsTopicMapper bmsTopicMapper; 35 | @Autowired 36 | private BmsFollowMapper bmsFollowMapper; 37 | 38 | @Override 39 | public UmsUser executeRegister(RegisterDTO dto) { 40 | //查询是否有相同用户名的用户 41 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 42 | wrapper.eq(UmsUser::getUsername, dto.getName()).or().eq(UmsUser::getEmail, dto.getEmail()); 43 | UmsUser umsUser = baseMapper.selectOne(wrapper); 44 | if (!ObjectUtils.isEmpty(umsUser)) { 45 | ApiAsserts.fail("账号或邮箱已存在!"); 46 | } 47 | UmsUser addUser = UmsUser.builder() 48 | .username(dto.getName()) 49 | .alias(dto.getName()) 50 | .password(MD5Utils.getPwd(dto.getPass())) 51 | .email(dto.getEmail()) 52 | .createTime(new Date()) 53 | .status(true) 54 | .build(); 55 | baseMapper.insert(addUser); 56 | 57 | return addUser; 58 | } 59 | @Override 60 | public UmsUser getUserByUsername(String username) { 61 | return baseMapper.selectOne(new LambdaQueryWrapper().eq(UmsUser::getUsername, username)); 62 | } 63 | @Override 64 | public String executeLogin(LoginDTO dto) { 65 | String token = null; 66 | try { 67 | UmsUser user = getUserByUsername(dto.getUsername()); 68 | String encodePwd = MD5Utils.getPwd(dto.getPassword()); 69 | if(!encodePwd.equals(user.getPassword())) 70 | { 71 | throw new Exception("密码错误"); 72 | } 73 | token = JwtUtil.generateToken(String.valueOf(user.getUsername())); 74 | } catch (Exception e) { 75 | log.warn("用户不存在or密码验证失败=======>{}", dto.getUsername()); 76 | } 77 | return token; 78 | } 79 | @Override 80 | public ProfileVO getUserProfile(String id) { 81 | ProfileVO profile = new ProfileVO(); 82 | UmsUser user = baseMapper.selectById(id); 83 | BeanUtils.copyProperties(user, profile); 84 | // 用户文章数 85 | int count = bmsTopicMapper.selectCount(new LambdaQueryWrapper().eq(BmsPost::getUserId, id)); 86 | profile.setTopicCount(count); 87 | 88 | // 粉丝数 89 | int followers = bmsFollowMapper.selectCount((new LambdaQueryWrapper().eq(BmsFollow::getParentId, id))); 90 | profile.setFollowerCount(followers); 91 | 92 | return profile; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/douyuehan/doubao/utils/MD5Utils.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao.utils; 2 | 3 | 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | 8 | public class MD5Utils { 9 | 10 | public static String getPwd(String pwd) { 11 | try { 12 | // 创建加密对象 13 | MessageDigest digest = MessageDigest.getInstance("md5"); 14 | 15 | // 调用加密对象的方法,加密的动作已经完成 16 | byte[] bs = digest.digest(pwd.getBytes()); 17 | // 接下来,我们要对加密后的结果,进行优化,按照mysql的优化思路走 18 | // mysql的优化思路: 19 | // 第一步,将数据全部转换成正数: 20 | String hexString = ""; 21 | for (byte b : bs) { 22 | // 第一步,将数据全部转换成正数: 23 | // 解释:为什么采用b&255 24 | /* 25 | * b:它本来是一个byte类型的数据(1个字节) 255:是一个int类型的数据(4个字节) 26 | * byte类型的数据与int类型的数据进行运算,会自动类型提升为int类型 eg: b: 1001 1100(原始数据) 27 | * 运算时: b: 0000 0000 0000 0000 0000 0000 1001 1100 255: 0000 28 | * 0000 0000 0000 0000 0000 1111 1111 结果:0000 0000 0000 0000 29 | * 0000 0000 1001 1100 此时的temp是一个int类型的整数 30 | */ 31 | int temp = b & 255; 32 | // 第二步,将所有的数据转换成16进制的形式 33 | // 注意:转换的时候注意if正数>=0&&<16,那么如果使用Integer.toHexString(),可能会造成缺少位数 34 | // 因此,需要对temp进行判断 35 | if (temp < 16 && temp >= 0) { 36 | // 手动补上一个“0” 37 | hexString = hexString + "0" + Integer.toHexString(temp); 38 | } else { 39 | hexString = hexString + Integer.toHexString(temp); 40 | } 41 | } 42 | return hexString; 43 | } catch (NoSuchAlgorithmException e) { 44 | // TODO Auto-generated catch block 45 | e.printStackTrace(); 46 | } 47 | return ""; 48 | } 49 | 50 | 51 | // public static void main(String[] args) { 52 | // String pwd = MD5Utils.getPwd("234"); 53 | // System.out.println(pwd); 54 | // } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/resources/application-dev.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8000 3 | 4 | web: 5 | domain: http://localhost 6 | 7 | spring: 8 | datasource: 9 | driver-class-name: com.mysql.cj.jdbc.Driver 10 | username: root 11 | password: root 12 | url: jdbc:mysql://localhost:3306/doubao?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8 13 | type: com.zaxxer.hikari.HikariDataSource 14 | 15 | logging: 16 | level: 17 | root: info 18 | com.douyuehan.doubao: debug -------------------------------------------------------------------------------- /src/main/resources/application-prod.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8088 3 | 4 | web: 5 | domain: http://localhost 6 | 7 | spring: 8 | datasource: 9 | driver-class-name: com.mysql.cj.jdbc.Driver 10 | username: root 11 | password: root 12 | url: jdbc:mysql://localhost:3306/doubao?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8 13 | type: com.zaxxer.hikari.HikariDataSource 14 | 15 | logging: 16 | level: 17 | root: info 18 | com.douyuehan.doubao: info -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: dev -------------------------------------------------------------------------------- /src/main/resources/mapper/BmsCommentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/mapper/BmsPostMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 42 | 43 | 50 | 51 | 78 | 79 | -------------------------------------------------------------------------------- /src/main/resources/mapper/BmsPostTagMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/mapper/BmsTipMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /src/test/java/com/douyuehan/doubao/DoubaoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.douyuehan.doubao; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DoubaoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | --------------------------------------------------------------------------------