1. 项目概述与技术栈选型
这个基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的入校申报审批系统,是一个典型的现代化前后端分离架构的Web应用。我在实际开发这类校园管理系统时发现,这种技术组合能够很好地平衡开发效率、性能需求和维护成本。
核心架构设计思路:
- 前端采用Vue3组合式API开发,相比Vue2选项式API更灵活
- 后端使用SpringBoot2.x稳定版本,避免新版本潜在的兼容性问题
- ORM层选用MyBatis-Plus而非JPA,主要考虑复杂查询场景的灵活性
- 数据库使用MySQL8.0,充分利用其JSON支持、窗口函数等新特性
提示:MySQL8.0默认使用caching_sha2_password认证插件,连接时需注意驱动兼容性
2. 系统功能模块拆解
2.1 申报流程引擎设计
审批系统的核心是流程引擎,我们采用状态机模式实现:
java复制// 申报状态枚举定义
public enum ApplyStatus {
DRAFT("草稿"),
SUBMITTED("已提交"),
DEPARTMENT_APPROVING("部门审批中"),
SCHOOL_APPROVING("校级审批中"),
APPROVED("已通过"),
REJECTED("已驳回");
private final String desc;
// ...
}
状态转换规则通过策略模式实现,每个转换操作对应一个具体的策略类。这种设计便于后期添加新的审批环节。
2.2 前后端接口规范
RESTful接口设计遵循以下原则:
- 资源命名使用复数形式(如
/api/applications) - 状态码规范:200(成功)、400(参数错误)、401(未认证)、403(无权限)
- 分页参数统一使用
pageNum和pageSize
前端axios拦截器示例:
javascript复制// 请求拦截
axios.interceptors.request.use(config => {
config.headers['Authorization'] = getToken()
return config
})
// 响应拦截
axios.interceptors.response.use(response => {
return response.data
}, error => {
if (error.response.status === 401) {
router.push('/login')
}
return Promise.reject(error)
})
3. 关键技术实现细节
3.1 MyBatis-Plus高级应用
分页查询配置:
java复制@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
动态表名处理(用于多租户场景):
java复制public class DynamicTableNameParser implements ITableNameHandler {
@Override
public String dynamicTableName(String sql, String tableName) {
return getCurrentTenantId() + "_" + tableName;
}
}
3.2 Vue3组合式API实践
审批表单组件封装:
vue复制<script setup>
import { ref, computed } from 'vue'
const formData = ref({
name: '',
idCard: '',
visitReason: '',
// ...
})
const isFormValid = computed(() => {
return formData.value.name &&
/^\d{17}[\dXx]$/.test(formData.value.idCard)
})
</script>
4. 部署与性能优化
4.1 MySQL8.0配置建议
ini复制[mysqld]
# 使用新的数据字典
default_authentication_plugin=mysql_native_password
# 优化InnoDB配置
innodb_buffer_pool_size = 2G
innodb_log_file_size = 256M
# 启用窗口函数
windowing_use_high_precision = ON
4.2 SpringBoot性能调优
JVM参数推荐:
code复制-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
-Xms2g -Xmx2g
5. 常见问题解决方案
5.1 MyBatis-Plus更新问题
遇到updateById执行成功但实际未修改数据的情况,通常是因为:
- 实体类ID字段未加
@TableId注解 - 乐观锁版本号字段配置错误
- 更新字段值为null时需使用
updateWrapper.set
5.2 Vue3路由缓存失效
三级嵌套路由缓存问题解决方案:
javascript复制// router.js
{
path: '/parent',
component: Parent,
children: [
{
path: 'child',
component: Child,
children: [
{
path: 'grandchild',
component: GrandChild,
meta: { keepAlive: true } // 需要缓存的组件
}
]
}
]
}
6. 开发环境搭建指南
6.1 后端环境
- JDK1.8+(推荐Amazon Corretto11)
- Maven3.6+
- 初始化命令:
bash复制mvn archetype:generate \
-DgroupId=com.yourdomain \
-DartifactId=campus-approval \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
6.2 前端环境
- Node.js 16+
- 创建Vue3项目:
bash复制npm init vue@latest
- 推荐VS Code插件:
- Volar(Vue3官方推荐)
- ESLint
- Prettier
7. 项目文档规范
7.1 API文档
使用Swagger3配置:
java复制@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.select()
.apis(RequestHandlerSelectors.basePackage("com.yourpackage.controller"))
.paths(PathSelectors.any())
.build();
}
}
7.2 数据库设计文档
推荐使用PDManer或Navicat Data Modeler生成ER图,包含:
- 表结构定义
- 索引设计
- 外键关系
8. 安全防护措施
8.1 认证与授权
JWT实现方案:
java复制public class JwtUtil {
private static final String SECRET = "your-256-bit-secret";
public static String generateToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600_000))
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
}
// 验证方法...
}
8.2 SQL注入防护
MyBatis-Plus内置防护措施:
- 使用
#{}占位符而非字符串拼接 - 禁止前端直接传递排序字段,使用白名单过滤:
java复制public class SqlFilter {
private static final Set<String> ALLOWED_ORDER_FIELDS = Set.of("create_time", "id");
public static String safeOrder(String input) {
return ALLOWED_ORDER_FIELDS.contains(input) ? input : "id";
}
}
9. 测试策略
9.1 单元测试
SpringBoot测试示例:
java复制@SpringBootTest
class ApprovalServiceTest {
@Autowired
private ApprovalService service;
@Test
void testApproveFlow() {
Application app = new Application();
app.setStatus(SUBMITTED);
service.approve(app, "department_leader");
assertEquals(DEPARTMENT_APPROVING, app.getStatus());
}
}
9.2 前端组件测试
使用Vitest测试Vue3组件:
javascript复制import { mount } from '@vue/test-utils'
import ApprovalForm from './ApprovalForm.vue'
test('form validation', async () => {
const wrapper = mount(ApprovalForm)
await wrapper.find('#submit').trigger('click')
expect(wrapper.find('.error').exists()).toBe(true)
})
10. 项目扩展方向
10.1 微服务改造
可分拆为:
- 认证服务
- 流程引擎服务
- 通知服务
- 报表服务
使用Spring Cloud Alibaba组件:
xml复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
10.2 移动端适配
基于Vue3的响应式设计:
css复制/* 移动端样式覆盖 */
@media (max-width: 768px) {
.form-container {
padding: 10px;
}
.form-item {
flex-direction: column;
}
}
在实际部署时发现,MySQL8.0的默认配置可能不适合生产环境,特别是连接数设置和内存分配需要根据服务器配置调整。建议在正式上线前进行至少一轮压力测试,使用JMeter模拟并发审批请求,观察系统在不同负载下的表现。
