1. 项目背景与核心价值
2020年以来的全球公共卫生事件彻底改变了传统办公模式,居家办公从临时方案演变为企业常态化运营选择。这套基于SpringBoot+Vue3+MyBatis的疫情居家办公系统,正是针对混合办公场景下的痛点设计的企业级解决方案。
技术栈选型的深层考量:
- 后端采用SpringBoot 2.7.x + MyBatis-Plus 3.5.x组合,其自动装配特性可快速搭建RESTful API服务,MyBatis的动态SQL能力完美适配复杂业务查询
- 前端选用Vue3 + TypeScript + Pinia架构,Composition API使状态管理更清晰,搭配Vite构建工具实现秒级热更新
- 数据库采用MySQL 8.0,利用窗口函数优化统计报表查询,配合Redis缓存高频访问数据
实际开发中发现:当并发用户超过500时,纯MySQL查询响应时间会从200ms陡增至1.2s,通过引入Redis缓存用户权限数据后,性能回升至300ms左右
2. 系统架构设计解析
2.1 前后端分离实践方案
采用JWT+RBAC的认证授权模式,前端通过axios拦截器自动携带token。为解决跨域问题,SpringBoot需配置:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.maxAge(3600);
}
}
关键踩坑点:
- 开发环境使用proxy代理,但生产环境必须配置Nginx反向代理
- Vue3的.env环境变量需以VITE_前缀声明,否则构建时会被过滤
2.2 核心功能模块设计
| 模块 | 技术实现 | 性能优化点 |
|---|---|---|
| 考勤打卡 | 地理围栏算法+WiFi指纹验证 | 使用Redis GEO存储位置数据 |
| 视频会议 | WebRTC + Coturn穿透服务器 | 动态码率调整策略 |
| 任务管理 | 基于WebSocket的实时通知 | 消息幂等处理 |
| 健康上报 | 定时任务扫描未填报人员 | 批量插入优化 |
3. 数据库设计与优化
3.1 关键表结构示例
sql复制CREATE TABLE `work_report` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '关联用户表',
`content` text COLLATE utf8mb4_bin NOT NULL,
`submit_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-待审核 1-已通过',
`feedback` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_status` (`user_id`,`status`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
索引优化经验:
- 为status字段添加普通索引反而降低性能,改为联合索引后查询速度提升4倍
- TEXT类型字段必须单独建表,否则影响主表查询效率
3.2 事务处理要点
使用Spring声明式事务时要注意:
java复制@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void approveReport(Long reportId) {
// 先更新状态
reportMapper.updateStatus(reportId, APPROVED);
// 再写入审批记录
auditLogMapper.insert(new AuditLog(reportId, "APPROVE"));
// 发送通知(异步)
notificationService.sendApproveNotice(reportId);
}
踩坑记录:异步方法调用会导致事务失效,最终采用@Async+TransactionTemplate组合方案
4. 前端工程化实践
4.1 Vue3组合式API应用
typescript复制// 使用setup语法糖
<script setup lang="ts">
const tableData = ref<ReportItem[]>([])
const loading = ref(false)
// 带分页的查询方法
const fetchData = async (page: number) => {
loading.value = true
try {
const res = await api.getReports({ page })
tableData.value = res.data
} finally {
loading.value = false
}
}
// 自动清理副作用
onMounted(() => {
fetchData(1)
const timer = setInterval(fetchData, 60000)
onUnmounted(() => clearInterval(timer))
})
</script>
性能优化技巧:
- 使用v-memo缓存静态列表项
- 动态导入组件实现路由懒加载
- 采用Virtual Scroll处理万级数据列表
4.2 状态管理方案对比
| 方案 | 适用场景 | 本项目选择原因 |
|---|---|---|
| Pinia | 中小型应用 | 类型支持完善,DevTools友好 |
| Vuex | 大型复杂应用 | 维护成本较高 |
| 原生provide | 简单组件通信 | 缺乏状态持久化 |
5. 部署与监控方案
5.1 容器化部署脚本
dockerfile复制# 前端Dockerfile
FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
# 后端Dockerfile
FROM openjdk:17-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
CI/CD关键配置:
- 使用GitHub Actions实现自动化构建
- 通过Docker Compose编排服务依赖
- 采用Blue-Green部署策略降低风险
5.2 监控指标采集
yaml复制# Prometheus配置示例
scrape_configs:
- job_name: 'springboot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['backend:8080']
- job_name: 'node'
static_configs:
- targets: ['frontend:9100']
告警规则经验:
- 当JVM内存使用率持续5分钟>80%触发告警
- 接口99线响应时间>1s需要立即排查
- 数据库连接池使用率>90%时扩容
6. 典型问题解决方案
6.1 文件上传断点续传
前端采用分片上传策略:
javascript复制const chunkSize = 2 * 1024 * 1024 // 2MB
const uploadFile = async (file) => {
const chunks = Math.ceil(file.size / chunkSize)
for (let i = 0; i < chunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize)
await api.uploadChunk({
chunk,
index: i,
total: chunks,
fileHash: await calculateHash(file)
})
}
}
后端配合Redis记录上传进度:
java复制public void uploadChunk(ChunkDTO dto) {
String key = "upload:" + dto.getFileHash();
redisTemplate.opsForValue().setBit(key, dto.getIndex(), true);
if (redisTemplate.opsForValue().bitCount(key) == dto.getTotal()) {
mergeChunks(dto.getFileHash());
}
}
6.2 并发修改冲突处理
采用乐观锁机制:
sql复制UPDATE work_report
SET content = #{content}, version = version + 1
WHERE id = #{id} AND version = #{version}
前端处理冲突提示:
typescript复制const handleSave = async () => {
try {
await api.updateReport(formData)
} catch (e) {
if (e.response?.status === 409) {
ElMessage.error('文档已被他人修改,请刷新后重试')
fetchLatestData()
}
}
}
7. 安全防护措施
7.1 接口安全设计
- 参数校验:使用Hibernate Validator
java复制@PostMapping("/reports")
public Result createReport(@Valid @RequestBody ReportCreateDTO dto) {
// ...
}
- SQL防护:MyBatis严格参数绑定
xml复制<select id="selectByUser" resultType="Report">
SELECT * FROM work_report
WHERE user_id = #{userId} <!-- 禁止${}拼接 -->
</select>
- XSS防御:前端使用DOMPurify
javascript复制import DOMPurify from 'dompurify'
const clean = DOMPurify.sanitize(dirtyHTML)
7.2 敏感数据保护
| 数据类型 | 保护方案 | 实现方式 |
|---|---|---|
| 用户密码 | BCrypt哈希 | Spring Security |
| 身份证号 | AES加密存储 | Jasypt |
| 联系方式 | 数据库字段权限控制 | MyBatis拦截器 |
| 日志信息 | 脱敏处理 | Logback替换规则 |
8. 扩展能力设计
8.1 插件化架构
定义扩展点接口:
java复制public interface ApprovalPlugin {
String pluginId();
void beforeApprove(Report report);
void afterApprove(Report report);
}
通过SPI机制加载:
java复制ServiceLoader<ApprovalPlugin> plugins = ServiceLoader.load(ApprovalPlugin.class);
plugins.forEach(plugin -> plugin.beforeApprove(report));
8.2 多租户方案
采用共享数据库独立Schema模式:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/tenant_${tenantId}
动态数据源切换:
java复制public class TenantContext {
private static final ThreadLocal<String> currentTenant = new ThreadLocal<>();
public static void setTenant(String tenantId) {
currentTenant.set(tenantId);
}
public static String getTenant() {
return currentTenant.get();
}
}
9. 性能调优实战
9.1 Nginx配置优化
nginx复制http {
# 开启gzip
gzip on;
gzip_min_length 1k;
gzip_types text/plain application/javascript;
# 静态资源缓存
location ~* \.(js|css|png)$ {
expires 365d;
add_header Cache-Control "public";
}
}
9.2 JVM参数调整
bash复制java -jar app.jar \
-Xms512m -Xmx1024m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:ParallelGCThreads=4 \
-XX:ConcGCThreads=2
监控数据对比:
- 默认配置:GC耗时120ms/次,吞吐量92%
- 调优后:GC耗时45ms/次,吞吐量97%
10. 项目演进方向
-
智能化扩展:
- 接入NLP实现工作报告自动评分
- 使用OpenCV检测视频会议参与状态
-
移动端适配:
- 开发React Native跨端应用
- 集成推送通知能力
-
生态集成:
- 对接企业微信/钉钉开放平台
- 开发Chrome插件实现网页快捷操作
这套系统在实际部署中经历过3次重大版本迭代,目前支撑着某科技公司800+员工的日常远程协作。最大的收获是认识到:技术架构的扩展性比初期功能的完备性更重要,良好的分层设计使得后续新增健康打卡、物资申领等功能时,开发效率提升了60%以上。
