Skip to content

About

SpringBoot 3 + Vue3 前后端分离项目模版,已实现登录注册,限流等功能,可直接上手编写业务

Resources

Code of conduct

Stars

374 stars

Watchers

6 watching

Forks

Latest commit

 

History

12 Commits

Folders and files

Repository files navigation

前后端分离项目(JWT方案)

采用SpringBoot3 + Vue3编写的前后端分离模版项目,集成多种技术栈,使用JWT校验方案。


后端功能与技术点

用户注册、用户登录、重置密码等基础功能以及对应接口

  • 采用Mybatis-Plus作为持久层框架,使用更便捷
  • 采用Redis存储注册/重置操作验证码,带过期时间控制
  • 采用RabbitMQ积压邮件发送任务,再由监听器统一处理
  • 采用SpringSecurity作为权限校验框架,手动整合Jwt校验方案
  • 采用Redis进行IP地址限流处理,防刷接口
  • 视图层对象和数据层对象分离,编写工具方法利用反射快速互相转换
  • 错误和异常页面统一采用JSON格式返回,前端处理响应更统一
  • 手动处理跨域,采用过滤器实现
  • 使用Swagger作为接口文档自动生成,已自动配置登录相关接口
  • 采用过滤器实现对所有请求自动生成雪花ID方便线上定位问题
  • 针对于多环境进行处理,开发环境和生产环境采用不同的配置
  • 日志中包含单次请求完整信息以及对应的雪花ID,支持文件记录
  • 项目整体结构清晰,职责明确,注释全面,开箱即用

前端功能与技术点

用户注册、用户登录、重置密码等界面,以及一个简易的主页

  • 采用Vue-Router作为路由
  • 采用Axios作为异步请求框架
  • 采用Element-Plus作为UI组件库
  • 使用VueUse适配深色模式切换
  • 使用unplugin-auto-import按需引入,减少打包后体积

二次开发指引

1. 项目结构

.
├── database.sql                       # 数据库初始化脚本
├── my-project-backend                 # Spring Boot 后端
│   ├── pom.xml                        # 依赖、Maven 环境与资源过滤配置
│   └── src/main
│       ├── java/com/example
│       │   ├── config                 # Security、Swagger、消息队列等配置
│       │   ├── controller             # 接口入口,exception 包处理异常响应
│       │   ├── entity
│       │   │   ├── dto                # 数据库实体
│       │   │   └── vo                 # request 请求对象、response 响应对象
│       │   ├── filter                 # JWT 校验、跨域、限流与请求日志
│       │   ├── listener               # 邮件队列消费者
│       │   ├── mapper                 # MyBatis-Plus 数据访问接口
│       │   ├── service                # 业务接口及 impl 实现
│       │   └── utils                  # JWT、限流、常量等公共工具
│       └── resources                  # 多环境配置与日志配置
└── my-project-frontend                # Vue 前端
    ├── vite.config.js                 # 构建、路径别名与 Element Plus 按需引入
    └── src
        ├── main.js                    # 应用入口与后端请求地址
        ├── net/index.js               # 请求封装、登录与令牌管理
        ├── router/index.js            # 页面路由与登录守卫
        └── views                      # 页面,welcome 目录存放登录、注册等页面

2. 开发环境与本地启动

依赖 说明
JDK 17,与后端 pom.xml 中的 Java 版本保持一致
Maven 3.6.3 或更高版本
Node.js / npm 建议使用 Node.js 22 LTS,通过 npm 安装前端依赖
MySQL 8.x,初始化脚本使用 utf8mb4_0900_ai_ci 排序规则
Redis 用于验证码、JWT 黑名单和请求限流
RabbitMQ 用于异步发送验证码邮件
SMTP 邮箱 开启 SMTP 服务,准备发件地址和授权码

先创建二开项目使用的 MySQL 数据库,再向该库导入根目录的 database.sql。默认配置连接名为 test 的数据库。脚本会删除并重建 db_account 表,适合在新建的开发库中导入;初始化后没有预设账号,可通过注册页面创建用户。

启动 MySQL、Redis 和 RabbitMQ,按本地环境修改 application-dev.yml:

配置项 修改内容
spring.datasource 数据库地址、库名、用户名和密码
spring.data.redis 当前文件未显式配置,默认连接 localhost:6379、数据库 0;使用其他实例或密码时补充此配置
spring.rabbitmq RabbitMQ 地址、账号、密码和 virtual host,账号需要有对应 virtual host 的权限
spring.mail SMTP 地址、发件邮箱和授权码,端口、认证及 SSL/TLS 参数按邮箱服务商要求配置
spring.security.jwt 项目自己的签名密钥、令牌有效期与登录频率限制,其中 expire 单位为小时
spring.web.cors 允许访问后端的前端来源、请求方法及是否携带凭证
spring.web.verify / spring.web.flow 验证邮件发送间隔和请求限流参数,时间单位为秒

后端默认使用 dev Maven profile,在项目根目录执行:

cd my-project-backend
mvn spring-boot:run -Pdev

后端开发环境默认监听 8080 端口,接口文档地址为 http://localhost:8080/swagger-ui/index.html,OpenAPI JSON 地址为 http://localhost:8080/v3/api-docs。

前端请求地址在 src/main.js 的 axios.defaults.baseURL 中配置,当前为 http://localhost:8080,后端地址变化时同步修改。在另一个终端从项目根目录执行:

cd my-project-frontend
npm install
npm run dev

打开 Vite 输出的本地地址,默认是 http://localhost:5173。当前前端直接请求后端地址,vite.config.js 未配置接口代理。

3. 新增后端业务接口

新增模块可以参考 Account、AccountMapper、AccountService 和 AccountServiceImpl 的组织方式:

  1. 在数据库中建立业务表,在 entity/dto 中添加对应实体,通过 @TableName、@TableId 声明表名与主键。
  2. 在 mapper 中添加带 @Mapper 的接口并继承 BaseMapper<实体>,在 service 和 service/impl 中实现业务逻辑,复用 MyBatis-Plus 的查询、保存和更新能力。
  3. 在 entity/vo/request 中定义请求对象,使用 Jakarta Validation 注解并在 Controller 参数上添加 @Valid;数据库实体与对外响应对象分别定义。
  4. 在 controller 中添加 /api/业务名 接口,统一使用 RestBean.success(...) 或 RestBean.failure(...) 返回结果,通过 @Tag、@Operation 补充接口文档。

RestBean<T> 包含 id(请求追踪 ID)、code、data 和 message。前端请求封装根据响应体中的 code 判断业务结果,成功为 200,登录失效为 401,无权限为 403。HTTP 状态码与响应体中的业务状态码需要分别查看。

以“获取当前用户信息”为例,可以复用现有账户服务。先新增 my-project-backend/src/main/java/com/example/entity/vo/response/AccountInfoVO.java,声明需要返回的字段:

package com.example.entity.vo.response;

import lombok.Data;

@Data
public class AccountInfoVO {
    Integer id;
    String username;
    String email;
}

再新增 my-project-backend/src/main/java/com/example/controller/AccountController.java:

package com.example.controller;

import com.example.entity.RestBean;
import com.example.entity.vo.response.AccountInfoVO;
import com.example.service.AccountService;
import com.example.utils.Const;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/account")
public class AccountController {

    @Resource
    AccountService accountService;

    @GetMapping("/me")
    public RestBean<AccountInfoVO> me(@RequestAttribute(Const.ATTR_USER_ID) Integer id) {
        return RestBean.success(accountService.getById(id).asViewObject(AccountInfoVO.class));
    }
}

JwtAuthenticationFilter 会在令牌校验成功后,将用户 ID 写入 Const.ATTR_USER_ID 对应的请求属性。需要识别当前用户的接口可以按上面的方式读取。Account 已实现 BaseData,asViewObject(...) 会复制同名字段到具有公共无参构造方法的 VO;新增实体需要此能力时也可实现 BaseData。响应 VO 只声明对外需要的字段,例如上面的示例不会返回账户密码。

4. 新增前端页面与联调

在 src/views 中新增页面,例如 ProfileView.vue,通过 src/net/index.js 提供的 get、post 请求后端。封装会自动携带 JWT、处理业务失败提示和登录失效,成功回调收到的是 RestBean.data:

<script setup>
import { onMounted, ref } from 'vue'
import { get } from '@/net'

const account = ref({})

onMounted(() => {
  get('/api/account/me', data => {
    account.value = data
  })
})
</script>

<template>
  <div>
    <div>用户名:{{ account.username }}</div>
    <div>邮箱:{{ account.email }}</div>
  </div>
</template>

在 src/router/index.js 的 routes 数组中注册页面,并为路由设置 name:

{
    path: '/index/profile',
    name: 'profile',
    component: () => import('@/views/ProfileView.vue')
}

当前路由守卫会将已登录用户从名称以 welcome 开头的路由跳转到 /index,并拦截未登录用户访问以 /index 开头的路径。新增 /settings 等其他需要登录的路径时,应同步调整守卫规则。页面访问规则与后端接口权限分别配置。

页面使用 Vue 单文件组件和 <script setup> 编写;@ 指向 src。Element Plus 组件已配置按需引入,Vue 的 ref、reactive 等 API 按现有页面风格显式导入。

5. 认证与公共能力扩展

  • 登录由 SecurityConfiguration 中的 Spring Security 表单登录处理,地址为 POST /api/auth/login,参数为 username、password,请求类型为 application/x-www-form-urlencoded。前端直接复用 login(...) 方法。
  • 登录成功后,前端保存令牌及过期时间;勾选“记住我”时使用 localStorage,否则使用 sessionStorage。后续请求携带 Authorization: Bearer <token>,退出登录复用 logout(...),后端会将令牌加入 Redis 黑名单。
  • SecurityConfiguration 当前放行 /api/auth/**、/error 和 Swagger 相关路径,其他请求要求拥有 Const.ROLE_DEFAULT,默认值为 user。公开接口通过 requestMatchers(...).permitAll() 明确配置,需要登录的业务接口使用独立的业务路径。
  • 扩展角色时,同步修改角色常量、账户角色及 SecurityConfiguration 的匹配规则。数据库角色值使用 user、admin 这样的名称,Spring Security 的 roles(...) 会添加 ROLE_ 前缀。角色权限写入 JWT,修改角色后需要重新登录以生成包含新权限的令牌。
  • 密码处理复用注入的 PasswordEncoder,其实现为 BCrypt;JWT 操作复用 JwtUtils,限流操作复用 FlowUtils,Redis key 前缀、队列名等常量集中放在 Const 中。
  • 注册和重置密码验证码通过 mail 队列发送,邮件标题与正文在 MailQueueListener 中修改,队列声明位于 RabbitConfiguration。当前验证码有效期在 AccountServiceImpl 中设置为 3 分钟,调整时同步更新邮件中的说明。
  • 请求日志由 RequestLogFilter 记录,可用响应中的 id 对照日志中的 reqId 定位请求;日志文件位于后端进程工作目录下的 log/,滚动策略在 logback-spring.xml 中配置。

6. 打包与环境切换

后端通过 Maven profile 选择环境:application.yml 中的 @environment@ 会在 Maven 处理资源时替换,构建产物只包含公共配置和所选环境的配置文件。开发环境使用 -Pdev,生产环境使用 -Pprod;切换环境时使用 clean 清理旧资源。

先按部署环境修改 application-prod.yml 中的数据库、Redis、RabbitMQ、SMTP 和 JWT 配置,再从项目根目录打包后端:

cd my-project-backend
mvn clean package -Pprod -DskipTests
java -jar target/my-project-backend-0.0.1-SNAPSHOT.jar

当前生产配置监听 80 端口并关闭 OpenAPI 文档。仅在启动命令中切换 Spring profile 不会补入构建时未包含的环境配置文件,部署时应使用对应 Maven profile 生成的产物。

前端打包前,将 src/main.js 中的 axios.defaults.baseURL 改为实际后端地址;如果通过同域反向代理转发 /api,可改为 /。在已安装前端依赖的基础上,从项目根目录执行:

cd my-project-frontend
npm run build

将生成的 my-project-frontend/dist/ 部署到静态资源服务器。路由使用 History 模式,需要为前端页面配置回退到 index.html,例如 Nginx 的 try_files $uri $uri/ /index.html;,并为 /api 单独配置后端转发。

About

SpringBoot 3 + Vue3 前后端分离项目模版,已实现登录注册,限流等功能,可直接上手编写业务

Resources

Code of conduct

Stars

374 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages