首页
/ 【72小时限时分享】SpringBoot3+Vue3全栈开发脚手架:从0到1搭建企业级权限系统

【72小时限时分享】SpringBoot3+Vue3全栈开发脚手架:从0到1搭建企业级权限系统

2026-02-04 04:25:07作者:滕妙奇

你还在为全栈项目搭建重复造轮子?还在纠结前后端分离架构如何设计?本文将带你基于SpringBoot3-Vue3-Demo实战模板,7步构建包含用户认证、权限管理、数据交互的企业级全栈应用,附赠完整代码和部署指南,让你从此告别996式基础开发!

读完本文你将获得:

  • 一套可直接商用的SpringBoot3+Vue3权限架构方案
  • 5个核心业务模块的完整实现代码(用户/角色/菜单/登录/文件上传)
  • 前后端数据交互的最佳实践(DTO/VO分层+统一响应处理)
  • 3种缓存策略在实际项目中的应用技巧
  • 从零到一的部署文档与性能优化指南

项目架构全景图

SpringBoot3-Vue3-Demo采用经典的分层架构设计,后端基于SpringBoot3构建RESTful API,前端使用Vue3+Element UI实现响应式界面,整体架构如图所示:

flowchart TD
    Client[用户浏览器] -->|HTTP/HTTPS| Nginx[Nginx服务器]
    Nginx -->|API请求| Backend[SpringBoot3后端]
    Nginx -->|静态资源| Frontend[Vue3前端]
    
    subgraph Backend
        Controller[控制器层] --> Service[服务层]
        Service --> Repository[数据访问层]
        Repository --> DB[(MySQL数据库)]
        Service --> Cache[(本地缓存)]
        Controller --> Security[Spring Security]
        Security --> JWT[JWT令牌]
    end
    
    subgraph Frontend
        Views[视图组件] --> Vuex[状态管理]
        Vuex --> API[API请求模块]
        API --> Axios[Axios拦截器]
        Views --> Router[Vue Router]
        Views --> UI[Element UI组件]
    end

技术栈选型对比表

技术领域 选型方案 优势分析 替代方案 替代方案劣势
后端框架 SpringBoot 3 原生支持Java 17+,性能提升30% SpringBoot 2.x 不支持虚拟线程,响应式编程需额外依赖
前端框架 Vue 3 + Composition API 更好的TypeScript支持,组件逻辑复用更灵活 Vue 2 + Options API 大型项目维护困难,TypeScript集成度低
权限认证 Spring Security + JWT 无状态设计,易于水平扩展 Shiro 分布式场景下配置复杂
ORM框架 MyBatis SQL优化灵活,性能损耗低 Spring Data JPA 复杂查询性能较差,SQL优化困难
缓存方案 Caffeine本地缓存 吞吐量高,内存占用低 Redis 需额外部署,增加系统复杂度
前端UI库 Element UI 组件丰富,企业级应用成熟 Ant Design Vue 体积较大,学习曲线陡峭

核心功能模块详解

1. 认证授权系统

认证授权模块是企业级应用的核心,本项目基于Spring Security+JWT实现了完整的认证流程,其工作原理如下:

sequenceDiagram
    participant 客户端
    participant 认证过滤器
    participant 用户服务
    participant JWT工具
    participant 安全上下文

    客户端->>认证过滤器: 发送登录请求(用户名/密码)
    认证过滤器->>用户服务: 调用loadUserByUsername()
    用户服务->>数据库: 查询用户信息
    数据库-->>用户服务: 返回用户信息(含加密密码)
    用户服务-->>认证过滤器: 返回UserDetails对象
    认证过滤器->>认证过滤器: 密码比对
    alt 认证成功
        认证过滤器->>JWT工具: 生成JWT令牌
        JWT工具-->>认证过滤器: 返回token
        认证过滤器->>安全上下文: 设置认证信息
        认证过滤器-->>客户端: 返回token+用户信息
    else 认证失败
        认证过滤器-->>客户端: 返回401未授权
    end

后端实现核心代码

LoginController.java

@RestController
public class LoginController extends BaseController {

    @Autowired
    private LoginService loginService;

    @PostMapping("login")
    public R<?> login(@RequestBody LoginUserDto loginUserDto) {
        if (StringUtils.isBlank(loginUserDto.getUserName())) {
            throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);
        }
        return R.ok(loginService.login(loginUserDto));
    }

    @GetMapping("isLogin")
    public R<?> isLogin() {
        return R.ok(SecurityUtils.getUserId());
    }

    @PostMapping("reg")
    public R<?> reg(@RequestBody SysUser user) {
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        user.setBirthday(new Date());
        userService.save(user);
        // 分配默认角色
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(user.getId());
        sysUserRole.setRoleId("2"); // 普通用户角色
        userRoleService.save(sysUserRole);
        return R.ok();
    }
}

LoginServiceImpl.java

public class LoginServiceImpl implements LoginService {
    
    @Override
    public LoginUserVo login(LoginUserDto loginUserDto) {
        // 1. 获取用户信息
        UserDetails userDetails = userDetailsService.loadUserByUsername(loginUserDto.getUserName());
        
        // 2. 验证密码
        if (!passwordEncoder.matches(loginUserDto.getPassword(), userDetails.getPassword())) {
            throw new SystemException(AppHttpCodeEnum.LOGIN_ERROR);
        }
        
        // 3. 生成JWT令牌
        LoginUser loginUser = (LoginUser) userDetails;
        String token = JwtUtils.createJWT(loginUser.getUser().getId().toString());
        
        // 4. 构建返回对象
        LoginUserVo loginUserVo = new LoginUserVo();
        loginUserVo.setToken(token);
        loginUserVo.setUserInfo(loginUser);
        
        return loginUserVo;
    }
}

前端实现核心代码

login.js

import request from '@/utils/request'

// 用户登录
export function login(data) {
  return request({
    url: '/login',
    method: 'post',
    data: data
  })
}

// 用户注册
export function reg(data) {
  return request({
    url: '/reg',
    method: 'post',
    data: data
  })
}

// 获取当前登录状态
export function getLoginStatus() {
  return request({
    url: '/isLogin',
    method: 'get'
  })
}

Login.vue

<template>
  <div class="login-container">
    <el-card class="login-card">
      <el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-width="80px">
        <el-form-item label="用户名" prop="userName">
          <el-input v-model="loginForm.userName" placeholder="请输入用户名"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input type="password" v-model="loginForm.password" placeholder="请输入密码"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleLogin" style="width: 100%">登录</el-button>
        </el-form-item>
        <el-form-item style="text-align: right">
          <el-button type="text" @click="goToRegister">注册账号</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { login } from '@/api/login'
import { ElMessage } from 'element-plus'

const router = useRouter()
const loginForm = ref({
  userName: '',
  password: ''
})

const loginRules = ref({
  userName: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
})

const handleLogin = async () => {
  try {
    const response = await login(loginForm.value)
    localStorage.setItem('token', response.data.token)
    localStorage.setItem('userInfo', JSON.stringify(response.data.userInfo))
    ElMessage.success('登录成功')
    router.push('/home')
  } catch (error) {
    ElMessage.error(error.response?.data?.msg || '登录失败')
  }
}

const goToRegister = () => {
  router.push('/register')
}
</script>

2. 用户管理模块

用户管理模块实现了用户信息的CRUD操作,采用DTO/VO分层模式,有效隔离了内部实体与外部接口。核心代码结构如下:

classDiagram
    class SysUserController {
        +getUserList()
        +getUserById()
        +saveUser()
        +updateUser()
        +deleteUser()
    }
    
    class SysUserService {
        +listUsers(PageParam)
        +getUserById(Long)
        +createUser(SysUserDto)
        +updateUser(SysUserDto)
        +removeUser(Long)
    }
    
    class SysUserMapper {
        +selectPage(Page, QueryWrapper)
        +selectById(Serializable)
        +insert(Object)
        +updateById(Object)
        +deleteById(Serializable)
    }
    
    SysUserController --> SysUserService
    SysUserService --> SysUserMapper

数据传输对象设计

LoginUserDto.java (数据传输对象)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginUserDto {
    private String userName;  // 用户名
    private String password;  // 密码
    private String code;      // 验证码
    private String uuid;      // 验证码唯一标识
}

LoginUserVo.java (视图对象)

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class LoginUserVo {
    private String token;       // JWT令牌
    private LoginUser userInfo; // 用户详细信息
}

3. 缓存策略实现

项目使用Caffeine本地缓存提升系统性能,主要应用于用户信息、角色权限等高频访问且变更不频繁的数据。缓存配置如下:

CacheConfig.java

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        
        // 设置不同缓存的过期策略
        cacheManager.setCacheSpecification("userInfo=30m,roleInfo=60m,menuInfo=120m");
        
        // 配置Caffeine缓存属性
        cacheManager.setCaffeine(caffeineCacheBuilder());
        
        return cacheManager;
    }
    
    Caffeine<Object, Object> caffeineCacheBuilder() {
        return Caffeine.newBuilder()
                // 初始缓存容量
                .initialCapacity(100)
                // 最大缓存容量
                .maximumSize(1000)
                // 记录缓存命中率
                .recordStats();
    }
}

缓存使用示例

@Service
public class SysUserServiceImpl implements SysUserService {

    @Cacheable(value = "userInfo", key = "#id")
    @Override
    public SysUser getUserById(Long id) {
        return sysUserMapper.selectById(id);
    }
    
    @CacheEvict(value = "userInfo", key = "#user.id")
    @Override
    public boolean updateUser(SysUser user) {
        return sysUserMapper.updateById(user) > 0;
    }
    
    @CacheEvict(value = "userInfo", allEntries = true)
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点清空缓存
    public void clearUserCache() {
        log.info("定时清空用户缓存");
    }
}

项目部署与优化指南

1. 环境准备清单

环境要求 版本号 检查命令 安装方式
JDK 17+ java -version Oracle JDK / OpenJDK
Maven 3.6+ mvn -version Maven官网
Node.js 16+ node -v Node.js官网
MySQL 8.0+ mysql -V MySQL官网
Git 2.30+ git --version Git官网

2. 快速部署步骤

步骤1:克隆项目代码

git clone https://gitcode.com/weixin_46699933/SpringBoot3-Vue3-Demo.git
cd SpringBoot3-Vue3-Demo

步骤2:初始化数据库

# 导入SQL脚本
mysql -u root -p < demo-admin/sql/test.sql

步骤3:配置数据库连接

# demo-admin/src/main/resources/application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/springboot_vue_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: root123
    driver-class-name: com.mysql.cj.jdbc.Driver

步骤4:启动后端服务

cd demo-admin
mvn spring-boot:run

步骤5:构建并启动前端服务

cd demo-vue
npm install  # 安装依赖
npm run dev  # 开发环境启动
# 或执行 npm run build 构建生产环境包

3. 性能优化建议

  1. 数据库优化

    • 为常用查询字段添加索引(如user_name, role_id等)
    • 大表使用分表策略,如按用户ID哈希分表
    • 合理配置连接池参数:
    spring:
      datasource:
        hikari:
          maximum-pool-size: 20
          minimum-idle: 5
          idle-timeout: 300000
          connection-timeout: 20000
    
  2. 缓存优化

    • 热点数据缓存预热
    • 实现缓存降级机制,避免缓存穿透
    • 定期清理过期缓存,释放内存空间
  3. 前端优化

    • 路由懒加载减少初始加载时间
    • 组件按需引入,减小打包体积
    • 接口数据缓存,减少重复请求

项目扩展指南

1. 功能扩展路线图

timeline
    title 项目功能扩展路线图
    2025年Q1 : 集成Redis分布式缓存
    2025年Q2 : 添加消息队列实现异步处理
    2025年Q3 : 引入Elasticsearch实现全文搜索
    2025年Q4 : 集成Docker容器化部署
    2026年Q1 : 实现微服务拆分

2. 常见问题解决方案

Q: 如何集成第三方登录?
A: 可通过OAuth2.0协议集成,步骤如下:

  1. 添加Spring Security OAuth2依赖
  2. 配置第三方登录服务商信息(微信/QQ/GitHub)
  3. 实现OAuth2登录处理器
  4. 前端添加第三方登录按钮及回调处理

Q: 如何实现文件上传到云存储?
A: 修改UploadServiceImpl实现,示例如下:

@Service
public class UploadServiceImpl implements UploadService {
    
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    
    @Override
    public String upload(MultipartFile file) {
        // 1. 初始化OSS客户端
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        
        try {
            // 2. 生成唯一文件名
            String fileName = UUID.randomUUID().toString() + getFileExtension(file.getOriginalFilename());
            
            // 3. 上传文件到OSS
            ossClient.putObject(bucketName, "upload/" + fileName, file.getInputStream());
            
            // 4. 生成访问URL
            return "https://" + bucketName + "." + endpoint + "/upload/" + fileName;
        } catch (Exception e) {
            throw new SystemException(AppHttpCodeEnum.FILE_UPLOAD_ERROR);
        } finally {
            // 5. 关闭OSS客户端
            ossClient.shutdown();
        }
    }
    
    private String getFileExtension(String fileName) {
        return fileName.substring(fileName.lastIndexOf("."));
    }
}

总结与展望

SpringBoot3-Vue3-Demo作为一款企业级全栈开发脚手架,通过合理的架构设计和最佳实践,为开发者提供了开箱即用的开发体验。本文详细介绍了项目的核心功能模块、架构设计、实现细节和部署流程,希望能帮助开发者快速上手并应用到实际项目中。

项目目前已实现基础的用户认证、权限管理、数据交互等核心功能,未来将重点扩展微服务支持、多租户架构、分布式事务等企业级特性。我们欢迎社区贡献代码和建议,共同打造更强大的全栈开发工具。

读者互动

如果本文对你有帮助,请帮忙点赞、收藏、关注三连支持!你在使用过程中遇到任何问题,或有功能改进建议,欢迎在评论区留言讨论。下期我们将带来《SpringBoot3集成分布式事务实战》,敬请期待!

配套资源

  1. 完整源代码:已包含在项目仓库中
  2. 数据库脚本:demo-admin/sql/test.sql
  3. 接口文档:启动项目后访问 http://localhost:8080/swagger-ui.html
  4. 前端组件库:基于Element UI二次封装的企业级组件
登录后查看全文
热门项目推荐
相关项目推荐