学校事务管理系统。 系统基于 vue+springboot+mybatisplus 开发的前后台分离项目。 系统亮点:角色权限的设置,分6中不同角色。 超级管理员功能:角色管理,权限管理(给角色分配菜单权限),管理员设置(设置商户管理员和教务管理员)。 教务管理员功能:学籍管理,教师管理,课程管理,自习室管理。 老师功能:课程设置(设置教授课程的名额考试时间),成绩管理(给学生打分)。 学生功能:查看学籍信息,修改密码,校内服务(预约选课,预约订餐,预约自习室)。 商户管理员功能:商户评定(对商户服务进行打分),商户管理。 商户功能:商品管理,订单管理。 运行环境: idea,MySQL5,jdk8。
最近参与开发了一款学校事务管理系统,技术栈用了现在最流行的Vue+SpringBoot组合。这个项目最有趣的地方在于其复杂的角色权限体系——整整六种角色在系统里各司其职,比大学学生会部门划分还细致。咱们先看段权限拦截的代码,感受下这个权限系统的设计:
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PostMapping("/updateRolePermissions") public AjaxResult updateRolePermissions(@RequestBody RolePermissionDTO dto) { // 更新角色权限关联关系 roleService.updateRolePermissions(dto); return AjaxResult.success(); }这个@PreAuthorize注解是Spring Security的玩法,通过自定义的权限校验器ss.hasPermi来验证当前用户是否具备修改角色权限的资格。有意思的是权限标识符的命名规则,采用系统模块:功能点:操作类型的三段式结构,这样在数据库里存权限时就特别清晰:
CREATE TABLE `sys_menu` ( `menu_id` bigint(20) NOT NULL AUTO_INCREMENT, `menu_name` varchar(50) DEFAULT '' COMMENT '菜单名称', `perms` varchar(100) DEFAULT NULL COMMENT '权限标识', `menu_type` char(1) DEFAULT '' COMMENT '类型(M目录 C菜单 F按钮)', PRIMARY KEY (`menu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;说到数据库,教务管理员最核心的学籍管理模块用MyBatis Plus实现起来简直不要太爽。来看这个动态查询的骚操作:
public PageResult<StudentVO> queryStudents(StudentQuery query) { return new PageResult<>(studentMapper.selectPage( new Page<>(query.getPageNum(), query.getPageSize()), Wrappers.<Student>lambdaQuery() .like(StringUtils.isNotEmpty(query.getName()), Student::getName, query.getName()) .eq(query.getStatus() != null, Student::getStatus, query.getStatus()) .between(query.getStartDate() != null && query.getEndDate() != null, Student::getEnrollmentDate, query.getStartDate(), query.getEndDate()) )); }这个lambdaQuery()链式调用把动态SQL写得跟说话一样自然。当查询条件为空时,MyBatis Plus会自动忽略对应的where子句,比XML里写优雅多了。
学生端的预约功能最有意思,比如选课时的并发控制。我们用了Redis的分布式锁来防止超选:
public boolean selectCourse(Long courseId, Long studentId) { String lockKey = "course_lock:" + courseId; RLock lock = redissonClient.getLock(lockKey); try { if (lock.tryLock(3, 5, TimeUnit.SECONDS)) { Course course = courseMapper.selectById(courseId); if (course.getRemainSeats() > 0) { courseMapper.deductSeat(courseId); enrollMapper.insert(new Enroll(studentId, courseId)); return true; } } } finally { lock.unlock(); } return false; }这里用Redisson实现的分布式锁比原生Redis命令方便不少,特别是自动续期的设计让开发者不用操心锁过期的问题。
学校事务管理系统。 系统基于 vue+springboot+mybatisplus 开发的前后台分离项目。 系统亮点:角色权限的设置,分6中不同角色。 超级管理员功能:角色管理,权限管理(给角色分配菜单权限),管理员设置(设置商户管理员和教务管理员)。 教务管理员功能:学籍管理,教师管理,课程管理,自习室管理。 老师功能:课程设置(设置教授课程的名额考试时间),成绩管理(给学生打分)。 学生功能:查看学籍信息,修改密码,校内服务(预约选课,预约订餐,预约自习室)。 商户管理员功能:商户评定(对商户服务进行打分),商户管理。 商户功能:商品管理,订单管理。 运行环境: idea,MySQL5,jdk8。
前端路由配置也暗藏玄机。通过动态路由表实现菜单权限控制:
// 过滤有权限的路由 function filterAsyncRoutes(routes, roles) { return routes.filter(route => { if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { return true } }) } // 动态添加路由 router.beforeEach((to, from, next) => { if (store.getters.roles.length === 0) { store.dispatch('GetInfo').then(() => { const accessRoutes = filterAsyncRoutes(asyncRoutes, store.getters.roles) router.addRoutes(accessRoutes) next({ ...to, replace: true }) }) } })这种设计让不同角色登录后看到的菜单完全不同。比如普通学生绝对看不到商户评分页面,而商户管理员也接触不到成绩管理模块。
开发过程中遇到最坑的问题当属MyBatis Plus的版本兼容性。项目初期用了3.4.0版本,结果发现Page对象的分页参数在MySQL5下运行异常,升级到3.4.3之后才正常。所以用老版本MySQL的同学要特别注意依赖版本的选择。
项目部署时还有个冷知识:Vue生产环境部署要特别注意路由的history模式配置。我们在Nginx里加了这段配置才解决刷新404的问题:
location / { try_files $uri $uri/ /index.html; }整个项目做下来,最大的感受是权限系统设计就像搭乐高。每个权限标识都是一个小积木,通过合理的组合方式,最终搭建出能满足六种角色需求的完整系统。特别是前后端都做权限验证的设计,虽然开发时麻烦了点,但上线后确实有效防止了越权操作。