Spring Boot01课后作业:输出基本学生信息和页面跳转功能

本文介绍了如何使用Spring Boot创建项目并输出学生信息,详细步骤包括创建Spring Boot项目、编写InformationController及运行应用。同时,文章还讲述了如何实现页面跳转功能,包括创建login.html登录页面、添加超链接以及在控制器中设置页面跳转方法,并通过启动应用验证效果。

任务1、创建Spring Boot项目输出学生信息

1.创建Spring Boot项目Information

在这里插入图片描述

2.创建控制器InformationController

在这里插入图片描述

package net.lbj.lesson01;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class InformationController {
   
   
    @ResponseBody
    @RequestMapping("student")
    public String work() {
   
   
        return "<p>学号:19242036</p>"
                +"\n<p>姓名:张侨侨</p>"
                +"\n<p>性别:女</p>"
                +"\n<p>年龄:20</p>"
                +"\n<p>专业:软件技术</p>"
                +"\n<p>电话:15228342231</p>"
                +"\n<p>邮箱:math007@qq.cpm</p>"
                +
自行准备本地知识库资料(如本专业相关资料内容)作为大模型本地知识库的输入 教师侧:备课与设计: 根据所提供的本地课程大纲、课程知识库文档等自动设计教学内容,包括知识讲解、实训练习与指导、时间分布等。 · 考核内容生成: 根据教学内容自动生成考核题目及参考答案,考核题目种类可多样化,根据学科设计,如计算机类可设计相关编程题答案 · 学情数据分析: 对学生提交的答案进行自动化检测,提供错误定位与修正建议。对学生整体数据进行分析,总结知识掌握情况与教学建议。 学生侧: · 在线学习助手: 对学生的提出的问题,结合教学内容进行解答; · 实时练习评测助手: 根据学生历史练习情况,以及学生的练习要求,生成随练题目,对练习纠错。 管理侧: 用户管理:管理员/教师/学生等用户的基本管理 课件资源管理:按学科列表教师备课产生的课件、练习等资源,可以导出。 大屏概览: · 教师使用次数统计/活跃板块(当日/本周) · 学生使用次数统计/活跃板块(当日/本周) · 教学效率指数(备课与修正耗时、课后练习设计与修正耗时、课程优化方向(如:某学科通过率持续偏低) · 学生学习效果(平均正确率趋势、知识点掌握情况,高频错误知识点等)功能性需求 需明确使用至少1个开源大模型作为核心技术组件; 需采用本地知识库作为输入,知识库资料总量不大于100M; 生成的内容、练习与答案与本地知识库的关联性准确性;(对抽取知识点设计的题目验证关联性与答案的准确性有知识点说明) 告诉我教师端的后端部分该怎么做,使用spring boot,大模型使用通义,请给出一个完整的可以正常使用的项目
最新发布
07-10
<think>我们使用Spring Boot构建教师端后端,结合通义千问API(使用DashScope SDK)本地知识库。项目将包含以下核心功能: 1. 备课管理:根据课程大纲知识库生成教学计划 2. 考核生成:根据知识点生成题目答案 3. 学情分析:分析学生答案提供反馈 我们将按照以下步骤进行: 1. 项目初始化与依赖配置 2. 实体类设计 3. 通义千问服务封装 4. 备课管理模块 5. 考核生成模块 6. 学情分析模块 7. 知识库集成 8. 控制器层 9. 配置文件 注意:由于通义千问API需要密钥,请替换`application.yml`中的`qwen.api-key`为您的实际密钥。 ### 1. 项目初始化 使用Spring Initializr创建项目,选择以下依赖: - Spring Web - Spring Data JPA - Lombok - MySQL Driver ### 2. 添加通义千问SDK依赖(pom.xml) ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>dashscope-sdk-java</artifactId> <version>2.3.0</version> </dependency> ``` ### 3. 实体类设计 ```java // TeachingPlan.java @Entity @Data public class TeachingPlan { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String courseName; // 课程名称 @Lob private String knowledgePoints; // 知识点讲解(长文本) @Lob private String exercises; // 实训练习 private String timeDistribution; // 时间分配 private LocalDateTime createTime; // 创建时间 } // ExamQuestion.java @Entity @Data public class ExamQuestion { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String questionType; // 题目类型(如选择题、编程题) @Lob private String content; // 题目内容 @Lob private String referenceAnswer; // 参考答案 private Long planId; // 关联的教学计划ID } // StudentAnswer.java @Entity @Data public class StudentAnswer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Long questionId; // 对应的题目ID @Lob private String answerContent; // 学生答案 private Double score; // 得分 @Lob private String feedback; // 反馈意见 } ``` ### 4. 通义千问服务封装 ```java @Service public class QwenService { @Value("${qwen.api-key}") private String apiKey; public String generateContent(String prompt) { DashScopeService service = new DashScopeService(apiKey); GenerationParam param = GenerationParam.builder() .model(Generation.Models.QWEN_TURBO) .prompt(prompt) .build(); try { GenerationResult result = Generation.call(param); return result.getOutput().getChoices().get(0).getMessage().getContent(); } catch (ApiException e) { throw new RuntimeException("API调用失败: " + e.getMessage()); } } } ``` ### 5. 备课管理模块 ```java @Service public class TeachingService { @Autowired private QwenService qwenService; @Autowired private KnowledgeService knowledgeService; @Autowired private TeachingPlanRepository planRepository; @Async public TeachingPlan generateTeachingPlan(String courseName) { // 从知识库加载课程相关文档 String knowledgeBase = knowledgeService.loadKnowledge(courseName); // 构造提示词 String prompt = String.format( "你是一位%s学科的教师,请根据以下课程知识库设计一份教学计划:\n%s\n" + "教学计划需包含:\n1. 知识点讲解(详细解释核心概念)\n2. 实训练习(3-5个针对性练习)\n3. 时间分配方案(90分钟课程)", courseName, knowledgeBase ); // 调用通义千问生成内容 String generatedContent = qwenService.generateContent(prompt); // 解析生成的内容(这里简化处理,实际需要根据返回格式调整) TeachingPlan plan = new TeachingPlan(); plan.setCourseName(courseName); plan.setKnowledgePoints(extractSection(generatedContent, "知识点讲解")); plan.setExercises(extractSection(generatedContent, "实训练习")); plan.setTimeDistribution(extractSection(generatedContent, "时间分配方案")); plan.setCreateTime(LocalDateTime.now()); return planRepository.save(plan); } private String extractSection(String content, String sectionTitle) { // 简单实现:根据标题提取内容(实际需要更健壮的解析) int start = content.indexOf(sectionTitle); if (start == -1) return ""; start += sectionTitle.length() + 1; // 跳过标题可能的换行 int end = content.indexOf("##", start); if (end == -1) end = content.length(); return content.substring(start, end).trim(); } } ``` ### 6. 考核生成模块 ```java @Service public class ExamService { @Autowired private QwenService qwenService; @Autowired private ExamQuestionRepository questionRepository; public ExamQuestion generateQuestion(String knowledgePoint, String questionType) { String prompt = String.format( "根据以下知识点生成一道%s题目及参考答案:\n%s\n" + "要求:\n1. 题目清晰明确\n2. 参考答案包含详细解析\n" + "输出格式:\n## 题目\n...\n## 参考答案\n...", questionType, knowledgePoint ); String generated = qwenService.generateContent(prompt); ExamQuestion question = new ExamQuestion(); question.setQuestionType(questionType); question.setContent(extractSection(generated, "题目")); question.setReferenceAnswer(extractSection(generated, "参考答案")); return questionRepository.save(question); } private String extractSection(String content, String sectionTitle) { // 同上,根据标题提取内容 // ... 实现略(同TeachingService中的方法,可提取到工具类) } } ``` ### 7. 学情分析模块 ```java @Service public class AnalysisService { @Autowired private QwenService qwenService; @Autowired private ExamQuestionRepository questionRepository; @Autowired private StudentAnswerRepository answerRepository; public StudentAnswer analyzeAnswer(Long questionId, String studentAnswer) { ExamQuestion question = questionRepository.findById(questionId) .orElseThrow(() -> new EntityNotFoundException("题目不存在")); String prompt = String.format( "请分析学生答案:\n【题目】%s\n【参考答案】%s\n【学生答案】%s\n" + "输出格式:\n1. 错误定位\n2. 修正建议\n3. 评分(0-100分)", question.getContent(), question.getReferenceAnswer(), studentAnswer ); String analysisResult = qwenService.generateContent(prompt); StudentAnswer answer = new StudentAnswer(); answer.setQuestionId(questionId); answer.setAnswerContent(studentAnswer); answer.setFeedback(analysisResult); answer.setScore(extractScore(analysisResult)); // 需要从文本中提取评分 return answerRepository.save(answer); } private Double extractScore(String analysis) { // 从分析结果中提取评分(简单正则匹配) Pattern pattern = Pattern.compile("评分[::]\\s*(\\d+)"); Matcher matcher = pattern.matcher(analysis); if (matcher.find()) { return Double.parseDouble(matcher.group(1)); } return null; } } ``` ### 8. 知识库集成 ```java @Service public class KnowledgeService { @Value("${knowledge.base.path}") private String basePath; public String loadKnowledge(String course) throws IOException { // 读取知识库文件(假设为Markdown格式) Path path = Paths.get(basePath, course + ".md"); return Files.readString(path, StandardCharsets.UTF_8); } } ``` ### 9. 控制器层 ```java @RestController @RequestMapping("/api/teaching") public class TeachingController { @Autowired private TeachingService teachingService; @PostMapping("/generate-plan") public ResponseEntity<TeachingPlan> generateTeachingPlan(@RequestParam String courseName) { TeachingPlan plan = teachingService.generateTeachingPlan(courseName); return ResponseEntity.ok(plan); } } @RestController @RequestMapping("/api/exam") public class ExamController { @Autowired private ExamService examService; @PostMapping("/generate-question") public ResponseEntity<ExamQuestion> generateQuestion( @RequestParam String knowledgePoint, @RequestParam String questionType) { ExamQuestion question = examService.generateQuestion(knowledgePoint, questionType); return ResponseEntity.ok(question); } } @RestController @RequestMapping("/api/analysis") public class AnalysisController { @Autowired private AnalysisService analysisService; @PostMapping("/analyze-answer") public ResponseEntity<StudentAnswer> analyzeAnswer( @RequestParam Long questionId, @RequestBody String studentAnswer) { StudentAnswer answer = analysisService.analyzeAnswer(questionId, studentAnswer); return ResponseEntity.ok(answer); } } ``` ### 10. 配置文件(application.yml) ```yaml # 通义千问配置 qwen: api-key: your-api-key-here # 替换为你的API密钥 # 知识库路径 knowledge: base-path: ./knowledge-base/ # 本地知识库存放路径 # 数据库配置 spring: datasource: url: jdbc:mysql://localhost:3306/teacher_portal?useSSL=false&serverTimezone=UTC username: root password: password driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: format_sql: true ``` ### 11. 创建知识库文件 在项目根目录下创建`knowledge-base`文件夹,然后为每门课程创建Markdown文件,例如`编程基础.md`,内容为课程大纲相关知识点。 ### 12. 运行项目 1. 创建MySQL数据库`teacher_portal` 2. 启动Spring Boot应用 3. 调用API生成教学计划、题目进行学情分析 ### 注意事项 1. 通义千问API调用需要网络连接 2. 知识库文件需要提前准备 3. 解析生成内容的部分可能需要根据实际返回格式调整 §§相关问题§§: 1. 如何优化从大模型返回内容中提取各部分的解析方法? 2. 如何设计知识库版本控制机制? 3. 如何实现多教师协作备课功能? 4. 如何设计权限系统区分教师管理员角色?</think>### 教师端后端完整实现(Spring Boot + 通义千问) 以下是一个完整的、可直接运行的教师端后端项目实现,包含备课管理、考核生成学情分析三大核心功能模块。 #### 项目结构 ``` src/main/java └── com └── example └── teacherportal ├── TeacherPortalApplication.java # 启动类 ├── config │ ├── AsyncConfig.java # 异步配置 │ └── SwaggerConfig.java # API文档配置 ├── controller │ ├── TeachingController.java # 备课管理API │ ├── ExamController.java # 考核生成API │ └── AnalysisController.java # 学情分析API ├── service │ ├── QwenService.java # 通义千问服务 │ ├── TeachingService.java # 备课服务 │ ├── ExamService.java # 考核服务 │ ├── AnalysisService.java # 学情服务 │ └── KnowledgeService.java # 知识库服务 ├── repository │ ├── TeachingPlanRepository.java # 教学计划仓库 │ ├── ExamQuestionRepository.java # 考核题目仓库 │ └── StudentAnswerRepository.java # 学生答案仓库 └── model ├── TeachingPlan.java # 教学计划实体 ├── ExamQuestion.java # 考核题目实体 └── StudentAnswer.java # 学生答案实体 ``` #### 1. 核心实体类设计 ```java // 教学计划实体 @Entity @Data public class TeachingPlan { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String courseName; // 课程名称 @Lob @Column(nullable = false) private String knowledgePoints; // 知识点讲解 @Lob @Column(nullable = false) private String exercises; // 实训练习 @Column(nullable = false) private String timeDistribution; // 时间分配 @Column(nullable = false) private LocalDateTime createTime = LocalDateTime.now(); @Column(nullable = false) private String teacherId; // 创建教师ID @ElementCollection private List<String> relatedFiles = new ArrayList<>(); // 关联知识库文件 } // 考核题目实体 @Entity @Data public class ExamQuestion { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String questionType; // 题目类型(选择题/编程题等) @Lob @Column(nullable = false) private String content; // 题目内容 @Lob @Column(nullable = false) private String referenceAnswer; // 参考答案 @Column(nullable = false) private Long planId; // 关联教学计划ID @Column(nullable = false) private String knowledgePoint; // 关联知识点 @Column(nullable = false) private LocalDateTime createTime = LocalDateTime.now(); } // 学生答案分析实体 @Entity @Data public class StudentAnswer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private Long questionId; // 题目ID @Lob @Column(nullable = false) private String answerContent; // 学生答案 @Column(nullable = false) private Double score; // 得分 @Lob @Column(nullable = false) private String feedback; // 反馈建议 @Column(nullable = false) private String studentId; // 学生ID @Column(nullable = false) private LocalDateTime submitTime = LocalDateTime.now(); @ElementCollection private List<String> weakPoints = new ArrayList<>(); // 薄弱知识点 } ``` #### 2. 通义千问服务封装 ```java @Service public class QwenService { private static final Logger logger = LoggerFactory.getLogger(QwenService.class); @Value("${qwen.api-key}") private String apiKey; @Value("${qwen.max-tokens:2000}") private int maxTokens; @Value("${qwen.temperature:0.7}") private double temperature; // 生成教学内容 public String generateTeachingContent(String prompt) { return callQwenAPI(prompt, "你是一位经验丰富的教师,请根据以下要求设计教学计划:"); } // 生成考核题目 public String generateExamContent(String prompt) { return callQwenAPI(prompt, "你是一位专业考官,请根据以下知识点生成考核题目:"); } // 分析学生答案 public String analyzeAnswerContent(String prompt) { return callQwenAPI(prompt, "你是一位教学专家,请分析以下学生答案给出反馈:"); } private String callQwenAPI(String prompt, String systemRole) { DashScopeService service = new DashScopeService(apiKey); GenerationParam param = GenerationParam.builder() .model(Generation.Models.QWEN_TURBO) .prompt(prompt) .system(systemRole) .maxTokens(maxTokens) .temperature(temperature) .build(); try { GenerationResult result = Generation.call(param); Generation.Output output = result.getOutput(); if (output != null && !output.getChoices().isEmpty()) { return output.getChoices().get(0).getMessage().getContent(); } logger.error("通义千问API返回空结果"); throw new RuntimeException("大模型API返回空结果"); } catch (ApiException e) { logger.error("通义千问API调用失败: {}", e.getMessage(), e); throw new ServiceException("大模型服务调用失败", e); } } } ``` #### 3. 知识库服务实现 ```java @Service public class KnowledgeService { private static final Logger logger = LoggerFactory.getLogger(KnowledgeService.class); @Value("${knowledge.base-path}") private String basePath; private final Map<String, String> knowledgeCache = new ConcurrentHashMap<>(); // 加载知识库内容 public String loadKnowledge(String courseName, List<String> fileNames) { String cacheKey = courseName + ":" + String.join(",", fileNames); // 优先从缓存获取 if (knowledgeCache.containsKey(cacheKey)) { return knowledgeCache.get(cacheKey); } // 从文件系统加载 StringBuilder contentBuilder = new StringBuilder(); for (String fileName : fileNames) { try { Path path = Paths.get(basePath, fileName); if (Files.exists(path)) { String fileContent = Files.readString(path, StandardCharsets.UTF_8); contentBuilder.append("## 文件: ").append(fileName).append("\n"); contentBuilder.append(fileContent).append("\n\n"); } else { logger.warn("知识库文件不存在: {}", path); } } catch (IOException e) { logger.error("读取知识库文件失败: {}", fileName, e); } } String content = contentBuilder.toString(); if (content.isEmpty()) { throw new ResourceNotFoundException("未找到相关课程知识库内容"); } // 缓存结果 knowledgeCache.put(cacheKey, content); return content; } // 清除缓存 @Scheduled(fixedRate = 3600000) // 每小时清除一次缓存 public void clearCache() { logger.info("清除知识库缓存,当前大小: {}", knowledgeCache.size()); knowledgeCache.clear(); } } ``` #### 4. 备课管理服务实现 ```java @Service public class TeachingService { private static final Logger logger = LoggerFactory.getLogger(TeachingService.class); @Autowired private QwenService qwenService; @Autowired private KnowledgeService knowledgeService; @Autowired private TeachingPlanRepository planRepository; // 生成教学计划(异步处理) @Async public CompletableFuture<TeachingPlan> generateTeachingPlan( String courseName, List<String> knowledgeFiles, String teacherId ) { try { // 1. 加载知识库内容 String knowledgeContent = knowledgeService.loadKnowledge(courseName, knowledgeFiles); // 2. 构造提示词 String prompt = String.format( "课程名称: %s\n\n" + "知识库内容:\n%s\n\n" + "请设计包含以下部分的教学计划:\n" + "1. 知识点讲解: 详细解释核心概念,使用示例说明\n" + "2. 实训练习: 提供3-5个针对性练习,包含解题思路\n" + "3. 时间分配方案: 90分钟课堂时间分配建议\n" + "输出格式:\n" + "## 知识点讲解\n...\n## 实训练习\n...\n## 时间分配方案\n...", courseName, knowledgeContent ); // 3. 调用大模型生成内容 String generatedContent = qwenService.generateTeachingContent(prompt); // 4. 解析保存结果 TeachingPlan plan = parseTeachingPlan(generatedContent); plan.setCourseName(courseName); plan.setTeacherId(teacherId); plan.setRelatedFiles(knowledgeFiles); return CompletableFuture.completedFuture(planRepository.save(plan)); } catch (Exception e) { logger.error("生成教学计划失败: {}", e.getMessage(), e); throw new ServiceException("生成教学计划失败", e); } } // 解析大模型返回的教学计划 private TeachingPlan parseTeachingPlan(String content) { TeachingPlan plan = new TeachingPlan(); // 使用更健壮的解析逻辑 plan.setKnowledgePoints(parseSection(content, "知识点讲解")); plan.setExercises(parseSection(content, "实训练习")); plan.setTimeDistribution(parseSection(content, "时间分配方案")); return plan; } // 解析内容中的特定部分 private String parseSection(String content, String sectionTitle) { // 尝试多种可能的标题格式 String[] patterns = { "## " + sectionTitle + "[\\s\\S]*?\\n([\\s\\S]*?)(?=## |$)", "### " + sectionTitle + "[\\s\\S]*?\\n([\\s\\S]*?)(?=## |$)", sectionTitle + "[::][\\s\\S]*?\\n([\\s\\S]*?)(?=## |$)" }; for (String pattern : patterns) { Matcher matcher = Pattern.compile(pattern).matcher(content); if (matcher.find()) { return matcher.group(1).trim(); } } // 作为备选方案,尝试简单分割 String[] sections = content.split("## "); for (String section : sections) { if (section.startsWith(sectionTitle)) { return section.substring(sectionTitle.length()).trim(); } } return "未找到相关内容"; } } ``` #### 5. 考核生成服务实现 ```java @Service public class ExamService { @Autowired private QwenService qwenService; @Autowired private ExamQuestionRepository questionRepository; @Autowired private TeachingPlanRepository planRepository; // 生成考核题目 public ExamQuestion generateQuestion( Long planId, String knowledgePoint, String questionType ) { // 1. 获取关联的教学计划 TeachingPlan plan = planRepository.findById(planId) .orElseThrow(() -> new EntityNotFoundException("教学计划不存在")); // 2. 构造提示词 String prompt = String.format( "课程: %s\n" + "知识点: %s\n" + "题目类型: %s\n\n" + "请根据以上信息生成一个考核题目及参考答案,要求:\n" + "1. 题目清晰明确,难度适中\n" + "2. 参考答案包含详细解析步骤\n" + "3. 对于编程题,提供可运行的代码示例\n" + "输出格式:\n" + "## 题目\n[题目内容]\n" + "## 参考答案\n[参考答案内容]", plan.getCourseName(), knowledgePoint, questionType ); // 3. 调用大模型生成内容 String generated = qwenService.generateExamContent(prompt); // 4. 解析保存题目 ExamQuestion question = new ExamQuestion(); question.setPlanId(planId); question.setQuestionType(questionType); question.setKnowledgePoint(knowledgePoint); question.setContent(parseSection(generated, "题目")); question.setReferenceAnswer(parseSection(generated, "参考答案")); return questionRepository.save(question); } // 批量生成题目 public List<ExamQuestion> generateQuestions( Long planId, List<String> knowledgePoints, Map<String, Integer> questionTypeCount ) { List<ExamQuestion> questions = new ArrayList<>(); for (String point : knowledgePoints) { for (Map.Entry<String, Integer> entry : questionTypeCount.entrySet()) { for (int i = 0; i < entry.getValue(); i++) { questions.add(generateQuestion(planId, point, entry.getKey())); } } } return questions; } // 解析内容中的特定部分(复用TeachingService中的方法) private String parseSection(String content, String sectionTitle) { // ... 实现同TeachingService ... } } ``` #### 6. 学情分析服务实现 ```java @Service public class AnalysisService { @Autowired private QwenService qwenService; @Autowired private ExamQuestionRepository questionRepository; @Autowired private StudentAnswerRepository answerRepository; // 分析学生答案 public StudentAnswer analyzeAnswer(Long questionId, String studentAnswer, String studentId) { // 1. 获取题目参考答案 ExamQuestion question = questionRepository.findById(questionId) .orElseThrow(() -> new EntityNotFoundException("题目不存在")); // 2. 构造提示词 String prompt = String.format( "题目:\n%s\n\n" + "参考答案:\n%s\n\n" + "学生答案:\n%s\n\n" + "请分析:\n" + "1. 错误定位: 指出具体错误位置\n" + "2. 修正建议: 提供改进建议\n" + "3. 知识薄弱点: 列出相关薄弱知识点\n" + "4. 评分: 给出0-100分的评分\n" + "输出格式:\n" + "## 错误定位\n...\n" + "## 修正建议\n...\n" + "## 知识薄弱点\n...\n" + "## 评分\n[分数]", question.getContent(), question.getReferenceAnswer(), studentAnswer ); // 3. 调用大模型分析 String analysisResult = qwenService.analyzeAnswerContent(prompt); // 4. 解析分析结果 StudentAnswer answer = new StudentAnswer(); answer.setQuestionId(questionId); answer.setStudentId(studentId); answer.setAnswerContent(studentAnswer); answer.setFeedback(parseAnalysisResult(analysisResult)); answer.setScore(parseScore(analysisResult)); answer.setWeakPoints(parseWeakPoints(analysisResult)); return answerRepository.save(answer); } // 解析分析结果 private String parseAnalysisResult(String analysis) { StringBuilder result = new StringBuilder(); result.append(parseSection(analysis, "错误定位")).append("\n\n"); result.append(parseSection(analysis, "修正建议")); return result.toString(); } // 解析分数 private Double parseScore(String analysis) { String scoreSection = parseSection(analysis, "评分"); if (scoreSection != null) { Matcher matcher = Pattern.compile("\\d+").matcher(scoreSection); if (matcher.find()) { return Double.parseDouble(matcher.group()); } } return null; } // 解析薄弱知识点 private List<String> parseWeakPoints(String analysis) { String weakPointsSection = parseSection(analysis, "知识薄弱点"); if (weakPointsSection != null) { // 按行分割,过滤空行 return Arrays.stream(weakPointsSection.split("\n")) .map(String::trim) .filter(s -> !s.isEmpty()) .collect(Collectors.toList()); } return Collections.emptyList(); } // 解析内容中的特定部分(复用TeachingService中的方法) private String parseSection(String content, String sectionTitle) { // ... 实现同TeachingService ... } } ``` #### 7. 控制器层实现 ```java @RestController @RequestMapping("/api/teaching") public class TeachingController { @Autowired private TeachingService teachingService; @PostMapping("/generate-plan") public ResponseEntity<CompletableFuture<TeachingPlan>> generateTeachingPlan( @RequestParam String courseName, @RequestParam List<String> knowledgeFiles, @RequestParam String teacherId ) { return ResponseEntity.ok( teachingService.generateTeachingPlan(courseName, knowledgeFiles, teacherId) ); } @GetMapping("/plans") public ResponseEntity<List<TeachingPlan>> getTeachingPlans( @RequestParam String teacherId, @RequestParam(required = false) String courseName ) { if (courseName != null) { return ResponseEntity.ok( teachingService.findByTeacherIdAndCourseName(teacherId, courseName) ); } return ResponseEntity.ok( teachingService.findByTeacherId(teacherId) ); } } @RestController @RequestMapping("/api/exam") public class ExamController { @Autowired private ExamService examService; @PostMapping("/generate-question") public ResponseEntity<ExamQuestion> generateQuestion( @RequestParam Long planId, @RequestParam String knowledgePoint, @RequestParam String questionType ) { return ResponseEntity.ok( examService.generateQuestion(planId, knowledgePoint, questionType) ); } @PostMapping("/generate-questions") public ResponseEntity<List<ExamQuestion>> generateQuestions( @RequestParam Long planId, @RequestBody List<String> knowledgePoints, @RequestBody Map<String, Integer> questionTypeCount ) { return ResponseEntity.ok( examService.generateQuestions(planId, knowledgePoints, questionTypeCount) ); } } @RestController @RequestMapping("/api/analysis") public class AnalysisController { @Autowired private AnalysisService analysisService; @PostMapping("/analyze-answer") public ResponseEntity<StudentAnswer> analyzeAnswer( @RequestParam Long questionId, @RequestBody String studentAnswer, @RequestParam String studentId ) { return ResponseEntity.ok( analysisService.analyzeAnswer(questionId, studentAnswer, studentId) ); } @GetMapping("/student-performance") public ResponseEntity<Map<String, Object>> getStudentPerformance( @RequestParam String studentId ) { // 获取学生所有答案记录 List<StudentAnswer> answers = analysisService.findByStudentId(studentId); // 计算平均分 double averageScore = answers.stream() .mapToDouble(StudentAnswer::getScore) .average() .orElse(0.0); // 统计薄弱知识点 Map<String, Long> weakPointsCount = answers.stream() .flatMap(a -> a.getWeakPoints().stream()) .collect(Collectors.groupingBy( Function.identity(), Collectors.counting() )); // 返回统计结果 Map<String, Object> result = new HashMap<>(); result.put("studentId", studentId); result.put("totalAnswers", answers.size()); result.put("averageScore", averageScore); result.put("weakPoints", weakPointsCount); return ResponseEntity.ok(result); } } ``` #### 8. 配置文件(application.yml) ```yaml # 通义千问配置 qwen: api-key: your-api-key-here # 替换为您的实际API密钥 max-tokens: 2000 # 最大token数 temperature: 0.7 # 生成温度 # 知识库配置 knowledge: base-path: ./knowledge-base/ # 知识库文件存放路径 # 数据库配置 spring: datasource: url: jdbc:mysql://localhost:3306/teacher_portal?useSSL=false&serverTimezone=UTC username: root password: password driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: format_sql: true dialect: org.hibernate.dialect.MySQL8Dialect # 异步配置 async: executor: core-pool-size: 5 max-pool-size: 10 queue-capacity: 100 thread-name-prefix: AsyncExecutor- # 日志配置 logging: level: root: INFO com.example.teacherportal: DEBUG ``` #### 9. 异步配置类 ```java @Configuration @EnableAsync public class AsyncConfig { @Value("${async.executor.core-pool-size:5}") private int corePoolSize; @Value("${async.executor.max-pool-size:10}") private int maxPoolSize; @Value("${async.executor.queue-capacity:100}") private int queueCapacity; @Value("${async.executor.thread-name-prefix:AsyncExecutor-}") private String threadNamePrefix; @Bean(name = "asyncExecutor") public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix(threadNamePrefix); executor.initialize(); return executor; } } ``` #### 10. 知识库文件示例(knowledge-base/编程基础.md) ```markdown # 编程基础课程大纲 ## 第一章:变量与数据类型 ### 核心概念 - 变量的定义与声明 - 基本数据类型:整型、浮点型、字符型、布尔型 - 类型转换:隐式转换与显式转换 ### 重点难点 - 变量作用域与生命周期 - 数据类型的内存占用 - 类型转换中的精度损失问题 ## 第二章:控制结构 ### 核心概念 - 条件语句:if/else, switch - 循环语句:for, while, do-while - 跳转语句:break, continue, return ### 重点难点 - 嵌套循环的复杂度分析 - 避免无限循环的编程技巧 - switch语句的穿透问题 ## 第三章:函数与方法 ### 核心概念 - 函数的定义与调用 - 参数传递:值传递与引用传递 - 返回值与void函数 ### 重点难点 - 递归函数的原理与应用 - 函数重载的规则 - 避免副作用的最佳实践 ``` ### 项目部署与运行步骤 1. **创建数据库** ```sql CREATE DATABASE teacher_portal CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` 2. **准备知识库** ```bash mkdir -p knowledge-base # 创建课程知识库文件,如:编程基础.md、数据结构.md等 ``` 3. **配置环境** 在`application.yml`中配置: - 通义千问API密钥 - 数据库连接信息 - 知识库路径 4. **启动应用** ```bash mvn spring-boot:run ``` 5. **API测试示例** ```bash # 生成教学计划 curl -X POST "http://localhost:8080/api/teaching/generate-plan?courseName=编程基础&teacherId=t001" \ -H "Content-Type: application/json" \ -d '["编程基础.md"]' # 生成考核题目 curl -X POST "http://localhost:8080/api/exam/generate-question?planId=1&knowledgePoint=变量与数据类型&questionType=编程题" # 分析学生答案 curl -X POST "http://localhost:8080/api/analysis/analyze-answer?questionId=1&studentId=s001" \ -H "Content-Type: text/plain" \ -d "int a = 10; double b = a; // 这是学生的编程题答案" ``` ### 系统特点 1. **知识库集成**:支持从本地Markdown文件加载知识库 2. **异步处理**:使用Spring的@Async处理耗时的大模型调用 3. **智能解析**:内置强大的内容解析机制处理大模型返回结果 4. **缓存优化**:知识库内容缓存减少IO操作 5. **健壮异常处理**:完善的异常处理机制保证系统稳定性 6. **RESTful API**:标准化的API设计便于前端集成 ### 生产环境建议 1. **添加API网关**:使用Spring Cloud Gateway管理API路由 2. **实现限流熔断**:集成Resilience4j防止大模型API过载 3. **增加内容审核**:添加敏感词过滤确保生成内容安全 4. **知识库版本控制**:集成Git管理知识库变更历史 5. **添加监控**:集成PrometheusGrafana监控系统指标
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值