项目源码:https://gitee.com/zero-one-zsj/forum
字段 | 类型 | 非空 (Y/N) | 主键 (Y/N) | 默认值 | 备注 |
|---|---|---|---|---|---|
id | bigint | Y | Y | 编号,主键自增 | |
username | varchar(20) | Y | N | 用户名,唯一 | |
password | varchar(32) | Y | N | 加密后的密码 | |
nickname | varchar(50) | Y | N | 昵称 | |
phoneNum | varchar(20) | N | N | 手机号 | |
varchar(50) | N | N | 电子邮箱 | ||
gender | tinyint | Y | N | 2 | 性别 0 女,1 男,2 保密 |
salt | varchar(32) | Y | N | 为密码加盐 | |
avatarUrl | varchar(255) | N | N | 用户头像路径 | |
articleCount | int | Y | N | 0 | 发帖数量 |
isAdmin | tinyint | Y | N | 0 | 是否管理员 0 否,1 是 |
remark | varchar(1000) | N | N | 备注,自我介绍 | |
state | tinyint | Y | N | 0 | 状态 0 正常,1 禁言 |
deleteState | tinyint | Y | N | 0 | 是否删除,0 否,1 是 |
createTime | dateTime | Y | N | 创建时间,精确到秒 | |
updateTime | dateTime | Y | N | 更新时间,精确到秒 |
DROP DATABASE IF EXISTS forum_db;
#创建数据库并指定字符集
CREATE DATABASE forum_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE forum_db;
#创建用户表
DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user(
id BIGINT PRIMARY KEY auto_increment COMMENT '编号,主键自增',
username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名,唯一',
`password` VARCHAR(32) NOT NULL COMMENT '加密后的密码',
nickname VARCHAR(50) NOT NULL COMMENT '昵称',
phoneNum VARCHAR(20) COMMENT '手机号',
email VARCHAR(50) COMMENT '电子邮箱',
gender TINYINT NOT NULL DEFAULT 2 COMMENT '性别 0女,1男,2保密',
salt VARCHAR(32) NOT NULL COMMENT '为密码加盐',
avatarUrl VARCHAR(255) COMMENT '用户头像路径',
avatarCount INT NOT NULL DEFAULT 0 COMMENT '发帖数量',
isAdmin TINYINT NOT NULL DEFAULT 0 COMMENT '是否是管理员 0否,1是',
remark VARCHAR(100) COMMENT '备注,自我介绍',
state TINYINT NOT NULL DEFAULT 0 COMMENT '状态 0正常,1禁言',
deleteState TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除,0否,1是',
createTime DATETIME NOT NULL COMMENT '创建时间,精确到秒',
updateTime DATETIME NOT NULL COMMENT '更新时间,精确到秒'
);-- ----------------------------
-- 创建版块表 t_board
-- ----------------------------
DROP TABLE IF EXISTS `t_board`;
CREATE TABLE `t_board` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '版块编号,主键,⾃增',
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '版块名,⾮空',
`articleCount` int(11) NOT NULL DEFAULT 0 COMMENT '帖⼦数量,默认0',
`sort` 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;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;-- ----------------------------
-- 创建帖⼦回复表 t_article_reply
-- ----------------------------
DROP TABLE IF EXISTS `t_article_reply`;
CREATE TABLE `t_article_reply` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号,主键,⾃增',
`articleId` bigint(20) NOT NULL COMMENT '关联帖子编号,⾮空',
`postUserId` bigint(20) NOT NULL COMMENT '楼主⽤⼾,关联⽤⼾编号,⾮空',
`replyId` bigint(20) NULL DEFAULT NULL COMMENT '关联回复编号,⽀持楼中楼',
`replyUserId` bigint(20) NULL DEFAULT NULL COMMENT '楼主下的回复⽤⼾编号,支持楼中楼',
`content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '回贴内容,⻓度500个字符,⾮空',
`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;-- ----------------------------
-- 创建站内信表 for t_message
-- ----------------------------
DROP TABLE IF EXISTS `t_message`;
CREATE TABLE `t_message` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '站内信编号,主键,⾃增',
`postUserId` bigint(20) NOT NULL COMMENT '发送者,并联⽤⼾编号',
`receiveUserId` bigint(20) NOT NULL COMMENT '接收者,并联⽤⼾编号',
`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '内容,⾮空,⻓度255个字符',
`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;DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '⽤⼾编号,主键,⾃增',
`username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '⽤⼾名,⾮空,唯⼀',
`password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '加密后的密码',
`nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT
NULL COMMENT '昵称,⾮空',
`phoneNum` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL COMMENT '⼿机号',
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL COMMENT '邮箱地址',
`gender` tinyint(4) NOT NULL DEFAULT 2 COMMENT '0⼥ 1男 2保密,⾮空,默认2',
`salt` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
COMMENT '为密码加盐,⾮空',
`avatarUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci
NULL DEFAULT NULL COMMENT '⽤⼾头像URL,默认系统图⽚',
`articleCount` int(11) NOT NULL DEFAULT 0 COMMENT '发帖数量,⾮空,默认0',
`isAdmin` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否管理员,0否 1是,默认0',
`remark` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL COMMENT '备注,⾃我介绍',
`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,
UNIQUE INDEX `user_username_uindex`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_general_ci COMMENT = '⽤⼾表' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;统一管理版本,在properties标签中加入版本号
<!-- 定义一些全局的参数 -->
<properties>
<!-- JDK的版本号 -->
<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>
<!-- 数据库驱动 -->
<mysql-connector.version>8.0.33</mysql-connector.version>
<!-- Mybatis依赖-->
<mybatis-starter.version>2.3.0</mybatis-starter.version>
<!-- 数据源 -->
<druid-starter.version>1.2.16</druid-starter.version>
<!-- Mybatis generator-->
<mybatis-generator-plugin-version>1.4.1</mybatis-generator-plugin-version>
<!-- springfox -->
<springfox-boot-starter.version>3.0.0</springfox-boot-starter.version>
</properties>
springfox-boot-starter是 Spring 生态中用于集成 Swagger 的工具
添加依赖,在dependencies标签中加入相关依赖
<!-- Mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<!-- Mybatis 依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-starter.version}</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid-starter.version}</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>在spring节点下添加数据源配置项
spring:
application:
name: 论坛系统
# 配置数据源
datasource:
url: jdbc:mysql://127.0.0.1:3306/forum_db?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: jqka
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 58080 #自定义服务器端口
logging:
pattern:
dateformat: MM-dd HH:mm:ss #日期显示格式
level:
root: info #日志默认级别
com.example.forum: debug #指定包下的日志级别
file:
path: D:/JavaCode/log统一管理版本,在properties标签中加入版本号
<!-- Mybatis generator-->
<mybatis-generator-plugin-version>1.4.1</mybatis-generator-plugin-version>在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>驱动包:mysql-connector-java-5.1.49.jar
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 驱动包路径,location中路径替换成自己本地路径 -->
<classPathEntry location="D:\JavaCode\project\forum\forum\mysql-connector-java-5.1.49.jar"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- 禁用自动生成的注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="true"/>
</commentGenerator>
<!-- 连接配置 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/forum_db?characterEncoding=utf8&useSSL=false"
userId="root"
password="jqka">
</jdbcConnection>
<javaTypeResolver>
<!-- 小数统一转为BigDecimal -->
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 实体类生成位置 -->
<javaModelGenerator targetPackage="com.example.forum.model" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- mapper.xml生成位置 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- DAO类生成位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.forum.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 配置生成表与实例, 只需要修改表名tableName, 与对应类名domainObjectName 即可-->
<table tableName="t_article" domainObjectName="Article" enableSelectByExample="false"
enableDeleteByExample="false" enableDeleteByPrimaryKey="false" enableCountByExample="false"
enableUpdateByExample="false">
<!-- 类的属性用数据库中的真实字段名做为属性名, 不指定这个属性会自动转换 _ 为驼峰命名规则-->
<property name="useActualColumnNames" value="true"/>
</table>
<table tableName="t_article_reply" domainObjectName="ArticleReply" enableSelectByExample="false"
enableDeleteByExample="false" enableDeleteByPrimaryKey="false" enableCountByExample="false"
enableUpdateByExample="false">
<property name="useActualColumnNames" value="true"/>
</table>
<table tableName="t_board" domainObjectName="Board" enableSelectByExample="false" enableDeleteByExample="false"
enableDeleteByPrimaryKey="false" enableCountByExample="false" enableUpdateByExample="false">
<property name="useActualColumnNames" value="true"/>
</table>
<table tableName="t_message" domainObjectName="Message" enableSelectByExample="false"
enableDeleteByExample="false" enableDeleteByPrimaryKey="false" enableCountByExample="false"
enableUpdateByExample="false">
<property name="useActualColumnNames" value="true"/>
</table>
<table tableName="t_user" domainObjectName="User" enableSelectByExample="false" enableDeleteByExample="false"
enableDeleteByPrimaryKey="false" enableCountByExample="false" enableUpdateByExample="false">
<property name="useActualColumnNames" value="true"/>
</table>
</context>
</generatorConfiguration>

<!-- useGeneratedKeys = true -->
<!-- keyProperty = 主键字段-->
<!-- 当插⼊⼀条数据后,可以通过user.getId()获取到自动生成的Id值,如果方法中需要立即获取
Id值,加⼊这个配置 -->
<insert id="insert" parameterType="com.example.forum.model.User"
useGeneratedKeys="true" keyProperty="id" >useGeneratedKeys="true":开启 “自动获取数据库生成的主键” 功能(适用于数据库主键自增的场景,如 MySQL 的 AUTO_INCREMENT)。
keyProperty="id":指定将数据库生成的主键值,回填到 User 实体类的 id 属性中(插入后可直接通过 user.getId() 获取自动生成的主键)。
dao包下的每个xxxMapper.java加入@Mapper注解(不加也行)
配置 Mapper 扫描路径(如通过 @MapperScan("com.example.forum.dao"))的核心作用是:告诉框架 “去哪里找数据访问接口(Mapper)”,并自动为这些接口创建实现类
核心功能
@MapperScan 指定路径后,MyBatis 会自动识别该包下的接口为数据访问层(DAO)组件,省去了在每个 Mapper 接口上单独添加 @Mapper 注解的麻烦。
mybatis-spring-boot-starter),实现两者的无缝集成,使得 Mapper 接口可以通过 @Autowired 直接注入到 Service 层使用。
package com.example.forum.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
/**
* 配置mybatis的扫描路径
*/
@Configuration
@MapperScan("com.example.forum.dao")
public class MyBatisConfig {
}application.yml中加入mybatis配置
# mybatis 相关配置,单独配置,顶格写
mybatis:
mapper-locations: classpath:mapper/**/*.xml # 指定 xxxMapper.xml的扫描路径# 查看当前状态,列出未修改后添加的文件
git status
# 添加修改后的文件到暂存区,再次运行git status,上⾯的文件会变为绿色显示
git add .
# 提交到本地仓库
git commit -m '第⼀次提交'
# 推送到远程仓库
git push对执行业务处理逻辑过程中可能出现的成功与失败状态做针对性描述,用枚举定义状态码,先定义一部分,业务中遇到新的问题再添加
package com.example.forum.common;
public enum ResultCode {
/** 定义状态码 */
SUCCESS (0, "成功"),
FAILED (1000, "操作失败"),
FAILED_UNAUTHORIZED (1001, "未授权"),
FAILED_PARAMS_VALIDATE (1002, "参数校验失败"),
FAILED_FORBIDDEN (1003, "禁⽌访问"),
FAILED_CREATE (1004, "新增失败"),
FAILED_NOT_EXISTS (1005, "资源不存在"),
AILED_USER_EXISTS (1101, "用户已存在"),
FAILED_USER_NOT_EXISTS (1102, "用户不存在"),
FAILED_LOGIN (1103, "用户名或密码错误"),
FAILED_USER_BANNED (1104, "您已被禁言, 请联系管理员, 并重新登录."),
FAILED_TWO_PWD_NOT_SAME (1105, "两次输的密码不⼀致"),
ERROR_SERVICES (2000, "服务器内部错误"),
ERROR_IS_NULL (2001, "IS NULL.");
//状态码
int code;
//描述信息
String message;
ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
//使用@Getter也可以
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return "code = " + code + ", message = " + message + ". ";
}
}系统实现前后端分离,统一返回JSON格式的字符串,需要定义一个类,其中包含状态码,描述信息,返回的结果数据
方法签名 | 作用(什么时候用) | 举个实际例子(接口返回) |
|---|---|---|
static AppResult success() | 无数据、无自定义消息:只需要告诉前端 “操作成功”(比如删除数据、修改状态成功) | 前端调用 “删除用户” 接口,返回:{"code":200, "message":"操作成功", "data":null} |
static AppResult success(String message) | 无数据、但要自定义提示(比如 “注销账号成功”,而非默认的 “操作成功”) | 前端调用 “注销账号” 接口,返回:{"code":200, "message":"注销账号成功", "data":null} |
<T> AppResult<T> success(T data) | 有数据、用默认消息:需要返回业务数据(比如查询列表、查询详情) | 前端调用 “查询用户列表” 接口,返回:{"code":200, "message":"操作成功", "data":[{id:1,name:"张三"}]} |
static <T> AppResult<T> success(String message, T data) | 有数据、且自定义提示:既要返回数据,又要个性化提示(比如 “查询我的订单成功”) | 前端调用 “查询我的订单” 接口,返回:{"code":200, "message":"查询我的订单成功", "data":[{orderId:1,price:100}]} |
方法签名 | 作用(什么时候用) | 举个实际例子(接口返回) |
|---|---|---|
static AppResult failed() | 无自定义消息:通用失败(比如服务器未知错误,用默认的 “操作失败”) | 前端调用 “提交订单” 时数据库报错,返回:{"code":500, "message":"操作失败", "data":null} |
static AppResult failed(String message) | 自定义失败提示:需要告诉前端具体失败原因(比如 “手机号已被注册”) | 前端调用 “注册” 时手机号重复,返回:{"code":500, "message":"手机号已被注册", "data":null} |
static AppResult failed(ResultCode resultCode) | 用枚举定义的失败场景:统一管理特定失败(比如参数错误、无权限,避免硬编码状态码) | 前端调用 “查询用户” 时传错参数,返回:{"code":400, "message":"参数错误", "data":null}(对应 ResultCode.PARAM_ERROR) |
ApplicationException 是 项目自定义的 “业务异常类”,专门用于处理 业务逻辑层面的错误(比如 “手机号已注册”“余额不足”“无权限操作” 等),区别于 Java 自带的 “系统异常”(如 NullPointerException 空指针、ArrayIndexOutOfBoundsException 数组越界)。它的核心作用是 “将业务失败信息标准化封装,方便全局统一处理,最终给前端返回一致的错误响应”。
ApplicationException 是业务错误的 “标准化载体”:
使用@ControllerAdvice+@ExceptionHandler注解实现统一异常处理
@ControllerAdvice 会拦截所有标注了 @Controller 或 @RestController 的类中未被手动 try-catch 的异常(即业务代码中向外抛出的异常)。
@ExceptionHandler(异常类型.class),可以按异常类型分流处理:
ApplicationException):返回提前定义的错误信息(如 “用户名已存在”);
NullPointerException):返回兜底提示(如 “服务异常,请稍后再试”)。
解决的核心问题: 全局化、标准化、解耦化
try-catch

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ApplicationException.class)
@ResponseBody
public AppResult applicationExceptionHandler(ApplicationException e) {
e.printStackTrace();
log.error(e.getMessage());
//优先返回异常中携带的标准化错误结果(ErrorResult)
if (e.getErrorResult() != null) {
// 返回异常类中记录的状态
return e.getErrorResult();
}
//非空校验
//若异常无携带结果,校验异常消息是否为空
if (e.getMessage() == null || "".equals(e.getMessage())) {
//返回默认服务错误
return AppResult.failed(ResultCode.ERROR_SERVICES);
}
// 返回具体异常信息
return AppResult.failed(e.getMessage());
}
@ExceptionHandler(Exception.class)
@ResponseBody
public AppResult exceptionHandler(Exception e) {
//打印异常信息
e.printStackTrace();
//打印日志
log.error(e.getMessage());
//非空判断
if (e.getMessage() == null || "".equals(e.getMessage())) {
return AppResult.failed(ResultCode.ERROR_SERVICES);
}
//返回异常信息
return AppResult.failed(e.getMessage());
}
}@GetMapping("/exception")
public String exception() throws Exception {
throw new Exception("抛出exception异常...");
}
@GetMapping("/application")
public String application() {
throw new ApplicationException("抛出applicationException异常...");
}

拦截路径是指我们定义的这个拦截器,对哪些请求生效
我们在注册配置拦截器的时候,通过addPathPatterns()方法指定要拦截哪些请求.也可以通过excludePathPatterns()指定不拦截哪些请求.
上述代码中,我们配置的是/**,表示拦截所有的请求。
比如用户登录校验,我们希望可以对除了登录之外所有的路径生效。
@Configuration
public class AppInterceptorConfigurer implements WebMvcConfigurer {
//注入自定义的登录拦截器
@Resource
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加登录拦截器
registry.addInterceptor(loginInterceptor) // 添加⽤⼾登录拦截器
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/sign-in.html") // 排除登录HTML
.excludePathPatterns("/sign-up.html") // 排除注册HTML
.excludePathPatterns("/user/login") // 排除登录api接⼝
.excludePathPatterns("/user/register") // 排除注册api接⼝
.excludePathPatterns("/user/logout") // 排除退出api接⼝
.excludePathPatterns("/swagger*/**") // 排除登录swagger下所有
.excludePathPatterns("/v3*/**") // 排除登录v3下所有,与 swagger相关
.excludePathPatterns("/dist/**") // 排除所有静态⽂件
.excludePathPatterns("/image/**")
.excludePathPatterns("/**.ico")
.excludePathPatterns("/js/**");
}
}
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Value(("${404Lounge.login.url}"))
private String defaultURL;
/**
*
* 前置处理(对请求的预处理)
* @return true: 继续流程 false:流程终止
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取session对象
HttpSession session = request.getSession();
//判断session是否有效
if(session != null && session.getAttribute(AppConfig.USER_SESSION) != null){
return true;
}
//校验URL是否正确
if(!defaultURL.startsWith("/")) {
defaultURL = "/" + defaultURL;
}
//强制将未登录用户的请求重定向到登录页面
response.sendRedirect(defaultURL);
//中断流程
return false;
}
}Swagger简介:Swagger是一套API定义的规范,按照这套规范的要求去定义接口及接口相关信息,
再通过可以解析这套规范工具,就可以生成各种格式的接口文档,以及在线接口调试页面,通过自动
文档的方式,解决了接口文档更新不及时的问题。
Springfox简介:是对Swagger规范解析并生成文档的一个实现。
Springfox文档:http://springfox.github.io/springfox/docs/snapshot/
统一管理版本,在properties标签中加入版本号
<springfox-boot-starter.version>3.0.0springfox-boot-starter.version> 引入相关依赖
<!-- 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>package com.example.forum.config;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Swagger配置类
*
*/
// 配置类
@Configuration
// 开启Springfox-Swagger
@EnableOpenApi
public class SwaggerConfig {/**
* Springfox-Swagger基本配置
* @return
*/
@Bean
public Docket createApi() {
Docket docket = new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.forum.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
// 配置API基本信息
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfoBuilder()
.title("404客厅API")
.description("404客厅系统前后端分离API测试")
.contact(new Contact("404Lounge",
"http://62.234.142.221:58080/sign-in.html", "435752097@qq.com"))
.version("1.0")
.build();
return apiInfo;
}
/**
* 解决SpringBoot 6.0以上与Swagger 3.0.0 不兼容的问题
* 复制即可
**/
@Bean
public WebMvcEndpointHandlerMapping
webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier,
ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
Collection<ExposableWebEndpoint> webEndpoints =
webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping =
this.shouldRegisterLinksMapping(webEndpointProperties, environment,
basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints,
endpointMediaTypes,
corsProperties.toCorsConfiguration(), new
EndpointLinksResolver(allEndpoints, basePath),
shouldRegisterLinksMapping, null);
}
private boolean shouldRegisterLinksMapping(WebEndpointProperties
webEndpointProperties, Environment environment,
String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() &&
(StringUtils.hasText(basePath)
||
ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}
}在spring节点下添加mvc配置项
由于SpringBoot2.6之后版本把SpringMVC路径匹配策略修改为 MatchingStrategy.PATH_PATTERN_PARSER; 而Springfox-Swagger还没有更新版本,我们暂时先把路径匹配策略回退到之前的 MatchingStrategy.ANT_PATH_MATCHER
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER #Springfox-Swagger兼容性配置
@Api(tags = "测试类相关接口")
@RestController
@RequestMapping("/test")
public class TestController {
@ApiOperation("测试接口1,你好Spring boot")
@GetMapping("/hello")
public String hello() {
return "hello";
}
@ApiOperation("测试接口4,按传入的姓名传入你好信息")
@PostMapping("/helloByName")
public AppResult helloByName(@ApiParam("姓名") @RequestParam("name") String name) {
return AppResult.success("hello " + name);
}
@ApiOperation("测试接口2,显示抛出异常信息")
@GetMapping("/exception")
public String exception() throws Exception {
throw new Exception("抛出exception异常...");
}
@ApiOperation("测试接口3,显示自定义异常信息")
@GetMapping("/application")
public String application() {
throw new ApplicationException("抛出applicationException异常...");
}
}

项目中使用commons-codec,它是Apache提供的用于摘要运算、编码解码的工具包。常见的编码解码工具Base64、MD5、HeX、SHA1、DES等。
pom.xml中导入依赖,SpringBoot已经对这个包做了版本管理,所以这里不用指定版本号
<!-- 编码解码加密工具包-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>密码加密流程:
定义一个原始密码
生成盐值(拢动字符)
原密码进行MD5加密 = 密文1
密文1 + 盐值 = 密文2
对密文2进行MD5加密
public class MD5Util {
//传入原字符串后可以得到一个经过md5加密的密文
/**
* 对字符串进行明文加密
* @param str 明文
* @return 返回密文
*/
public static String md5(String str) {
return DigestUtils.md5Hex(str);
}
/**
* 对用户密码进行加密
* 原始字符串加密后与扰动字符串组合再进⾏⼀次MD5加密
* @param str 密码明文
* @param salt 扰动字符 盐值
* @return 返回密文
*/
public static String md5Salt(String str, String salt) {
return md5(md5(str) + salt);
}
}String salt = UUIDUtil.UUID_32();
String ciphertext = MD5Util.md5Salt(password, salt);UUID(Universally Unique Identifier)是一种 “全球唯一” 的字符串标识(基于时间戳、机器 MAC 地址、随机数等信息生成),几乎不会出现重复。
package com.example.forum.utils;
import java.util.UUID;
public class UUIDUtil {
/**
* 标准的UUID
* @return
*/
public static String UUID_36() {
return UUID.randomUUID().toString();
}
/**
* 生成一个32位的 UUID 去掉 4 个 -
* @return
*/
public static String UUID_32() {
return UUID.randomUUID().toString().replace("-", "");
}
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
username | 用户名 | String | 必须 | |
nickname | 昵称 | String | 与用户名相同 | 必须 |
password | 密码 | String | 必须 | |
passwordRepeat | 确认密码 | String | 必须,与密码相同 |
// 请求
POST /user/register HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=user222&nickname=user222&password=123456&passwordRepeat=123456
// 响应
HTTP/1.1 200
Content-Type: application/json
{"code":0,"message":"成功","data":null}
添加API注解和校验注解
参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
username | 用户名 | String | 必须 | |
password | 密码 | String | 必须 |
// 请求
POST /user/login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=bitboy&password=123456
// 响应
HTTP/1.1 200
Content-Type: application/json
{"code":0,"message":"成功","data":null}设置session的意义:
参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 用户 Id | long | 可以为空 |
// 请求
GET /user/info HTTP/1.1
GET /user/info?id=1 HTTP/1.1
// 响应
HTTP/1.1 200
Content-type: application/json
//具体的User对象
{
"code": 0,
"message": "成功",
"data": {
"id": 25,
"username": "user223",
"nickname": "user223",
"phoneNum": null,
"email": null,
"gender": 1,
"avatarUrl": null,
"articleCount": 0,
"isAdmin": 0,
"state": 0,
"createTime": "2025-09-08 15:06:10",
"updateTime": "2025-09-08 15:06:10"
}
}
修复返回值存在的缺陷

修改日期格式为yyyy-MM-dd HH:mm:ss,在application.yml中添加配置
jackson:
date-format: yyyy-MM-dd HH:mm:ss # 日期格式
default-property-inclusion: NON_NULL # 不为null时序列化无参数要求
实现逻辑
用户访问退出接口
服务器注销Session
返回成功或失败
如果返回成功浏览器跳转到相应页面
结束
退出后跳转到前端登陆界面
// 请求
GET http://127.0.0.1:58080/user/logout HTTP/1.1
// 响应
HTTP/1.1 200
Content-Type: application/json
{"code":0,"message":"成功","data":null}在Contrller中实现销毁Session就完成了用户退出功能,不需要编写Service层代码
LoginInterceptor,重写preHandle方法 true: 继续流程 false:流程终止
修改application.yml配置文件,添加跳转页面
CodeOnHub:
login:
url: sign-in.html # 未登录状况下强制跳转页面AppInterceptorConfigurer 拦截路径
在首页显示的版块信息,可以通过以下两种方式解决
方法一:单独提供查询前N条记录的接口,用来控制首页中版块的个数
方法二:通过配置表中state字段来实现,提供查询所有版块的接口
两种方式任选一个都可以,项目中使用方法一
无参数要求
实现逻辑:
请求 URL:http://127.0.0.1:58080/board/topList
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": [
{
"id": 1,
"name": "Java",
"articleCount": 5,
"sort": 1,
"state": 0,
"createTime": "2023-01-14 11:02:18",
"updateTime": "2023-01-14 11:02:18"
},
{
"id": 2,
"name": "C++",
"articleCount": 1,
"sort": 2,
"state": 0,
"createTime": "2023-01-14 11:02:41",
"updateTime": "2023-01-14 11:02:41"
}
]
}在Mapper.xml中编写SQL语句 BoardExtMapper.xml
SELECT * FROM t_board WHERE state = 0 AND deleteState = 0 ORDER BY sort ASC LIMIT 0,9# 项目自定义相关配置
CodeOnHub:
login:
url: sign-in.html # 未登录状况下强制跳转页面
index: # 首页配置节点
board-num: 9 # 首页中显示的版块个数在Mapper.java中定义方法
List<Board> selectByNum(@Param("num") Integer num);定义Service接口
实现Service接口
单元测试
Controller实现方法并对外提供API接口

测试API接口
实现前端逻辑,完成前后端交互
参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 版块 Id | long | 必须 |
请求方式:GET
请求 URL:http://127.0.0.1:58080/board/getById
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": {
"id": 1,
"name": "Java",
"articleCount": 5,
"sort": 1,
"state": 0,
"createTime": "2025-01-14 11:02:18",
"updateTime": "2025-01-14 11:02:18"
}
}
参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
boardId | 版块 Id | long | 必须 | |
title | 文章标题 | String | 必须 | |
content | 帖子内容 | String | 必须 |
// 请求
POST http://127.0.0.1:58080/article/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
boardId=1&title=% E6% B5%8B% E8% AF%95% E6%96% B0% E5% B8%96% E5% AD%90% E6% A0%87% E9% A2%98&content=% E6% B5%8B% E8% AF%95% E6%96% B0% E5% B8%96% E5% AD%90% E5%86%85% E5% AE% B9
// 响应
HTTP/1.1 200
Content-Type: application/json
{"code":0,"message":"成功","data":null}对应版块中显示的帖子列表以发布时间降序排列,不传入版块Id返回所有帖子

参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
boardId | 版块 Id | Long | 可为空 |
// 请求
// 返回指定版块下的帖子列表
GET http://127.0.0.1:58080/article/getAllByBoardId?boardId=1 HTTP/1.1
// 返回所有的帖子列表
GET http://127.0.0.1:58080/article/getAllByBoardId HTTP/1.1
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": [
{
"id": 17,
"boardId": 1,
"userId": 1,
"title": "测试删除",
"visitCount": 8,
"replyCount": 1,
"likeCount": 1,
"state": 0,
"createTime": "2025-07-05 04:10:46",
"updateTime": "2025-07-05 11:22:43",
"board": {
"id": 1,
"name": "Java"
},
"user": {
"id": 1,
"nickname": "bitboy",
"phoneNum": null,
"email": null,
"gender": 1,
"avatarUrl": null
},
"own": false
}

多表关联查询
关联用户表(t_user)和文章表(t_article),主要是为了在查询帖子列表时,同时获取发布该帖子的用户信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.forum.dao.ArticleMapper">
<!-- 自定义结果集映射-->
<resultMap id="AllInfoResultMap" type="com.example.forum.model.Article" extends="ResultMapWithBLOBs">
<!--关联的用户的映射-->
<association property="user" resultMap="com.example.forum.dao.UserMapper.BaseResultMap"
columnPrefix="u_"/>
<!-- 关联版块的映射 -->
<association property="board" resultMap="com.example.forum.dao.BoardMapper.BaseResultMap"
columnPrefix="b_" />
</resultMap>
<!-- 查询所有未被删除的帖子列表,不包含content-->
<select id="selectAll" resultMap="AllInfoResultMap">
select
u.id as u_id,
u.avatarUrl as u_avatarUrl,
u.nickname as u_nickname,
a.id,
a.boardId,
a.userId,
a.title,
a.visitCount,
a.replyCount,
a.likeCount,
a.state,
a.createTime,
a.updateTime
from t_article a, t_user u
where a.userId = u.id
and a.deleteState = 0
order by a.createTime DESC;
</select>
<!-- 根据板块Id查询所有未被删除的帖子列表,不包含content-->
<select id="selectAllByBoardId" resultMap="AllInfoResultMap" parameterType="java.lang.Long">
select
u.id as u_id,
u.avatarUrl as u_avatarUrl,
u.nickname as u_nickname,
a.id,
a.boardId,
a.userId,
a.title,
a.visitCount,
a.replyCount,
a.likeCount,
a.state,
a.createTime,
a.updateTime
from t_article a, t_user u
where a.userId = u.id
and a.deleteState = 0
and a.boardId = #{boardId,jdbcType=BIGINT}
order by a.createTime DESC;
</select>
<select id="selectDetailById" resultMap="AllInfoResultMap" parameterType="java.lang.Long">
select
u.id as u_id,
u.avatarUrl as u_avatarUrl,
u.nickname as u_nickname,
u.gender as u_gender,
u.isAdmin as u_isAdmin,
u.state as u_state,
u.deleteState as u_deleteState,
b.id as b_id,
b.name as b_name,
b.state as b_state,
b.deleteState as b_deleteState,
a.id,
a.boardId,
a.userId,
a.title,
a.content,
a.visitCount,
a.replyCount,
a.likeCount,
a.state,
a.createTime,
a.updateTime
from
t_article a, t_user u, t_board b
where
a.userId = u.id
and
a.boardId = b.id
and a.deleteState = 0
and a.id = #{id,jdbcType=BIGINT}
</select>
</mapper>
<mapper namespace="com.example.forum.dao.ArticleMapper">namespace:指定该 XML 映射文件对应的 Mapper 接口全路径(ArticleMapper.java)。
namespace 关联接口与 XML,确保接口中的方法能找到对应的 SQL 语句。
<resultMap id="AllInfoResultMap"
type="com.example.forum.model.Article" extends="ResultMapWithBLOBs"><resultMap> 标签(自定义结果集映射)
id="AllInfoResultMap":当前结果集映射的唯一标识,供 <select> 等标签的 resultMap 属性引用。
type="com.example.forum.model.Article":指定该结果集映射对应的实体类(将查询结果封装为 Article 对象)。
extends="ResultMapWithBLOBs":继承另一个结果集映射(ResultMapWithBLOBs,通常包含文章内容等大字段的映射),避免重复定义公共字段。
子标签 <association>(关联对象映射)
<!--关联的用户的映射-->
<association property="user"
resultMap="com.example.forum.dao.UserMapper.BaseResultMap" columnPrefix="u_"/>property="user": 目标实体类中的属性名,指定 Article 类中存储用户信息的属性名。
resultMap="...":关联的用户结果集映射, 复用 UserMapper 中定义的 BaseResultMap(用户信息的字段映射规则)。
columnPrefix="u_":查询结果中用户相关字段的前缀(如 u_id、u_nickname),MyBatis 会自动去掉前缀并匹配 User 类的属性(如 u_id → id,u_nickname → nickname)。
<!-- 关联版块的映射 -->
<association property="board"
resultMap="com.example.forum.dao.BoardMapper.BaseResultMap" columnPrefix="b_"/>作用与用户关联类似,将查询结果中以 b_ 为前缀的字段(如 b_id、b_name)映射到 Article 类的 board 属性(private Board board;)。
关联用户的映射

将 u_ 前缀的字段通过 UserMapper 的 BaseResultMap 映射到 article的user 中进行多表关联查询,让数据库的关联数据与 Java 的对象关系自动对应
将带 u_ 前缀的用户字段映射到 Article 的 user 属性(即 User 对象)。

这种 MyBatis 结果集映射(尤其是通过 <association> 关联映射)的核心目的是 “自动将数据库中的关联数据转换为 Java 中的对象关系,简化开发并保证数据一致性”
查询用户的帖子列表,这是两个表
参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 帖子 Id | long | 必须 |
请求方式:GET
请求 URL:http://127.0.0.1:58080/article/getById
{
"code": 0,
"message": "成功",
"data": {
"id": 1,
"boardId": 1,
"userId": 1,
"title": "单元测试",
"visitCount": 14,
"replyCount": 2,
"likeCount": 3,
"state": 0,
"createTime": "2025-07-02 06:46:32",
"updateTime": "2025-07-05 10:16:43",
"content": "测试内容",
"board": {
"id": 1,
"name": "Java"
},
"user": {
"id": 1,
"nickname": "bitboy",
"phoneNum": null,
"email": null,
"gender": 1,
"avatarUrl": null
},
"own": true
}
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 帖子 Id | Long | 必须 | |
title | 文章标题 | String | 必须 | |
content | 帖子内容 | String | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/article/modify
请求头:Content-Type: application/x-www-form-urlencoded
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": null
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 帖子 Id | long | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/article/thumbsUp
请求头:Content-Type: application/x-www-form-urlencoded
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": null
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 帖子 Id | long | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/article/delete
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": null
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
articleId | 帖子 Id | Long | 必须 | |
content | 回复内容 | String | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/reply/create
请求头:Content-Type: application/x-www-form-urlencoded
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": null
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
articleId | 帖子 Id | Long | 必须 |
请求方式:GET
请求 URL:http://127.0.0.1:58080/reply/getReplies
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": [
{
"id": 9,
"articleId": 1,
"postUserId": 2,
"content": "回复没试",
"likeCount": 0,
"state": 0,
"createTime": "2023-07-09 06:39:45",
"updateTime": "2023-07-09 06:39:45",
"user": {
"id": 2,
"nickname": "bitgirl",
"phoneNum": null,
"email": null,
"gender": 2,
"avatarUrl": null
}
}
]
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
receiveUserId | 接收用户 Id | Long | 必须 | |
content | 站内信内容 | String | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/message/send
请求头:Content-Type: application/x-www-form-urlencoded
{
"code": 0,
"message": "成功",
"data": null
}无
请求方式:GET
请求 URL:http://127.0.0.1.41:58080/message/getUnreadCount
响应状态码:200
Content-Type:application/json
{"code":0,"message":"成功","data":1}无
请求方式:GET
请求 URL:http://127.0.0.1:58080/message/getAll
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": [
{
"id": 11,
"postUserId": 32,
"receiveUserId": 3,
"content": "真的可以发出去吗\n",
"state": 2,
"createTime": "2023-06-20 11:21:09",
"updateTime": "2023-06-25 11:24:38",
"postUser": {
"id": 32,
"nickname": "ljl",
"phoneNum": null,
"email": null,
"gender": 2,
"avatarUrl": null
}
},
{
"id": 10,
// 其余消息数据(因截图未完全展示,此处省略)
}
]
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
id | 站内信 Id | long | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/message/markRead
请求头:Content-Type: application/x-www-form-urlencoded
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": null
}参数名 | 描述 | 类型 | 默认值 | 条件 |
|---|---|---|---|---|
repliedId | 站内信 Id | Long | 必须 | |
content | 内容 | String | 必须 |
请求方式:POST
请求 URL:http://127.0.0.1:58080/message/reply
请求头:Content-Type: application/x-www-form-urlencoded
响应状态码:200
Content-Type:application/json
{
"code": 0,
"message": "成功",
"data": null
}