1. 项目概述
这个基于Java Spring Boot和Vue.js的公寓管理系统是我最近完成的一个实战项目,它主要面向高校学生公寓管理场景。系统实现了从学生入住到日常管理的全流程数字化,包括学生信息管理、公寓分配、卫生检查、报修处理等核心功能模块。
在实际开发过程中,我发现传统公寓管理存在几个痛点:纸质档案容易丢失、报修流程繁琐、卫生检查记录不透明。这个系统正是为了解决这些问题而设计的,通过前后端分离架构,实现了管理效率和学生体验的双重提升。
2. 技术架构解析
2.1 后端技术选型
选择Spring Boot作为后端框架主要基于以下几个考虑:
- 快速启动:内置Tomcat服务器,无需额外配置
- 自动配置:根据pom.xml中的依赖自动配置Bean
- 生态丰富:整合MyBatis Plus、Spring Security等组件非常方便
核心依赖配置示例:
xml复制<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
2.2 前端技术选型
Vue.js的选择主要基于其:
- 响应式数据绑定:自动更新UI,减少DOM操作
- 组件化开发:提高代码复用率
- 轻量高效:虚拟DOM优化性能
典型组件结构:
code复制src/
├── components/
│ ├── StudentInfo.vue
│ ├── RepairForm.vue
│ └── DormSelect.vue
├── router/
├── store/
└── views/
2.3 数据库设计
MySQL数据库设计遵循第三范式,主要表结构包括:
- 学生表(student_info)
- 公寓表(dormitory)
- 维修表(repair_record)
- 卫生检查表(hygiene_check)
关键表关系图:
code复制学生表 1:n 维修记录表
公寓表 1:n 学生表
公寓表 1:n 卫生检查表
3. 核心功能实现
3.1 学生信息管理模块
采用RBAC权限模型,实现不同角色的权限控制:
- 管理员:增删改查所有学生信息
- 宿管:查看和修改所辖公寓学生信息
- 学生:仅查看本人信息
核心代码片段:
java复制@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping("/list")
@PreAuthorize("hasRole('ADMIN')")
public R list(@RequestParam Map<String, Object> params) {
PageUtils page = studentService.queryPage(params);
return R.ok().put("page", page);
}
}
3.2 公寓分配算法
实现智能分配算法考虑因素:
- 同专业/班级优先同住
- 特殊需求学生优先安排
- 空床位自动匹配
分配逻辑伪代码:
code复制function allocate(student):
preferred_dorm = findDormByMajor(student.major)
if preferred_dorm.hasVacancy():
return preferred_dorm
else:
return findNearestDorm(preferred_dorm)
3.3 报修流程设计
状态机设计:
code复制待受理 → 已分配 → 维修中 → 已完成
↘ 已驳回
关键字段:
- 报修类型(水电/家具/网络)
- 紧急程度(高/中/低)
- 维修人员
- 完成时间
4. 安全与认证方案
4.1 JWT认证实现
采用Token机制实现无状态认证:
- 用户登录成功后生成Token
- Token包含用户ID、角色等信息
- 前端存储Token并在后续请求中携带
Token生成核心代码:
java复制public String generateToken(Long userId, String username, String role) {
String token = UUID.randomUUID().toString();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR, 2); // 2小时有效期
TokenEntity tokenEntity = new TokenEntity();
tokenEntity.setUserId(userId);
tokenEntity.setToken(token);
tokenEntity.setExpireTime(cal.getTime());
tokenMapper.insert(tokenEntity);
return token;
}
4.2 接口权限控制
使用Spring Security实现方法级权限控制:
java复制@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
}
5. 系统测试实践
5.1 测试策略
采用分层测试策略:
- 单元测试(Service层)
- 集成测试(Controller层)
- 端到端测试(前端+后端)
测试覆盖率目标:
- 业务逻辑层:≥80%
- 控制器层:≥70%
- DAO层:≥90%
5.2 典型测试用例
登录功能测试矩阵:
| 测试场景 | 输入数据 | 预期结果 | 实际结果 |
|---|---|---|---|
| 正确凭证 | 有效用户名+密码 | 登录成功 | 通过 |
| 错误密码 | 正确用户+错误密码 | 提示密码错误 | 通过 |
| 空用户名 | 空用户+任意密码 | 提示用户名为空 | 通过 |
| 过期Token | 过期Token访问API | 返回401 | 通过 |
5.3 性能测试结果
使用JMeter进行压力测试:
- 并发100用户登录:平均响应时间<500ms
- 学生列表查询:TPS达到120/s
- 持续运行24小时:内存泄漏<3%
6. 部署与运维方案
6.1 生产环境部署
推荐部署架构:
code复制Nginx(负载均衡)
├── Spring Boot应用1
├── Spring Boot应用2
└── Vue静态资源
MySQL(主从复制)
Docker部署示例:
dockerfile复制# Spring Boot应用
FROM openjdk:11
COPY target/dorm-system.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
# Nginx配置
server {
listen 80;
location /api {
proxy_pass http://springboot:8080;
}
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
}
6.2 监控方案
建议监控指标:
- 应用健康:Spring Boot Actuator
- 接口性能:Prometheus + Grafana
- 日志分析:ELK Stack
关键报警阈值:
- CPU使用率>80%持续5分钟
- 接口错误率>1%
- 数据库连接数>80%
7. 开发经验总结
在实际开发中,有几个关键点值得注意:
-
MyBatis Plus动态表名问题
在多租户场景下,需要通过自定义拦截器实现动态表名:java复制public class DynamicTableNameInterceptor implements InnerInterceptor { @Override public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 替换SQL中的表名逻辑 } } -
Vue组件通信优化
对于深层嵌套组件,推荐使用Vuex替代props层层传递:javascript复制// store/modules/dorm.js const actions = { async fetchDormList({ commit }, params) { const res = await api.getDormList(params) commit('SET_LIST', res.data) } } -
Spring Boot缓存策略
对于高频访问的学生列表,采用二级缓存:java复制@Cacheable(value = "student", key = "#pageNum+'-'+#pageSize") public Page<Student> getStudentPage(int pageNum, int pageSize) { return studentMapper.selectPage(new Page<>(pageNum, pageSize), null); } -
跨域解决方案
生产环境推荐配置:java复制@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("https://yourdomain.com") .allowedMethods("*") .allowCredentials(true) .maxAge(3600); } }
这个项目从技术选型到最终上线历时3个月,期间遇到了不少挑战,比如MyBatis Plus的多租户支持、Vue大型表单的性能优化等。通过这个项目,我深刻体会到良好的架构设计对后期维护的重要性,特别是在需求变更频繁的教育领域。