SpringBoot 2.6.7 + Vue 2 + MyBatis-Plus 3.5.1:手把手教你从零搭建一个带登录注册的学生管理系统

张开发
2026/5/8 1:22:08 15 分钟阅读
SpringBoot 2.6.7 + Vue 2 + MyBatis-Plus 3.5.1:手把手教你从零搭建一个带登录注册的学生管理系统
SpringBoot 2.6.7 Vue 2 MyBatis-Plus 3.5.1从零构建学生管理系统的实战指南在当今快速发展的软件开发领域掌握全栈开发技能已成为开发者的核心竞争力。本文将带你深入探索如何利用SpringBoot 2.6.7、Vue 2和MyBatis-Plus 3.5.1这一黄金组合从零开始构建一个功能完善的学生管理系统。不同于简单的教程复现我们将重点关注版本兼容性、开发效率提升和实际项目中的最佳实践。1. 技术栈选型与版本锁定1.1 为什么选择这个技术组合SpringBoot 2.6.7作为Java生态中最受欢迎的微服务框架提供了开箱即用的特性配置和强大的自动装配能力。搭配MyBatis-Plus 3.5.1可以极大简化数据库操作同时保留SQL的灵活性。前端选择Vue 2而非Vue 3主要考虑企业级项目的稳定性和组件生态成熟度。版本兼容性矩阵组件版本关键依赖SpringBoot2.6.7spring-boot-starter-parentMyBatis-Plus3.5.1mybatis-plus-boot-starterVue2.6.14vue-cliElement-UI2.15.9element-ui1.2 开发环境准备确保你的开发环境满足以下要求JDK 1.8推荐Amazon Corretto 8Node.js 14.x LTS版本MySQL 5.7或MariaDB 10.3IntelliJ IDEA Ultimate社区版也可用VS Code或WebStorm前端开发提示使用nvm管理Node.js版本可以避免全局安装带来的冲突问题# 安装nvmMac/Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash # 安装指定Node版本 nvm install 14.21.3 nvm use 14.21.32. 后端工程搭建2.1 初始化SpringBoot项目使用Spring Initializr创建项目时特别注意依赖选择访问 https://start.spring.io选择Project: MavenLanguage: JavaSpring Boot: 2.6.7添加依赖Spring WebLombokMySQL Driver或者直接使用以下pom.xml配置?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.6.7/version relativePath/ /parent dependencies dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.1/version /dependency !-- 其他依赖... -- /dependencies /project2.2 MyBatis-Plus配置技巧在application.yml中配置数据源和MyBatis-Plusmybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted # 逻辑删除字段 logic-delete-value: 1 # 删除值 logic-not-delete-value: 0 # 未删除值常用注解速查表注解作用示例TableName指定表名TableName(sys_user)TableId主键标识TableId(type IdType.AUTO)TableField字段映射TableField(user_name)Version乐观锁Version private Integer version3. 前端架构设计3.1 Vue项目初始化与配置使用Vue CLI创建项目时选择Vue 2模板vue create student-frontend关键依赖版本控制{ dependencies: { vue: ^2.6.14, element-ui: ^2.15.9, axios: ^0.27.2, vue-router: ^3.5.1 } }3.2 前端工程化实践推荐的项目结构src/ ├── api/ # API请求封装 ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── router/ # 路由配置 ├── store/ # Vuex状态管理 ├── utils/ # 工具函数 ├── views/ # 页面组件 ├── App.vue # 根组件 └── main.js # 入口文件在main.js中配置全局拦截器axios.interceptors.request.use(config { config.headers[Authorization] localStorage.getItem(token) || return config }, error { return Promise.reject(error) }) axios.interceptors.response.use(response { if (response.data.code 401) { router.push(/login) } return response }, error { return Promise.reject(error) })4. 核心功能实现4.1 登录认证与权限控制后端采用JWT实现认证public class JwtUtil { private static final String SECRET your-secret-key; private static final long EXPIRATION 86400000L; // 24小时 public static String generateToken(UserDetails userDetails) { return Jwts.builder() .setSubject(userDetails.getUsername()) .setExpiration(new Date(System.currentTimeMillis() EXPIRATION)) .signWith(SignatureAlgorithm.HS512, SECRET) .compact(); } public static String getUsernameFromToken(String token) { return Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token) .getBody() .getSubject(); } }前端路由守卫实现router.beforeEach((to, from, next) { const isAuthenticated localStorage.getItem(token) if (to.matched.some(record record.meta.requiresAuth) !isAuthenticated) { next(/login) } else { next() } })4.2 学生管理CRUD实现利用MyBatis-Plus的Service层封装Service public class StudentServiceImpl extends ServiceImplStudentMapper, Student implements StudentService { Override public PageStudent getStudentPage(PageParam param) { return this.page(new Page(param.getPage(), param.getSize()), new LambdaQueryWrapperStudent() .like(StringUtils.isNotBlank(param.getKeyword()), Student::getName, param.getKeyword()) .orderByDesc(Student::getCreateTime)); } }前端使用Element-UI表格组件template el-table :datatableData stylewidth: 100% el-table-column propid label学号 width180/el-table-column el-table-column propname label姓名 width180/el-table-column el-table-column label操作 template #defaultscope el-button sizemini clickhandleEdit(scope.row)编辑/el-button el-button sizemini typedanger clickhandleDelete(scope.row)删除/el-button /template /el-table-column /el-table /template5. 联调与部署实战5.1 跨域问题解决方案SpringBoot配置CORSConfiguration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowedHeaders(*) .maxAge(3600); } }或者使用Nginx反向代理server { listen 80; server_name your.domain.com; location /api { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { root /path/to/frontend/dist; try_files $uri $uri/ /index.html; } }5.2 性能优化技巧后端缓存策略Cacheable(value students, key #id) public Student getById(Long id) { return getById(id); } CacheEvict(value students, key #id) public void updateStudent(Student student) { updateById(student); }前端懒加载优化const StudentList () import(./views/StudentList.vue) const routes [ { path: /students, component: StudentList } ]6. 常见问题排查指南6.1 版本冲突解决方案使用Maven依赖树分析工具mvn dependency:tree -Dincludescom.baomidou:mybatis-plus*常见冲突场景MyBatis与MyBatis-Plus版本不匹配SpringBoot与SpringCloud版本不兼容Jackson版本冲突6.2 典型错误处理问题1前端请求报404错误排查步骤检查后端接口路径是否正确确认Controller是否有RestController注解查看是否配置了正确的RequestMapping问题2MyBatis-Plus插入返回null主键解决方案TableId(type IdType.AUTO) private Long id;问题3Vue页面刷新后路由丢失解决方法const router new VueRouter({ mode: history, base: process.env.BASE_URL, routes })7. 项目扩展方向7.1 功能增强建议加入成绩统计分析功能实现Excel导入导出添加教师管理模块开发移动端适配7.2 技术深度扩展集成Spring Security实现RBAC使用WebSocket实现实时通知接入ELK实现日志分析引入Docker容器化部署在实际开发中我发现MyBatis-Plus的Lambda表达式能极大提高代码可读性特别是在复杂查询场景下。例如下面这种多条件动态查询用Lambda方式写起来非常清晰public ListStudent searchStudents(SearchParam param) { return lambdaQuery() .like(StringUtils.isNotBlank(param.getName()), Student::getName, param.getName()) .ge(param.getMinAge() ! null, Student::getAge, param.getMinAge()) .le(param.getMaxAge() ! null, Student::getAge, param.getMaxAge()) .orderByDesc(Student::getCreateTime) .list(); }

更多文章