1. 企业级教学管理系统架构解析
这套教学管理系统采用SpringBoot+Vue+MyBatis+MySQL的技术组合,是当前企业级应用开发的黄金搭配。SpringBoot 2.7.4作为后端框架,提供了自动配置和快速启动的特性;Vue 3.2作为前端框架,配合Element Plus组件库实现响应式界面;MyBatis 3.5作为ORM框架,与MySQL 8.0数据库协同工作。
这种架构设计的优势在于:
- 前后端完全分离,通过RESTful API交互
- 采用JWT进行身份认证和权限控制
- 使用Redis 6.2缓存热点数据
- 通过Swagger 3.0自动生成API文档
- 集成Logback进行日志管理
提示:在实际部署时,建议将Nginx配置为静态资源服务器和反向代理,可以显著提升系统性能。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心功能模块实现
2.1 用户权限管理系统
采用RBAC(基于角色的访问控制)模型设计,包含以下核心表结构:
sql复制CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`salt` varchar(20) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`mobile` varchar(100) DEFAULT NULL,
`status` tinyint DEFAULT '1',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
权限控制通过Spring Security实现,关键配置类:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login", "/captcha.jpg").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
2.2 课程管理模块
包含课程创建、排课、选课等完整流程。核心业务逻辑处理示例:
java复制@Service
public class CourseServiceImpl implements CourseService {
@Autowired
private CourseMapper courseMapper;
@Transactional
@Override
public void createCourse(CourseDTO dto) {
// 验证教师信息
Teacher teacher = teacherMapper.selectById(dto.getTeacherId());
if(teacher == null) {
throw new BusinessException("教师不存在");
}
// 创建课程
Course course = new Course();
BeanUtils.copyProperties(dto, course);
course.setCreateTime(new Date());
courseMapper.insert(course);
// 处理课程时间冲突
checkScheduleConflict(course);
}
private void checkScheduleConflict(Course course) {
// 实现时间冲突检测逻辑
}
}
3. 数据库设计与优化
3.1 主要表结构设计
系统包含50+张业务表,核心表关系如下:
| 表名 | 描述 | 记录数预估 | 索引策略 |
|---|---|---|---|
| sys_user | 系统用户 | 10,000 | 主键+username唯一索引 |
| sys_role | 角色 | 20 | 主键 |
| sys_menu | 菜单权限 | 100 | 主键+parent_id索引 |
| edu_course | 课程 | 5,000 | 主键+teacher_id索引 |
| edu_student | 学生 | 50,000 | 主键+class_id索引 |
| edu_score | 成绩 | 500,000 | 复合索引(course_id, student_id) |
3.2 查询性能优化
针对大数据量表采用以下优化策略:
- 合理设计复合索引
- 对大文本字段使用垂直分表
- 历史数据归档策略
- 使用MyBatis二级缓存
- 复杂查询走存储过程
成绩统计查询优化示例:
sql复制-- 原始查询
EXPLAIN SELECT s.student_name, c.course_name, sc.score
FROM edu_student s
JOIN edu_score sc ON s.student_id = sc.student_id
JOIN edu_course c ON sc.course_id = c.course_id
WHERE s.class_id = 101;
-- 优化后查询
CREATE INDEX idx_student_class ON edu_student(class_id);
CREATE INDEX idx_score_relation ON edu_score(student_id, course_id);
SELECT s.student_name, c.course_name, sc.score
FROM edu_student s FORCE INDEX(idx_student_class)
JOIN edu_score sc FORCE INDEX(idx_score_relation) ON s.student_id = sc.student_id
JOIN edu_course c ON sc.course_id = c.course_id
WHERE s.class_id = 101;
4. 系统部署与运维
4.1 生产环境部署方案
推荐使用Docker Compose部署,docker-compose.yml示例:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
container_name: edu-mysql
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: edu_system
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
ports:
- "3306:3306"
restart: always
redis:
image: redis:6.2
container_name: edu-redis
ports:
- "6379:6379"
volumes:
- ./redis/data:/data
restart: always
backend:
build: ./backend
container_name: edu-backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
environment:
- SPRING_PROFILES_ACTIVE=prod
restart: always
frontend:
build: ./frontend
container_name: edu-frontend
ports:
- "80:80"
depends_on:
- backend
restart: always
4.2 监控与日志收集
建议集成以下监控组件:
- Prometheus + Grafana监控系统指标
- ELK收集和分析日志
- SkyWalking进行分布式追踪
- 自定义健康检查接口
SpringBoot监控配置示例:
properties复制# application-prod.properties
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.metrics.export.prometheus.enabled=true
management.metrics.tags.application=edu-system
5. 二次开发指南
5.1 代码规范与风格
项目采用以下开发规范:
- 后端Java代码遵循Alibaba Java Coding Guidelines
- 前端使用ESLint进行代码检查
- Git提交信息遵循Conventional Commits规范
- API设计遵循RESTful最佳实践
- 使用Lombok减少样板代码
5.2 常见扩展场景
- 多租户支持:通过TenantFilter实现租户隔离
- 第三方登录:集成OAuth2.0协议
- 文件存储:支持本地/MinIO/阿里云OSS
- 消息通知:集成邮件/短信/WebSocket
- 数据分析:使用Apache POI/ECharts
多租户实现示例:
java复制public class TenantContext {
private static final ThreadLocal<String> CURRENT_TENANT = new ThreadLocal<>();
public static void setTenantId(String tenantId) {
CURRENT_TENANT.set(tenantId);
}
public static String getTenantId() {
return CURRENT_TENANT.get();
}
public static void clear() {
CURRENT_TENANT.remove();
}
}
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor interceptor = new PaginationInterceptor();
interceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return interceptor;
}
@Bean
public TenantSqlParser tenantSqlParser() {
return new TenantSqlParser()
.setTenantHandler(new TenantHandler() {
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public Expression getTenantId() {
return new StringValue(TenantContext.getTenantId());
}
@Override
public boolean doTableFilter(String tableName) {
// 过滤不需要租户隔离的表
return !Arrays.asList("edu_course", "edu_student").contains(tableName);
}
});
}
}
6. 安全防护策略
6.1 常见安全威胁防护
- SQL注入:使用MyBatis预编译语句
- XSS攻击:前端使用DOMPurify过滤,后端统一转义
- CSRF攻击:虽然使用JWT无状态认证,但仍建议关键操作验证Referer
- 暴力破解:登录接口增加验证码和限流
- 数据泄露:敏感字段加密存储
密码加密实现:
java复制public class PasswordUtil {
private static final int HASH_ITERATIONS = 1024;
private static final int SALT_SIZE = 8;
public static String encrypt(String password, String salt) {
return new SimpleHash("SHA-256", password, salt, HASH_ITERATIONS).toHex();
}
public static String generateSalt() {
return RandomStringUtils.randomAlphanumeric(SALT_SIZE);
}
public static boolean validate(String inputPwd, String dbPwd, String salt) {
return encrypt(inputPwd, salt).equals(dbPwd);
}
}
6.2 审计日志设计
关键操作审计表结构:
sql复制CREATE TABLE `sys_log` (
`log_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`operation` varchar(50) DEFAULT NULL,
`method` varchar(100) DEFAULT NULL,
`params` text,
`time` bigint DEFAULT NULL,
`ip` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`log_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
AOP实现审计日志:
java复制@Aspect
@Component
public class LogAspect {
@Autowired
private SysLogService logService;
@Pointcut("@annotation(com.edu.annotation.Log)")
public void logPointCut() {}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
saveLog(point, time);
return result;
}
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = new SysLog();
Log logAnnotation = method.getAnnotation(Log.class);
if(logAnnotation != null) {
sysLog.setOperation(logAnnotation.value());
}
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
Object[] args = joinPoint.getArgs();
try {
String params = JSON.toJSONString(args);
sysLog.setParams(params);
} catch (Exception e) {
sysLog.setParams(Arrays.toString(args));
}
sysLog.setTime(time);
sysLog.setUsername(SecurityUtils.getUsername());
sysLog.setIp(IPUtils.getIpAddr());
sysLog.setCreateTime(new Date());
logService.save(sysLog);
}
}
