目录
前言概述
一.前期准备
项目演示
用户注册
用户登录
主页面
发帖页面
个人信息及修改
用户主帖
站内信
需求分析
技术选型
二.建表分析
三.环境搭建
技术环境的检查与安装
检查JDK
编辑
检查数据库
检查Maven
检查git
编辑
项目启动的通用配置
新建项目
文件通用配置
修改编码格式为UTF-8
检查代码的自动补全:Settings --> Edit --> General --> code completion
检查配置自动导包:Settings --> Edit --> General --> auto import
配置Maven镜像:
配置热部署:配置这两处
pom文件配置:(在此处我直接一次性引入全部了,有需要的选择性复制即可)
四.创建项目
定义状态码
定义通用返回结果
自定义异常
全局异常处理
登录拦截器
Swagger实现
随机字符串的生成与密码加密
用户部分(后续博客进行补充处理)
用户注册
用户登录
用户退出
个人信息展示
修改个人信息
修改密码
板块部分(后续博客进行补充处理)
获取板块信息
帖子部分(后续博客进行补充处理)
帖子列表
用户帖子列表
发布帖子
帖子详情
编辑帖子
点赞帖子
帖子回复
展示帖子回复
前言概述
本次博客是对基于前后端交互的论坛系统进行介绍,希望能给大家带来一定的帮助~
一.前期准备
项目演示
用户注册
用户登录
主页面
发帖页面
个人信息及修改
用户主帖
站内信
需求分析
整个项目主要基于管理员和普通用户两种使用主体进行开发和设计的,对于基本的业务功能的总览如下:
▪ 注册登录▪ 帖⼦列表, 发布帖⼦, 删除帖⼦, 回复帖⼦等功能.▪ ⽀持个⼈主⻚的展⽰/编辑▪ ⽀持帖⼦按版块分类.▪ ⽀持站内私信▪ 管理员可以添加/删除/修改版块▪ 管理员可以管理所有帖⼦
技术选型
整个项目的完整实现主要依托于以下技术:
◦ Spring◦ Spring Boot◦ MyBatis◦ Tomcat◦ Nginx
◦ HTML, CSS, JavaScript◦ jQuery◦ Bootstrap
◦ MySQL
◦ Maven
◦ Git 2.36.X + GITEE这些技术集体的版本如下:
不同技术的对应的具体版本如下:(考虑到不同springboot版本只与一些技术的特定版本兼容,所以必须规定好各个技术的版本号)
二.建表分析
我们根据不同的业务要求建立不同的表格:
1.注册登录涉及与用户表的增删查看,需要设计用户表
2.需要在主页显示不同的板块,涉及板块表的操作,需要设计板块表
3.需要实现对帖子列表的增删查改,需要设计帖子表
4.帖子回复的展示需要设计帖子回复表
5.站内信的实现需要设计一张信息回复表
对应的SQL脚本如下:(完整无编号版本请私信我)
-- ----------------------------
-- 创建数据库,并指定字符集
-- ----------------------------
drop database if exists forum_db;
create database forum_db character set utf8mb4 collate utf8mb4_general_ci;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- 创建帖⼦表 t_article
-- ----------------------------
DROP TABLE IF EXISTS `t_article`;
CREATE TABLE `t_article` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '帖⼦编号,主键,⾃增',
`boardId` bigint(20) NOT NULL COMMENT '关联板块编号,⾮空',
`userId` bigint(20) NOT NULL COMMENT '发帖⼈,⾮空,关联⽤⼾编号',
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '标题,⾮空,最⼤⻓度100个字符',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
COMMENT '帖⼦正⽂,⾮空',
`visitCount` int(11) NOT NULL DEFAULT 0 COMMENT '访问量,默认0',
`replyCount` int(11) NOT NULL DEFAULT 0 COMMENT '回复数据,默认0',
`likeCount` int(11) NOT NULL DEFAULT 0 COMMENT '点赞数,默认0',
`state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0正常 1 禁⽤,默认0',
`deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0 否 1 是,默认0',
`createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,⾮空',
`updateTime` datetime NOT NULL COMMENT '修改时间,精确到秒,⾮空',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_general_ci COMMENT = '帖⼦表' ROW_FORMAT = Dynamic;
-- ----------------------------
32 -- 创建帖⼦回复表 t_article_reply
33 -- ----------------------------
34 DROP TABLE IF EXISTS `t_article_reply`;
35 CREATE TABLE `t_article_reply` (
36 `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号,主键,⾃增',
37 `articleId` bigint(20) NOT NULL COMMENT '关联帖⼦编号,⾮空',
38 `postUserId` bigint(20) NOT NULL COMMENT '楼主⽤⼾,关联⽤⼾编号,⾮空',
39 `replyId` bigint(20) NULL DEFAULT NULL COMMENT '关联回复编号,⽀持楼中楼',
40 `replyUserId` bigint(20) NULL DEFAULT NULL COMMENT '楼主下的回复⽤⼾编号,⽀持楼
中楼',
41 `content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '回贴内容,⻓度500个字符,⾮空',
42 `likeCount` int(11) NOT NULL DEFAULT 0 COMMENT '点赞数,默认0',
43 `state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0 正常,1禁⽤,默认0',
44 `deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否 1是,默认0',
45 `createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,⾮空',
46 `updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒,⾮空',
47 PRIMARY KEY (`id`) USING BTREE
48 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_general_ci COMMENT = '帖⼦回复表' ROW_FORMAT = Dynamic;
49
50 -- ----------------------------
51 -- 创建版块表 t_board
52 -- ----------------------------
53 DROP TABLE IF EXISTS `t_board`;
54 CREATE TABLE `t_board` (
55 `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '版块编号,主键,⾃增',
56 `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
COMMENT '版块名,⾮空',
57 `articleCount` int(11) NOT NULL DEFAULT 0 COMMENT '帖⼦数量,默认0',
58 `sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序优先级,升序,默认0,',
59 `state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态,0 正常,1禁⽤,默认0',
60 `deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否,1是,默认0',
61 `createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,⾮空',
62 `updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒,⾮空',
63 PRIMARY KEY (`id`) USING BTREE
64 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_general_ci COMMENT = '版块表' ROW_FORMAT = Dynamic;
65
66 -- ----------------------------
67 -- 创建站内信表 for t_message
68 -- ----------------------------
69 DROP TABLE IF EXISTS `t_message`;
70 CREATE TABLE `t_message` (
71 `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '站内信编号,主键,⾃增',
72 `postUserId` bigint(20) NOT NULL COMMENT '发送者,并联⽤⼾编号',
73 `receiveUserId` bigint(20) NOT NULL COMMENT '接收者,并联⽤⼾编号',
74 `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '内容,⾮空,⻓度255个字符',
75 `state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0未读 1已读,默认0',
76 `deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否,1是,默认0',
77 `createTime` datetime NOT NULL COMMENT '创建时间,精确到秒,⾮空',
78 `updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒,⾮空',
79 PRIMARY KEY (`id`) USING BTREE
80 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_general_ci COMMENT = '站内信表' ROW_FORMAT = Dynamic;
81
82 -- ----------------------------
83 -- 创建⽤⼾表 for t_user
84 -- ----------------------------
85 DROP TABLE IF EXISTS `t_user`;
86 CREATE TABLE `t_user` (
87 `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '⽤⼾编号,主键,⾃增',
88 `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '⽤⼾名,⾮空,唯⼀',
89 `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '加密后的密码',
90 `nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '昵称,⾮空',
91 `phoneNum` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL COMMENT '⼿机号',
92 `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL COMMENT '邮箱地址',
93 `gender` tinyint(4) NOT NULL DEFAULT 2 COMMENT '0⼥ 1男 2保密,⾮空,默认2',
94 `salt` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
COMMENT '为密码加盐,⾮空',
95 `avatarUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci
NULL DEFAULT NULL COMMENT '⽤⼾头像URL,默认系统图⽚',
96 `articleCount` int(11) NOT NULL DEFAULT 0 COMMENT '发帖数量,⾮空,默认0',
97 `isAdmin` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否管理员,0否 1是,默认0',
98 `remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL COMMENT '备注,⾃我介绍',
99 `state` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态 0 正常,1 禁⾔,默认0',
100 `deleteState` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否删除 0否 1是,默认0',
101 `createTime` datetime NOT NULL COMMENT '创建时间,精确到秒',
102 `updateTime` datetime NOT NULL COMMENT '更新时间,精确到秒',
103 PRIMARY KEY (`id`) USING BTREE,
104 UNIQUE INDEX `user_username_uindex`(`username`) USING BTREE
105 ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_general_ci COMMENT = '⽤⼾表' ROW_FORMAT = Dynamic;
106
107 SET FOREIGN_KEY_CHECKS = 1;
108
109 -- 写⼊版块信息数据
110 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (1, 'Java', 0, 1, 0, 0,
'2023-01-14 19:02:18', '2023-01-14 19:02:18');
111 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (2, 'C++', 0, 2, 0, 0, '2023-
01-14 19:02:41', '2023-01-14 19:02:41');
112 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (3, '前端技术', 0, 3, 0, 0,
'2023-01-14 19:02:52', '2023-01-14 19:02:52');
113 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (4, 'MySQL', 0, 4, 0, 0,
'2023-01-14 19:03:02', '2023-01-14 19:03:02');
114 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (5, '⾯试宝典', 0, 5, 0, 0,
'2023-01-14 19:03:24', '2023-01-14 19:03:24');
115 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (6, '经验分享', 0, 6, 0, 0,
'2023-01-14 19:03:48', '2023-01-14 19:03:48');
116 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (7, '招聘信息', 0, 7, 0, 0,
'2023-01-25 21:25:33', '2023-01-25 21:25:33');
117 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (8, '福利待遇', 0, 8, 0, 0,
'2023-01-25 21:25:58', '2023-01-25 21:25:58');
118 INSERT INTO `t_board` (`id`, `name`, `articleCount`, `sort`, `state`,
`deleteState`, `createTime`, `updateTime`) VALUES (9, '灌⽔区', 0, 9, 0, 0,
'2023-01-25 21:26:12', '2023-01-25 21:26:12');
三.环境搭建
技术环境的检查与安装
检查JDK
指令:java- version
查看结果为1.8.x版本
检查数据库
确认数据库版本为5.7.x
指令:mysql -uroot -p
检查Maven
指令:mvn -v
确保maven版本在3.5.x以上
配置maven镜像(将以下代码在记事本中保存,将记事本更名为settings.xml,以后在ideal中直接更改maven镜像为此)
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
| This is the configuration file for Maven. It can be specified at two levels:
|
| 1. User Level. This settings.xml file provides configuration for a single user,
| and is normally provided in ${user.home}/.m2/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -s /path/to/user/settings.xml
|
| 2. Global Level. This settings.xml file provides configuration for all Maven
| users on a machine (assuming they're all using the same Maven
| installation). It's normally provided in
| ${maven.conf}/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -gs /path/to/global/settings.xml
|
| The sections in this sample file are intended to give you a running start at
| getting the most out of your Maven installation. Where appropriate, the default
| values (values used when the setting is not specified) are provided.
|
|-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<!-- interactiveMode
| This will determine whether maven prompts you when it needs input. If set to false,
| maven will use a sensible default value, perhaps based on some other setting, for
| the parameter in question.
|
| Default: true
<interactiveMode>true</interactiveMode>
-->
<!-- offline
| Determines whether maven should attempt to connect to the network when executing a build.
| This will have an effect on artifact downloads, artifact deployment, and others.
|
| Default: false
<offline>false</offline>
-->
<!-- pluginGroups
| This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
| when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
| "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
|-->
<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
</pluginGroups>
<!-- proxies
| This is a list of proxies which can be used on this machine to connect to the network.
| Unless otherwise specified (by system property or command-line switch), the first proxy
| specification in this list marked as active will be used.
|-->
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
-->
</proxies>
<!-- servers
| This is a list of authentication profiles, keyed by the server-id used within the system.
| Authentication profiles can be used whenever maven must make a connection to a remote server.
|-->
<servers>
<!-- server
| Specifies the authentication information to use when connecting to a particular server, identified by
| a unique name within the system (referred to by the 'id' attribute below).
|
| NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
| used together.
|
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
-->
<!-- Another sample, using keys to authenticate.
<server>
<id>siteServer</id>
<privateKey>/path/to/private/key</privateKey>
<passphrase>optional; leave empty if not used.</passphrase>
</server>
-->
</servers>
<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>
-->
<mirror>
<id>aliyun-public</id>
<mirrorOf>*</mirrorOf>
<name>aliyun public</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
<id>aliyun-central</id>
<mirrorOf>*</mirrorOf>
<name>aliyun central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
<mirror>
<id>aliyun-spring</id>
<mirrorOf>*</mirrorOf>
<name>aliyun spring</name>
<url>https://maven.aliyun.com/repository/spring</url>
</mirror>
</mirrors>
<!-- profiles
| This is a list of profiles which can be activated in a variety of ways, and which can modify
| the build process. Profiles provided in the settings.xml are intended to provide local machine-
| specific paths and repository locations which allow the build to work in the local environment.
|
| For example, if you have an integration testing plugin - like cactus - that needs to know where
| your Tomcat instance is installed, you can provide a variable here such that the variable is
| dereferenced during the build process to configure the cactus plugin.
|
| As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
| section of this document (settings.xml) - will be discussed later. Another way essentially
| relies on the detection of a system property, either matching a particular value for the property,
| or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
| value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
| Finally, the list of active profiles can be specified directly from the command line.
|
| NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
| repositories, plugin repositories, and free-form properties to be used as configuration
| variables for plugins in the POM.
|
|-->
<profiles>
<!-- profile
| Specifies a set of introductions to the build process, to be activated using one or more of the
| mechanisms described above. For inheritance purposes, and to activate profiles via <activatedProfiles/>
| or the command line, profiles have to have an ID that is unique.
|
| An encouraged best practice for profile identification is to use a consistent naming convention
| for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', 'user-brett', etc.
| This will make it more intuitive to understand what the set of introduced profiles is attempting
| to accomplish, particularly when you only have a list of profile id's for debug.
|
| This profile example uses the JDK version to trigger activation, and provides a JDK-specific repo.
<profile>
<id>jdk-1.4</id>
<activation>
<jdk>1.4</jdk>
</activation>
<repositories>
<repository>
<id>jdk14</id>
<name>Repository for JDK 1.4 builds</name>
<url>http://www.myhost.com/maven/jdk14</url>
<layout>default</layout>
<snapshotPolicy>always</snapshotPolicy>
</repository>
</repositories>
</profile>
-->
<!--
| Here is another profile, activated by the system property 'target-env' with a value of 'dev',
| which provides a specific path to the Tomcat instance. To use this, your plugin configuration
| might hypothetically look like:
|
| ...
| <plugin>
| <groupId>org.myco.myplugins</groupId>
| <artifactId>myplugin</artifactId>
|
| <configuration>
| <tomcatLocation>${tomcatPath}</tomcatLocation>
| </configuration>
| </plugin>
| ...
|
| NOTE: If you just wanted to inject this configuration whenever someone set 'target-env' to
| anything, you could just leave off the <value/> inside the activation-property.
|
<profile>
<id>env-dev</id>
<activation>
<property>
<name>target-env</name>
<value>dev</value>
</property>
</activation>
<properties>
<tomcatPath>/path/to/tomcat/instance</tomcatPath>
</properties>
</profile>
-->
</profiles>
<!-- activeProfiles
| List of profiles that are active for all builds.
|
<activeProfiles>
<activeProfile>alwaysActiveProfile</activeProfile>
<activeProfile>anotherAlwaysActiveProfile</activeProfile>
</activeProfiles>
-->
</settings>
检查git
指令:git --version
项目启动的通用配置
新建项目
文件通用配置
修改编码格式为UTF-8
将以下两处设置的字符集格式修改为UTF-8
检查代码的自动补全:Settings --> Edit --> General --> code completion
检查配置自动导包:Settings --> Edit --> General --> auto import
配置Maven镜像:
配置热部署:配置这两处
pom文件配置:(在此处我直接一次性引入全部了,有需要的选择性复制即可)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liujianlei</groupId>
<artifactId>forum_system</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>forum_system</name>
<description>forum_system</description>
<properties>
<!-- JAVA 版本 -->
<java.version>1.8</java.version>
<!-- 编译环境JDK版本 -->
<maven.compiler.source>${java.version}</maven.compiler.source>
<!-- 运⾏环境JVM版本 -->
<maven.compiler.target>${java.version}</maven.compiler.target>
<!-- 构建项⽬指定编码集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 管理依赖版块号-->
<spring-boot-version>2.7.6</spring-boot-version>
<!-- 数据库连接-->
<mysql-connector.version>5.1.49</mysql-connector.version>
<!-- mybatis -->
<mybatis-starter>2.3.0</mybatis-starter>
<!-- 数据源 -->
<druid-starter>1.2.15</druid-starter>
<!-- mybatis ⽣成器 -->
<mybatis-generator-plugin-version>1.4.1</mybatis-generator-plugin-version>
<!-- API测试接⼝⽣成 -->
<springfox-boot-starter.version>3.0.0</springfox-boot-starter.version>
<!--自动生成mapper文件和对应的类-->
<mybatis-generator-plugin-version>1.4.1</mybatis-generator-plugin-version>
<!--注释类版本-->
<springfox-boot-starter.version>3.0.0</springfox-boot-starter.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mysql连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<!-- mybatis 依赖
其中已经包含了spring-jdbc不再重复引用,
此项目中使用spring-jdbc提供的HikariCP做为数据源, 相关配置在yml文件中
-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-starter}</version>
</dependency>
<!-- 阿里巴巴druid数据源,如果使用SpringBoot默认的数据源,删除或注释这个依赖即可 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid-starter}</version>
</dependency>
<!-- API⽂档⽣成,基于swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox-boot-starter.version}</version>
</dependency>
<!-- SpringBoot健康监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--导入编码解码工具依赖包-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- mybatis 生成器插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>${mybatis-generator-plugin-version}</version>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<!-- 运行生成器的阶段 -->
<phase>deploy</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<!-- 相关配置 -->
<configuration>
<!-- 打开日志 -->
<verbose>true</verbose>
<!-- 允许覆盖 -->
<overwrite>true</overwrite>
<!-- 配置文件路径 -->
<configurationFile>
src/main/resources/mybatis/generatorConfig.xml
</configurationFile>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
四.创建项目
定义状态码
通过使用枚举类自定义状态码,对项目中成功和失败的结果状态进行针对性的描述
定义通用返回结果
目的:系统实现前后端分离,定义一个类,其中包括返回的提示信息,返回的状态码,返回的数据,统一返回json字符串,规范返回结果
public enum ResultCode {
/** 定义状态码 */
SUCCESS (0, "成功"),
FAILED (1000, "失败"),
FAILED_UNAUTHORIZED (1001, "未授权"),
FAILED_PARAMS_VALIDATE (1002, "参数校验失败"),
FAILED_FORBIDDEN (1003, "禁止访问"),
FAILED_CREATE (1004, "新增失败"),
FAILED_NOT_EXISTS (1005, "资源不存在"),
FAILED_USER_EXISTS (1101, "用户已存在"),
FAILED_USER_NOT_EXISTS (1102, "用户不存在"),
FAILED_USER_BANNED (1103, "您已被禁言, 请联系管理员, 并重新登录."),
USER_NOT_LOG(1104,"用户未登录"),
FAILED_TWO_PWD_NOT_SAME (1105, "两次输入的密码不一致"),
FAILED_LOGIN (1106, "用户名或密码错误"),
FAILED_PASSWORD (1107, "密码错误"),
ERROR_SERVICES (2000, "服务器内部错误"),
ERROR_IS_NULL (2001, "IS NULL."),
ERROR_INSERT (2002, "数据写入失败"),
ERROR_UPDATE (2003, "数据更新失败");
// 状态码
long code;
// 状态描述
String message;
// 构造方法
ResultCode(long code, String message) {
this.code = code;
this.message = message;
}
public long getCode() {
return code;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return "code = " + code + ", message = " + message + ". ";
}
}
自定义异常
自定义异常信息,与控制器捕获异常相配合,对捕获的异常进行自定义的描述,规范异常抛出的返回结果
public class ApplicationException extends RuntimeException {
private static final long serialVersionUID = -3533806916645793660L;
// 自定义错误
protected AppResult errorResult;
// 指定状态码,异常描述
public ApplicationException(AppResult errorResult) {
super(errorResult.getMessage());
this.errorResult = errorResult;
}
// 自定义异常描述
public ApplicationException(String message) {
super(message);
}
// 指定异常
public ApplicationException(Throwable cause) {
super(cause);
}
// 自定义异常描述,异常信息
public ApplicationException(String message, Throwable cause) {
super(message, cause);
}
public AppResult getErrorResult() {
return errorResult;
}
}
全局异常处理
通过(控制器增强)@ControllerAdvice和(统一异常处理)@ExceptionHandler注解进行统一的异常处理,规范异常抛出的结果
@Slf4j
//控制器增强
@ControllerAdvice
public class GlobalExceptionHandler {
//以json形式返回数据
@ResponseBody
//处理异常的范围
@ExceptionHandler(ApplicationException.class)
public AppResult ApplicationExceptionHandler(ApplicationException e){
log.info("捕获到异常....");
//打印错误信息
e.getStackTrace();
//打印日志信息
log.error(e.getMessage());
//判断是否是自定义异常
if(e.getErrorResult()!=null){
return e.getErrorResult();
}
//处理异常
return AppResult.failed(e.getMessage());
}
//以json形式返回数据
@ResponseBody
//处理异常的范围
@ExceptionHandler(Exception.class)
public AppResult ExceptionHandler(Exception e){
log.info("捕获到异常....");
//打印错误信息
e.getStackTrace();
//打印日志信息
log.error("错误信息为:"+e.getMessage());
//判断是否是自定义异常
if(e.getMessage()==null){
return AppResult.failed(ResultCode.ERROR_SERVICES);
}
//处理异常
return AppResult.failed(e.getMessage());
}
}
登录拦截器
定义拦截器,并在拦截器的配置类中添加拦截器和自定义拦截路径和放行路径,并使用preHandle()对拦截的路径进行统一处理(登录校验)
@Configuration
public class AppInterceptorConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器和拦截路径
registry.addInterceptor(new LoginInterceptor()) // 添加用户登录拦截器
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/sign-in.html") // 排除登录HTML
.excludePathPatterns("/sign-up.html") // 排除注册HTML
.excludePathPatterns("/user/login") // 排除登录api接口
.excludePathPatterns("/user/register") // 排除注册api接口
.excludePathPatterns("/swagger*/**") // 排除登录swagger下所有
.excludePathPatterns("/v3*/**") // 排除登录v3下所有,与swagger相关
.excludePathPatterns("/dist/**") // 排除所有静态文件
.excludePathPatterns("/image/**")
.excludePathPatterns("/js/**");
}
}
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("拦截器拦截到请求...");
//获取session
HttpSession session = request.getSession(false);
if(session!=null&&session.getAttribute(AppConfig.USER_SESSION)!=null){
//用户已登录
return true;
}
//设置强制跳转
response.sendRedirect("/sign-in.html");
return false;
}
}
Swagger实现
按照swagger规范定义接口和接口信息,并通过工具对接口信息进行解析,从而生成各种格式的接口文档和在线的调试页面,通过这种自动文档的方式,解决接口文档更新不及时的问题
随机字符串的生成与密码加密
使用md5实现对密码的加密
public class MD5Utils {
/**
* 普通MD5加密
* @param str 原始字符串
* @return 一次MD5加密后的密文
*/
public static String md5 (String str) {
return DigestUtils.md5Hex(str);
}
/**
* 原始字符串与Key组合进行一次MD5加密
* @param str 原始字符串
* @param key
* @return 组合字符串一次MD5加密后的密文
*/
public static String md5 (String str, String key) {
return DigestUtils.md5Hex(str + key);
}
/**
* 原始字符串加密后与扰动字符串组合再进行一次MD5加密
* @param str 原始字符串
* @param salt 扰动字符串
* @return 加密后的密文
*/
public static String md5Salt (String str, String salt) {
return DigestUtils.md5Hex(DigestUtils.md5Hex(str) + salt);
}
/**
* 校验原文与盐加密后是否与传入的密文相同
* @param original 原字符串
* @param salt 扰动字符串
* @param ciphertext 密文
* @return true 相同, false 不同
*/
public static boolean verifyOriginalAndCiphertext (String original, String salt, String ciphertext) {
String md5text = md5Salt(original, salt);
if (md5text.equalsIgnoreCase(ciphertext)) {
return true;
}
return false;
}
}