1. 项目概述:校园服务平台的现代化技术栈实践
这个基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的校园服务平台,是当前高校信息化建设中典型的全栈解决方案。我在实际开发中发现,这种技术组合特别适合处理校园场景中高并发、多终端的业务需求。平台通常包含课表查询、成绩管理、校园卡服务、场地预约等核心模块,而技术栈的选型直接决定了系统的扩展性和维护成本。
SpringBoot2作为后端框架,其自动配置特性让快速搭建微服务成为可能。配合MyBatis-Plus的增强CRUD功能,开发效率比传统MyBatis提升40%以上。前端选用Vue3的组合式API写法,使得复杂交互界面的代码组织更加清晰。MySQL8.0的窗口函数和CTE特性,则完美支持了校园业务中的各类统计报表需求。
提示:新手开发者常犯的错误是直接复制文档中的配置,而忽略校园业务特有的并发场景。比如选课系统的乐观锁控制,就需要在MyBatis-Plus的@Version注解基础上做二次开发。
2. 技术栈深度解析与选型依据
2.1 SpringBoot2的核心优势
采用2.x版本而非最新的3.x,主要考虑的是企业现有JDK版本的兼容性。在校园环境中,服务器往往采用长期支持版JDK(如JDK11),而SpringBoot3强制要求JDK17+。实际配置时需要注意:
yaml复制# application.yml典型配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/campus?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 加密后的密码应使用Jasypt处理
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER # 兼容Vue路由模式
特别要关注自动配置的排除项。比如当需要接入多个数据源时(可能连接旧版教务系统),需要这样处理:
java复制@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class
})
2.2 Vue3的组合式API实践
相比Vue2的Options API,Vue3的setup语法糖更适合校园应用的多模块场景。典型如成绩查询模块:
vue复制<script setup>
import { ref, onMounted } from 'vue'
import { getGradeList } from '@/api/education'
const loading = ref(false)
const gradeData = ref([])
onMounted(async () => {
loading.value = true
try {
gradeData.value = await getGradeList()
} finally {
loading.value = false
}
})
</script>
踩坑经验:在IE兼容性要求高的校园环境(如机房老电脑),需要额外配置@vitejs/plugin-legacy:
javascript复制// vite.config.js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
targets: ['defaults', 'not IE 11'] // 根据实际情况调整
})
]
}
2.3 MyBatis-Plus的高效开发模式
MyBatis-Plus的Lambda查询方式极大简化了DAO层代码。以教室预约模块为例:
java复制public Page<Classroom> queryAvailable(ClassroomQuery query) {
return lambdaQuery()
.eq(Classroom::getBuilding, query.getBuilding())
.ge(Classroom::getCapacity, query.getMinCapacity())
.between(Classroom::getFreeTime, query.getStart(), query.getEnd())
.page(new Page<>(query.getPage(), query.getSize()));
}
但要注意:校园系统的数据权限控制需要自定义拦截器。比如不同学院只能查看本学院的设备信息:
java复制public class DataPermissionInterceptor implements InnerInterceptor {
@Override
public void beforeQuery(Executor executor, MappedStatement ms,
Object parameter, RowBounds rowBounds, ResultHandler resultHandler,
BoundSql boundSql) {
// 获取当前用户院系信息
String dept = SecurityUtils.getCurrentUserDept();
// 修改SQL添加数据权限过滤
...
}
}
2.4 MySQL8.0的关键特性应用
窗口函数对于成绩排名等场景非常实用:
sql复制SELECT
student_id,
course_name,
score,
RANK() OVER (PARTITION BY course_id ORDER BY score DESC) AS rank
FROM grades
WHERE semester = '2023-2024-1'
配置建议:在my.cnf中优化连接池参数以适应校园高峰期的并发访问:
ini复制[mysqld]
innodb_buffer_pool_size = 2G # 建议物理内存的50-70%
max_connections = 500 # 根据服务器配置调整
thread_cache_size = 32 # 减少线程创建开销
3. 系统架构设计与实现细节
3.1 前后端分离架构实践
采用Nginx作为静态资源服务器和反向代理的典型配置:
nginx复制server {
listen 80;
server_name campus.example.com;
# Vue前端项目
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# SpringBoot API接口
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
跨域问题的解决方案:除了常规的CORS配置外,校园网特殊环境下可能需要处理预检请求:
java复制@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(false)
.maxAge(3600);
}
}
3.2 模块化设计与业务拆分
典型的校园服务模块划分:
| 模块 | 技术实现要点 | 典型接口示例 |
|---|---|---|
| 身份认证 | JWT+Spring Security | /auth/login |
| 教务管理 | MyBatis-Plus多表关联查询 | /edu/course/list |
| 校园卡 | Redis缓存+事务控制 | /card/consume |
| 消息中心 | WebSocket长连接 | /ws/message |
| 文件服务 | MinIO对象存储 | /file/upload |
3.3 数据库设计规范
遵循校园信息标准的ER图设计原则:
sql复制CREATE TABLE `student` (
`id` bigint NOT NULL COMMENT '学号',
`name` varchar(50) COLLATE utf8mb4_bin NOT NULL,
`college_id` int DEFAULT NULL COMMENT '所属学院',
`major_id` int DEFAULT NULL COMMENT '专业',
PRIMARY KEY (`id`),
KEY `idx_college` (`college_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE TABLE `course_selection` (
`id` bigint NOT NULL AUTO_INCREMENT,
`student_id` bigint NOT NULL,
`course_id` int NOT NULL,
`selection_time` datetime NOT NULL,
`version` int DEFAULT '0' COMMENT '乐观锁版本号',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_student_course` (`student_id`,`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
索引设计经验:在选课系统这类高并发场景,联合唯一索引比程序校验更可靠。
4. 开发环境搭建与调试技巧
4.1 本地开发环境配置
推荐使用Docker Compose快速启动依赖服务:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: campus
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
redis:
image: redis:alpine
ports:
- "6379:6379"
前端开发时,建议配置Vite的代理解决跨域:
javascript复制// vite.config.js
export default {
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
}
4.2 接口联调最佳实践
使用Swagger3+Knife4j打造可交互的API文档:
java复制@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.campus"))
.paths(PathSelectors.any())
.build();
}
}
配合前端的环境变量配置:
env复制# .env.development
VITE_API_BASE_URL=/api
VITE_USE_MOCK=true
4.3 性能优化实战
针对校园高峰期访问的优化方案:
- 二级缓存配置示例(Redis + MyBatis):
java复制@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
- 接口防刷策略(使用Guava RateLimiter):
java复制@Aspect
@Component
public class RateLimitAspect {
private final RateLimiter limiter = RateLimiter.create(100); // 每秒100个请求
@Around("@annotation(rateLimit)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
if (limiter.tryAcquire()) {
return joinPoint.proceed();
}
throw new BusinessException("访问过于频繁,请稍后再试");
}
}
5. 典型业务场景实现
5.1 课表查询的树形结构处理
使用Vue3的递归组件展示院系-专业-班级层级:
vue复制<template>
<ul>
<li v-for="node in treeData" :key="node.id">
{{ node.name }}
<tree-node v-if="node.children" :nodes="node.children"/>
</li>
</ul>
</template>
<script setup>
defineProps({
nodes: Array
})
</script>
后端使用MyBatis-Plus的@TableField注解处理树形结构:
java复制@Data
public class Department {
private Long id;
private String name;
private Long parentId;
@TableField(exist = false)
private List<Department> children;
}
5.2 选课系统的高并发控制
采用Redis分布式锁+数据库乐观锁的双重保障:
java复制public boolean selectCourse(Long studentId, Long courseId) {
String lockKey = "lock:course:" + courseId;
try {
// 获取分布式锁
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
throw new BusinessException("系统繁忙,请重试");
}
// 检查选课资格
// ...
// 乐观锁更新
int updated = courseSelectionMapper.updateSelection(
studentId, courseId, System.currentTimeMillis());
return updated > 0;
} finally {
redisTemplate.delete(lockKey);
}
}
5.3 校园卡交易的幂等性设计
使用唯一事务编号保证重复请求的幂等处理:
sql复制CREATE TABLE `card_transaction` (
`id` bigint NOT NULL AUTO_INCREMENT,
`transaction_no` varchar(32) NOT NULL COMMENT '唯一交易编号',
`card_id` varchar(20) NOT NULL,
`amount` decimal(10,2) NOT NULL,
`balance` decimal(10,2) NOT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_transaction_no` (`transaction_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
对应的Service层实现:
java复制@Transactional
public void consume(String transactionNo, String cardId, BigDecimal amount) {
// 检查是否已处理过
if (transactionMapper.existsByTransactionNo(transactionNo)) {
return;
}
// 扣款逻辑
cardMapper.deductBalance(cardId, amount);
// 记录交易
CardTransaction transaction = new CardTransaction();
transaction.setTransactionNo(transactionNo);
// 设置其他字段...
transactionMapper.insert(transaction);
}
6. 部署与运维方案
6.1 生产环境部署清单
必备的服务器资源配置建议:
| 服务 | 最低配置 | 推荐配置 | 备注 |
|---|---|---|---|
| 应用服务器 | 2核4G | 4核8G | 建议至少2节点做集群 |
| MySQL | 4核8G | 8核16G | SSD存储必备 |
| Redis | 2核4G | 4核8G | 主从模式 |
| Nginx | 1核2G | 2核4G | 负载均衡需要更高配置 |
6.2 容器化部署实践
使用Dockerfile构建SpringBoot应用镜像:
dockerfile复制FROM openjdk:11-jre
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
对应的Kubernetes部署示例:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: campus-backend
spec:
replicas: 3
selector:
matchLabels:
app: campus-backend
template:
metadata:
labels:
app: campus-backend
spec:
containers:
- name: app
image: registry.example.com/campus:1.0.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
---
apiVersion: v1
kind: Service
metadata:
name: campus-service
spec:
selector:
app: campus-backend
ports:
- protocol: TCP
port: 80
targetPort: 8080
6.3 监控与日志方案
Prometheus + Grafana的监控配置示例:
yaml复制# application.yml配置
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
tags:
application: campus-platform
日志收集建议采用ELK栈:
xml复制<!-- logback-spring.xml配置 -->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash:5044</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"app":"campus","env":"${spring.profiles.active}"}</customFields>
</encoder>
</appender>
7. 常见问题排查手册
7.1 启动类问题排查
问题1:SpringBoot启动报错找不到application.properties
根本原因:资源文件未正确打包。解决方案:
- 检查pom.xml资源过滤配置:
xml复制<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 确认打包后的jar文件中是否存在配置文件:
bash复制jar tf target/campus.jar | grep application.properties
问题2:Lombok注解不生效
典型错误信息:"you aren't using a compiler supported by lombok"
解决方法:
- IDE安装Lombok插件
- 在pom.xml中明确指定版本:
xml复制<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
7.2 数据库连接问题
问题3:MySQL8.0连接失败
常见错误:
- "Public Key Retrieval is not allowed"
- "The server time zone value is unrecognized"
解决方案:
- JDBC连接字符串添加参数:
properties复制spring.datasource.url=jdbc:mysql://localhost:3306/campus?\
useSSL=false&\
serverTimezone=Asia/Shanghai&\
allowPublicKeyRetrieval=true
- 确认MySQL用户权限:
sql复制CREATE USER 'campus'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT ALL PRIVILEGES ON campus.* TO 'campus'@'%';
FLUSH PRIVILEGES;
7.3 前端部署问题
问题4:Vue3路由刷新404
Nginx配置需要添加try_files规则:
nginx复制location / {
try_files $uri $uri/ /index.html;
}
问题5:生产环境API请求跨域
虽然开发环境配置了代理,但生产环境需要:
- Nginx添加CORS头:
nginx复制location /api/ {
add_header 'Access-Control-Allow-Origin' '$http_origin';
add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization';
# 其他代理配置...
}
- 或者后端统一处理:
java复制@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
8. 项目文档编写规范
8.1 接口文档标准
使用Swagger注解增强可读性:
java复制@Operation(summary = "获取学生课表")
@GetMapping("/timetable/{studentId}")
public Result<TimeTableVO> getTimeTable(
@Parameter(description = "学号", required = true)
@PathVariable String studentId,
@Parameter(description = "学期", example = "2023-2024-1")
@RequestParam(required = false) String semester) {
// 实现逻辑
}
8.2 数据库设计文档
建议包含以下要素:
- 表结构说明
- 索引设计理由
- 关键字段枚举值
- 表关系图(使用PlantUML等工具生成)
示例格式:
markdown复制## 学生表(student)
| 字段 | 类型 | 必填 | 说明 |
|-------------|--------------|------|----------------|
| id | bigint | 是 | 学号,主键 |
| name | varchar(50) | 是 | 学生姓名 |
| college_id | int | 是 | 所属学院ID |
**索引:**
- 主键索引:id
- 普通索引:college_id(用于按学院查询)
**关联表:**
- 与college表通过college_id关联
- 与course_selection表通过id关联
8.3 部署手册要点
完整的部署手册应包含:
- 环境要求清单(JDK版本、Node版本等)
- 数据库初始化脚本
- 配置文件模板(application.yml示例)
- 启动/停止脚本示例
- 健康检查接口说明(如/actuator/health)
9. 扩展与二次开发建议
9.1 微服务化改造
当系统规模扩大时,可考虑拆分为:
- 认证服务(Spring Security + OAuth2)
- 教务核心服务
- 校园卡服务
- 消息推送服务
使用Spring Cloud Alibaba组件集成:
xml复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
9.2 移动端适配方案
方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| Uni-app | 一套代码多端运行 | 复杂功能性能受限 |
| Flutter | 高性能,漂亮UI | 学习曲线陡峭 |
| 原生+H5混合 | 灵活性高 | 维护成本高 |
个人推荐:对性能要求不高的管理端功能使用Uni-app:
javascript复制// uni-app调用原生功能示例
uni.scanCode({
success: res => {
this.code = res.result;
}
});
9.3 低代码平台集成
可集成Jeecg-Boot等低代码平台快速生成管理后台:
- 添加依赖:
xml复制<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-spring-boot-starter</artifactId>
<version>2.4.0</version>
</dependency>
- 实体类继承基础模型:
java复制@Data
@TableName("student")
public class Student extends BaseEntity {
// 原有字段...
}
10. 测试策略与质量保障
10.1 单元测试规范
MyBatis-Plus测试示例:
java复制@SpringBootTest
public class CourseServiceTest {
@Autowired
private CourseService courseService;
@Test
@Rollback
public void testSelectCourse() {
Long studentId = 20230001L;
Long courseId = 101L;
boolean result = courseService.selectCourse(studentId, courseId);
assertTrue(result);
// 验证重复选课
assertThrows(BusinessException.class, () -> {
courseService.selectCourse(studentId, courseId);
});
}
}
10.2 接口测试方案
使用TestContainers进行集成测试:
java复制@Testcontainers
@SpringBootTest
public class CardControllerIT {
@Container
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0");
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}
@Test
void testConsume() {
// 测试代码...
}
}
10.3 前端测试实践
Vue3组件测试配置:
javascript复制// vitest.config.js
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'happy-dom',
coverage: {
reporter: ['text', 'json', 'html']
}
}
})
测试用例示例:
javascript复制import { mount } from '@vue/test-utils'
import GradeTable from '../GradeTable.vue'
test('displays grades correctly', async () => {
const wrapper = mount(GradeTable, {
props: {
grades: [
{ course: '数学', score: 90 },
{ course: '英语', score: 85 }
]
}
})
expect(wrapper.findAll('tr').length).toBe(3) // 表头+两行数据
expect(wrapper.text()).toContain('数学')
})
11. 安全防护方案
11.1 认证与授权体系
JWT增强方案:使用双token机制(accessToken + refreshToken)
java复制public class JwtTokenUtil {
// accessToken有效期30分钟
private static final long ACCESS_EXPIRE = 30 * 60 * 1000;
// refreshToken有效期7天
private static final long REFRESH_EXPIRE = 7 * 24 * 60 * 60 * 1000;
public String generateAccessToken(UserDetails user) {
// 生成逻辑...
}
public String generateRefreshToken(UserDetails user) {
// 生成逻辑...
}
}
11.2 SQL注入防护
MyBatis-Plus的自动过滤机制:
java复制@RestController
@RequestMapping("/student")
public class StudentController {
@GetMapping
public Page<Student> list(
@RequestParam(required = false) String name,
Pageable pageable) {
// 自动防止SQL注入
return studentService.lambdaQuery()
.like(StringUtils.isNotBlank(name), Student::getName, name)
.page(pageable);
}
}
11.3 XSS防护方案
前端使用DOMPurify过滤:
javascript复制import DOMPurify from 'dompurify'
const clean = DOMPurify.sanitize(dirtyHtml)
后端统一处理:
java复制@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new XssInterceptor())
.addPathPatterns("/**");
}
}
12. 性能调优实战记录
12.1 数据库查询优化
慢查询定位与优化步骤:
- 开启慢查询日志:
ini复制# my.cnf
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
- 使用EXPLAIN分析:
sql复制EXPLAIN SELECT * FROM course_selection
WHERE student_id = 20230001
ORDER BY selection_time DESC
LIMIT 10;
- 添加合适索引:
sql复制ALTER TABLE course_selection
ADD INDEX idx_student_time (student_id, selection_time);
12.2 接口响应优化
缓存策略设计:
| 数据类型 | 缓存策略 | 过期时间 |
|---|---|---|
| 静态配置 | 永久缓存 | 不过期 |
| 课表信息 | 定时刷新 | 1天 |
| 成绩信息 | 用户触发更新 | 30分钟 |
| 校园卡余额 | 写穿透 | 5分钟 |
Spring Cache配置示例:
java复制@Cacheable(value = "timetable", key = "#studentId + '-' + #semester")
public TimeTableVO getTimeTable(String studentId, String semester) {
// 查询逻辑
}
@CacheEvict(value = "timetable", key = "#studentId + '-' + #semester")
public void updateTimeTable(String studentId, String semester) {
// 更新逻辑
}
12.3 前端性能优化
Vue3特定优化技巧:
- 组件懒加载:
javascript复制const CourseList = defineAsyncComponent(() =>
import('./components/CourseList.vue')
)
- 列表虚拟滚动:
vue复制<template>
<RecycleScroller
class="scroller"
:items="largeList"
:item-size="50"
key-field="id">
<template #default="{ item }">
<div class="item">{{ item.name }}</div>
</template>
</RecycleScroller>
</template>
- 图片懒加载:
html复制<img v-lazy="imageUrl" alt="校园风光">
13. 项目演进与版本管理
13.1 Git分支策略
校园项目推荐采用改进的Git Flow:
code复制main - 生产环境代码(保护分支)
release/* - 预发布分支
develop - 集成测试分支
feature/* - 功能开发分支
hotfix/* - 紧急修复分支
13.2 版本号规范
遵循语义化版本控制(SemVer):
code复制MAJOR.MINOR.PATCH
- MAJOR:不兼容的API修改
- MINOR:向后兼容的功能新增
- PATCH:向后兼容的问题修正
示例变更日志:
markdown复制## [1.2.0] - 2023-08-15
### Added
- 新增实验室预约功能
- 支持微信小程序端登录
### Changed
- 优化选课系统并发控制
### Fixed
- 修复校园卡交易重复扣款问题
13.3 依赖版本管理
使用Maven的dependencyManagement统一管理:
xml复制<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
前端使用.npmrc锁定安装版本:
ini复制# .npmrc
engine-strict=true
save-exact=true
14. 团队协作规范
14.1 代码风格统一
后端Java规范:
- 使用Spotless自动格式化:
xml复制<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.27.0</version>
<configuration>
<java>
<googleJavaFormat/>
<removeUnusedImports/>
</java>
</configuration>
</plugin>
前端ESLint配置:
javascript复制// .eslintrc.js
module.exports = {
rules: {
'vue/multi-word-component-names': 'off',
'vue/no-setup-props-destructure': 'off'
}
}
14.2 提交信息规范
采用Conventional Commits格式:
code复制<type>[optional scope]: <description>
[optional body]
[optional footer]
常用type类型:
- feat:新功能
- fix:bug修复
- docs:文档变更
- style:代码格式
- refactor:重构代码
- test:测试相关
- chore:构建/工具变更
示例:
code复制feat(education): 添加成绩统计分析功能
新增学生成绩分布图接口
新增班级平均分对比功能
Closes #123
14.3 代码审查要点
审查清单示例:
| 检查项 | 标准 |
|---|---|
| 代码风格 | 符合项目规范 |
| 单元测试覆盖率 | 新增代码>=80% |
| 日志记录 | 关键操作有INFO日志 |
| 异常处理 | 捕获具体异常而非Throwable |
| 安全防护 | 无SQL注入/XSS风险 |
| 性能考虑 | 大数据量查询有分页 |
15. 项目交接与知识传承
15.1 交接文档清单
完整的项目交接应包含:
- 系统架构图(C4模型)
- 部署拓扑图
- 领域模型图
- 核心流程时序图
- 运维手册(含监控指标说明)
- 已知问题列表
- 技术债务清单
15.2 知识传承会议
建议开展以下主题的分享会:
- 领域模型设计思路
- 关键技术决策背后的考量
- 典型业务场景的实现方案
- 曾遇到的重大故障及解决方案
- 未来可能的扩展方向
15.3 持续改进机制
建立技术雷达评估体系:
| 技术/工具 | 分类 | 现状 | 建议 |
|---|---|---|---|
| Vue3 | 语言框架 | 采用 | 继续使用 |
| Spring Boot 3 | 语言框架 | 评估 | 暂不升级 |
| MySQL 8.0 | 数据存储 | 采用 | 扩展集群 |
| Redis | 缓存 | 采用 | 增加哨兵 |
定期(如每季度)召开技术评审会,评估各项技术的适用性。
