基于 Spring Boot 3.5 + Spring Security + JWT + MyBatis Plus 的商城后端管理系统,实现了完整的用户认证授权、RBAC 权限管理功能。
- id: 用户ID(主键,自增)
- username: 用户名(唯一)
- password: 密码(BCrypt 加密)
- email: 邮箱
- status: 状态(1=启用,0=禁用)
- created_at: 创建时间
- updated_at: 更新时间
- role_id: 角色ID(主键,自增)
- role_name: 角色名称
- role_code: 角色代码(ADMIN/EDITOR/USER)
- description: 描述
- status: 状态
- create_at: 创建时间
- update_at: 更新时间
- permission_id: 权限ID(主键,自增)
- permission_name: 权限名称
- permission_code: 权限代码(如:product:view)
- resource: 资源类型
- action: 操作类型
- description: 描述
- id: 主键
- user_id: 用户ID(外键)
- role_id: 角色ID(外键)
- create_at: 创建时间
- id: 主键
- role_id: 角色ID(外键)
- permission_id: 权限ID(外键)
product_reviews(商品评价表,见 product_schema.sql)
- id: 主键
- product_id: 商品ID(外键)
- user_id: 用户ID
- order_item_id: 订单项ID(可选)
- rating: 评分 1-5
- content: 评价内容
- images: 图片 JSON
- reply: 商家回复内容
- status: 1=显示, 0=隐藏
- created_at: 创建时间
review_replies(评价回复表)
- id: 主键
- review_id: 评价ID(外键)
- user_id: 用户ID
- content: 回复内容
- created_at: 创建时间
review_likes(评价点赞表)
- id: 主键
- review_id: 评价ID(外键)
- user_id: 用户ID
- created_at: 创建时间
- 唯一约束: (review_id, user_id)
review_reports(评价举报表)
- id: 主键
- review_id: 评价ID(外键)
- user_id: 用户ID
- reason: 举报原因
- status: 0=待处理, 1=已处理, 2=已驳回
- created_at: 创建时间
addresses(地址表)
- id: 主键
- user_id: 用户ID(外键)
- receiver_name: 收件人姓名
- phone: 联系电话
- province, city, district, detail: 地址字段
- is_default: 是否默认(0/1)
- created_at, updated_at: 时间戳
cart(购物车表)
- id: 主键
- user_id: 用户ID(外键)
- product_id: 商品ID(外键)
- quantity: 商品数量
- selected: 是否选中用于下单(0/1)
- created_at, updated_at: 时间戳
orders(订单表)
- id: 主键
- order_no: 订单号(唯一)
- user_id: 用户ID(外键)
- address_id: 收货地址ID
- total_amount: 订单总金额
- status: 订单状态(PENDING_PAYMENT/PAID/SHIPPED/COMPLETED/CANCELLED)
- payment_status: 支付状态(UNPAID/PAID/CANCELLED)
- remark: 备注
- created_at, updated_at: 时间戳
order_items(订单明细表)
- id: 主键
- order_id: 订单ID(外键)
- product_id: 商品ID
- product_name: 商品名称(冗余)
- sku_info: 规格信息
- price: 单价
- quantity: 数量
- total_amount: 小计金额
payments(支付记录)
- id: 主键
- order_id: 订单ID(外键)
- amount: 支付金额
- method: 支付方式
- status: 支付状态(PENDING/SUCCESS/FAILED)
- transaction_id: 第三方交易号
- paid_at: 支付时间
order_status_history(订单状态历史)
- id: 主键
- order_id: 订单ID(外键)
- status: 状态
- remark: 备注
- created_at: 时间戳
payments(支付记录表,见 payment_schema.sql)
- id: 主键
- order_id: 订单ID(外键)
- user_id: 用户ID(外键)
- payment_method: 支付方式(alipay/wechat/bank_card)
- payment_amount: 支付金额
- payment_status: 支付状态(pending/success/failed/refunded)
- transaction_id: 第三方交易ID
- payment_time: 支付时间
- refund_amount: 退款金额
- refund_time: 退款时间
- refund_reason: 退款原因
- callback_data: 回调数据(JSON)
- created_at: 创建时间
- updated_at: 更新时间
| 角色 | 角色代码 | 权限 |
|---|---|---|
| 系统管理员 | ADMIN | 所有权限(编辑报表、编辑商品、查看报表、查看商品、删除商品) |
| 编辑 | EDITOR | 查看、编辑商品和报表权限 |
| 普通用户 | USER | 查看商品和报表权限 |
# 1. 创建数据库
CREATE DATABASE shop DEFAULT CHARACTER SET utf8mb4;
# 2. 执行初始化脚本
mysql -u root -p shop < sql/rbac_init.sql
# 3. 若使用商品与评论模块,再执行(需先有 products、users 等表)
mysql -u root -p shop < sql/product_schema.sql
mysql -u root -p shop < sql/review_schema.sql
# 4. 若使用支付模块,再执行
mysql -u root -p shop < sql/payment_schema.sql
编辑 src/main/resources/application.properties:
spring.datasource.username=your_username spring.datasource.password=your_password
spring.data.redis.host=localhost spring.data.redis.port=6379 spring.data.redis.password=
jwt.secret=your-secret-key-change-this-in-production-environment-minimum-256-bits jwt.access-token-expiration=7200 jwt.refresh-token-expiration=604800
server.port=8080
### 4. 运行项目
```bash
# 使用 Maven 运行
mvn spring-boot:run
# 或打包后运行
mvn clean package
java -jar target/demo1-0.0.1-SNAPSHOT.jar
http://localhost:8080application/jsonBearer {token} (登录后需要)POST /user/registerUser
Content-Type: application/json
{
"username": "test",
"password": "123456"
}
响应示例:
{
"code": 200,
"msg": "注册成功",
"data": null
}
POST /auth/login
Content-Type: application/json
{
"username": "test",
"password": "123456"
}
响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1,
"username": "test",
"token": "eyJhbGciOiJIUzI1NiJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"loginTime": "2026-01-25"
}
}
当 Access Token 过期时,可以使用 Refresh Token 换取新的 Access Token,Refresh Token 的有效期默认为 7 天(可通过 jwt.refresh-token-expiration 配置调整)。
POST /auth/refresh
Content-Type: application/x-www-form-urlencoded
refreshToken=<refreshToken>
响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 7200
}
}
注意:刷新接口允许匿名访问(/auth/refresh 已加入安全白名单),但 refresh token 本身必须有效且与服务器在 Redis 中保存的值匹配。
GET /auth/logout
Authorization: Bearer {token}
响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"message": "登出成功",
"logoutTime": "2026-01-25"
}
}
GET /auth/profile
Authorization: Bearer {token}
响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1,
"name": "test",
"email": "test@example.com",
"status": 1,
"nowTime": "2026-01-25"
}
}
POST /user/update
Authorization: Bearer {token}
Content-Type: application/json
{
"email": "newemail@example.com"
}
POST /user/changePassword
Authorization: Bearer {token}
Content-Type: application/json
{
"oldPassword": "123456",
"newPassword": "654321"
}
GET /user/permissions
Authorization: Bearer {token}
响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"userId": 1,
"username": "test",
"email": null,
"roles": [
{
"roleId": 2,
"roleName": "普通用户",
"roleCode": "USER",
"description": "普通用户",
"status": 1
}
],
"permissions": [
{
"permissionId": 1,
"permissionName": "查看商品",
"permissionCode": "product:view",
"resource": "product",
"action": "view",
"description": "查看商品权限"
},
{
"permissionId": 4,
"permissionName": "查看报表",
"permissionCode": "report:view",
"resource": "report",
"action": "view",
"description": "查看报表权限"
}
]
}
}
GET /user/roles
Authorization: Bearer {token}
GET /user/permissions/list
Authorization: Bearer {token}
商品模块提供标准的 CRUD 接口,支持分页查询与模糊搜索。
Base URL: http://localhost:8080
请求头(通用):
Content-Type: application/json(POST/PUT)Authorization: Bearer {token}(需要鉴权的接口)POST /product
Headers: Authorization: Bearer {token}
Body (JSON):
{
"categoryId": 1,
"sku": "PHN-0001",
"name": "示例手机 A1",
"subtitle": "全面屏 / 128GB",
"description": "示例手机 A1,性能均衡。",
"price": 1999.00,
"originalPrice": 2499.00,
"stock": 120,
"status": 1,
"isFeatured": 1,
"coverUrl": "https://example.com/images/phone_a1.jpg",
"weight": 0.18
}
必填字段:name, categoryId, price, stock。
写操作权限:需要 EDITOR 或 ADMIN 角色(后端根据 RBAC 检查 product:create/product:edit 权限)。
示例 curl:
curl -X POST "http://localhost:8080/product" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"categoryId":1,"sku":"PHN-0001","name":"示例手机 A1","price":1999.00,"stock":120}'
成功响应示例:
{
"code":200,
"msg":"操作成功",
"data":{
"id":101,
"name":"示例手机 A1"
}
}
GET /product/{id}
Path param: id (Long)
Headers: Authorization: Bearer {token}
GET /product?page=1&size=10&name=手机
Headers: Authorization: Bearer {token}
Query params:
- page: integer, 默认 1
- size: integer, 默认 10
- name: string, 可选,按 name 模糊匹配
PATCH /product/{id}
Headers: Authorization: Bearer {token}
Body: 与创建接口相同的 JSON 结构,但只需要包含要修改的字段(只会合并非 null 字段)
示例:只修改价格和库存
{
"price": 1899.00,
"stock": 100
}
说明:
PATCH /product/{id},后端可能同时支持 PATCH /product?id={id} 或在请求体中包含 id(兼容性由后端决定)。EDITOR 或 ADMIN 角色;查看需要登录(USER 及以上)。DELETE /product/{id}
Headers: Authorization: Bearer {token}
PATCH /product/{id}/status?status=1
Headers: Authorization: Bearer {token}
Query params:
- status: integer, 必选,`1`=上架,`0`=下架
说明:写操作需要 EDITOR 或 ADMIN 角色。示例:把 id=101 的商品下架
curl -X PATCH "http://localhost:8080/product/101/status?status=0" \
-H "Authorization: Bearer ${TOKEN}"
成功响应示例:
{
"code":200,
"msg":"设置成功",
"data":null
}
评论模块提供商品评价的发布、查询、回复、点赞、举报及按评分/时间筛选。
Base URL: http://localhost:8080
请求头(通用):
Content-Type: application/json(POST/PUT)Authorization: Bearer {token}(发布、回复、点赞、举报、商家回复等需登录)POST /review
Headers: Authorization: Bearer {token}
Body (JSON):
{
"productId": 1,
"rating": 5,
"content": "非常不错,性价比高。",
"images": "[\"https://example.com/1.jpg\"]"
}
必填字段:productId。rating 为 1–5,默认 5;content、images 可选。
成功响应:返回完整评价对象(含 id、点赞数、回复列表等)。
GET /review/product/{productId}?page=1&size=10&rating=5&sortBy=time_desc
Query 参数:
page: 页码,默认 1size: 每页条数,默认 10rating: 可选,1–5,仅返回该评分的评价sortBy: 可选,time_desc(默认)| time_asc | rating_desc | rating_asc无需登录。响应为分页结果,每条包含评价信息、回复列表、点赞数、当前用户是否已点赞(未登录为 false)。
GET /review/{reviewId}
返回单条评价详情(含回复列表、点赞数、当前用户是否已点赞)。无需登录。
POST /review/reply
Headers: Authorization: Bearer {token}
Body (JSON):
{
"reviewId": 1,
"content": "同意,确实很划算。"
}
必填:reviewId、content。成功返回 "回复成功"。
PUT /review/{reviewId}/seller-reply
Headers: Authorization: Bearer {token}
Body (JSON):
{
"content": "感谢您的支持,欢迎再次购买。"
}
将内容写入该评价的 reply 字段。成功返回 "回复成功"。
POST /review/{reviewId}/like
Headers: Authorization: Bearer {token}
同一用户对同一评价再次请求即取消点赞。响应 data 为 true 表示当前为已点赞状态,false 表示已取消。
POST /review/report
Headers: Authorization: Bearer {token}
Body (JSON):
{
"reviewId": 1,
"reason": "不当言论"
}
必填:reviewId;reason 可选。成功返回 "举报已提交"。
对外提供多级分类管理接口,支持树形查询与 CRUD(写操作需要鉴权)。
POST /categories
Headers: Authorization: Bearer {token}
Body (JSON):
{
"parentId": 1, // 可选,顶级分类可为空
"name": "手机",
"slug": "electronics-phones",
"description": "手机分类",
"sortOrder": 1,
"status": 1
}
必填字段:name。
写操作权限:只有 EDITOR 或 ADMIN 可创建/更新/删除分类(后端通过 role/permission 控制)。
重要约束:
slug 应保持在同一层级唯一(后端应做唯一性检查)。示例 curl:
curl -X POST "http://localhost:8080/categories" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"parentId":0,"name":"电子产品","slug":"electronics","sortOrder":1}'
GET /categories/{id}
Headers: Authorization: Bearer {token}
PATCH /categories/{id}
Headers: Authorization: Bearer {token}
Body: 只包含需要修改的字段,例如:
{
"name": "手机及配件",
"sortOrder": 2
}
DELETE /categories/{id}
Headers: Authorization: Bearer {token}
GET /categories/tree
Headers: Authorization: Bearer {token}
GET /categories?parentId=1
Headers: Authorization: Bearer {token}
说明:返回的分类对象包含 children 字段(数组)表示下级分类。
示例响应片段:
{
"code":200,
"msg":"操作成功",
"data":[
{
"id":1,
"name":"电子产品",
"children":[
{"id":2,"name":"手机"},
{"id":3,"name":"笔记本"}
]
}
]
}
下面列出项目中已实现的购物车、地址与订单相关接口、请求示例与说明。
注意:需要登录的接口请在请求头中带上
Authorization: Bearer {token}。
POST /cart/add
Content-Type: application/json
Authorization: Bearer {token}
{
"productId": 1,
"quantity": 2
}
POST /cart/update
Content-Type: application/json
Authorization: Bearer {token}
{
"id": 10,
"quantity": 3
}
DELETE /cart/{id}
Authorization: Bearer {token}
GET /cart/list
Authorization: Bearer {token}
POST /address/add
Content-Type: application/json
Authorization: Bearer {token}
{
"receiverName": "张三",
"phone": "13800000000",
"province": "广东省",
"city": "深圳市",
"district": "南山区",
"detail": "科技园路100号",
"isDefault": 1
}
POST /address/update
Content-Type: application/json
Authorization: Bearer {token}
{
"id": 1,
"receiverName": "张三",
"phone": "13800000000",
"province": "广东省",
"city": "深圳市",
"district": "南山区",
"detail": "科技园路101号",
"isDefault": 1
}
DELETE /address/{id}
Authorization: Bearer {token}
GET /address/list
Authorization: Bearer {token}
当添加或更新地址并设置 isDefault=1 时,系统会将该用户其它地址设为非默认。
支持从购物车下单或直接传入商品项下单,支持分页查询、订单详情、状态流转和统计。
POST /order/create
Content-Type: application/json
Authorization: Bearer {token}
{
"items": [ { "productId": 1, "quantity": 2 } ], // 可选,若为空则使用购物车 selected=1 的项
"addressId": 1,
"remark": "请尽快发货"
}
返回:创建的 Order 实体(包含 orderNo, totalAmount, status 等)。
GET /order/list?pageNum=1&pageSize=10&status=PAID
Authorization: Bearer {token}
Order 实体)GET /order/{id}
Authorization: Bearer {token}
POST /order/{id}/pay // 标记为已支付
POST /order/{id}/ship // 标记为已发货
POST /order/{id}/complete // 标记为已完成
POST /order/{id}/cancel // 取消订单
GET /order/stats
Authorization: Bearer {token}
返回当前用户各状态订单数量(PENDING_PAYMENT、PAID、SHIPPED、COMPLETED、CANCELLED)。