概述 针对作业批改系统(Spring Boot 4.0.4 + OpenClaw Gateway)进行了一轮系统优化,涵盖定时任务、插件稳定性、接口文档、缓存性能四个维度。
一、OpenClaw Cron 定时播报 需求 每周五在 QQ 群自动播报未完成作业的学生名单。
架构 1 2 3 4 5 OpenClaw cron(每周五 20:00) → web_fetch → 触发 Spring Boot /api/homework/tasks/remind-all → TaskReminderService.sendRecurringStatusReminder() → 查 class_student + submission → 未交名单 → OneBotHttpService → Napcat HTTP → QQ 群消息
关键代码 HomeworkTaskMapper.java — 查活跃作业:
1 2 3 @Select("SELECT * FROM homework_task WHERE status != 'closed' " + "AND deadline IS NOT NULL AND deadline > NOW() ORDER BY deadline ASC") List<HomeworkTask> selectActiveWithDeadline () ;
TaskReminderService.java — 定期播报方法:
1 2 3 4 5 6 7 8 9 public void sendRecurringStatusReminder (Long taskId) { List<Map<String, Object>> unsubmitted = classStudentMapper .selectUnsubmittedByTaskId(task.getClassId(), taskId); Integer submittedCount = classStudentMapper .countSubmittedByTaskId(task.getClassId(), taskId); Integer totalCount = classStudentMapper.countByClassId(task.getClassId()); }
HomeworkController.java — 触发端点:
1 2 3 4 5 6 7 8 @GetMapping("/tasks/remind-all") public ResponseEntity<?> remindAllTasks() { List<HomeworkTask> activeTasks = taskMapper.selectActiveWithDeadline(); for (HomeworkTask task : activeTasks) { taskReminderService.sendRecurringStatusReminder(task.getId()); } return ResponseEntity.ok(Map.of("code" , 200 , "message" , "已处理" )); }
OpenClaw cron 配置 :
1 2 3 4 5 6 7 8 openclaw cron add \ --name "作业完成情况定时播报" \ --cron "0 20 * * 5" \ --tz "Asia/Shanghai" \ --session isolated \ --agent jarvis \ --light-context \ --message "用 web_fetch 请求 http://localhost:8080/api/homework/tasks/remind-all..."
二、OneBot 插件稳定性修复 问题 QQ 群消息偶尔发不出去,日志显示 bufferLen=0, chunks=0,同时 OneBot 插件反复重载。
根因链 1 2 3 4 5 memory_search 工具卡 126s → event loop 延迟飙到 90s → 插件健康检查触发重载 → dispatcher 回调被销毁 → 消息丢失
修复 jarvis agent 设置 skills: ["homework-grader"],移除 memory-core 技能:
1 2 3 4 5 6 7 8 9 10 { "agents" : { "list" : [ { "id" : "jarvis" , "skills" : [ "homework-grader" ] } ] } }
QQ 群消息收发走 onebot channel plugin ,与 skills 无关,不影响消息功能。
三、Dashboard 数据定时上报 RAG 需求 教师端控制台「上传数据库」功能改为每天自动执行,无需手动触发。
实现 DemoApplication.java — 启用调度:
DashboardUploadScheduler.java — 定时调度器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Component @RequiredArgsConstructor public class DashboardUploadScheduler { private final ClassInfoMapper classInfoMapper; private final DashboardService dashboardService; private final DashboardRagService dashboardRagService; private final VectorStoreService vectorStoreService; @Scheduled(cron = "0 0 2 * * ?", zone = "Asia/Shanghai") public void scheduledUpload () { List<ClassInfo> classes = classInfoMapper.selectList(null ); for (ClassInfo cls : classes) { if (vectorStoreService.existsToday("dashboard_" + cls.getId())) { continue ; } DashboardUploadDTO data = buildUploadData(cls); dashboardRagService.uploadDashboard(data); } } }
四、Swagger API 文档 技术选型 Spring Boot 4.x 使用 Spring Framework 7.x,knife4j 4.5.0 内置的 springdoc 2.3.0 不兼容。最终使用 springdoc-openapi 3.0.0 。
依赖 1 2 3 4 5 <dependency > <groupId > org.springdoc</groupId > <artifactId > springdoc-openapi-starter-webmvc-ui</artifactId > <version > 3.0.0</version > </dependency >
配置 OpenAPI Bean — 添加 JWT Bearer 认证方案:
1 2 3 4 5 6 7 8 9 10 11 12 @Bean public OpenAPI openAPI () { return new OpenAPI () .info(new Info ().title("作业批改系统 API" ).version("1.0" )) .addSecurityItem(new SecurityRequirement ().addList("Bearer" )) .components(new Components () .addSecuritySchemes("Bearer" , new SecurityScheme () .name("Bearer" ) .type(SecurityScheme.Type.HTTP) .scheme("bearer" ) .bearerFormat("JWT" ))); }
SecurityConfig.java — 放行 Swagger 路径:
1 2 3 .requestMatchers("/api/auth/**" , "/api/homework/**" , "/v3/api-docs/**" , "/swagger-ui/**" , "/swagger-ui.html" , "/doc.html" , "/webjars/**" ) .permitAll()
访问
API 文档 JSON:http://localhost:8080/v3/api-docs
Swagger UI:http://localhost:8080/swagger-ui.html
右上角 Authorize → 输入 Bearer <JWT Token> → 在线调试
五、Spring Cache 缓存优化 技术选型 Caffeine 本地缓存(内存缓存,零网络开销,适合单机部署)。
依赖 1 2 3 4 5 6 7 8 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-cache</artifactId > </dependency > <dependency > <groupId > com.github.ben-manes.caffeine</groupId > <artifactId > caffeine</artifactId > </dependency >
缓存配置 1 2 3 4 5 6 7 8 9 @Bean public CacheManager cacheManager () { CaffeineCacheManager manager = new CaffeineCacheManager (); manager.setCaffeine(Caffeine.newBuilder() .maximumSize(200 ) .expireAfterWrite(30 , TimeUnit.MINUTES) .recordStats()); return manager; }
缓存注解 DashboardServiceImpl.java — 查询缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 @CacheConfig(cacheNames = "dashboard") @Cacheable(key = "'metrics:' + #classId") public DashboardMetricsDTO getMetrics (Long classId) { ... }@Cacheable(key = "'scoreDist:' + #classId") public List<ScoreDistributionDTO> getScoreDistribution (Long classId) { ... }@Cacheable(key = "'knowledge:' + #classId") public List<KnowledgeMasteryDTO> getKnowledgeMastery (Long classId) { ... }@Cacheable(key = "'errors:' + #classId") public List<FrequentErrorDTO> getFrequentErrors (Long classId) { ... }
缓存清除 学生提交作业和批改完成时清除对应班级缓存:
1 2 3 4 5 6 7 8 var cache = cacheManager.getCache("dashboard" );if (cache != null ) { cache.evict("metrics:" + classId); cache.evict("scoreDist:" + classId); cache.evict("knowledge:" + classId); cache.evict("errors:" + classId); }
总结
模块
技术点
效果
定时播报
OpenClaw cron + Spring API
每周五自动推送未交名单
插件稳定
skills 白名单
解决 OneBot 重载丢消息
自动上报
@Scheduled + Caffeine
每日凌晨自动同步 RAG
API 文档
springdoc 3.0.0 + JWT
Swagger UI 可视化调试
查询加速
@Cacheable + Caffeine
Dashboard 响应毫秒级